| @@ -49,12 +49,43 @@ | ||
| 49 | 49 | } |
| 50 | 50 | |
| 51 | 51 | |
| 52 | 52 | /** |
| 53 | - * Add debug menu (developer only - hidden by default) | |
| 53 | + * Whether debug tooling is allowed to run at all right now. | |
| 54 | + * | |
| 55 | + * `manage_options` alone isn't a real restriction — every site admin has | |
| 56 | + * it, so this page and its AJAX handlers were reachable by anyone on any | |
| 57 | + * site. Hard-disabled: the menu item, the page, and every AJAX handler | |
| 58 | + * are unreachable for all users on all sites, no toggle or capability | |
| 59 | + * bypasses this. The class and its methods are left in place; only | |
| 60 | + * access is blocked. | |
| 54 | 61 | */ |
| 62 | + private static function is_debug_tools_enabled() { | |
| 63 | + return false; | |
| 64 | + } | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * Whether a URL's crawl pipeline has completed, per the bounded | |
| 68 | + * Metasync_Otto_Job_Status store. Replaces the legacy unbounded | |
| 69 | + * metasync_otto_crawldata option lookup: state history is pruned | |
| 70 | + * 48 hours after completion, so a URL finished longer ago reads as | |
| 71 | + * "not crawled" here without implying Otto never touched it. | |
| 72 | + */ | |
| 73 | + private static function is_url_crawled($url) { | |
| 74 | + if (!class_exists('Metasync_Otto_Job_Status')) { | |
| 75 | + return false; | |
| 76 | + } | |
| 77 | + $entry = Metasync_Otto_Job_Status::get($url); | |
| 78 | + return is_array($entry) | |
| 79 | + && isset($entry['state']) | |
| 80 | + && $entry['state'] === Metasync_Otto_Job_Status::STATE_COMPLETED; | |
| 81 | + } | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * Add debug menu (internal only - hidden on customer production sites) | |
| 85 | + */ | |
| 55 | 86 | public function add_debug_menu() { |
| 56 | - if (!current_user_can('manage_options')) { | |
| 87 | + if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) { | |
| 57 | 88 | return; |
| 58 | 89 | } |
| 59 | 90 | |
| 60 | 91 | $menu_slug = Metasync_Admin::$page_slug; |
| @@ -72,9 +103,9 @@ | ||
| 72 | 103 | /** |
| 73 | 104 | * Create the debug page |
| 74 | 105 | */ |
| 75 | 106 | public function create_debug_page() { |
| 76 | - if (!current_user_can('manage_options')) { | |
| 107 | + if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) { | |
| 77 | 108 | wp_die('Unauthorized'); |
| 78 | 109 | } |
| 79 | 110 | |
| 80 | 111 | $whitelabel_otto_name = Metasync::get_whitelabel_otto_name(); |
| @@ -88,9 +119,8 @@ | ||
| 88 | 119 | <?php $this->render_url_testing_section(); ?> |
| 89 | 120 | <?php $this->render_configuration_status(); ?> |
| 90 | 121 | <?php $this->render_notification_endpoint_status(); ?> |
| 91 | 122 | <?php $this->render_api_connectivity_status(); ?> |
| 92 | - <?php $this->render_crawl_data_status(); ?> | |
| 93 | 123 | <?php $this->render_processing_status(); ?> |
| 94 | 124 | <?php $this->render_debug_tools(); ?> |
| 95 | 125 | </div> |
| 96 | 126 | </div> |
| @@ -228,14 +258,14 @@ | ||
| 228 | 258 | </div> |
| 229 | 259 | |
| 230 | 260 | <div class="debug-item info"> |
| 231 | 261 | <strong>Current User:</strong> |
| 232 | - <span class="debug-value"><?php echo esc_html($current_user->user_login); ?> (ID: <?php echo $current_user->ID; ?>)</span> | |
| 262 | + <span class="debug-value"><?php echo esc_html($current_user->user_login); ?> (ID: <?php echo (int) $current_user->ID; ?>)</span> | |
| 233 | 263 | </div> |
| 234 | 264 | |
| 235 | 265 | <div class="debug-item info"> |
| 236 | 266 | <strong>User Roles:</strong> |
| 237 | - <span class="debug-value"><?php echo implode(', ', $current_user->roles); ?></span> | |
| 267 | + <span class="debug-value"><?php echo esc_html(implode(', ', $current_user->roles)); ?></span> | |
| 238 | 268 | </div> |
| 239 | 269 | |
| 240 | 270 | <div class="debug-item success"> |
| 241 | 271 | <strong>Debug Access Active</strong> |
| @@ -331,9 +361,9 @@ | ||
| 331 | 361 | </div> |
| 332 | 362 | |
| 333 | 363 | <div class="debug-item info"> |
| 334 | 364 | <strong>Plugin Version:</strong> |
| 335 | - <span class="debug-value"><?php echo defined('METASYNC_VERSION') ? METASYNC_VERSION : 'Unknown'; ?></span> | |
| 365 | + <span class="debug-value"><?php echo esc_html(defined('METASYNC_VERSION') ? METASYNC_VERSION : 'Unknown'); ?></span> | |
| 336 | 366 | </div> |
| 337 | 367 | </div> |
| 338 | 368 | <?php |
| 339 | 369 | } |
| @@ -435,64 +465,13 @@ | ||
| 435 | 465 | <?php |
| 436 | 466 | } |
| 437 | 467 | |
| 438 | 468 | /** |
| 439 | - * Render crawl data status | |
| 440 | - */ | |
| 441 | - private function render_crawl_data_status() { | |
| 442 | - $crawl_data = get_option('metasync_otto_crawldata'); | |
| 443 | - | |
| 444 | - ?> | |
| 445 | - <div class="debug-section"> | |
| 446 | - <h3><span class="status-indicator <?php echo !empty($crawl_data) ? 'status-success' : 'status-warning'; ?>"></span>Crawl Data Status</h3> | |
| 447 | - | |
| 448 | - <div class="debug-item <?php echo !empty($crawl_data) ? 'success' : 'warning'; ?>"> | |
| 449 | - <strong>Crawl Data Available:</strong> | |
| 450 | - <span class="debug-value"><?php echo !empty($crawl_data) ? 'Yes' : 'No'; ?></span> | |
| 451 | - </div> | |
| 452 | - | |
| 453 | - <?php if (!empty($crawl_data)): ?> | |
| 454 | - <div class="debug-item info"> | |
| 455 | - <strong>Domain:</strong> | |
| 456 | - <span class="debug-value"><?php echo esc_html($crawl_data['domain'] ?? 'Not Set'); ?></span> | |
| 457 | - </div> | |
| 458 | - | |
| 459 | - <div class="debug-item info"> | |
| 460 | - <strong>Total URLs Crawled:</strong> | |
| 461 | - <span class="debug-value"><?php echo count($crawl_data['urls'] ?? []); ?></span> | |
| 462 | - </div> | |
| 463 | - | |
| 464 | - <div class="debug-item info"> | |
| 465 | - <strong>Last Updated:</strong> | |
| 466 | - <span class="debug-value"><?php echo $this->get_option_last_updated('metasync_otto_crawldata'); ?></span> | |
| 467 | - </div> | |
| 468 | - | |
| 469 | - <div class="debug-item info"> | |
| 470 | - <strong>Sample URLs:</strong> | |
| 471 | - <div class="debug-value"> | |
| 472 | - <?php | |
| 473 | - $sample_urls = array_slice($crawl_data['urls'] ?? [], 0, 5); | |
| 474 | - foreach ($sample_urls as $url) { | |
| 475 | - echo esc_html($url) . '<br>'; | |
| 476 | - } | |
| 477 | - if (count($crawl_data['urls'] ?? []) > 5) { | |
| 478 | - echo '... and ' . (count($crawl_data['urls']) - 5) . ' more'; | |
| 479 | - } | |
| 480 | - ?> | |
| 481 | - </div> | |
| 482 | - </div> | |
| 483 | - <?php endif; ?> | |
| 484 | - </div> | |
| 485 | - <?php | |
| 486 | - } | |
| 487 | - | |
| 488 | - /** | |
| 489 | 469 | * Render processing status |
| 490 | 470 | */ |
| 491 | 471 | private function render_processing_status() { |
| 492 | 472 | $current_url = $this->get_current_url(); |
| 493 | - $otto_pixel = new Metasync_otto_pixel(Metasync::get_option('general')['otto_pixel_uuid'] ?? ''); | |
| 494 | - $is_crawled = $otto_pixel->is_url_crawled($current_url); | |
| 473 | + $is_crawled = self::is_url_crawled($current_url); | |
| 495 | 474 | $render_diagnostics = $this->get_render_strategy_diagnostics(); |
| 496 | 475 | |
| 497 | 476 | ?> |
| 498 | 477 | <div class="debug-section"> |
| @@ -514,19 +493,19 @@ | ||
| 514 | 493 | </div> |
| 515 | 494 | |
| 516 | 495 | <div class="debug-item info"> |
| 517 | 496 | <strong>Page Type:</strong> |
| 518 | - <span class="debug-value"><?php echo $this->get_page_type(); ?></span> | |
| 497 | + <span class="debug-value"><?php echo esc_html($this->get_page_type()); ?></span> | |
| 519 | 498 | </div> |
| 520 | 499 | |
| 521 | 500 | <div class="debug-item info"> |
| 522 | 501 | <strong>Cache Status:</strong> |
| 523 | - <span class="debug-value"><?php echo $this->get_cache_status(); ?></span> | |
| 502 | + <span class="debug-value"><?php echo esc_html($this->get_cache_status()); ?></span> | |
| 524 | 503 | </div> |
| 525 | 504 | |
| 526 | 505 | <div class="debug-item info"> |
| 527 | 506 | <strong>Processing Method:</strong> |
| 528 | - <span class="debug-value"><?php echo $this->get_processing_method(); ?></span> | |
| 507 | + <span class="debug-value"><?php echo esc_html($this->get_processing_method()); ?></span> | |
| 529 | 508 | </div> |
| 530 | 509 | |
| 531 | 510 | <?php if (!empty($render_diagnostics) && isset($render_diagnostics['available']) === false): ?> |
| 532 | 511 | <div class="debug-item info"> |
| @@ -638,29 +617,8 @@ | ||
| 638 | 617 | return !is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200; |
| 639 | 618 | } |
| 640 | 619 | |
| 641 | 620 | /** |
| 642 | - * Get option last updated time | |
| 643 | - */ | |
| 644 | - private function get_option_last_updated($option_name) { | |
| 645 | - global $wpdb; | |
| 646 | - | |
| 647 | - $result = $wpdb->get_var($wpdb->prepare( | |
| 648 | - "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s", | |
| 649 | - $option_name | |
| 650 | - )); | |
| 651 | - | |
| 652 | - if ($result) { | |
| 653 | - $data = maybe_unserialize($result); | |
| 654 | - if (isset($data['last_updated'])) { | |
| 655 | - return date('Y-m-d H:i:s', $data['last_updated']); | |
| 656 | - } | |
| 657 | - } | |
| 658 | - | |
| 659 | - return 'Unknown'; | |
| 660 | - } | |
| 661 | - | |
| 662 | - /** | |
| 663 | 621 | * Get current URL |
| 664 | 622 | */ |
| 665 | 623 | private function get_current_url() { |
| 666 | 624 | $scheme = is_ssl() ? 'https' : 'http'; |
| @@ -760,9 +718,9 @@ | ||
| 760 | 718 | */ |
| 761 | 719 | public function ajax_test_otto_api() { |
| 762 | 720 | check_ajax_referer('metasync_otto_debug', 'nonce'); |
| 763 | 721 | |
| 764 | - if (!current_user_can('manage_options')) { | |
| 722 | + if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) { | |
| 765 | 723 | wp_die('Unauthorized'); |
| 766 | 724 | } |
| 767 | 725 | |
| 768 | 726 | $general_options = Metasync::get_option('general'); |
| @@ -816,9 +774,9 @@ | ||
| 816 | 774 | */ |
| 817 | 775 | public function ajax_test_notification_endpoint() { |
| 818 | 776 | check_ajax_referer('metasync_otto_debug', 'nonce'); |
| 819 | 777 | |
| 820 | - if (!current_user_can('manage_options')) { | |
| 778 | + if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) { | |
| 821 | 779 | wp_die('Unauthorized'); |
| 822 | 780 | } |
| 823 | 781 | |
| 824 | 782 | $endpoint_url = rest_url('metasync/v1/otto_crawl_notify'); |
| @@ -858,20 +816,23 @@ | ||
| 858 | 816 | * AJAX handler for clearing OTTO cache |
| 859 | 817 | */ |
| 860 | 818 | public function ajax_clear_otto_cache() { |
| 861 | 819 | check_ajax_referer('metasync_otto_debug', 'nonce'); |
| 862 | - | |
| 863 | - if (!current_user_can('manage_options')) { | |
| 820 | + | |
| 821 | + if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) { | |
| 864 | 822 | wp_die('Unauthorized'); |
| 865 | 823 | } |
| 866 | - | |
| 867 | - // Clear crawl data | |
| 824 | + | |
| 825 | + // Clear the retired crawl-data option if an internal debug tool is | |
| 826 | + // ever re-enabled. This explicit action is harmless and preserves | |
| 827 | + // the old clear-cache contract; production never reaches this | |
| 828 | + // handler because debug tools are hard-disabled. | |
| 868 | 829 | delete_option('metasync_otto_crawldata'); |
| 869 | - | |
| 830 | + | |
| 870 | 831 | // Clear any cached API responses |
| 871 | 832 | $general_options = Metasync::get_option('general'); |
| 872 | 833 | $otto_uuid = $general_options['otto_pixel_uuid'] ?? ''; |
| 873 | - | |
| 834 | + | |
| 874 | 835 | if (!empty($otto_uuid)) { |
| 875 | 836 | delete_transient(Metasync_Heartbeat_Manager::public_hash_cache_key($otto_uuid)); |
| 876 | 837 | } |
| 877 | 838 | |
| @@ -891,9 +852,9 @@ | ||
| 891 | 852 | */ |
| 892 | 853 | public function ajax_simulate_crawl_notification() { |
| 893 | 854 | check_ajax_referer('metasync_otto_debug', 'nonce'); |
| 894 | 855 | |
| 895 | - if (!current_user_can('manage_options')) { | |
| 856 | + if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) { | |
| 896 | 857 | wp_die('Unauthorized'); |
| 897 | 858 | } |
| 898 | 859 | |
| 899 | 860 | $general_options = Metasync::get_option('general'); |
| @@ -930,9 +891,9 @@ | ||
| 930 | 891 | public function ajax_test_specific_url() { |
| 931 | 892 | try { |
| 932 | 893 | check_ajax_referer('metasync_otto_debug', 'nonce'); |
| 933 | 894 | |
| 934 | - if (!current_user_can('manage_options')) { | |
| 895 | + if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) { | |
| 935 | 896 | wp_die('Unauthorized'); |
| 936 | 897 | } |
| 937 | 898 | |
| 938 | 899 | $test_url = sanitize_url($_POST['test_url'] ?? ''); |
| @@ -964,9 +925,9 @@ | ||
| 964 | 925 | |
| 965 | 926 | wp_send_json_success($results); |
| 966 | 927 | |
| 967 | 928 | } catch (Exception $e) { |
| 968 | - error_log('MetaSync OTTO Debug: Exception in ajax_test_specific_url: ' . $e->getMessage()); | |
| 929 | + error_log('MetaSync OTTO Debug: Exception in ajax_test_specific_url: ' . $e->getMessage()); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- unreachable in production | |
| 969 | 930 | wp_send_json_error('Exception: ' . $e->getMessage()); |
| 970 | 931 | } |
| 971 | 932 | } |
| 972 | 933 | |
| @@ -975,9 +936,9 @@ | ||
| 975 | 936 | */ |
| 976 | 937 | public function ajax_emulate_otto_changes() { |
| 977 | 938 | check_ajax_referer('metasync_otto_debug', 'nonce'); |
| 978 | 939 | |
| 979 | - if (!current_user_can('manage_options')) { | |
| 940 | + if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) { | |
| 980 | 941 | wp_die('Unauthorized'); |
| 981 | 942 | } |
| 982 | 943 | |
| 983 | 944 | $test_url = sanitize_url($_POST['test_url'] ?? ''); |
| @@ -1071,27 +1032,27 @@ | ||
| 1071 | 1032 | /** |
| 1072 | 1033 | * Test crawl status for URL |
| 1073 | 1034 | */ |
| 1074 | 1035 | private function test_crawl_status($url) { |
| 1075 | - if (class_exists('Metasync_otto_pixel')) { | |
| 1076 | - $otto_pixel = new Metasync_otto_pixel(false); | |
| 1077 | - $is_crawled = $otto_pixel->is_url_crawled($url); | |
| 1078 | - | |
| 1079 | - // Get crawl data from options | |
| 1080 | - $crawl_data = get_option('metasync_otto_crawldata'); | |
| 1081 | - | |
| 1036 | + if (class_exists('Metasync_Otto_Job_Status')) { | |
| 1037 | + $entry = Metasync_Otto_Job_Status::get($url); | |
| 1038 | + $is_crawled = is_array($entry) | |
| 1039 | + && isset($entry['state']) | |
| 1040 | + && $entry['state'] === Metasync_Otto_Job_Status::STATE_COMPLETED; | |
| 1041 | + | |
| 1082 | 1042 | return array( |
| 1083 | 1043 | 'status' => 'success', |
| 1084 | 1044 | 'is_crawled' => $is_crawled, |
| 1085 | - 'crawl_data' => $crawl_data, | |
| 1086 | - 'total_crawled_urls' => count($crawl_data['urls'] ?? array()), | |
| 1087 | - 'domain' => $crawl_data['domain'] ?? 'Not set' | |
| 1045 | + 'job_state' => is_array($entry) && isset($entry['state']) ? $entry['state'] : 'unknown', | |
| 1046 | + 'job_stage' => is_array($entry) && isset($entry['stage']) ? $entry['stage'] : '', | |
| 1047 | + 'job_attempts' => is_array($entry) && isset($entry['attempts']) ? (int) $entry['attempts'] : 0, | |
| 1048 | + 'job_updated' => is_array($entry) && isset($entry['updated']) ? $entry['updated'] : null | |
| 1088 | 1049 | ); |
| 1089 | 1050 | } |
| 1090 | - | |
| 1051 | + | |
| 1091 | 1052 | return array( |
| 1092 | 1053 | 'status' => 'error', |
| 1093 | - 'message' => Metasync::get_whitelabel_otto_name() . ' pixel class not available' | |
| 1054 | + 'message' => Metasync::get_whitelabel_otto_name() . ' job status class not available' | |
| 1094 | 1055 | ); |
| 1095 | 1056 | } |
| 1096 | 1057 | |
| 1097 | 1058 | /** |
| @@ -1097,9 +1058,9 @@ | ||
| 1097 | 1058 | /** |
| 1098 | 1059 | * Test page type detection |
| 1099 | 1060 | */ |
| 1100 | 1061 | private function test_page_type_detection($url) { |
| 1101 | - $parsed_url = parse_url($url); | |
| 1062 | + $parsed_url = wp_parse_url($url); | |
| 1102 | 1063 | $path = $parsed_url['path'] ?? '/'; |
| 1103 | 1064 | |
| 1104 | 1065 | $detection = array( |
| 1105 | 1066 | 'url' => $url, |
| @@ -1198,9 +1159,9 @@ | ||
| 1198 | 1159 | public function ajax_simple_test() { |
| 1199 | 1160 | try { |
| 1200 | 1161 | check_ajax_referer('metasync_otto_debug', 'nonce'); |
| 1201 | 1162 | |
| 1202 | - if (!current_user_can('manage_options')) { | |
| 1163 | + if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) { | |
| 1203 | 1164 | wp_send_json_error('Unauthorized'); |
| 1204 | 1165 | } |
| 1205 | 1166 | |
| 1206 | 1167 | wp_send_json_success(array( |
| @@ -1210,9 +1171,9 @@ | ||
| 1210 | 1171 | 'nonce_verified' => true |
| 1211 | 1172 | )); |
| 1212 | 1173 | |
| 1213 | 1174 | } catch (Exception $e) { |
| 1214 | - error_log('MetaSync OTTO Debug: Exception in ajax_simple_test: ' . $e->getMessage()); | |
| 1175 | + error_log('MetaSync OTTO Debug: Exception in ajax_simple_test: ' . $e->getMessage()); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- unreachable in production | |
| 1215 | 1176 | wp_send_json_error('Exception: ' . $e->getMessage()); |
| 1216 | 1177 | } |
| 1217 | 1178 | } |
| 1218 | 1179 | |
| @@ -1222,9 +1183,9 @@ | ||
| 1222 | 1183 | public function ajax_test_db_permissions() { |
| 1223 | 1184 | try { |
| 1224 | 1185 | check_ajax_referer('metasync_otto_debug', 'nonce'); |
| 1225 | 1186 | |
| 1226 | - if (!current_user_can('manage_options')) { | |
| 1187 | + if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) { | |
| 1227 | 1188 | wp_send_json_error('Unauthorized'); |
| 1228 | 1189 | } |
| 1229 | 1190 | |
| 1230 | 1191 | $results = array( |
| @@ -1244,9 +1205,9 @@ | ||
| 1244 | 1205 | |
| 1245 | 1206 | // Test 2: Check if we can access Action Scheduler tables |
| 1246 | 1207 | global $wpdb; |
| 1247 | 1208 | $table_name = $wpdb->prefix . 'actionscheduler_actions'; |
| 1248 | - $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name; | |
| 1209 | + $table_exists = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $wpdb->esc_like($table_name))) == $table_name; // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- admin debug tool — scratch diagnostics storage outside any WordPress API | |
| 1249 | 1210 | |
| 1250 | 1211 | $results['tests']['table_access'] = array( |
| 1251 | 1212 | 'table_exists' => $table_exists, |
| 1252 | 1213 | 'table_name' => $table_name, |
| @@ -1254,9 +1215,9 @@ | ||
| 1254 | 1215 | ); |
| 1255 | 1216 | |
| 1256 | 1217 | // Test 3: Try to insert a test record |
| 1257 | 1218 | if ($table_exists) { |
| 1258 | - $insert_result = $wpdb->insert( | |
| 1219 | + $insert_result = $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- admin debug tool — scratch diagnostics storage outside any WordPress API | |
| 1259 | 1220 | $table_name, |
| 1260 | 1221 | array( |
| 1261 | 1222 | 'hook' => 'metasync_debug_test', |
| 1262 | 1223 | 'status' => 'pending', |
| @@ -1275,9 +1236,9 @@ | ||
| 1275 | 1236 | ); |
| 1276 | 1237 | |
| 1277 | 1238 | // Clean up test record |
| 1278 | 1239 | if ($insert_result !== false && $wpdb->insert_id) { |
| 1279 | - $wpdb->delete($table_name, array('ID' => $wpdb->insert_id)); | |
| 1240 | + $wpdb->delete($table_name, array('ID' => $wpdb->insert_id)); // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- admin debug tool — scratch diagnostics storage outside any WordPress API | |
| 1280 | 1241 | } |
| 1281 | 1242 | } |
| 1282 | 1243 | |
| 1283 | 1244 | // Test 4: Check WordPress cron functionality |
| @@ -1289,9 +1250,9 @@ | ||
| 1289 | 1250 | |
| 1290 | 1251 | wp_send_json_success($results); |
| 1291 | 1252 | |
| 1292 | 1253 | } catch (Exception $e) { |
| 1293 | - error_log('MetaSync OTTO Debug: Exception in ajax_test_db_permissions: ' . $e->getMessage()); | |
| 1254 | + error_log('MetaSync OTTO Debug: Exception in ajax_test_db_permissions: ' . $e->getMessage()); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- unreachable in production | |
| 1294 | 1255 | wp_send_json_error('Exception: ' . $e->getMessage()); |
| 1295 | 1256 | } |
| 1296 | 1257 | } |
| 1297 | 1258 | } |