| @@ -262,16 +262,10 @@ | ||
| 262 | 262 | add_action('metasync_api_key_changed', array('Metasync_Admin_Navigation', 'invalidate_admin_bar_status_cache'), 10, 0); |
| 263 | 263 | |
| 264 | 264 | add_action('admin_init', array($this, 'initialize_cookie')); |
| 265 | 265 | add_action('admin_init', array($this, 'maybe_redirect_to_wizard')); |
| 266 | + add_action('admin_init', array($this, 'redirect_legacy_instant_indexing_page')); | |
| 266 | 267 | |
| 267 | - // The redirect must run on admin_menu, not admin_init: in current | |
| 268 | - // WordPress the unregistered-page access check in wp-admin/includes/ | |
| 269 | - // menu.php fires from wp-admin/menu.php (required at admin.php:163), | |
| 270 | - // which is BEFORE admin_init (admin.php:180). Hooked on admin_init the | |
| 271 | - // redirect never ran — WP died with a 403 first for the removed slug. | |
| 272 | - add_action('admin_menu', array($this, 'redirect_legacy_instant_indexing_page')); | |
| 273 | - | |
| 274 | 268 | // Add admin_post hooks for form submissions (WordPress standard way - no output buffering needed) |
| 275 | 269 | add_action('admin_post_metasync_clear_all_cache_plugins', array($this, 'handle_clear_all_cache_plugins')); |
| 276 | 270 | add_action('admin_post_metasync_clear_otto_cache_all', array($this, 'handle_clear_otto_cache_all')); |
| 277 | 271 | add_action('admin_post_metasync_clear_otto_cache_url', array($this, 'handle_clear_otto_cache_url')); |
| @@ -394,8 +388,11 @@ | ||
| 394 | 388 | |
| 395 | 389 | # Add AJAX handlers for Bing Instant Indexing (IndexNow) |
| 396 | 390 | add_action('wp_ajax_metasync_send_bing_indexnow', array($this, 'ajax_send_bing_indexnow')); |
| 397 | 391 | |
| 392 | + # Add hooks for instant indexing settings saves | |
| 393 | + add_action('admin_init', array($this, 'save_instant_indexing_settings')); | |
| 394 | + | |
| 398 | 395 | # Add hooks for instant indexing post actions |
| 399 | 396 | add_filter('post_row_actions', array($this, 'add_instant_indexing_post_actions'), 10, 2); |
| 400 | 397 | add_filter('page_row_actions', array($this, 'add_instant_indexing_post_actions'), 10, 2); |
| 401 | 398 | |
| @@ -703,8 +700,10 @@ | ||
| 703 | 700 | */ |
| 704 | 701 | public function maybe_redirect_to_wizard() { |
| 705 | 702 | // Only redirect if wizard should be shown |
| 706 | 703 | if (get_option('metasync_show_wizard') && !isset($_GET['page'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- isset() routing check for a redirect to a fixed admin URL |
| 704 | + delete_option('metasync_show_wizard'); | |
| 705 | + | |
| 707 | 706 | // Don't redirect during AJAX, cron, or bulk activation |
| 708 | 707 | if (wp_doing_ajax() || wp_doing_cron() || isset($_GET['activate-multi'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- isset() routing check for a redirect to a fixed admin URL |
| 709 | 708 | return; |
| 710 | 709 | } |
| @@ -713,9 +712,8 @@ | ||
| 713 | 712 | if (!Metasync::current_user_has_plugin_access()) { |
| 714 | 713 | return; |
| 715 | 714 | } |
| 716 | 715 | |
| 717 | - delete_option('metasync_show_wizard'); | |
| 718 | 716 | wp_safe_redirect(admin_url('admin.php?page=' . self::$page_slug . '-setup-wizard')); |
| 719 | 717 | exit; |
| 720 | 718 | } |
| 721 | 719 | } |
| @@ -725,12 +723,8 @@ | ||
| 725 | 723 | * |
| 726 | 724 | * The menu entry is gone, but bookmarks and external links can still target |
| 727 | 725 | * the old URL. Resolve the current white-label slug rather than assuming |
| 728 | 726 | * "searchatlas". |
| 729 | - * | |
| 730 | - * Hooked on admin_menu (see its registration): the unregistered-page 403 in | |
| 731 | - * wp-admin/includes/menu.php fires before admin_init, so any later hook | |
| 732 | - * would be too late to redirect. | |
| 733 | 727 | */ |
| 734 | 728 | public function redirect_legacy_instant_indexing_page() { |
| 735 | 729 | if (wp_doing_ajax() || wp_doing_cron() || !is_admin() || !isset($_GET['page'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only navigation values for a same-site redirect |
| 736 | 730 | return; |
| @@ -923,11 +917,10 @@ | ||
| 923 | 917 | 'all' |
| 924 | 918 | ); |
| 925 | 919 | } |
| 926 | 920 | |
| 927 | - // Enqueue wizard CSS on all MetaSync pages because the reusable consent | |
| 928 | - // card is also displayed inside General Settings. | |
| 929 | - if (strpos($current_page, self::$page_slug) === 0 || (isset($_GET['page']) && strpos(sanitize_key(wp_unslash($_GET['page'])), '-setup-wizard') !== false)) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only page check to pick stylesheets | |
| 921 | + // Enqueue wizard CSS if on wizard page | |
| 922 | + if (isset($_GET['page']) && strpos(sanitize_key(wp_unslash($_GET['page'])), '-setup-wizard') !== false) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only page check to pick stylesheets | |
| 930 | 923 | wp_enqueue_style( |
| 931 | 924 | $this->plugin_name . '-setup-wizard', |
| 932 | 925 | plugin_dir_url(__FILE__) . 'css/metasync-setup-wizard.css', |
| 933 | 926 | array($this->plugin_name . '-dashboard'), |
| @@ -3364,9 +3357,9 @@ | ||
| 3364 | 3357 | |
| 3365 | 3358 | update_option('metasync_sitemap_settings', $sitemap_settings); |
| 3366 | 3359 | |
| 3367 | 3360 | // Regenerate sitemap with new content settings |
| 3368 | - $result = $sitemap_generator->generate_sitemap( true ); | |
| 3361 | + $result = $sitemap_generator->generate_sitemap(); | |
| 3369 | 3362 | if (is_wp_error($result)) { |
| 3370 | 3363 | echo '<div class="notice notice-error"><p>' . esc_html( |
| 3371 | 3364 | /* translators: %s: error message. */ |
| 3372 | 3365 | sprintf(__('Settings saved but sitemap generation failed: %s', 'metasync'), $result->get_error_message()) |
| @@ -3520,9 +3513,9 @@ | ||
| 3520 | 3513 | gc_collect_cycles(); |
| 3521 | 3514 | } |
| 3522 | 3515 | |
| 3523 | 3516 | // Generate main sitemap (its index will include news/video since they now exist) |
| 3524 | - $result = $sitemap_generator->generate_sitemap( true ); | |
| 3517 | + $result = $sitemap_generator->generate_sitemap(); | |
| 3525 | 3518 | |
| 3526 | 3519 | if (is_wp_error($result)) { |
| 3527 | 3520 | $error_msg = $result->get_error_message(); |
| 3528 | 3521 | error_log('[MetaSync] Sitemap generation failed: ' . $error_msg); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- genuine failure path, bounded, no secrets |
| @@ -3943,9 +3936,9 @@ | ||
| 3943 | 3936 | { |
| 3944 | 3937 | register_rest_route('metasync/v1', '/ping', array( |
| 3945 | 3938 | 'methods' => array('GET', 'POST'), |
| 3946 | 3939 | 'callback' => array($this, 'handle_ping_rest_endpoint'), |
| 3947 | - 'permission_callback' => '__return_true', | |
| 3940 | + 'permission_callback' => '__return_true', // Allow public access | |
| 3948 | 3941 | 'args' => array( |
| 3949 | 3942 | 'test' => array( |
| 3950 | 3943 | 'description' => 'Optional test parameter', |
| 3951 | 3944 | 'type' => 'string', |
| @@ -6475,8 +6468,44 @@ | ||
| 6475 | 6468 | |
| 6476 | 6469 | require_once plugin_dir_path(dirname(__FILE__)) . 'bing-index/class-metasync-bing-instant-index.php'; |
| 6477 | 6470 | $bing_instant_index = new Metasync_Bing_Instant_Index(); |
| 6478 | 6471 | $bing_instant_index->send(); |
| 6472 | + } | |
| 6473 | + | |
| 6474 | + /** | |
| 6475 | + * Save instant indexing settings (Google and Bing) | |
| 6476 | + * | |
| 6477 | + * @since 2.6.0 | |
| 6478 | + * @return void | |
| 6479 | + */ | |
| 6480 | + public function save_instant_indexing_settings() | |
| 6481 | + { | |
| 6482 | + // Check if this is a settings submission | |
| 6483 | + if (!isset($_POST['submit'])) { | |
| 6484 | + return; | |
| 6485 | + } | |
| 6486 | + | |
| 6487 | + // This handler runs on admin_init, which also fires inside | |
| 6488 | + // admin-ajax.php before its login gate, so a bare isset() check let | |
| 6489 | + // any request (including logged-out ones) rewrite the auto-submit | |
| 6490 | + // post types. Require the nonce and plugin access before writing. | |
| 6491 | + if (!isset($_POST['metasync_instant_indexing_nonce']) | |
| 6492 | + || !wp_verify_nonce(sanitize_key(wp_unslash($_POST['metasync_instant_indexing_nonce'])), 'metasync_instant_indexing_settings') | |
| 6493 | + || !Metasync::current_user_has_plugin_access()) { | |
| 6494 | + return; | |
| 6495 | + } | |
| 6496 | + | |
| 6497 | + // Save post types for Google Instant Indexing auto-submit | |
| 6498 | + if (isset($_POST['metasync_post_types'])) { | |
| 6499 | + $post_data = metasync_sanitize_input_array($_POST); | |
| 6500 | + $post_types = is_array($post_data['metasync_post_types']) ? array_map('sanitize_title', $post_data['metasync_post_types']) : []; | |
| 6501 | + | |
| 6502 | + $settings = get_option('metasync_options_instant_indexing', ['post_types' => []]); | |
| 6503 | + $settings['post_types'] = array_values($post_types); | |
| 6504 | + update_option('metasync_options_instant_indexing', $settings); | |
| 6505 | + } | |
| 6506 | + | |
| 6507 | + // Note: Bing Instant Indexing settings are saved via AJAX in save_bing_inline_settings_ajax() | |
| 6479 | 6508 | } |
| 6480 | 6509 | |
| 6481 | 6510 | /** |
| 6482 | 6511 | * Save Bing instant indexing settings from inline form (Indexation Control page) |