! empty( $a['post_types'] ) ? $a['post_types'] : array( 'post' ), 'posts_per_page' => -1, 'post_status' => 'publish' ); if ( ! empty( $a['s'] ) ) { $q['s'] = $a['s']; } if ( ! empty( $a['author'] ) ) { $q['author'] = (int) $a['author']; } if ( ! empty( $a['cat'] ) ) { $q['cat'] = (int) $a['cat']; } $date_query = array(); if ( ! empty( $a['date_from'] ) ) { $date_query[] = array( 'after' => $a['date_from'] ); } if ( ! empty( $a['date_to'] ) ) { $date_query[] = array( 'before' => $a['date_to'] ); } if ( $date_query ) { $q['date_query'] = $date_query; } return $q; } private function run_export( $args ) { $dir = $this->ensure_dir(); if ( ! $dir ) { return array( 'ok' => false, 'file' => '', 'count' => 0, 'size_kb' => 0 ); } $q = new WP_Query( $this->build_query( $args ) ); $flags = 0; if ( defined( 'JSON_UNESCAPED_UNICODE' ) ) { $flags |= JSON_UNESCAPED_UNICODE; } if ( defined( 'JSON_UNESCAPED_SLASHES' ) ) { $flags |= JSON_UNESCAPED_SLASHES; } if ( empty( $args['minify'] ) && defined( 'JSON_PRETTY_PRINT' ) ) { $flags |= JSON_PRETTY_PRINT; } $count = 0; $files = array(); if ( $q->have_posts() ) { while ( $q->have_posts() ) { $q->the_post(); $p = get_post(); $payload = $this->extract_payload( $p ); if ( empty( $args['include_acf'] ) ) { unset( $payload['acf'] ); } $json = function_exists( 'wp_json_encode' ) ? wp_json_encode( $payload, $flags ) : json_encode( $payload ); $fn = 'post-' . $p->ID . '.json'; file_put_contents( trailingslashit( $dir ) . $fn, $json ); $files[] = $fn; $count++; } wp_reset_postdata(); } $file_out = ''; $size_kb = 0; $stamp = date_i18n( 'Ymd-His' ); if ( ! empty( $args['zip'] ) && class_exists( 'ZipArchive' ) ) { $zipname = 'ai-json-export-' . $stamp . '.zip'; $zip = new ZipArchive(); $zip_path = trailingslashit( $dir ) . $zipname; if ( true === $zip->open( $zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) { $size_total = 0; foreach ( $files as $fn ) { $path = trailingslashit( $dir ) . $fn; if ( file_exists( $path ) ) { $zip->addFile( $path, $fn ); $size_total += filesize( $path ); } } $zip->close(); $this->log_export( $zipname, $count, round( $size_total / 1024, 1 ), $args ); $file_out = $zipname; $size_kb = round( $size_total / 1024, 1 ); } } else { $outname = 'ai-json-export-' . $stamp . '.json'; $bundle = array(); foreach ( $files as $fn ) { $p = trailingslashit( $dir ) . $fn; if ( file_exists( $p ) ) { $bundle[] = json_decode( file_get_contents( $p ), true ); } } $json_bundle = function_exists( 'wp_json_encode' ) ? wp_json_encode( $bundle, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ) : json_encode( $bundle ); file_put_contents( trailingslashit( $dir ) . $outname, $json_bundle ); $this->log_export( $outname, $count, round( strlen( $json_bundle ) / 1024, 1 ), $args ); $file_out = $outname; $size_kb = round( strlen( $json_bundle ) / 1024, 1 ); } return array( 'ok' => true, 'file' => $file_out, 'count' => $count, 'size_kb' => $size_kb ); } private function log_export( $filename, $count, $size_kb, $args ) { $u = wp_upload_dir(); $dir = trailingslashit( $u['basedir'] ) . self::EXPORT_DIR; $log = trailingslashit( $dir ) . self::LOG_FILE; if ( ! file_exists( $dir ) ) { wp_mkdir_p( $dir ); } $filters = sprintf( 'types:%s | author:%s | cat:%s | date:%s..%s | search:%s | acf:%s | min:%s | zip:%s', implode( ',', (array) $args['post_types'] ), ! empty( $args['author'] ) ? (int) $args['author'] : '-', ! empty( $args['cat'] ) ? (int) $args['cat'] : '-', ! empty( $args['date_from'] ) ? $args['date_from'] : '-', ! empty( $args['date_to'] ) ? $args['date_to'] : '-', ! empty( $args['s'] ) ? $args['s'] : '-', ! empty( $args['include_acf'] ) ? '1' : '0', ! empty( $args['minify'] ) ? '1' : '0', ! empty( $args['zip'] ) ? '1' : '0' ); $fh = fopen( $log, file_exists( $log ) ? 'a' : 'w' ); if ( $fh ) { fputcsv( $fh, array( date_i18n( 'c' ), $filename, $count, $size_kb, $filters ) ); fclose( $fh ); } } public function handle_export() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'No permission.', 'ai-json-extractor-auto-embed-lite' ) ); } check_admin_referer( 'aije_export' ); $a = array( 'post_types' => isset( $_POST['post_types'] ) ? array_map( 'sanitize_key', (array) $_POST['post_types'] ) : array( 'post', 'page' ), 'author' => isset( $_POST['author'] ) ? (int) $_POST['author'] : 0, 'cat' => isset( $_POST['cat'] ) ? (int) $_POST['cat'] : 0, 'date_from' => isset( $_POST['date_from'] ) ? sanitize_text_field( wp_unslash( $_POST['date_from'] ) ) : '', 'date_to' => isset( $_POST['date_to'] ) ? sanitize_text_field( wp_unslash( $_POST['date_to'] ) ) : '', 's' => isset( $_POST['s'] ) ? sanitize_text_field( wp_unslash( $_POST['s'] ) ) : '', 'include_acf' => ! empty( $_POST['include_acf'] ) ? 1 : 0, 'minify' => ! empty( $_POST['minify'] ) ? 1 : 0, 'zip' => ! empty( $_POST['zip'] ) ? 1 : 0 ); update_option( self::LAST_ARGS_OPT, $a, false ); $res = $this->run_export( $a ); wp_safe_redirect( add_query_arg( array( 'page' => 'aije-lite', 'tab' => 'export', 'export_done' => $res['ok'] ? 1 : 0, 'file' => $res['file'], 'count' => $res['count'], 'size_kb' => $res['size_kb'] ), admin_url( 'tools.php' ) ) ); exit; } public function handle_run_cron_now() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'No permission.', 'ai-json-extractor-auto-embed-lite' ) ); } check_admin_referer( 'aije_export' ); $a = get_option( self::LAST_ARGS_OPT, array( 'post_types' => array( 'post', 'page' ), 'author' => 0, 'cat' => 0, 'date_from' => '', 'date_to' => '', 's' => '', 'include_acf' => 1, 'minify' => 0, 'zip' => 1 ) ); $this->run_export( $a ); wp_safe_redirect( add_query_arg( array( 'page' => 'aije-lite', 'tab' => 'automation', 'ran' => 1 ), admin_url( 'tools.php' ) ) ); exit; } public function handle_clear_cron() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'No permission.', 'ai-json-extractor-auto-embed-lite' ) ); } check_admin_referer( 'aije_export' ); $t = wp_next_scheduled( self::CRON_EXPORT ); if ( $t ) { wp_unschedule_event( $t, self::CRON_EXPORT ); } wp_safe_redirect( add_query_arg( array( 'page' => 'aije-lite', 'tab' => 'automation', 'cleared' => 1 ), admin_url( 'tools.php' ) ) ); exit; } public function cron_export_runner() { $o = $this->get_opts(); if ( empty( $o['cron_enabled'] ) ) { return; } $a = get_option( self::LAST_ARGS_OPT, array( 'post_types' => array( 'post', 'page' ), 'author' => 0, 'cat' => 0, 'date_from' => '', 'date_to' => '', 's' => '', 'include_acf' => 1, 'minify' => 0, 'zip' => 1 ) ); $this->run_export( $a ); } private function maybe_reschedule_export( $enabled, $freq ) { $t = wp_next_scheduled( self::CRON_EXPORT ); if ( $enabled ) { if ( $t ) { wp_unschedule_event( $t, self::CRON_EXPORT ); } $key = ( $freq === 'weekly' ) ? 'aije_weekly' : 'aije_daily'; $schedules = wp_get_schedules(); if ( ! isset( $schedules[ $key ] ) ) { $key = 'daily'; } wp_schedule_event( time() + 300, $key, self::CRON_EXPORT ); } elseif ( $t ) { wp_unschedule_event( $t, self::CRON_EXPORT ); } } /* ===== PingHub ===== */ private function ensure_ping_cron() { $t = wp_next_scheduled( self::CRON_PING ); if ( ! $t ) { wp_schedule_event( time() + 600, 'aije_15min', self::CRON_PING ); } } public function on_transition_status( $new, $old, $post ) { $o = $this->get_opts(); if ( empty( $o['ping_enabled'] ) ) { return; } if ( ! in_array( $post->post_type, $o['enabled_post_types'], true ) ) { return; } if ( $new === 'publish' && $old !== 'publish' && in_array( 'publish', $o['ping_events'], true ) ) { $this->dispatch_ping( 'publish', $post->ID ); } } public function on_post_updated( $post_ID, $after, $before ) { $o = $this->get_opts(); if ( empty( $o['ping_enabled'] ) ) { return; } if ( ! in_array( $after->post_type, $o['enabled_post_types'], true ) ) { return; } if ( $after->post_status !== 'publish' ) { return; } if ( in_array( 'update', $o['ping_events'], true ) ) { $this->dispatch_ping( 'update', $post_ID ); } } private function push_ping_error( $url, $event, $post_id, $msg ) { $errs = get_option( self::PING_ERRORS_OPT, array() ); if ( ! is_array( $errs ) ) { $errs = array(); } $errs[] = array( 'time' => date_i18n( 'Y-m-d H:i:s' ), 'url' => $url, 'event' => $event, 'post_id' => $post_id, 'error' => $msg ); if ( count( $errs ) > 200 ) { $errs = array_slice( $errs, -200 ); } update_option( self::PING_ERRORS_OPT, $errs, false ); } private function dispatch_ping( $event, $post_id ) { $o = $this->get_opts(); $urls = array_filter( array_map( 'trim', preg_split( "/\r\n|\n|\r/", trim( $o['ping_urls'] ) ) ) ); if ( empty( $urls ) ) { return; } $post_obj = get_post( $post_id ); if ( ! $post_obj ) { return; } $payload = array( 'event' => $event, 'site' => get_bloginfo( 'name' ), 'time' => time(), 'post' => $this->extract_payload( $post_obj ) ); $json = function_exists( 'wp_json_encode' ) ? wp_json_encode( $payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ) : json_encode( $payload ); $headers = array( 'Content-Type' => 'application/json' ); if ( ! empty( $o['ping_secret'] ) ) { $headers['X-AIJE-Signature'] = 'sha256=' . hash_hmac( 'sha256', $json, $o['ping_secret'] ); } foreach ( $urls as $u ) { if ( $u === '' || substr( $u, 0, 1 ) === '#' ) { continue; } $resp = wp_remote_post( $u, array( 'method' => 'POST', 'timeout' => $o['ping_timeout'], 'headers' => $headers, 'body' => $json, 'blocking' => true, 'data_format' => 'body' ) ); if ( is_wp_error( $resp ) ) { $this->push_ping_error( $u, $event, $post_id, $resp->get_error_message() ); if ( ! empty( $o['ping_retry'] ) ) { $this->queue_ping( $u, $json, $headers ); } } else { $code = wp_remote_retrieve_response_code( $resp ); if ( $code < 200 || $code >= 300 ) { $this->push_ping_error( $u, $event, $post_id, 'HTTP ' . $code ); if ( ! empty( $o['ping_retry'] ) ) { $this->queue_ping( $u, $json, $headers ); } } } } } private function queue_ping( $url, $json, $headers ) { $q = get_option( self::PING_QUEUE_OPT, array() ); if ( ! is_array( $q ) ) { $q = array(); } $q[] = array( 'url' => $url, 'payload' => $json, 'headers' => $headers, 'tries' => 0, 'last' => time() ); update_option( self::PING_QUEUE_OPT, $q, false ); $this->ensure_ping_cron(); } public function cron_ping_runner() { $q = get_option( self::PING_QUEUE_OPT, array() ); if ( empty( $q ) || ! is_array( $q ) ) { return; } $o = $this->get_opts(); $next = array(); foreach ( $q as $job ) { $resp = wp_remote_post( $job['url'], array( 'method' => 'POST', 'timeout' => $o['ping_timeout'], 'headers' => $job['headers'], 'body' => $job['payload'], 'blocking' => true, 'data_format' => 'body' ) ); if ( is_wp_error( $resp ) ) { $job['tries'] = (int) $job['tries'] + 1; $this->push_ping_error( $job['url'], 'retry', 0, $resp->get_error_message() ); if ( $job['tries'] < 3 ) { $job['last'] = time(); $next[] = $job; } } else { $code = wp_remote_retrieve_response_code( $resp ); if ( $code < 200 || $code >= 300 ) { $job['tries'] = (int) $job['tries'] + 1; $this->push_ping_error( $job['url'], 'retry', 0, 'HTTP ' . $code ); if ( $job['tries'] < 3 ) { $job['last'] = time(); $next[] = $job; } } } } update_option( self::PING_QUEUE_OPT, $next, false ); } public function handle_test_ping() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'No permission.', 'ai-json-extractor-auto-embed-lite' ) ); } check_admin_referer( 'aije_export' ); $post_id = isset( $_POST['post_id'] ) ? (int) $_POST['post_id'] : 0; $event = isset( $_POST['event'] ) ? sanitize_key( $_POST['event'] ) : 'update'; if ( $post_id > 0 ) { $this->dispatch_ping( $event, $post_id ); } wp_safe_redirect( add_query_arg( array( 'page' => 'aije-lite', 'tab' => 'pinghub', 'test' => 1 ), admin_url( 'tools.php' ) ) ); exit; } public function handle_flush_queue() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'No permission.', 'ai-json-extractor-auto-embed-lite' ) ); } check_admin_referer( 'aije_export' ); $this->cron_ping_runner(); wp_safe_redirect( add_query_arg( array( 'page' => 'aije-lite', 'tab' => 'pinghub', 'flushed' => 1 ), admin_url( 'tools.php' ) ) ); exit; } }