| @@ -217,10 +217,15 @@ | ||
| 217 | 217 | // ------------------------------------------------------------------ |
| 218 | 218 | |
| 219 | 219 | public function create_admin_settings_page() |
| 220 | 220 | { |
| 221 | - $active_tab = isset($_GET['tab']) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'general'; | |
| 221 | + if (isset($_REQUEST['metasync_password_reset'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- routing check, the reset form verifies its own nonce | |
| 222 | + Metasync_Admin_Ajax::instance()->render_password_reset_page(); | |
| 223 | + return; | |
| 224 | + } | |
| 222 | 225 | |
| 226 | + $active_tab = isset($_GET['tab']) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'general'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only tab selection | |
| 227 | + | |
| 223 | 228 | $whitelabel_settings = Metasync::get_whitelabel_settings(); |
| 224 | 229 | |
| 225 | 230 | $user_password = $whitelabel_settings['settings_password'] ?? ''; |
| 226 | 231 | $hide_settings_enabled = !empty($whitelabel_settings['hide_settings']); |
| @@ -245,9 +250,9 @@ | ||
| 245 | 250 | |
| 246 | 251 | $auth = new Metasync_Auth_Manager('whitelabel', 1800); |
| 247 | 252 | $password_validated = $auth->has_access(); |
| 248 | 253 | |
| 249 | - if (isset($_POST['whitelabel_password_submit']) && !$password_validated) { | |
| 254 | + if (isset($_POST['whitelabel_password_submit']) && !$password_validated) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- read-only access check for a display message | |
| 250 | 255 | $password_error = 'Incorrect password. Please try again.'; |
| 251 | 256 | } |
| 252 | 257 | } |
| 253 | 258 | |
| @@ -344,63 +349,8 @@ | ||
| 344 | 349 | <?php endif; ?> |
| 345 | 350 | |
| 346 | 351 | </div> |
| 347 | 352 | |
| 348 | - <script> | |
| 349 | - jQuery(document).ready(function($) { | |
| 350 | - $('#whitelabel_password').focus(); | |
| 351 | - | |
| 352 | - $('#whitelabel_password').on('keypress', function(e) { | |
| 353 | - if (e.which === 13) { | |
| 354 | - $(this).closest('form').submit(); | |
| 355 | - } | |
| 356 | - }); | |
| 357 | - | |
| 358 | - <?php if (current_user_can('manage_options')): ?> | |
| 359 | - $('#metasync-forgot-password-link').on('click', function(e) { | |
| 360 | - e.preventDefault(); | |
| 361 | - | |
| 362 | - var $link = $(this); | |
| 363 | - var $message = $('#metasync-recovery-message'); | |
| 364 | - | |
| 365 | - $link.css('pointer-events', 'none').css('opacity', '0.6'); | |
| 366 | - $message.removeClass('success error').hide(); | |
| 367 | - $message.html('⏳ Sending recovery email...').css('background', '#f0f6fc').css('color', '#0c5ba5').css('border', '1px solid #cfe2f3').fadeIn(200); | |
| 368 | - | |
| 369 | - $.ajax({ | |
| 370 | - url: ajaxurl, | |
| 371 | - type: 'POST', | |
| 372 | - data: { | |
| 373 | - action: 'metasync_recover_password', | |
| 374 | - nonce: '<?php echo wp_create_nonce('metasync_recover_password_nonce'); ?>' | |
| 375 | - }, | |
| 376 | - success: function(response) { | |
| 377 | - $link.css('pointer-events', 'auto').css('opacity', '1'); | |
| 378 | - | |
| 379 | - if (response.success) { | |
| 380 | - $message.addClass('success').html('✅ ' + response.data.message) | |
| 381 | - .css('background', '#d4edda') | |
| 382 | - .css('color', '#155724') | |
| 383 | - .css('border', '1px solid #c3e6cb'); | |
| 384 | - } else { | |
| 385 | - $message.addClass('error').html('❌ ' + response.data.message) | |
| 386 | - .css('background', '#f8d7da') | |
| 387 | - .css('color', '#721c24') | |
| 388 | - .css('border', '1px solid #f5c6cb'); | |
| 389 | - } | |
| 390 | - }, | |
| 391 | - error: function() { | |
| 392 | - $link.css('pointer-events', 'auto').css('opacity', '1'); | |
| 393 | - $message.addClass('error').html('❌ An error occurred. Please try again.') | |
| 394 | - .css('background', '#f8d7da') | |
| 395 | - .css('color', '#721c24') | |
| 396 | - .css('border', '1px solid #f5c6cb'); | |
| 397 | - } | |
| 398 | - }); | |
| 399 | - }); | |
| 400 | - <?php endif; ?> | |
| 401 | - }); | |
| 402 | - </script> | |
| 403 | 353 | <?php |
| 404 | 354 | return; |
| 405 | 355 | } elseif (!$password_protection_enabled) { |
| 406 | 356 | ?> |
| @@ -414,8 +364,9 @@ | ||
| 414 | 364 | } |
| 415 | 365 | ?> |
| 416 | 366 | |
| 417 | 367 | <form method="post" action="options.php?tab=<?php echo esc_attr( $active_tab ); ?>" id="metaSyncGeneralSetting"> |
| 368 | + <input type="hidden" name="metasync_pw_reset_generation" value="<?php echo esc_attr((string) (int) get_option('metasync_pw_reset_generation', 0)); ?>" /> | |
| 418 | 369 | <?php |
| 419 | 370 | settings_fields(Metasync_Admin::option_group); |
| 420 | 371 | |
| 421 | 372 | wp_nonce_field('meta_sync_general_setting_nonce', 'meta_sync_nonce'); |
| @@ -443,8 +394,11 @@ | ||
| 443 | 394 | |
| 444 | 395 | <?php |
| 445 | 396 | $this->admin->render_accordion_sections(Metasync_Admin::$page_slug . '_general'); |
| 446 | 397 | ?> |
| 398 | + <p style="margin: 20px 0 0 0; font-size: 13px; color: var(--dashboard-text-secondary);"> | |
| 399 | + Breadcrumb settings now live on their own page: <a href="<?php echo esc_url(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-breadcrumbs')); ?>">Breadcrumbs</a>. | |
| 400 | + </p> | |
| 447 | 401 | </div> |
| 448 | 402 | |
| 449 | 403 | <div class="dashboard-card"> |
| 450 | 404 | <h2>Content Genius Synchronization<?php Metasync::render_tooltip_icon('cg_sync_section', sprintf('Syncing sends this site\'s categories and authors to %s, so Content Genius can assign the right category and author when publishing articles to this site.', Metasync::get_effective_plugin_name())); ?></h2> |
| @@ -954,10 +908,10 @@ | ||
| 954 | 908 | </div> |
| 955 | 909 | <?php endif; ?> |
| 956 | 910 | |
| 957 | 911 | <?php |
| 958 | - if (isset($_GET['debug_mode_enabled']) && $_GET['debug_mode_enabled'] == '1'): | |
| 959 | - $indefinite = isset($_GET['indefinite']) && $_GET['indefinite'] == '1'; | |
| 912 | + if (isset($_GET['debug_mode_enabled']) && $_GET['debug_mode_enabled'] == '1'): // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only result flag for a static notice | |
| 913 | + $indefinite = isset($_GET['indefinite']) && $_GET['indefinite'] == '1'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only result flag for a static notice | |
| 960 | 914 | ?> |
| 961 | 915 | <div class="notice notice-success inline" style="margin-bottom: 20px;"> |
| 962 | 916 | <p> |
| 963 | 917 | <strong>✅ Success!</strong> Debug mode has been enabled<?php echo $indefinite ? ' indefinitely' : ' for 24 hours'; ?>. |
| @@ -964,9 +918,9 @@ | ||
| 964 | 918 | </p> |
| 965 | 919 | </div> |
| 966 | 920 | <?php endif; ?> |
| 967 | 921 | |
| 968 | - <?php if (isset($_GET['debug_mode_disabled']) && $_GET['debug_mode_disabled'] == '1'): ?> | |
| 922 | + <?php if (isset($_GET['debug_mode_disabled']) && $_GET['debug_mode_disabled'] == '1'): // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only result flag for a static notice ?> | |
| 969 | 923 | <div class="notice notice-info inline" style="margin-bottom: 20px;"> |
| 970 | 924 | <p> |
| 971 | 925 | <strong>ℹ️ Debug Mode Disabled:</strong> Debug mode has been successfully disabled. |
| 972 | 926 | </p> |
| @@ -972,9 +926,9 @@ | ||
| 972 | 926 | </p> |
| 973 | 927 | </div> |
| 974 | 928 | <?php endif; ?> |
| 975 | 929 | |
| 976 | - <?php if (isset($_GET['debug_mode_extended']) && $_GET['debug_mode_extended'] == '1'): ?> | |
| 930 | + <?php if (isset($_GET['debug_mode_extended']) && $_GET['debug_mode_extended'] == '1'): // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only result flag for a static notice ?> | |
| 977 | 931 | <div class="notice notice-success inline" style="margin-bottom: 20px;"> |
| 978 | 932 | <p> |
| 979 | 933 | <strong>✅ Extended!</strong> Debug mode has been extended for another 24 hours. |
| 980 | 934 | </p> |
| @@ -980,9 +934,9 @@ | ||
| 980 | 934 | </p> |
| 981 | 935 | </div> |
| 982 | 936 | <?php endif; ?> |
| 983 | 937 | |
| 984 | - <?php if (isset($_GET['debug_error']) && $_GET['debug_error'] == '1'): ?> | |
| 938 | + <?php if (isset($_GET['debug_error']) && $_GET['debug_error'] == '1'): // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only result flag for a static notice ?> | |
| 985 | 939 | <div class="notice notice-error inline" style="margin-bottom: 20px;"> |
| 986 | 940 | <p> |
| 987 | 941 | <strong>❌ Error:</strong> Unable to perform the debug mode operation. Please try again. |
| 988 | 942 | </p> |
| @@ -1163,22 +1117,22 @@ | ||
| 1163 | 1117 | var blockedClass = result.blocked ? 'blocked' : 'allowed'; |
| 1164 | 1118 | |
| 1165 | 1119 | html += '<div class="test-result-item ' + statusClass + '">'; |
| 1166 | 1120 | html += '<div class="test-result-header">'; |
| 1167 | - html += '<h4>' + statusIcon + ' ' + result.method + ' Request - ' + blockedStatus + '</h4>'; | |
| 1121 | + html += '<h4>' + statusIcon + ' ' + escapeHtml(result.method) + ' Request - ' + blockedStatus + '</h4>'; | |
| 1168 | 1122 | html += '<span class="test-status ' + blockedClass + '">' + blockedStatus + '</span>'; |
| 1169 | 1123 | html += '</div>'; |
| 1170 | 1124 | |
| 1171 | 1125 | html += '<div class="test-result-details">'; |
| 1172 | - html += '<p><strong>Response Time:</strong> ' + result.response_time + '</p>'; | |
| 1173 | - html += '<p><strong>Status:</strong> ' + result.status + '</p>'; | |
| 1126 | + html += '<p><strong>Response Time:</strong> ' + escapeHtml(result.response_time) + '</p>'; | |
| 1127 | + html += '<p><strong>Status:</strong> ' + escapeHtml(result.status) + '</p>'; | |
| 1174 | 1128 | |
| 1175 | 1129 | if (result.status_code) { |
| 1176 | - html += '<p><strong>HTTP Status Code:</strong> <span class="status-code">' + result.status_code + '</span></p>'; | |
| 1130 | + html += '<p><strong>HTTP Status Code:</strong> <span class="status-code">' + escapeHtml(result.status_code) + '</span></p>'; | |
| 1177 | 1131 | } |
| 1178 | 1132 | |
| 1179 | 1133 | if (result.error) { |
| 1180 | - html += '<p><strong>Error:</strong> <span class="error-message">' + result.error + '</span></p>'; | |
| 1134 | + html += '<p><strong>Error:</strong> <span class="error-message">' + escapeHtml(result.error) + '</span></p>'; | |
| 1181 | 1135 | } |
| 1182 | 1136 | |
| 1183 | 1137 | if (result.body) { |
| 1184 | 1138 | html += '<p><strong>Response Body:</strong></p>'; |
| @@ -1188,9 +1142,9 @@ | ||
| 1188 | 1142 | if (result.headers && Object.keys(result.headers).length > 0) { |
| 1189 | 1143 | html += '<p><strong>Response Headers:</strong></p>'; |
| 1190 | 1144 | html += '<pre class="response-headers">'; |
| 1191 | 1145 | Object.keys(result.headers).forEach(function(key) { |
| 1192 | - html += key + ': ' + result.headers[key] + '\n'; | |
| 1146 | + html += escapeHtml(key) + ': ' + escapeHtml(result.headers[key]) + '\n'; | |
| 1193 | 1147 | }); |
| 1194 | 1148 | html += '</pre>'; |
| 1195 | 1149 | } |
| 1196 | 1150 | |
| @@ -1203,9 +1157,9 @@ | ||
| 1203 | 1157 | html += '<p><strong>Parsed Response:</strong></p>'; |
| 1204 | 1158 | html += '<pre class="parsed-response">' + escapeHtml(JSON.stringify(result.parsed_response, null, 2)) + '</pre>'; |
| 1205 | 1159 | } |
| 1206 | 1160 | |
| 1207 | - html += '<p><strong>Details:</strong> ' + result.details + '</p>'; | |
| 1161 | + html += '<p><strong>Details:</strong> ' + escapeHtml(result.details) + '</p>'; | |
| 1208 | 1162 | html += '</div>'; |
| 1209 | 1163 | html += '</div>'; |
| 1210 | 1164 | }); |
| 1211 | 1165 | |
| @@ -1220,9 +1174,9 @@ | ||
| 1220 | 1174 | '>': '>', |
| 1221 | 1175 | '"': '"', |
| 1222 | 1176 | '\'': ''' |
| 1223 | 1177 | }; |
| 1224 | - return text.replace(/[&<>"']/g, function(m) { return map[m]; }); | |
| 1178 | + return String(text).replace(/[&<>"']/g, function(m) { return map[m]; }); | |
| 1225 | 1179 | } |
| 1226 | 1180 | }); |
| 1227 | 1181 | </script> |
| 1228 | 1182 | |
| @@ -1355,41 +1309,41 @@ | ||
| 1355 | 1309 | } |
| 1356 | 1310 | </style> |
| 1357 | 1311 | |
| 1358 | 1312 | <?php if ($active_tab === 'advanced'): ?> |
| 1359 | - <?php if (isset($_GET['settings_cleared']) && $_GET['settings_cleared'] == '1'): ?> | |
| 1313 | + <?php if (isset($_GET['settings_cleared']) && $_GET['settings_cleared'] == '1'): // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only result flag for a static notice ?> | |
| 1360 | 1314 | <div class="notice notice-success is-dismissible"> |
| 1361 | 1315 | <p><strong>✅ Success!</strong> All plugin settings have been cleared successfully and a new Plugin Auth Token has been generated. Please reconfigure the plugin as needed.</p> |
| 1362 | 1316 | </div> |
| 1363 | 1317 | <?php endif; ?> |
| 1364 | 1318 | |
| 1365 | - <?php if (isset($_GET['clear_settings_error']) && $_GET['clear_settings_error'] == '1'): ?> | |
| 1319 | + <?php if (isset($_GET['clear_settings_error']) && $_GET['clear_settings_error'] == '1'): // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only result flag for a static notice ?> | |
| 1366 | 1320 | <div class="notice notice-error is-dismissible"> |
| 1367 | 1321 | <p><strong>❌ Error!</strong> Failed to clear settings due to a security check failure. Please try again.</p> |
| 1368 | 1322 | </div> |
| 1369 | 1323 | <?php endif; ?> |
| 1370 | 1324 | |
| 1371 | - <?php if (isset($_GET['log_cleared']) && $_GET['log_cleared'] == '1'): ?> | |
| 1325 | + <?php if (isset($_GET['log_cleared']) && $_GET['log_cleared'] == '1'): // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only result flag for a static notice ?> | |
| 1372 | 1326 | <div class="notice notice-success is-dismissible"> |
| 1373 | 1327 | <p><strong>✅ Success!</strong> Error logs have been cleared successfully.</p> |
| 1374 | 1328 | </div> |
| 1375 | 1329 | <?php endif; ?> |
| 1376 | 1330 | |
| 1377 | - <?php if (isset($_GET['clear_error']) && $_GET['clear_error'] == '1'): ?> | |
| 1331 | + <?php if (isset($_GET['clear_error']) && $_GET['clear_error'] == '1'): // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only result flag for a static notice ?> | |
| 1378 | 1332 | <div class="notice notice-error is-dismissible"> |
| 1379 | 1333 | <p><strong>❌ Error!</strong> Failed to clear error logs due to a security check failure. Please try again.</p> |
| 1380 | 1334 | </div> |
| 1381 | 1335 | <?php endif; ?> |
| 1382 | 1336 | |
| 1383 | - <?php if (isset($_GET['access_roles_saved']) && $_GET['access_roles_saved'] == '1'): ?> | |
| 1337 | + <?php if (isset($_GET['access_roles_saved']) && $_GET['access_roles_saved'] == '1'): // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only result flag for a static notice ?> | |
| 1384 | 1338 | <div class="notice notice-success is-dismissible"> |
| 1385 | 1339 | <p><strong>✅ Success!</strong> Plugin access roles have been saved successfully.</p> |
| 1386 | 1340 | </div> |
| 1387 | 1341 | <?php endif; ?> |
| 1388 | 1342 | |
| 1389 | - <?php if (isset($_GET['access_roles_error']) && $_GET['access_roles_error'] == '1'): ?> | |
| 1343 | + <?php if (isset($_GET['access_roles_error']) && $_GET['access_roles_error'] == '1'): // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only result flag for a static notice ?> | |
| 1390 | 1344 | <div class="notice notice-error is-dismissible"> |
| 1391 | - <p><strong>❌ Error!</strong> Failed to save plugin access roles. <?php echo isset($_GET['message']) ? esc_html(urldecode($_GET['message'])) : 'Please try again.'; ?></p> | |
| 1345 | + <p><strong>❌ Error!</strong> Failed to save plugin access roles. <?php echo isset($_GET['message']) ? esc_html(urldecode($_GET['message'])) : 'Please try again.'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only error text, escaped on output ?></p> | |
| 1392 | 1346 | </div> |
| 1393 | 1347 | <?php endif; ?> |
| 1394 | 1348 | |
| 1395 | 1349 | <?php endif; ?> |
| @@ -1423,8 +1377,15 @@ | ||
| 1423 | 1377 | } |
| 1424 | 1378 | |
| 1425 | 1379 | public function create_admin_robots_txt_page() |
| 1426 | 1380 | { |
| 1381 | + // The form below rewrites the site's physical robots.txt — restrict | |
| 1382 | + // that to site admins, not just anyone who can open the page via | |
| 1383 | + // plugin_access_roles. The nonce is CSRF protection, not authorization. | |
| 1384 | + if (!empty($_POST) && !current_user_can('manage_options')) { | |
| 1385 | + wp_die(esc_html__('Sorry, you are not allowed to manage robots.txt settings.', 'metasync')); | |
| 1386 | + } | |
| 1387 | + | |
| 1427 | 1388 | ?> |
| 1428 | 1389 | <?php $this->admin->render_layout_open('Robots.txt', 'robots_txt', 'Control which pages search engines can crawl.'); ?> |
| 1429 | 1390 | |
| 1430 | 1391 | <?php |
| @@ -1487,84 +1448,8 @@ | ||
| 1487 | 1448 | { |
| 1488 | 1449 | require_once plugin_dir_path(dirname(__FILE__)) . 'views/metasync-report-issue.php'; |
| 1489 | 1450 | } |
| 1490 | 1451 | |
| 1491 | - public function create_admin_xml_sitemap_page() | |
| 1492 | - { | |
| 1493 | - require_once plugin_dir_path(dirname(__FILE__)) . 'sitemap/class-metasync-sitemap-generator.php'; | |
| 1494 | - | |
| 1495 | - $sitemap_generator = new Metasync_Sitemap_Generator(); | |
| 1496 | - | |
| 1497 | - if (isset($_POST['metasync_sitemap_nonce'])) { | |
| 1498 | - check_admin_referer('metasync_sitemap_action', 'metasync_sitemap_nonce'); | |
| 1499 | - | |
| 1500 | - if (isset($_POST['generate_sitemap'])) { | |
| 1501 | - $disabled_plugins = $sitemap_generator->disable_other_sitemap_generators(); | |
| 1502 | - | |
| 1503 | - $result = $sitemap_generator->generate_sitemap(); | |
| 1504 | - | |
| 1505 | - if (is_wp_error($result)) { | |
| 1506 | - error_log('[MetaSync] Sitemap generation failed: ' . $result->get_error_message()); | |
| 1507 | - echo '<div class="notice notice-error"><p>' . esc_html__('Sitemap generation failed. Please try again or check the error logs.', 'metasync') . '</p></div>'; | |
| 1508 | - } elseif (false === $result) { | |
| 1509 | - echo '<div class="notice notice-error"><p>' . esc_html__('Sitemap generation failed: the sitemap data could not be stored, so no sitemap is being served. Check your object cache and database write settings, then try again.', 'metasync') . '</p></div>'; | |
| 1510 | - } else { | |
| 1511 | - $message = esc_html__('Sitemap generated successfully!', 'metasync'); | |
| 1512 | - if ($disabled_plugins) { | |
| 1513 | - $message .= ' ' . esc_html__('Conflicting sitemap generators have been automatically disabled.', 'metasync'); | |
| 1514 | - } | |
| 1515 | - | |
| 1516 | - $robots_result = get_transient('metasync_sitemap_robots_updated'); | |
| 1517 | - if ($robots_result && $robots_result['success']) { | |
| 1518 | - if ($robots_result['action'] === 'added') { | |
| 1519 | - $message .= ' ' . esc_html__('Sitemap URL has been added to robots.txt.', 'metasync'); | |
| 1520 | - } elseif ($robots_result['action'] === 'updated') { | |
| 1521 | - $message .= ' ' . esc_html__('Sitemap URL has been updated in robots.txt.', 'metasync'); | |
| 1522 | - } elseif ($robots_result['action'] === 'created') { | |
| 1523 | - $message .= ' ' . esc_html__('robots.txt file has been created with sitemap URL.', 'metasync'); | |
| 1524 | - } | |
| 1525 | - delete_transient('metasync_sitemap_robots_updated'); | |
| 1526 | - } | |
| 1527 | - | |
| 1528 | - echo '<div class="notice notice-success"><p>' . esc_html($message) . '</p></div>'; | |
| 1529 | - } | |
| 1530 | - } elseif (isset($_POST['enable_auto_update'])) { | |
| 1531 | - update_option('metasync_sitemap_auto_update', true); | |
| 1532 | - $sitemap_generator->setup_auto_update_hooks(); | |
| 1533 | - echo '<div class="notice notice-success"><p>' . esc_html__('Auto-update enabled!', 'metasync') . '</p></div>'; | |
| 1534 | - } elseif (isset($_POST['disable_auto_update'])) { | |
| 1535 | - update_option('metasync_sitemap_auto_update', false); | |
| 1536 | - echo '<div class="notice notice-success"><p>' . esc_html__('Auto-update disabled!', 'metasync') . '</p></div>'; | |
| 1537 | - } elseif (isset($_POST['delete_sitemap'])) { | |
| 1538 | - $deleted = $sitemap_generator->delete_sitemap(); | |
| 1539 | - if ($deleted) { | |
| 1540 | - update_option('metasync_sitemap_auto_update', false); | |
| 1541 | - // Re-enable WP core sitemap so the site isn't left with zero sitemaps | |
| 1542 | - delete_option('metasync_disable_wp_sitemap'); | |
| 1543 | - echo '<div class="notice notice-success"><p>' . esc_html__('Sitemap deleted successfully!', 'metasync') . '</p></div>'; | |
| 1544 | - } else { | |
| 1545 | - echo '<div class="notice notice-error"><p>' . esc_html__('Failed to delete sitemap. The file may not exist or is not writable.', 'metasync') . '</p></div>'; | |
| 1546 | - } | |
| 1547 | - } elseif (isset($_POST['enable_other_sitemaps'])) { | |
| 1548 | - $enabled_plugins = $sitemap_generator->enable_other_sitemap_generators(); | |
| 1549 | - if ($enabled_plugins) { | |
| 1550 | - echo '<div class="notice notice-success"><p>' . esc_html__('Other sitemap plugins have been re-enabled successfully!', 'metasync') . '</p></div>'; | |
| 1551 | - } else { | |
| 1552 | - echo '<div class="notice notice-info"><p>' . esc_html__('No sitemap plugins were found to re-enable.', 'metasync') . '</p></div>'; | |
| 1553 | - } | |
| 1554 | - } | |
| 1555 | - } | |
| 1556 | - | |
| 1557 | - $sitemap_exists = $sitemap_generator->sitemap_exists(); | |
| 1558 | - $sitemap_url = $sitemap_generator->get_sitemap_url(); | |
| 1559 | - $url_count = $sitemap_generator->count_urls(); | |
| 1560 | - $last_generated = $sitemap_generator->get_last_generated_time(); | |
| 1561 | - $auto_update_enabled = get_option('metasync_sitemap_auto_update', false); | |
| 1562 | - $active_sitemap_plugins = $sitemap_generator->check_active_sitemap_plugins(); | |
| 1563 | - | |
| 1564 | - require_once plugin_dir_path(dirname(__FILE__)) . 'views/metasync-xml-sitemap.php'; | |
| 1565 | - } | |
| 1566 | - | |
| 1567 | 1452 | public function create_admin_custom_pages_page() |
| 1568 | 1453 | { |
| 1569 | 1454 | ?> |
| 1570 | 1455 | <?php $this->admin->render_layout_open('Custom Pages', 'custom_pages', 'Create blank canvas pages for Elementor, Divi, or Gutenberg.'); ?> |
| @@ -1615,12 +1500,14 @@ | ||
| 1615 | 1500 | } |
| 1616 | 1501 | |
| 1617 | 1502 | public function create_admin_breadcrumbs_page() |
| 1618 | 1503 | { |
| 1619 | - $page_slug = Metasync_Admin::$page_slug . '_breadcrumbs'; | |
| 1620 | 1504 | ?> |
| 1621 | 1505 | <?php $this->admin->render_layout_open('Breadcrumbs', 'breadcrumbs', 'Configure breadcrumb trail settings and placement.'); ?> |
| 1622 | 1506 | |
| 1507 | + <?php /* options.php redirects back here with ?settings-updated=true; without this call the save confirmation never prints */ ?> | |
| 1508 | + <?php settings_errors(); ?> | |
| 1509 | + | |
| 1623 | 1510 | <form method="post" action="options.php"> |
| 1624 | 1511 | <div class="dashboard-card"> |
| 1625 | 1512 | <h2>Breadcrumbs Settings</h2> |
| 1626 | 1513 | <p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;">Configure how breadcrumb trails are displayed across your site.</p> |
| @@ -1625,9 +1512,9 @@ | ||
| 1625 | 1512 | <h2>Breadcrumbs Settings</h2> |
| 1626 | 1513 | <p style="color: var(--dashboard-text-secondary); margin-bottom: 20px;">Configure how breadcrumb trails are displayed across your site.</p> |
| 1627 | 1514 | <?php |
| 1628 | 1515 | settings_fields(Metasync_Admin::option_group); |
| 1629 | - do_settings_sections($page_slug); | |
| 1516 | + Metasync_Settings_Fields::instance()->render_breadcrumbs_section(); | |
| 1630 | 1517 | submit_button(); |
| 1631 | 1518 | ?> |
| 1632 | 1519 | </div> |
| 1633 | 1520 | </form> |
| @@ -1747,14 +1634,8 @@ | ||
| 1747 | 1634 | </div> |
| 1748 | 1635 | </form> |
| 1749 | 1636 | <?php $this->admin->render_layout_close(); ?> |
| 1750 | 1637 | <?php |
| 1751 | - } | |
| 1752 | - | |
| 1753 | - public function create_admin_google_instant_index_page() | |
| 1754 | - { | |
| 1755 | - // Delegates to the admin class which uses the shared credentials view | |
| 1756 | - $this->admin->create_admin_google_instant_index_page(); | |
| 1757 | 1638 | } |
| 1758 | 1639 | |
| 1759 | 1640 | public function create_admin_google_console_page() |
| 1760 | 1641 | { |