enabled = ! empty( $settings['generate_schema'] ); if ( $this->enabled ) { add_action( 'wp_head', array( $this, 'inject_schema' ), 99 ); add_action( 'save_post', array( $this, 'generate_and_cache_schema' ), 10, 2 ); } } public function inject_schema() { if ( ! is_singular() ) { return; } global $post; $post_id = $post->ID; // Check if schema is already cached $cached_schema = get_post_meta( $post_id, '_metaforge_ai_schema', true ); if ( ! empty( $cached_schema ) ) { $decoded = json_decode( $cached_schema, true ); if ( is_array( $decoded ) ) { echo "\n\n"; echo "\n"; } } } public function generate_and_cache_schema( $post_id, $post ) { // Prevent infinite loops if saving metadata inside save_post static $generating = false; if ( $generating ) { return; } // Skip revisions, autosaves, and non-singular updates if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) { return; } if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { return; } if ( ! current_user_can( 'edit_post', $post_id ) ) { return; } $client = new MetaForge_APIClient(); if ( ! $client->is_ready() ) { return; } $generating = true; $post_data = array( 'post_title' => $post->post_title, 'post_type' => $post->post_type, 'post_content' => wp_strip_all_tags( $post->post_content ), 'meta_data' => array(), ); $fm = new MetaForge_FieldManager(); $groups = $fm->get_groups_by_post_type( $post->post_type, $post_id ); foreach ( $groups as $group ) { foreach ( $group['fields'] as $field ) { $val = get_post_meta( $post_id, $field['name'], true ); if ( ! empty( $val ) ) { $post_data['meta_data'][ $field['name'] ] = is_array( $val ) ? wp_json_encode( $val ) : $val; } } } $system_prompt = 'You are an SEO expert. Your task is to generate valid JSON-LD schema markup based on the provided WordPress post data and its custom fields. Determine the most appropriate schema type (e.g., Article, Product, RealEstateListing, Person) based on the content. Return ONLY valid JSON. Do not return markdown blocks or HTML tags.'; $user_prompt = "Post Data:\n" . wp_json_encode( $post_data ); $response = $client->generate( $system_prompt, $user_prompt, true ); if ( ! is_wp_error( $response ) && ! empty( $response ) ) { $response = trim( $response ); if ( strpos( $response, '```json' ) === 0 ) { $response = substr( $response, 7 ); $response = substr( $response, 0, -3 ); $response = trim( $response ); } elseif ( strpos( $response, '```' ) === 0 ) { $response = substr( $response, 3 ); $response = substr( $response, 0, -3 ); $response = trim( $response ); } $decoded = json_decode( $response, true ); if ( json_last_error() === JSON_ERROR_NONE && is_array( $decoded ) ) { $decoded = map_deep( $decoded, 'sanitize_textarea_field' ); $clean_json = wp_json_encode( $decoded, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); update_post_meta( $post_id, '_metaforge_ai_schema', $clean_json ); } } $generating = false; } }