'POST', 'callback' => 'cmplz_scan_post_handler', 'permission_callback' => 'cmplz_user_can_manage', ) ); } /** * Handle POST /complianz/v1/scan/post. * * @param WP_REST_Request $request Incoming REST request. * @return WP_REST_Response */ function cmplz_scan_post_handler( WP_REST_Request $request ): WP_REST_Response { $post_id = absint( $request->get_param( 'post_id' ) ); if ( ! $post_id || ! get_post( $post_id ) ) { return new WP_REST_Response( array( 'queued' => false, 'error' => 'invalid_post', ), 400 ); } if ( get_post_status( $post_id ) !== 'publish' ) { return new WP_REST_Response( array( 'queued' => false, 'error' => 'not_published', ), 400 ); } if ( ! is_post_type_viewable( get_post_type( $post_id ) ) ) { return new WP_REST_Response( array( 'queued' => false, 'error' => 'not_viewable', ), 400 ); } cmplz_queue_post_for_scan( $post_id ); $error_code = COMPLIANZ::$wsc_scan_pro->start_post_scan( $post_id ); if ( null !== $error_code ) { return new WP_REST_Response( array( 'queued' => false, 'error_code' => $error_code, ), 200 ); } return new WP_REST_Response( array( 'queued' => true, 'post_id' => $post_id, ), 200 ); } // ── Local scan queue injection ──────────────────────────────────────────────── /** * Inject a post to the front of the local iframe scan queue. * * Removes the post from the processed list so the scan engine picks it up * on the next admin_footer cycle. Clears _cmplz_scanned_post so the column * status reflects the pending re-scan immediately. * * @param int $post_id WordPress post ID. */ function cmplz_queue_post_for_scan( int $post_id ): void { $processed = get_transient( 'cmplz_processed_pages_list' ); if ( is_array( $processed ) ) { $processed = array_values( array_diff( $processed, array( $post_id ) ) ); set_transient( 'cmplz_processed_pages_list', $processed, MONTH_IN_SECONDS ); } $pages = get_transient( 'cmplz_pages_list' ); if ( ! is_array( $pages ) ) { $pages = array(); } $pages = array_values( array_diff( $pages, array( $post_id ) ) ); array_unshift( $pages, $post_id ); set_transient( 'cmplz_pages_list', $pages, MONTH_IN_SECONDS ); delete_post_meta( $post_id, '_cmplz_scanned_post' ); } // ── JS asset ────────────────────────────────────────────────────────────────── /** * Enqueue the scan trigger JS on post list table screens. * * @param string $hook Current admin page hook. */ function cmplz_enqueue_scan_post_assets( string $hook ): void { if ( 'edit.php' !== $hook ) { return; } wp_enqueue_script( 'cmplz-scan-post', CMPLZ_URL . 'pro/scan/scan-post-trigger.js', array(), CMPLZ_VERSION, true ); wp_localize_script( 'cmplz-scan-post', 'cmplzScan', array( 'restUrl' => esc_url_raw( rest_url( 'complianz/v1' ) ), 'wpNonce' => wp_create_nonce( 'wp_rest' ), 'scanning' => __( 'Scanning…', 'complianz-gdpr' ), 'inProgress' => __( 'In progress', 'complianz-gdpr' ), 'errors' => array( 'cap_reached' => __( 'Too many scans in progress. Please wait.', 'complianz-gdpr' ), 'rate_limited' => __( 'Scan limit reached. Please wait a few minutes.', 'complianz-gdpr' ), 'already_inflight' => __( 'This page is already being scanned.', 'complianz-gdpr' ), 'wsc_disabled' => __( 'Website Scan is disabled.', 'complianz-gdpr' ), 'in_cooldown' => __( 'This page was scanned recently. Please wait before scanning again.', 'complianz-gdpr' ), 'api_error' => __( 'Scan could not be started. Please try again later.', 'complianz-gdpr' ), 'no_permalink' => __( 'This page has no public URL and cannot be scanned.', 'complianz-gdpr' ), ), ) ); }