| @@ -14,10 +14,10 @@ | ||
| 14 | 14 | * @wordpress-plugin |
| 15 | 15 | * Plugin Name: Search Atlas: The Premier AI SEO Plugin for Instant Optimization |
| 16 | 16 | * Plugin URI: https://searchatlas.com/ |
| 17 | 17 | * Description: Search Atlas SEO is an intuitive WordPress Plugin that transforms the most complicated, most labor-intensive SEO tasks into streamlined, straightforward processes. With a few clicks, the meta-bulk update feature automates the re-optimization of meta tags using AI to increase clicks. Stay up-to-date with the freshest Google Search data for your entire site or targeted URLs within the Meta Sync plug-in page. |
| 18 | - * Version: 2.6.21 | |
| 19 | - * Requires PHP: 8.2 | |
| 18 | + * Version: 2.6.26 | |
| 19 | + * Requires PHP: 8.1 | |
| 20 | 20 | * Author: Search Atlas |
| 21 | 21 | * Author URI: https://searchatlas.com |
| 22 | 22 | * License: GPL v3 |
| 23 | 23 | * License URI: https://www.gnu.org/licenses/gpl-3.0.txt |
| @@ -35,20 +35,26 @@ | ||
| 35 | 35 | // Canonical sanitizer — required explicitly (not via the committed classmap) |
| 36 | 36 | // so it is guaranteed loadable everywhere canonicals are read or written. |
| 37 | 37 | require_once __DIR__ . '/includes/class-metasync-canonical-sanitizer.php'; |
| 38 | 38 | |
| 39 | +// Editor-settings feature flags — required explicitly for the same reason: they | |
| 40 | +// gate output in the OTTO buffer and in third-party filter callbacks, both of | |
| 41 | +// which can run before the classmap has resolved anything else. | |
| 42 | +require_once __DIR__ . '/includes/class-metasync-feature-flags.php'; | |
| 43 | +Metasync_Feature_Flags::register_invalidation(); | |
| 44 | + | |
| 39 | 45 | /** |
| 40 | 46 | * Currently plugin version. |
| 41 | 47 | * Start at version 1.0.0 and use SemVer - https://semver.org |
| 42 | 48 | * Rename this for your plugin and update it as you release new versions. |
| 43 | 49 | */ |
| 44 | -$metasync_version = '2.6.21'; | |
| 50 | +$metasync_version = '2.6.26'; | |
| 45 | 51 | define('METASYNC_VERSION', preg_match('/^\d+\.\d+/', $metasync_version) ? $metasync_version : '9.9.9'); |
| 46 | 52 | /** |
| 47 | 53 | * Define the current required php version |
| 48 | 54 | * This will be used to validate whether the user can install the plugin or not |
| 49 | 55 | */ |
| 50 | -define('METASYNC_MIN_PHP', '8.2'); | |
| 56 | +define('METASYNC_MIN_PHP', '8.1'); | |
| 51 | 57 | |
| 52 | 58 | /** |
| 53 | 59 | * Define the current required php version |
| 54 | 60 | * This will be used to validate whether the user can install the plugin or not |
| @@ -119,8 +125,14 @@ | ||
| 119 | 125 | static $result = null; |
| 120 | 126 | if ($result !== null) { |
| 121 | 127 | return $result; |
| 122 | 128 | } |
| 129 | + // The MCP bridge intentionally boots WordPress with DOING_AJAX set, but it | |
| 130 | + // is a MetaSync entry point rather than an unrelated admin AJAX request. | |
| 131 | + // The constant is only ever defined as true by the bridge bootstraps. | |
| 132 | + if (defined('METASYNC_MCP_BRIDGE')) { | |
| 133 | + return ($result = false); | |
| 134 | + } | |
| 123 | 135 | if (!defined('DOING_AJAX') || !DOING_AJAX) { |
| 124 | 136 | return ($result = false); |
| 125 | 137 | } |
| 126 | 138 | $action = isset($_POST['action']) ? sanitize_text_field(wp_unslash($_POST['action'])) |
| @@ -171,8 +183,13 @@ | ||
| 171 | 183 | // Shared helpers (custom/LPS page detection + query exclusion) — loaded in all |
| 172 | 184 | // request contexts (admin, REST, MCP, AJAX) so every SEO surface uses one rule. |
| 173 | 185 | require_once plugin_dir_path( __FILE__ ) . 'includes/metasync-helpers.php'; |
| 174 | 186 | |
| 187 | +// Shared "results per page" selector helper used by the Redirections, 404 | |
| 188 | +// Monitor, Changes Log and Media Library admin list tables. Loaded early so | |
| 189 | +// the helper class is available before any list table instantiates. | |
| 190 | +require_once plugin_dir_path( __FILE__ ) . 'includes/class-metasync-per-page-helper.php'; | |
| 191 | + | |
| 175 | 192 | /** |
| 176 | 193 | * Include the Otto Pixel Php Code |
| 177 | 194 | */ |
| 178 | 195 | if (!metasync_is_non_metasync_admin_ajax()) { |
| @@ -348,9 +365,15 @@ | ||
| 348 | 365 | $bn = basename($file); |
| 349 | 366 | $content = @file_get_contents($file); |
| 350 | 367 | if (false !== $content) { |
| 351 | 368 | $tkey = 'metasync_vsm_' . md5($bn); |
| 352 | - set_transient($tkey, $content, 30 * DAY_IN_SECONDS); | |
| 369 | + // The news sitemap's entries are only valid inside Google News' | |
| 370 | + // 48-hour window, so it must not be migrated in under a 30-day | |
| 371 | + // TTL — that would re-introduce the staleness the generator's | |
| 372 | + // own bounded TTL exists to prevent. Regenerate-on-miss rebuilds | |
| 373 | + // it with a fresh date_query when this expires. | |
| 374 | + $ttl = ('news-sitemap.xml' === $bn) ? (int) (DAY_IN_SECONDS / 4) : 30 * DAY_IN_SECONDS; | |
| 375 | + set_transient($tkey, $content, $ttl); | |
| 353 | 376 | if (false !== get_transient($tkey)) { |
| 354 | 377 | @unlink($file); |
| 355 | 378 | $virtual_index[$bn] = $tkey; |
| 356 | 379 | if ($bn !== 'sitemap_index.xml' && $bn !== 'news-sitemap.xml' && $bn !== 'video-sitemap.xml') { |
| @@ -439,8 +462,23 @@ | ||
| 439 | 462 | MetaSync_DBMigration::cleanup_corrupted_canonicals(); |
| 440 | 463 | update_option('metasync_canonical_cleanup_done', 'done', false); |
| 441 | 464 | } |
| 442 | 465 | |
| 466 | + // One-time repair of Local Business logos corrupted to "http://<id>". | |
| 467 | + // The sanitizer fix stopped new corruption; this restores the | |
| 468 | + // attachment ID on sites that saved a logo before it. The corrupted | |
| 469 | + // value encodes the original ID exactly, so the rewrite is lossless. | |
| 470 | + // Claimed via add_option() — it fails when the row already exists, so | |
| 471 | + // concurrent requests can't run the repair twice, and the claim lands | |
| 472 | + // BEFORE the work: the repair itself is idempotent, and the read-side | |
| 473 | + // normalisation in the schema output and admin preview already | |
| 474 | + // protects output if a run is interrupted. | |
| 475 | + if (false === get_option('metasync_local_seo_logo_repair_done') | |
| 476 | + && add_option('metasync_local_seo_logo_repair_done', 'running', '', false)) { | |
| 477 | + MetaSync_DBMigration::repair_corrupted_local_seo_logo(); | |
| 478 | + update_option('metasync_local_seo_logo_repair_done', 'done', false); | |
| 479 | + } | |
| 480 | + | |
| 443 | 481 | // Migrate physical sitemap files on version update. |
| 444 | 482 | metasync_migrate_physical_sitemaps(); |
| 445 | 483 | |
| 446 | 484 | // Run full migration to ensure all tables are up to date |
| @@ -541,9 +579,9 @@ | ||
| 541 | 579 | } |
| 542 | 580 | } |
| 543 | 581 | |
| 544 | 582 | if ($should_import) { |
| 545 | - Metasync_Activator::check_whitelabel_settings_update(); | |
| 583 | + Metasync_Activator::check_whitelabel_settings_update(true); | |
| 546 | 584 | } |
| 547 | 585 | } |
| 548 | 586 | |
| 549 | 587 | // Hook into WordPress upgrader to detect plugin updates |
| @@ -552,25 +590,30 @@ | ||
| 552 | 590 | /** |
| 553 | 591 | * Fallback: Check for whitelabel file changes on admin pages |
| 554 | 592 | * This handles edge cases where upgrader_process_complete doesn't fire |
| 555 | 593 | * (e.g., FTP uploads, manual file replacements) |
| 556 | - * Only checks once per admin session to minimize performance impact | |
| 594 | + * Only checks once per admin request to minimize performance impact | |
| 557 | 595 | */ |
| 558 | -// function metasync_check_whitelabel_on_admin() | |
| 559 | -// { | |
| 560 | -// // Only check once per admin session to avoid overhead | |
| 561 | -// static $checked = false; | |
| 562 | -// if ($checked) { | |
| 563 | -// return; | |
| 564 | -// } | |
| 565 | -// $checked = true; | |
| 596 | +function metasync_check_whitelabel_on_admin() | |
| 597 | +{ | |
| 598 | + static $checked = false; | |
| 599 | + if ($checked || !current_user_can('manage_options')) { | |
| 600 | + return; | |
| 601 | + } | |
| 602 | + $checked = true; | |
| 566 | 603 | |
| 567 | -// require_once plugin_dir_path(__FILE__) . 'includes/class-metasync-activator.php'; | |
| 568 | -// Metasync_Activator::check_whitelabel_settings_update(); | |
| 569 | -// } | |
| 604 | + require_once plugin_dir_path(__FILE__) . 'includes/class-metasync-activator.php'; | |
| 570 | 605 | |
| 571 | -// Check for whitelabel changes on admin pages (fallback for edge cases) | |
| 572 | -// add_action('admin_init', 'metasync_check_whitelabel_on_admin', 1); | |
| 606 | + // Surface a persistently failing White Label import instead of | |
| 607 | + // retrying it silently on every admin request. | |
| 608 | + add_action('admin_notices', array('Metasync_Activator', 'render_whitelabel_import_failure_notice')); | |
| 609 | + | |
| 610 | + Metasync_Activator::check_whitelabel_settings_update(); | |
| 611 | +} | |
| 612 | + | |
| 613 | +// Retry package imports on an authorized admin request when an update completed | |
| 614 | +// through the public version-check or stale-classmap fallback path. | |
| 615 | +add_action('admin_init', 'metasync_check_whitelabel_on_admin', 1); | |
| 573 | 616 | |
| 574 | 617 | // Include Media Optimization Module |
| 575 | 618 | if (!metasync_is_non_metasync_admin_ajax()) { |
| 576 | 619 | require_once plugin_dir_path(__FILE__) . 'media-optimization/media-optimization-loader.php'; |