PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.7.2
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.7.2
2.7.1 2.7.2 2.7.0 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 All 141 releases
← All changes | includes/class-metasync-admin-navigation.php +15 -35 2.6.24 → 2.7.2 View file →
@@ -286,12 +286,8 @@
286 286 if (empty($whitelabel_settings['hide_indexation_control'])) {
287 287 $menu_items['seo_controls'] = ['title' => 'Indexation Control', 'slug_suffix' => '-seo-controls'];
288 288 }
289 289
290 - if ($general_options['enable_googleinstantindex'] ?? false) {
291 - $menu_items['instant_index'] = ['title' => 'Instant Indexing', 'slug_suffix' => '-instant-index'];
292 - }
293 -
294 290 if ($general_options['enable_google_console'] ?? false) {
295 291 $menu_items['google_console'] = ['title' => 'Google Console', 'slug_suffix' => '-google-console'];
296 292 }
297 293
@@ -506,20 +502,8 @@
506 502 'group' => 'seo'
507 503 ];
508 504 }
509 505
510 - // Instant Indexing - setting now stored in seo_controls (moved from Settings to Indexation Control)
511 - $seo_controls = Metasync::get_option('seo_controls');
512 - if ($seo_controls['enable_googleinstantindex'] ?? false) {
513 - $menu_items['instant_index'] = [
514 - 'title' => 'Instant Indexing',
515 - 'slug_suffix' => '-instant-index',
516 - 'callback' => 'create_admin_google_instant_index_page',
517 - 'internal_nav' => 'Instant Indexing',
518 - 'group' => 'seo'
519 - ];
520 - }
521 -
522 506 if ($general_options['enable_google_console'] ?? false) {
523 507 $menu_items['google_console'] = [
524 508 'title' => 'Google Console',
525 509 'slug_suffix' => '-google-console',
@@ -833,13 +817,8 @@
833 817
834 818 // Site Verification (in-page sidebar only in short mode)
835 819 $register_submenu('site_verification', 'Site Verification', 'Site Verification', $menu_capability, $menu_slug . '-search-engine-verify', array($admin, 'create_admin_search_engine_verification_page'));
836 820
837 - // Instant Indexing (conditional)
838 - if ($seo_controls['enable_googleinstantindex'] ?? false) {
839 - $register_submenu('instant_index', 'Instant Indexing', 'Instant Indexing', $menu_capability, $menu_slug . '-instant-index', array($admin, 'create_admin_google_instant_index_page'));
840 - }
841 -
842 821 // Google Console (conditional)
843 822 if ($general_options['enable_google_console'] ?? false) {
844 823 $register_submenu('google_console', 'Google Console', 'Google Console', $menu_capability, $menu_slug . '-google-console', array($admin, 'create_admin_google_console_page'));
845 824 }
@@ -920,10 +899,10 @@
920 899 // WordPress cannot resolve titles for pages registered under an empty
921 900 // parent, even though those pages remain reachable by URL. Restore the
922 901 // standard admin title format for our registered pages only.
923 902 add_filter('admin_title', function($admin_title, $title) use (&$admin_page_titles) {
924 - $current_page = isset($_GET['page']) && is_string($_GET['page'])
925 - ? sanitize_text_field(wp_unslash($_GET['page']))
903 + $current_page = isset($_GET['page']) && is_string($_GET['page']) // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only page slug for the admin title
904 + ? sanitize_text_field(wp_unslash($_GET['page'])) // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only page slug for the admin title
926 905 : '';
927 906
928 907 if (empty($title) && isset($admin_page_titles[$current_page])) {
929 908 $site_title = is_network_admin() || is_user_admin()
@@ -931,9 +910,9 @@
931 910 : get_bloginfo('name');
932 911
933 912 $admin_title = sprintf(
934 913 /* translators: 1: Admin page title, 2: Site or network title. */
935 - __('%1$s ‹ %2$s — WordPress'),
914 + __('%1$s ‹ %2$s — WordPress', 'metasync'),
936 915 $admin_page_titles[$current_page],
937 916 $site_title
938 917 );
939 918 }
@@ -1396,9 +1375,9 @@
1396 1375 $status_title_header = 'Not Synced - Heartbeat API not responding or unreachable';
1397 1376 $status_text_header = 'Not Synced';
1398 1377 }
1399 1378 ?>
1400 - <div class="metasync-integration-status <?php echo $status_class_header; ?>"
1379 + <div class="metasync-integration-status <?php echo esc_attr($status_class_header); ?>"
1401 1380 title="<?php echo esc_attr($status_title_header); ?>">
1402 1381 <span class="status-indicator"></span>
1403 1382 <span class="status-text"><?php echo esc_html($status_text_header); ?></span>
1404 1383 </div>
@@ -1478,10 +1457,10 @@
1478 1457
1479 1458 <?php
1480 1459 $page_slug = Metasync_Admin::$page_slug;
1481 1460 $is_plugin_page = (
1482 - (isset($_GET['page']) && strpos($_GET['page'], $page_slug) !== false) ||
1483 - (isset($_GET['page']) && strpos($_GET['page'], 'searchatlas') !== false)
1461 + (isset($_GET['page']) && strpos($_GET['page'], $page_slug) !== false) || // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only page check for an inline config script
1462 + (isset($_GET['page']) && strpos($_GET['page'], 'searchatlas') !== false) // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only page check for an inline config script
1484 1463 );
1485 1464 if ($is_plugin_page):
1486 1465 ?>
1487 1466 <script type="text/javascript">
@@ -1658,9 +1637,9 @@
1658 1637 * @param string $description Optional subtitle shown below the title.
1659 1638 */
1660 1639 public function render_layout_open($page_title = '', $current_page = '', $description = '')
1661 1640 {
1662 - $theme = esc_attr(get_option('metasync_theme', 'dark'));
1641 + $theme = get_option('metasync_theme', 'dark');
1663 1642 $plugin_name = Metasync::get_effective_plugin_name();
1664 1643 $general = Metasync::get_option('general') ?? [];
1665 1644 $is_connected = Metasync_Heartbeat_Manager::instance()->is_heartbeat_connected($general);
1666 1645 // badge reflects confirmed heartbeat health (connected / stale /
@@ -1669,9 +1648,9 @@
1669 1648 $logo = $this->resolve_logo_data();
1670 1649
1671 1650 $current_theme = get_option('metasync_theme', 'dark');
1672 1651 ?>
1673 - <div class="wrap metasync-dashboard-wrap" data-theme="<?php echo $theme; ?>">
1652 + <div class="wrap metasync-dashboard-wrap" data-theme="<?php echo esc_attr($theme); ?>">
1674 1653
1675 1654 <?php
1676 1655 // Inject whitelabel color palette overrides
1677 1656 $wl_settings = Metasync::get_whitelabel_settings();
@@ -1701,8 +1680,9 @@
1701 1680 $vars .= '--' . esc_attr($grad_var) . ':linear-gradient(135deg,' . esc_attr($from) . ' 0%,' . esc_attr($to) . ' 100%);';
1702 1681 }
1703 1682 }
1704 1683 if ($vars) {
1684 + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- CSS custom properties inside a raw <style> element; every value is a regex-validated hex color and HTML entities are not decoded in raw text elements
1705 1685 echo $selector . '{' . $vars . '}';
1706 1686 }
1707 1687 }
1708 1688 }
@@ -1862,12 +1842,12 @@
1862 1842 <ul>
1863 1843 <?php foreach ($seo_items as $key => $item):
1864 1844 $is_active = ($current_page === $key);
1865 1845 $icon = $icons[$key] ?? 'admin-generic';
1866 - $url = esc_url(admin_url('admin.php?page=' . $page_slug . $item['slug_suffix']));
1846 + $url = admin_url('admin.php?page=' . $page_slug . $item['slug_suffix']);
1867 1847 ?>
1868 1848 <li class="<?php echo $is_active ? 'metasync-sidenav-active' : ''; ?>">
1869 - <a href="<?php echo $url; ?>">
1849 + <a href="<?php echo esc_url($url); ?>">
1870 1850 <span class="metasync-sidenav-icon"><span class="dashicons dashicons-<?php echo esc_attr($icon); ?>"></span></span>
1871 1851 <?php echo esc_html($item['title']); ?>
1872 1852 </a>
1873 1853 </li>
@@ -1882,12 +1862,12 @@
1882 1862 <?php foreach ($plugin_items as $key => $item):
1883 1863 if ($key === 'report_issue') continue;
1884 1864 $is_active = ($current_page === $key);
1885 1865 $icon = $icons[$key] ?? 'admin-generic';
1886 - $url = esc_url(admin_url('admin.php?page=' . $page_slug . $item['slug_suffix']));
1866 + $url = admin_url('admin.php?page=' . $page_slug . $item['slug_suffix']);
1887 1867 ?>
1888 1868 <li class="<?php echo $is_active ? 'metasync-sidenav-active' : ''; ?>">
1889 - <a href="<?php echo $url; ?>">
1869 + <a href="<?php echo esc_url($url); ?>">
1890 1870 <span class="metasync-sidenav-icon"><span class="dashicons dashicons-<?php echo esc_attr($icon); ?>"></span></span>
1891 1871 <?php echo esc_html($item['title']); ?>
1892 1872 </a>
1893 1873 </li>
@@ -1938,9 +1918,9 @@
1938 1918 public function render_promo_sidebar()
1939 1919 {
1940 1920 $plugin_name = Metasync::get_effective_plugin_name();
1941 1921 $otto_name = Metasync::get_whitelabel_otto_name();
1942 - $settings_url = esc_url(admin_url('admin.php?page=' . Metasync_Admin::$page_slug));
1922 + $settings_url = admin_url('admin.php?page=' . Metasync_Admin::$page_slug);
1943 1923 $homepage = Metasync::HOMEPAGE_DOMAIN;
1944 1924 $docs_url = Metasync::DOCUMENTATION_DOMAIN;
1945 1925 // These links point at Search Atlas properties, so they only belong
1946 1926 // here while the plugin runs under its own name AND branding — a
@@ -1968,9 +1948,9 @@
1968 1948 <li><span class="promo-check">&#10003;</span> Real-time keyword tracking</li>
1969 1949 <li><span class="promo-check">&#10003;</span> Automated schema markup</li>
1970 1950 <li><span class="promo-check">&#10003;</span> Instant Google indexing</li>
1971 1951 </ul>
1972 - <a href="<?php echo $settings_url; ?>" class="metasync-promo-btn metasync-promo-btn--primary">
1952 + <a href="<?php echo esc_url($settings_url); ?>" class="metasync-promo-btn metasync-promo-btn--primary">
1973 1953 Connect Now
1974 1954 </a>
1975 1955 </div>
1976 1956