| @@ -899,10 +899,10 @@ | ||
| 899 | 899 | // WordPress cannot resolve titles for pages registered under an empty |
| 900 | 900 | // parent, even though those pages remain reachable by URL. Restore the |
| 901 | 901 | // standard admin title format for our registered pages only. |
| 902 | 902 | add_filter('admin_title', function($admin_title, $title) use (&$admin_page_titles) { |
| 903 | - $current_page = isset($_GET['page']) && is_string($_GET['page']) | |
| 904 | - ? 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 | |
| 905 | 905 | : ''; |
| 906 | 906 | |
| 907 | 907 | if (empty($title) && isset($admin_page_titles[$current_page])) { |
| 908 | 908 | $site_title = is_network_admin() || is_user_admin() |
| @@ -910,9 +910,9 @@ | ||
| 910 | 910 | : get_bloginfo('name'); |
| 911 | 911 | |
| 912 | 912 | $admin_title = sprintf( |
| 913 | 913 | /* translators: 1: Admin page title, 2: Site or network title. */ |
| 914 | - __('%1$s ‹ %2$s — WordPress'), | |
| 914 | + __('%1$s ‹ %2$s — WordPress', 'metasync'), | |
| 915 | 915 | $admin_page_titles[$current_page], |
| 916 | 916 | $site_title |
| 917 | 917 | ); |
| 918 | 918 | } |
| @@ -1375,9 +1375,9 @@ | ||
| 1375 | 1375 | $status_title_header = 'Not Synced - Heartbeat API not responding or unreachable'; |
| 1376 | 1376 | $status_text_header = 'Not Synced'; |
| 1377 | 1377 | } |
| 1378 | 1378 | ?> |
| 1379 | - <div class="metasync-integration-status <?php echo $status_class_header; ?>" | |
| 1379 | + <div class="metasync-integration-status <?php echo esc_attr($status_class_header); ?>" | |
| 1380 | 1380 | title="<?php echo esc_attr($status_title_header); ?>"> |
| 1381 | 1381 | <span class="status-indicator"></span> |
| 1382 | 1382 | <span class="status-text"><?php echo esc_html($status_text_header); ?></span> |
| 1383 | 1383 | </div> |
| @@ -1457,10 +1457,10 @@ | ||
| 1457 | 1457 | |
| 1458 | 1458 | <?php |
| 1459 | 1459 | $page_slug = Metasync_Admin::$page_slug; |
| 1460 | 1460 | $is_plugin_page = ( |
| 1461 | - (isset($_GET['page']) && strpos($_GET['page'], $page_slug) !== false) || | |
| 1462 | - (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 | |
| 1463 | 1463 | ); |
| 1464 | 1464 | if ($is_plugin_page): |
| 1465 | 1465 | ?> |
| 1466 | 1466 | <script type="text/javascript"> |
| @@ -1637,9 +1637,9 @@ | ||
| 1637 | 1637 | * @param string $description Optional subtitle shown below the title. |
| 1638 | 1638 | */ |
| 1639 | 1639 | public function render_layout_open($page_title = '', $current_page = '', $description = '') |
| 1640 | 1640 | { |
| 1641 | - $theme = esc_attr(get_option('metasync_theme', 'dark')); | |
| 1641 | + $theme = get_option('metasync_theme', 'dark'); | |
| 1642 | 1642 | $plugin_name = Metasync::get_effective_plugin_name(); |
| 1643 | 1643 | $general = Metasync::get_option('general') ?? []; |
| 1644 | 1644 | $is_connected = Metasync_Heartbeat_Manager::instance()->is_heartbeat_connected($general); |
| 1645 | 1645 | // badge reflects confirmed heartbeat health (connected / stale / |
| @@ -1648,9 +1648,9 @@ | ||
| 1648 | 1648 | $logo = $this->resolve_logo_data(); |
| 1649 | 1649 | |
| 1650 | 1650 | $current_theme = get_option('metasync_theme', 'dark'); |
| 1651 | 1651 | ?> |
| 1652 | - <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); ?>"> | |
| 1653 | 1653 | |
| 1654 | 1654 | <?php |
| 1655 | 1655 | // Inject whitelabel color palette overrides |
| 1656 | 1656 | $wl_settings = Metasync::get_whitelabel_settings(); |
| @@ -1680,8 +1680,9 @@ | ||
| 1680 | 1680 | $vars .= '--' . esc_attr($grad_var) . ':linear-gradient(135deg,' . esc_attr($from) . ' 0%,' . esc_attr($to) . ' 100%);'; |
| 1681 | 1681 | } |
| 1682 | 1682 | } |
| 1683 | 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 | |
| 1684 | 1685 | echo $selector . '{' . $vars . '}'; |
| 1685 | 1686 | } |
| 1686 | 1687 | } |
| 1687 | 1688 | } |
| @@ -1841,12 +1842,12 @@ | ||
| 1841 | 1842 | <ul> |
| 1842 | 1843 | <?php foreach ($seo_items as $key => $item): |
| 1843 | 1844 | $is_active = ($current_page === $key); |
| 1844 | 1845 | $icon = $icons[$key] ?? 'admin-generic'; |
| 1845 | - $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']); | |
| 1846 | 1847 | ?> |
| 1847 | 1848 | <li class="<?php echo $is_active ? 'metasync-sidenav-active' : ''; ?>"> |
| 1848 | - <a href="<?php echo $url; ?>"> | |
| 1849 | + <a href="<?php echo esc_url($url); ?>"> | |
| 1849 | 1850 | <span class="metasync-sidenav-icon"><span class="dashicons dashicons-<?php echo esc_attr($icon); ?>"></span></span> |
| 1850 | 1851 | <?php echo esc_html($item['title']); ?> |
| 1851 | 1852 | </a> |
| 1852 | 1853 | </li> |
| @@ -1861,12 +1862,12 @@ | ||
| 1861 | 1862 | <?php foreach ($plugin_items as $key => $item): |
| 1862 | 1863 | if ($key === 'report_issue') continue; |
| 1863 | 1864 | $is_active = ($current_page === $key); |
| 1864 | 1865 | $icon = $icons[$key] ?? 'admin-generic'; |
| 1865 | - $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']); | |
| 1866 | 1867 | ?> |
| 1867 | 1868 | <li class="<?php echo $is_active ? 'metasync-sidenav-active' : ''; ?>"> |
| 1868 | - <a href="<?php echo $url; ?>"> | |
| 1869 | + <a href="<?php echo esc_url($url); ?>"> | |
| 1869 | 1870 | <span class="metasync-sidenav-icon"><span class="dashicons dashicons-<?php echo esc_attr($icon); ?>"></span></span> |
| 1870 | 1871 | <?php echo esc_html($item['title']); ?> |
| 1871 | 1872 | </a> |
| 1872 | 1873 | </li> |
| @@ -1917,9 +1918,9 @@ | ||
| 1917 | 1918 | public function render_promo_sidebar() |
| 1918 | 1919 | { |
| 1919 | 1920 | $plugin_name = Metasync::get_effective_plugin_name(); |
| 1920 | 1921 | $otto_name = Metasync::get_whitelabel_otto_name(); |
| 1921 | - $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); | |
| 1922 | 1923 | $homepage = Metasync::HOMEPAGE_DOMAIN; |
| 1923 | 1924 | $docs_url = Metasync::DOCUMENTATION_DOMAIN; |
| 1924 | 1925 | // These links point at Search Atlas properties, so they only belong |
| 1925 | 1926 | // here while the plugin runs under its own name AND branding — a |
| @@ -1947,9 +1948,9 @@ | ||
| 1947 | 1948 | <li><span class="promo-check">✓</span> Real-time keyword tracking</li> |
| 1948 | 1949 | <li><span class="promo-check">✓</span> Automated schema markup</li> |
| 1949 | 1950 | <li><span class="promo-check">✓</span> Instant Google indexing</li> |
| 1950 | 1951 | </ul> |
| 1951 | - <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"> | |
| 1952 | 1953 | Connect Now |
| 1953 | 1954 | </a> |
| 1954 | 1955 | </div> |
| 1955 | 1956 | |