From 0e44c52ad89ca1993d6ea350fe1670fc1ba39d60 Mon Sep 17 00:00:00 2001 From: peptiderepo Date: Sat, 18 Apr 2026 00:39:10 +0700 Subject: [PATCH] feat: add AJAX endpoint for retroactive image generation Adds wp_ajax_prautoblogger_generate_image so images can be generated for existing posts that were published before image gen was enabled or fixed. Uses set_time_limit(120) to handle the Cloudflare API latency that caused fatals when run via Code Snippets init hook. Co-Authored-By: Claude Opus 4.6 --- includes/admin/class-admin-page.php | 1 + includes/class-executor.php | 57 +++++++++++++++++++++++++++++ includes/class-prautoblogger.php | 1 + 3 files changed, 59 insertions(+) diff --git a/includes/admin/class-admin-page.php b/includes/admin/class-admin-page.php index 214af00..0f157e1 100755 --- a/includes/admin/class-admin-page.php +++ b/includes/admin/class-admin-page.php @@ -70,6 +70,7 @@ class PRAutoBlogger_Admin_Page { wp_localize_script( 'prautoblogger-admin', 'prautobloggerAdmin', [ 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'generateNonce' => wp_create_nonce( 'prautoblogger_generate_now' ), + 'imageNonce' => wp_create_nonce( 'prautoblogger_generate_image' ), 'testNonce' => wp_create_nonce( 'prautoblogger_test_connection' ), 'reviewNonce' => wp_create_nonce( 'prautoblogger_review_queue' ), 'generatingText' => __( 'Generating...', 'prautoblogger' ), diff --git a/includes/class-executor.php b/includes/class-executor.php index abfa23e..2bd1a53 100644 --- a/includes/class-executor.php +++ b/includes/class-executor.php @@ -95,6 +95,63 @@ class PRAutoBlogger_Executor { } } + /** + * AJAX handler: generate images for existing posts that lack them. + * + * Accepts a `post_id` parameter. Generates Image A (article-driven) and + * sets it as the featured image. Useful for retroactively adding images + * to posts published before image generation was enabled/fixed. + * + * Side effects: Cloudflare API call, media library write, post meta update. + */ + public function on_ajax_generate_image(): void { + check_ajax_referer( 'prautoblogger_generate_image', 'nonce' ); + + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( [ 'message' => __( 'Insufficient permissions.', 'prautoblogger' ) ], 403 ); + return; + } + + // Image generation can take 20-30s on Cloudflare Workers AI. + // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged + @set_time_limit( 120 ); + + $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0; + if ( 0 === $post_id ) { + wp_send_json_error( [ 'message' => __( 'Missing post_id parameter.', 'prautoblogger' ) ] ); + return; + } + + $post = get_post( $post_id ); + if ( ! $post ) { + wp_send_json_error( [ 'message' => sprintf( __( 'Post %d not found.', 'prautoblogger' ), $post_id ) ] ); + return; + } + + try { + $pipeline = new PRAutoBlogger_Image_Pipeline(); + $article_data = [ + 'post_title' => $post->post_title, + 'post_content' => $post->post_content, + ]; + + $result = $pipeline->generate_and_attach_images( $post_id, $article_data, null ); + + // Set featured image if Image A was generated. + if ( ! empty( $result['image_a_id'] ) ) { + set_post_thumbnail( $post_id, $result['image_a_id'] ); + } + + wp_send_json_success( $result ); + } catch ( \Exception $e ) { + PRAutoBlogger_Logger::instance()->error( + 'Retroactive image gen failed for post ' . $post_id . ': ' . $e->getMessage(), + 'image_pipeline' + ); + wp_send_json_error( [ 'message' => $e->getMessage() ] ); + } + } + /** AJAX handler: test API connections (OpenRouter, Reddit). */ public function on_ajax_test_connection(): void { check_ajax_referer( 'prautoblogger_test_connection', 'nonce' ); diff --git a/includes/class-prautoblogger.php b/includes/class-prautoblogger.php index 6f915c4..4a045db 100644 --- a/includes/class-prautoblogger.php +++ b/includes/class-prautoblogger.php @@ -92,6 +92,7 @@ class PRAutoBlogger { /** Register AJAX handlers for admin actions. */ private function register_ajax_hooks(): void { add_action( 'wp_ajax_prautoblogger_generate_now', [ $this->executor, 'on_ajax_generate_now' ] ); + add_action( 'wp_ajax_prautoblogger_generate_image', [ $this->executor, 'on_ajax_generate_image' ] ); add_action( 'wp_ajax_prautoblogger_test_connection', [ $this->executor, 'on_ajax_test_connection' ] ); $review_queue = new PRAutoBlogger_Review_Queue();