namespace, '/' . $this->rest_base, array( array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'analyze' ), 'permission_callback' => array( $this, 'analyze_permissions_check' ), 'args' => array( 'post_id' => array( 'description' => __( 'The WordPress post ID to analyse.', 'ai-schema-gen' ), 'type' => 'integer', 'required' => true, 'sanitize_callback' => 'absint', ), ), ), ) ); } /** * Analyse post content and return schema suggestions. * * Uses the Content Analyzer for AI-based analysis and the Schema * Suggester for rule-based suggestions, then merges the results. * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error Response object or error. */ public function analyze( $request ) { $user_id = get_current_user_id(); $post_id = absint( $request->get_param( 'post_id' ) ); // Validate the post. $valid = $this->validate_post_id( $post_id ); if ( is_wp_error( $valid ) ) { return $valid; } // Check rate limit. $rate_limiter = new Schema_AI_Rate_Limiter(); if ( ! $rate_limiter->check( $user_id ) ) { $limit = $rate_limiter->get_limit( $user_id ); $remaining = $rate_limiter->remaining( $user_id ); $reset_at = $rate_limiter->get_reset_time( $user_id ); return new WP_Error( 'schema_ai_rate_limit_exceeded', __( 'Rate limit exceeded. Please try again later.', 'ai-schema-gen' ), array( 'status' => 429, 'limit' => $limit, 'remaining' => $remaining, 'reset_at' => $reset_at, ) ); } // Run AI-based content analysis. try { $content_analyzer = new Schema_AI_Content_Analyzer(); $analysis = $content_analyzer->analyze_page( $post_id ); } catch ( \Exception $e ) { return $this->error_response( 'schema_ai_analysis_failed', $e->getMessage(), 500 ); } // Run rule-based schema suggestions if the Suggester class exists. $suggestions = array(); if ( class_exists( 'Schema_AI_Schema_Suggester' ) ) { try { $suggester = new Schema_AI_Schema_Suggester(); $suggestions = $suggester->suggest( $post_id ); } catch ( \Exception $e ) { // Suggestions are non-critical; continue without them. $suggestions = array(); } } else { // Build basic suggestions from the AI analysis. $suggestions = $this->build_suggestions_from_analysis( $analysis ); } // Consume rate limit. $rate_limiter->consume( $user_id ); return $this->success_response( array( 'success' => true, 'analysis' => $analysis, 'suggestions' => $suggestions, ) ); } /** * Build basic schema suggestions from the AI analysis result. * * Fallback for when the Schema_AI_Schema_Suggester class is not * available. Extracts the primary schema and alternatives from * the analysis. * * @param array $analysis The AI analysis result. * @return array Array of suggestion objects. */ private function build_suggestions_from_analysis( $analysis ) { $suggestions = array(); if ( isset( $analysis['primary_schema'] ) ) { $suggestions[] = array( 'schema_type' => $analysis['primary_schema'], 'confidence' => isset( $analysis['confidence'] ) ? (float) $analysis['confidence'] : 0.5, 'reason' => isset( $analysis['reasoning'] ) ? $analysis['reasoning'] : __( 'AI-recommended primary schema type.', 'ai-schema-gen' ), 'source' => 'ai', ); } if ( isset( $analysis['alternative_schemas'] ) && is_array( $analysis['alternative_schemas'] ) ) { foreach ( $analysis['alternative_schemas'] as $alt ) { $suggestions[] = array( 'schema_type' => is_array( $alt ) && isset( $alt['type'] ) ? $alt['type'] : $alt, 'confidence' => is_array( $alt ) && isset( $alt['confidence'] ) ? (float) $alt['confidence'] : 0.3, 'reason' => __( 'AI-recommended alternative schema type.', 'ai-schema-gen' ), 'source' => 'ai', ); } } return $suggestions; } /** * Permission check for the analyse endpoint. * * The user must be logged in and able to edit the specified post. * * @param WP_REST_Request $request Full details about the request. * @return true|WP_Error True if allowed. */ public function analyze_permissions_check( $request ) { if ( ! is_user_logged_in() ) { return new WP_Error( 'schema_ai_not_logged_in', __( 'You must be logged in.', 'ai-schema-gen' ), array( 'status' => 401 ) ); } $post_id = absint( $request->get_param( 'post_id' ) ); if ( $post_id && ! current_user_can( 'edit_post', $post_id ) ) { return new WP_Error( 'schema_ai_forbidden', __( 'You do not have permission to edit this post.', 'ai-schema-gen' ), array( 'status' => 403 ) ); } return true; } }