Changeset 3791583
- Timestamp:
- 11/08/2026 10:32:17 PM (less than one hour ago)
- Location:
- videowhisper-agentic-optimization
- Files:
-
- 14 edited
- 1 copied
-
tags/1.9.0 (copied) (copied from videowhisper-agentic-optimization/trunk )
-
tags/1.9.0/includes/class-vwao-discovery-service.php (modified) (4 diffs)
-
tags/1.9.0/includes/class-vwao-multilingual.php (modified) (1 diff)
-
tags/1.9.0/includes/class-vwao-recovery.php (modified) (3 diffs)
-
tags/1.9.0/includes/class-vwao-standalone-seo.php (modified) (2 diffs)
-
tags/1.9.0/languages/videowhisper-agentic-optimization.pot (modified) (5 diffs)
-
tags/1.9.0/readme.txt (modified) (2 diffs)
-
tags/1.9.0/videowhisper-agentic-optimization.php (modified) (2 diffs)
-
trunk/includes/class-vwao-discovery-service.php (modified) (4 diffs)
-
trunk/includes/class-vwao-multilingual.php (modified) (1 diff)
-
trunk/includes/class-vwao-recovery.php (modified) (3 diffs)
-
trunk/includes/class-vwao-standalone-seo.php (modified) (2 diffs)
-
trunk/languages/videowhisper-agentic-optimization.pot (modified) (5 diffs)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/videowhisper-agentic-optimization.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
videowhisper-agentic-optimization/tags/1.9.0/includes/class-vwao-discovery-service.php
r3786442 r3791583 92 92 } 93 93 } 94 return hash( 'sha256', wp_json_encode( array( $this->settings->get_all(), VWAO_Multilingual::locale(), VWAO_SEO_Service::get_providers(), get_option( 'blog_public' ), $items ) ) ); 94 return hash( 'sha256', wp_json_encode( array( $this->settings->get_all(), VWAO_Multilingual::locale(), VWAO_SEO_Service::get_providers(), get_option( 'blog_public' ), self::configured_languages(), $items ) ) ); 95 } 96 /** Configured choices are distinct from each item's complete published variants. */ 97 private static function configured_languages() { 98 $rows = apply_filters( 'vwml_available_languages_v1', array(), 'discovery' ); 99 return is_array( $rows ) ? array_values( array_filter( array_keys( $rows ), static fn( $code ) => is_string( $code ) && preg_match( '/^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{2,8})*$/D', $code ) ) ) : array(); 100 } 101 private function language_lines() { 102 $codes = self::configured_languages(); 103 if ( ! $codes ) { return array(); } 104 $lines = array( 'Configured languages: ' . implode( ', ', $codes ), 'Only complete published translations appear in language-specific results.' ); 105 foreach ( $codes as $code ) { 106 $lines[] = '- ' . $code . ': ' . esc_url_raw( add_query_arg( 'language', $code, home_url( '/llms.txt' ) ) ); } 107 return $lines; 95 108 } 96 109 … … 256 269 $lines[] = 'Base URL: ' . $site['base_url']; 257 270 $lines[] = 'Language: ' . VWAO_Multilingual::language(); 271 $lines = array_merge( $lines, $this->language_lines() ); 258 272 $lines[] = 'Generated (GMT): ' . gmdate( 'c' ); 259 273 $lines[] = ''; … … 323 337 $lines[] = 'Base URL: ' . $site['base_url']; 324 338 $lines[] = 'Language: ' . VWAO_Multilingual::language(); 339 $lines = array_merge( $lines, $this->language_lines() ); 325 340 $lines[] = 'Generated (GMT): ' . gmdate( 'c' ); 326 341 $lines[] = ''; … … 435 450 $xml = '<?xml version="1.0" encoding="' . esc_attr( get_bloginfo( 'charset' ) ) . '"?>'; 436 451 $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:agent="urn:videowhisper:agentic:1.0">'; 452 $xml .= '<!-- Configured languages: ' . esc_html( implode( ', ', self::configured_languages() ) ) . '; per-URL available_languages lists complete published variants. -->'; 437 453 438 454 foreach ( $content as $group ) { -
videowhisper-agentic-optimization/tags/1.9.0/includes/class-vwao-multilingual.php
r3790761 r3791583 74 74 /** Register rendering hooks. */ 75 75 public static function hooks() { 76 add_filter( 'vwml_sitemap_source_allowed_v1', static function ( $allowed, $post ) { 77 if ( false === $allowed ) { return false; } 78 $seo = VWAO_SEO_Service::get_post_state( $post ); 79 return false === ( $seo['noindex'] ?? null ) && untrailingslashit( $seo['canonical'] ?? '' ) === untrailingslashit( get_permalink( $post ) ); 80 }, 10, 2 ); 76 81 add_filter( 77 82 'vwml_use_public_overlay', -
videowhisper-agentic-optimization/tags/1.9.0/includes/class-vwao-recovery.php
r3791079 r3791583 20 20 add_action( 'shutdown', array( __CLASS__, 'capture' ) ); 21 21 add_action( 'vwao_recovery_cleanup', array( __CLASS__, 'prune' ) ); 22 add_filter( 'vwml_legacy_source_id_v1', array( __CLASS__, 'translation_source' ), 10, 4 ); 23 } 24 /** Resolve only an existing, reviewed local redirect; never guess a target. */ 25 public static function translation_source( $id, $path, $locale = '', $request_path = '' ) { 26 unset( $locale ); 27 if ( $id || '1' !== get_option( 'vwao_recovery_schema' ) ) { return $id; } 28 global $wpdb; 29 foreach ( array_unique( array( self::path( $path ), self::path( $request_path ) ) ) as $candidate ) { 30 if ( ! $candidate || self::decision( $candidate ) ) { continue; } 31 $r = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM %i WHERE path_hash=%s AND state=%s', $wpdb->prefix . 'vwao_recovery_paths', hash( 'sha256', $candidate ), 'redirect' ), ARRAY_A ); 32 $p = $r && hash_equals( $r['path'], $candidate ) ? self::target( (int) $r['target_id'] ) : null; 33 if ( $p ) { return (int) $p->ID; } 34 } 35 return $id; 22 36 } 23 37 public static function settings() { … … 223 237 } 224 238 public static function version( $row ) { 225 return hash( 'sha256', wp_json_encode( array( get_current_blog_id(), $row['id'], $row['path'], $row['state'], $row['target_id'], $row['redirect_code'], $row['draft_id'], $row['revision'] ) ) ); 239 // Database rows and report rows use different scalar types. Bind the same 240 // normalized editorial state in both; traffic counters are not permissions. 241 return hash( 'sha256', wp_json_encode( array( get_current_blog_id(), (int) $row['id'], (string) $row['path'], (string) $row['state'], (int) $row['target_id'], (int) $row['redirect_code'], (int) $row['draft_id'], (int) $row['revision'] ) ) ); 226 242 } 227 243 public static function target( $id ) { … … 395 411 $p = self::target( $target ); 396 412 $existing = self::existing_id( $r['path'] ); 397 $draft = ! empty( $r['draft_id'] ) ? (int) $r['draft_id'] : 0; 398 if ( $draft ) { clean_post_cache( $draft ); } 399 // A linked editable recovery draft is retained, never overwritten or published. 400 $source_conflict = $existing && ( (int) $existing !== $draft || ! self::reusable_draft( $r ) ); 413 // Existing unpublished drafts remain untouched. A later real public 414 // page wins because runtime recovery only runs for an actual 404. 415 $source_conflict = $existing && is_post_publicly_viewable( get_post( $existing ) ); 401 416 if ( ! $p || ! in_array( $code, array( 301, 302 ), true ) || $source_conflict || self::decision( $r['path'] ) || self::same_path( get_permalink( $p ), $r['path'] ) ) { 402 417 return self::error(); } -
videowhisper-agentic-optimization/tags/1.9.0/includes/class-vwao-standalone-seo.php
r3789597 r3791583 116 116 add_filter( 'wp_robots', array( __CLASS__, 'robots' ), 20 ); 117 117 add_filter( 'wp_sitemaps_posts_query_args', array( __CLASS__, 'sitemap_query' ), 20, 2 ); 118 add_filter( 'posts_where', array( __CLASS__, 'sitemap_where' ), 20, 2 ); 118 119 } 119 120 … … 346 347 return $args; } 347 348 $args['has_password'] = false; 348 $clauses = array( 'relation' => 'AND' ); 349 if ( ! empty( $args['meta_query'] ) ) { 350 $clauses[] = $args['meta_query']; } 349 $args['vwao_sitemap_seo'] = true; 350 return $args; 351 } 352 353 /** Indexed exclusions avoid multiplying theme metadata rows across six joins. */ 354 public static function sitemap_where( $where, $query ) { 355 if ( true !== $query->get( 'vwao_sitemap_seo' ) || ! self::active() ) { return $where; } 356 global $wpdb; 351 357 foreach ( array( 352 '_vwao_seo_noindex' => array( '1' ),358 '_vwao_seo_noindex' => array( '1' ), 353 359 '_yoast_wpseo_meta-robots-noindex' => array( '1' ), 354 '_aioseo_robots_noindex' => array( '1', 'on', 'yes' ),355 '_seopress_robots_index' => array( 'yes' ),360 '_aioseo_robots_noindex' => array( '1', 'on', 'yes' ), 361 '_seopress_robots_index' => array( 'yes' ), 356 362 ) as $key => $values ) { 357 $clauses[] = array( 358 'relation' => 'OR', 359 array( 360 'key' => $key, 361 'compare' => 'NOT EXISTS', 362 ), 363 array( 364 'key' => $key, 365 'value' => $values, 366 'compare' => 'NOT IN', 367 ), 368 ); 369 } 370 $clauses[] = array( 371 'relation' => 'OR', 372 array( 373 'key' => 'rank_math_robots', 374 'compare' => 'NOT EXISTS', 375 ), 376 array( 377 'key' => 'rank_math_robots', 378 'value' => '"noindex"', 379 'compare' => 'NOT LIKE', 380 ), 381 ); 382 // Custom canonical destinations are not advertised as self-canonical sitemap URLs. 383 $clauses[] = array( 384 'relation' => 'OR', 385 array( 386 'key' => '_vwao_seo_canonical', 387 'compare' => 'NOT EXISTS', 388 ), 389 array( 390 'key' => '_vwao_seo_canonical', 391 'value' => '', 392 'compare' => '=', 393 ), 394 ); 395 $args['meta_query'] = $clauses; 396 return $args; 363 $holders = implode( ',', array_fill( 0, count( $values ), '%s' ) ); 364 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Core table identifiers and generated placeholder list; values are prepared. 365 $where .= $wpdb->prepare( " AND NOT EXISTS (SELECT 1 FROM {$wpdb->postmeta} vwao_sm WHERE vwao_sm.post_id={$wpdb->posts}.ID AND vwao_sm.meta_key=%s AND vwao_sm.meta_value IN ($holders))", array_merge( array( $key ), $values ) ); 366 } 367 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Core table identifiers; values are prepared. 368 $where .= $wpdb->prepare( " AND NOT EXISTS (SELECT 1 FROM {$wpdb->postmeta} vwao_sm WHERE vwao_sm.post_id={$wpdb->posts}.ID AND vwao_sm.meta_key=%s AND vwao_sm.meta_value LIKE %s)", 'rank_math_robots', '%' . $wpdb->esc_like( '"noindex"' ) . '%' ); 369 // Custom canonical destinations are excluded, including duplicate conflicting metadata. 370 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Core table identifiers; values are prepared. 371 $where .= $wpdb->prepare( " AND NOT EXISTS (SELECT 1 FROM {$wpdb->postmeta} vwao_sm WHERE vwao_sm.post_id={$wpdb->posts}.ID AND vwao_sm.meta_key=%s AND vwao_sm.meta_value<>%s)", '_vwao_seo_canonical', '' ); 372 return $where; 397 373 } 398 374 -
videowhisper-agentic-optimization/tags/1.9.0/languages/videowhisper-agentic-optimization.pot
r3791079 r3791583 3 3 msgid "" 4 4 msgstr "" 5 "Project-Id-Version: Agentic Optimization - SEO for AI Agents 1. 8.0\n"5 "Project-Id-Version: Agentic Optimization - SEO for AI Agents 1.9.0\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/videowhisper-agentic-optimization\n" 7 7 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" … … 10 10 "Content-Type: text/plain; charset=UTF-8\n" 11 11 "Content-Transfer-Encoding: 8bit\n" 12 "POT-Creation-Date: 2026-11-08T 13:59:03+00:00\n"12 "POT-Creation-Date: 2026-11-08T21:05:52+00:00\n" 13 13 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 14 14 "X-Generator: WP-CLI 2.12.0\n" … … 695 695 696 696 #. translators: 1: result cap, 2: max pages, 3: llms list cap. 697 #: includes/class-vwao-discovery-service.php:2 50697 #: includes/class-vwao-discovery-service.php:263 698 698 #, php-format 699 699 msgid "Use the Search endpoint for discovery, read specific items with Content or Markdown by numeric ID or content slug, including hierarchical paths (e.g., /content/25, /content/item1/item2/item3, or /markdown/item1/item2/item3). All listed endpoints are read-only and expose public content only. Search returns up to %1$d results per request across %2$d pages. This llms.txt file lists up to %3$d items per enabled content type, and pages can be unlimited when that option is enabled." 700 700 msgstr "" 701 701 702 #: includes/class-vwao-discovery-service.php:2 61703 #: includes/class-vwao-discovery-service.php:3 28702 #: includes/class-vwao-discovery-service.php:275 703 #: includes/class-vwao-discovery-service.php:343 704 704 msgid "Agent Endpoints" 705 705 msgstr "" 706 706 707 #: includes/class-vwao-discovery-service.php:2 62708 #: includes/class-vwao-discovery-service.php:3 29707 #: includes/class-vwao-discovery-service.php:276 708 #: includes/class-vwao-discovery-service.php:344 709 709 msgid "Discovery Files" 710 710 msgstr "" 711 711 712 712 #. translators: 1: item cap, 2: word cap. 713 #: includes/class-vwao-discovery-service.php:3 18713 #: includes/class-vwao-discovery-service.php:332 714 714 #, php-format 715 715 msgid "This expanded context file includes up to %1$d items per enabled content type and up to %2$d words per item to keep context manageable on large sites." … … 766 766 767 767 #: includes/class-vwao-multilingual.php:30 768 #: includes/class-vwao-multilingual.php:1 08768 #: includes/class-vwao-multilingual.php:112 769 769 msgid "Invalid content language." 770 770 msgstr "" … … 1073 1073 msgstr "" 1074 1074 1075 #: includes/class-vwao-recovery.php:2 771075 #: includes/class-vwao-recovery.php:287 1076 1076 msgid "Administrator access is required." 1077 1077 msgstr "" 1078 1078 1079 #: includes/class-vwao-recovery.php:4 591079 #: includes/class-vwao-recovery.php:469 1080 1080 msgid "The recovery item, destination or permissions changed. Review the current item again." 1081 1081 msgstr "" 1082 1082 1083 #: includes/class-vwao-recovery.php:4 631083 #: includes/class-vwao-recovery.php:473 1084 1084 msgid "Traffic Recovery storage is unavailable. Review database access, then save recovery settings to retry setup." 1085 1085 msgstr "" -
videowhisper-agentic-optimization/tags/1.9.0/readme.txt
r3791079 r3791583 108 108 * Analytics disabled by default 109 109 110 = Multilingual discovery = 111 112 When Agentic Multilingual Translator is active, discovery indexes list configured language choices separately from each page's complete published variants. Agent-facing translated content retains the original URL and available-language retrieval links. Reviewed local Traffic Recovery redirects can resolve old source slugs for legacy language URLs. Language sitemap entries respect the current original page's SEO indexing and canonical policy. 113 110 114 == Installation == 111 115 … … 222 226 == Changelog == 223 227 228 = 1.9.0 = 229 * Keep core sitemaps responsive on metadata-heavy builder pages with indexed SEO exclusions. Retain unpublished drafts when reviewing a missing-URL redirect. 230 * Discovery indexes list configured languages separately from complete published variants. 231 * Reviewed traffic recovery targets can resolve legacy translated permalinks; sitemap entries respect current source SEO policy. 232 233 224 234 = 1.8.0 = 225 235 * Add opt-in, bounded Traffic Recovery reports, configurable retention and private Site Manager reporting. -
videowhisper-agentic-optimization/tags/1.9.0/videowhisper-agentic-optimization.php
r3791079 r3791583 3 3 * Plugin Name: Agentic Optimization - SEO for AI Agents 4 4 * Description: Optional local search SEO editing plus agent-friendly discovery, markdown and read-only public REST/MCP access. 5 * Version: 1. 8.05 * Version: 1.9.0 6 6 * Requires at least: 6.9 7 7 * Requires PHP: 8.2 … … 19 19 defined( 'ABSPATH' ) || exit; 20 20 21 define( 'VWAO_VERSION', '1. 8.0' );21 define( 'VWAO_VERSION', '1.9.0' ); 22 22 define( 'VWAO_REWRITE_VERSION', '3' ); 23 23 define( 'VWAO_PLUGIN_FILE', __FILE__ ); -
videowhisper-agentic-optimization/trunk/includes/class-vwao-discovery-service.php
r3786442 r3791583 92 92 } 93 93 } 94 return hash( 'sha256', wp_json_encode( array( $this->settings->get_all(), VWAO_Multilingual::locale(), VWAO_SEO_Service::get_providers(), get_option( 'blog_public' ), $items ) ) ); 94 return hash( 'sha256', wp_json_encode( array( $this->settings->get_all(), VWAO_Multilingual::locale(), VWAO_SEO_Service::get_providers(), get_option( 'blog_public' ), self::configured_languages(), $items ) ) ); 95 } 96 /** Configured choices are distinct from each item's complete published variants. */ 97 private static function configured_languages() { 98 $rows = apply_filters( 'vwml_available_languages_v1', array(), 'discovery' ); 99 return is_array( $rows ) ? array_values( array_filter( array_keys( $rows ), static fn( $code ) => is_string( $code ) && preg_match( '/^[A-Za-z]{2,8}(?:-[A-Za-z0-9]{2,8})*$/D', $code ) ) ) : array(); 100 } 101 private function language_lines() { 102 $codes = self::configured_languages(); 103 if ( ! $codes ) { return array(); } 104 $lines = array( 'Configured languages: ' . implode( ', ', $codes ), 'Only complete published translations appear in language-specific results.' ); 105 foreach ( $codes as $code ) { 106 $lines[] = '- ' . $code . ': ' . esc_url_raw( add_query_arg( 'language', $code, home_url( '/llms.txt' ) ) ); } 107 return $lines; 95 108 } 96 109 … … 256 269 $lines[] = 'Base URL: ' . $site['base_url']; 257 270 $lines[] = 'Language: ' . VWAO_Multilingual::language(); 271 $lines = array_merge( $lines, $this->language_lines() ); 258 272 $lines[] = 'Generated (GMT): ' . gmdate( 'c' ); 259 273 $lines[] = ''; … … 323 337 $lines[] = 'Base URL: ' . $site['base_url']; 324 338 $lines[] = 'Language: ' . VWAO_Multilingual::language(); 339 $lines = array_merge( $lines, $this->language_lines() ); 325 340 $lines[] = 'Generated (GMT): ' . gmdate( 'c' ); 326 341 $lines[] = ''; … … 435 450 $xml = '<?xml version="1.0" encoding="' . esc_attr( get_bloginfo( 'charset' ) ) . '"?>'; 436 451 $xml .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:agent="urn:videowhisper:agentic:1.0">'; 452 $xml .= '<!-- Configured languages: ' . esc_html( implode( ', ', self::configured_languages() ) ) . '; per-URL available_languages lists complete published variants. -->'; 437 453 438 454 foreach ( $content as $group ) { -
videowhisper-agentic-optimization/trunk/includes/class-vwao-multilingual.php
r3790761 r3791583 74 74 /** Register rendering hooks. */ 75 75 public static function hooks() { 76 add_filter( 'vwml_sitemap_source_allowed_v1', static function ( $allowed, $post ) { 77 if ( false === $allowed ) { return false; } 78 $seo = VWAO_SEO_Service::get_post_state( $post ); 79 return false === ( $seo['noindex'] ?? null ) && untrailingslashit( $seo['canonical'] ?? '' ) === untrailingslashit( get_permalink( $post ) ); 80 }, 10, 2 ); 76 81 add_filter( 77 82 'vwml_use_public_overlay', -
videowhisper-agentic-optimization/trunk/includes/class-vwao-recovery.php
r3791079 r3791583 20 20 add_action( 'shutdown', array( __CLASS__, 'capture' ) ); 21 21 add_action( 'vwao_recovery_cleanup', array( __CLASS__, 'prune' ) ); 22 add_filter( 'vwml_legacy_source_id_v1', array( __CLASS__, 'translation_source' ), 10, 4 ); 23 } 24 /** Resolve only an existing, reviewed local redirect; never guess a target. */ 25 public static function translation_source( $id, $path, $locale = '', $request_path = '' ) { 26 unset( $locale ); 27 if ( $id || '1' !== get_option( 'vwao_recovery_schema' ) ) { return $id; } 28 global $wpdb; 29 foreach ( array_unique( array( self::path( $path ), self::path( $request_path ) ) ) as $candidate ) { 30 if ( ! $candidate || self::decision( $candidate ) ) { continue; } 31 $r = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM %i WHERE path_hash=%s AND state=%s', $wpdb->prefix . 'vwao_recovery_paths', hash( 'sha256', $candidate ), 'redirect' ), ARRAY_A ); 32 $p = $r && hash_equals( $r['path'], $candidate ) ? self::target( (int) $r['target_id'] ) : null; 33 if ( $p ) { return (int) $p->ID; } 34 } 35 return $id; 22 36 } 23 37 public static function settings() { … … 223 237 } 224 238 public static function version( $row ) { 225 return hash( 'sha256', wp_json_encode( array( get_current_blog_id(), $row['id'], $row['path'], $row['state'], $row['target_id'], $row['redirect_code'], $row['draft_id'], $row['revision'] ) ) ); 239 // Database rows and report rows use different scalar types. Bind the same 240 // normalized editorial state in both; traffic counters are not permissions. 241 return hash( 'sha256', wp_json_encode( array( get_current_blog_id(), (int) $row['id'], (string) $row['path'], (string) $row['state'], (int) $row['target_id'], (int) $row['redirect_code'], (int) $row['draft_id'], (int) $row['revision'] ) ) ); 226 242 } 227 243 public static function target( $id ) { … … 395 411 $p = self::target( $target ); 396 412 $existing = self::existing_id( $r['path'] ); 397 $draft = ! empty( $r['draft_id'] ) ? (int) $r['draft_id'] : 0; 398 if ( $draft ) { clean_post_cache( $draft ); } 399 // A linked editable recovery draft is retained, never overwritten or published. 400 $source_conflict = $existing && ( (int) $existing !== $draft || ! self::reusable_draft( $r ) ); 413 // Existing unpublished drafts remain untouched. A later real public 414 // page wins because runtime recovery only runs for an actual 404. 415 $source_conflict = $existing && is_post_publicly_viewable( get_post( $existing ) ); 401 416 if ( ! $p || ! in_array( $code, array( 301, 302 ), true ) || $source_conflict || self::decision( $r['path'] ) || self::same_path( get_permalink( $p ), $r['path'] ) ) { 402 417 return self::error(); } -
videowhisper-agentic-optimization/trunk/includes/class-vwao-standalone-seo.php
r3789597 r3791583 116 116 add_filter( 'wp_robots', array( __CLASS__, 'robots' ), 20 ); 117 117 add_filter( 'wp_sitemaps_posts_query_args', array( __CLASS__, 'sitemap_query' ), 20, 2 ); 118 add_filter( 'posts_where', array( __CLASS__, 'sitemap_where' ), 20, 2 ); 118 119 } 119 120 … … 346 347 return $args; } 347 348 $args['has_password'] = false; 348 $clauses = array( 'relation' => 'AND' ); 349 if ( ! empty( $args['meta_query'] ) ) { 350 $clauses[] = $args['meta_query']; } 349 $args['vwao_sitemap_seo'] = true; 350 return $args; 351 } 352 353 /** Indexed exclusions avoid multiplying theme metadata rows across six joins. */ 354 public static function sitemap_where( $where, $query ) { 355 if ( true !== $query->get( 'vwao_sitemap_seo' ) || ! self::active() ) { return $where; } 356 global $wpdb; 351 357 foreach ( array( 352 '_vwao_seo_noindex' => array( '1' ),358 '_vwao_seo_noindex' => array( '1' ), 353 359 '_yoast_wpseo_meta-robots-noindex' => array( '1' ), 354 '_aioseo_robots_noindex' => array( '1', 'on', 'yes' ),355 '_seopress_robots_index' => array( 'yes' ),360 '_aioseo_robots_noindex' => array( '1', 'on', 'yes' ), 361 '_seopress_robots_index' => array( 'yes' ), 356 362 ) as $key => $values ) { 357 $clauses[] = array( 358 'relation' => 'OR', 359 array( 360 'key' => $key, 361 'compare' => 'NOT EXISTS', 362 ), 363 array( 364 'key' => $key, 365 'value' => $values, 366 'compare' => 'NOT IN', 367 ), 368 ); 369 } 370 $clauses[] = array( 371 'relation' => 'OR', 372 array( 373 'key' => 'rank_math_robots', 374 'compare' => 'NOT EXISTS', 375 ), 376 array( 377 'key' => 'rank_math_robots', 378 'value' => '"noindex"', 379 'compare' => 'NOT LIKE', 380 ), 381 ); 382 // Custom canonical destinations are not advertised as self-canonical sitemap URLs. 383 $clauses[] = array( 384 'relation' => 'OR', 385 array( 386 'key' => '_vwao_seo_canonical', 387 'compare' => 'NOT EXISTS', 388 ), 389 array( 390 'key' => '_vwao_seo_canonical', 391 'value' => '', 392 'compare' => '=', 393 ), 394 ); 395 $args['meta_query'] = $clauses; 396 return $args; 363 $holders = implode( ',', array_fill( 0, count( $values ), '%s' ) ); 364 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Core table identifiers and generated placeholder list; values are prepared. 365 $where .= $wpdb->prepare( " AND NOT EXISTS (SELECT 1 FROM {$wpdb->postmeta} vwao_sm WHERE vwao_sm.post_id={$wpdb->posts}.ID AND vwao_sm.meta_key=%s AND vwao_sm.meta_value IN ($holders))", array_merge( array( $key ), $values ) ); 366 } 367 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Core table identifiers; values are prepared. 368 $where .= $wpdb->prepare( " AND NOT EXISTS (SELECT 1 FROM {$wpdb->postmeta} vwao_sm WHERE vwao_sm.post_id={$wpdb->posts}.ID AND vwao_sm.meta_key=%s AND vwao_sm.meta_value LIKE %s)", 'rank_math_robots', '%' . $wpdb->esc_like( '"noindex"' ) . '%' ); 369 // Custom canonical destinations are excluded, including duplicate conflicting metadata. 370 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Core table identifiers; values are prepared. 371 $where .= $wpdb->prepare( " AND NOT EXISTS (SELECT 1 FROM {$wpdb->postmeta} vwao_sm WHERE vwao_sm.post_id={$wpdb->posts}.ID AND vwao_sm.meta_key=%s AND vwao_sm.meta_value<>%s)", '_vwao_seo_canonical', '' ); 372 return $where; 397 373 } 398 374 -
videowhisper-agentic-optimization/trunk/languages/videowhisper-agentic-optimization.pot
r3791079 r3791583 3 3 msgid "" 4 4 msgstr "" 5 "Project-Id-Version: Agentic Optimization - SEO for AI Agents 1. 8.0\n"5 "Project-Id-Version: Agentic Optimization - SEO for AI Agents 1.9.0\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/videowhisper-agentic-optimization\n" 7 7 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" … … 10 10 "Content-Type: text/plain; charset=UTF-8\n" 11 11 "Content-Transfer-Encoding: 8bit\n" 12 "POT-Creation-Date: 2026-11-08T 13:59:03+00:00\n"12 "POT-Creation-Date: 2026-11-08T21:05:52+00:00\n" 13 13 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 14 14 "X-Generator: WP-CLI 2.12.0\n" … … 695 695 696 696 #. translators: 1: result cap, 2: max pages, 3: llms list cap. 697 #: includes/class-vwao-discovery-service.php:2 50697 #: includes/class-vwao-discovery-service.php:263 698 698 #, php-format 699 699 msgid "Use the Search endpoint for discovery, read specific items with Content or Markdown by numeric ID or content slug, including hierarchical paths (e.g., /content/25, /content/item1/item2/item3, or /markdown/item1/item2/item3). All listed endpoints are read-only and expose public content only. Search returns up to %1$d results per request across %2$d pages. This llms.txt file lists up to %3$d items per enabled content type, and pages can be unlimited when that option is enabled." 700 700 msgstr "" 701 701 702 #: includes/class-vwao-discovery-service.php:2 61703 #: includes/class-vwao-discovery-service.php:3 28702 #: includes/class-vwao-discovery-service.php:275 703 #: includes/class-vwao-discovery-service.php:343 704 704 msgid "Agent Endpoints" 705 705 msgstr "" 706 706 707 #: includes/class-vwao-discovery-service.php:2 62708 #: includes/class-vwao-discovery-service.php:3 29707 #: includes/class-vwao-discovery-service.php:276 708 #: includes/class-vwao-discovery-service.php:344 709 709 msgid "Discovery Files" 710 710 msgstr "" 711 711 712 712 #. translators: 1: item cap, 2: word cap. 713 #: includes/class-vwao-discovery-service.php:3 18713 #: includes/class-vwao-discovery-service.php:332 714 714 #, php-format 715 715 msgid "This expanded context file includes up to %1$d items per enabled content type and up to %2$d words per item to keep context manageable on large sites." … … 766 766 767 767 #: includes/class-vwao-multilingual.php:30 768 #: includes/class-vwao-multilingual.php:1 08768 #: includes/class-vwao-multilingual.php:112 769 769 msgid "Invalid content language." 770 770 msgstr "" … … 1073 1073 msgstr "" 1074 1074 1075 #: includes/class-vwao-recovery.php:2 771075 #: includes/class-vwao-recovery.php:287 1076 1076 msgid "Administrator access is required." 1077 1077 msgstr "" 1078 1078 1079 #: includes/class-vwao-recovery.php:4 591079 #: includes/class-vwao-recovery.php:469 1080 1080 msgid "The recovery item, destination or permissions changed. Review the current item again." 1081 1081 msgstr "" 1082 1082 1083 #: includes/class-vwao-recovery.php:4 631083 #: includes/class-vwao-recovery.php:473 1084 1084 msgid "Traffic Recovery storage is unavailable. Review database access, then save recovery settings to retry setup." 1085 1085 msgstr "" -
videowhisper-agentic-optimization/trunk/readme.txt
r3791079 r3791583 108 108 * Analytics disabled by default 109 109 110 = Multilingual discovery = 111 112 When Agentic Multilingual Translator is active, discovery indexes list configured language choices separately from each page's complete published variants. Agent-facing translated content retains the original URL and available-language retrieval links. Reviewed local Traffic Recovery redirects can resolve old source slugs for legacy language URLs. Language sitemap entries respect the current original page's SEO indexing and canonical policy. 113 110 114 == Installation == 111 115 … … 222 226 == Changelog == 223 227 228 = 1.9.0 = 229 * Keep core sitemaps responsive on metadata-heavy builder pages with indexed SEO exclusions. Retain unpublished drafts when reviewing a missing-URL redirect. 230 * Discovery indexes list configured languages separately from complete published variants. 231 * Reviewed traffic recovery targets can resolve legacy translated permalinks; sitemap entries respect current source SEO policy. 232 233 224 234 = 1.8.0 = 225 235 * Add opt-in, bounded Traffic Recovery reports, configurable retention and private Site Manager reporting. -
videowhisper-agentic-optimization/trunk/videowhisper-agentic-optimization.php
r3791079 r3791583 3 3 * Plugin Name: Agentic Optimization - SEO for AI Agents 4 4 * Description: Optional local search SEO editing plus agent-friendly discovery, markdown and read-only public REST/MCP access. 5 * Version: 1. 8.05 * Version: 1.9.0 6 6 * Requires at least: 6.9 7 7 * Requires PHP: 8.2 … … 19 19 defined( 'ABSPATH' ) || exit; 20 20 21 define( 'VWAO_VERSION', '1. 8.0' );21 define( 'VWAO_VERSION', '1.9.0' ); 22 22 define( 'VWAO_REWRITE_VERSION', '3' ); 23 23 define( 'VWAO_PLUGIN_FILE', __FILE__ );
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)