cache = new Schema_AI_Cache(); } /** * Analyze page content and detect schema type via the SaaS backend. * * @param int $post_id WordPress post ID. * @return array Analysis result. */ public function analyze_page( $post_id ) { $cache_key = 'analysis_' . $post_id . '_' . $this->get_content_hash( $post_id ); $cached = $this->cache->get( $cache_key ); if ( false !== $cached ) { return $cached; } $settings = get_option( 'schema_ai_settings', array() ); $api_key = ! empty( $settings['api_key'] ) ? $settings['api_key'] : ''; if ( empty( $api_key ) ) { return $this->fallback_analysis(); } $content = $this->prepare_content( $post_id ); $api_base = defined( 'SCHEMA_AI_API_BASE' ) ? SCHEMA_AI_API_BASE : 'https://api.aischemagen.com/api/v1'; $response = wp_remote_post( $api_base . '/analyze', array( 'timeout' => 30, 'headers' => array( 'Content-Type' => 'application/json', 'X-API-Key' => $api_key, ), 'body' => wp_json_encode( array( 'content' => $content ) ), ) ); if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { return $this->fallback_analysis(); } $body = json_decode( wp_remote_retrieve_body( $response ), true ); $analysis = isset( $body['data'] ) ? $body['data'] : null; if ( ! is_array( $analysis ) ) { return $this->fallback_analysis(); } $this->cache->set( $cache_key, $analysis, WEEK_IN_SECONDS ); return $analysis; } /** * Prepare content payload to send to the backend. */ public function prepare_content( $post_id ) { $post = get_post( $post_id ); if ( ! $post ) { return array(); } return array( 'url' => get_permalink( $post_id ), 'title' => $post->post_title, 'content' => $this->clean_content( $post->post_content ), 'excerpt' => get_the_excerpt( $post_id ), 'post_type' => $post->post_type, 'categories' => $this->get_categories( $post_id ), 'tags' => $this->get_tags( $post_id ), 'headings' => $this->extract_headings( $post->post_content ), 'images' => $this->get_images( $post_id ), 'published' => $post->post_date, 'modified' => $post->post_modified, ); } /** * Default analysis result when the backend is unreachable. */ private function fallback_analysis() { return array( 'primary_schema' => 'WebPage', 'confidence' => 0.5, 'alternative_schemas' => array(), 'detected_entities' => array(), 'missing_content' => array(), 'reasoning' => 'Could not reach AI Schema Gen backend.', ); } private function clean_content( $content ) { $content = do_shortcode( do_blocks( $content ) ); $content = wp_strip_all_tags( $content ); return preg_replace( '/\s+/', ' ', trim( $content ) ); } private function get_content_hash( $post_id ) { $post = get_post( $post_id ); return $post ? md5( $post->post_title . '|' . $post->post_content ) : ''; } private function get_categories( $post_id ) { $terms = get_the_terms( $post_id, 'category' ); return ( $terms && ! is_wp_error( $terms ) ) ? wp_list_pluck( $terms, 'name' ) : array(); } private function get_tags( $post_id ) { $terms = get_the_terms( $post_id, 'post_tag' ); return ( $terms && ! is_wp_error( $terms ) ) ? wp_list_pluck( $terms, 'name' ) : array(); } /** * Extract headings from HTML content. */ public function extract_headings( $content ) { preg_match_all( '/]*>(.*?)<\/h\1>/i', $content, $matches ); $headings = array(); for ( $i = 0; $i < count( $matches[0] ); $i++ ) { $headings[] = array( 'level' => (int) $matches[1][ $i ], 'text' => wp_strip_all_tags( $matches[2][ $i ] ), ); } return $headings; } /** * Get images from the post. */ public function get_images( $post_id ) { $images = array(); $thumbnail_id = get_post_thumbnail_id( $post_id ); if ( $thumbnail_id ) { $src = wp_get_attachment_image_src( $thumbnail_id, 'full' ); if ( $src ) { $images[] = array( 'url' => $src[0], 'width' => $src[1], 'height' => $src[2], ); } } return $images; } }