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 | admin/class-metasync-otto-debug.php +51 -104 2.7.0 → 2.7.2 View file →
@@ -63,8 +63,25 @@
63 63 return false;
64 64 }
65 65
66 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 + /**
67 84 * Add debug menu (internal only - hidden on customer production sites)
68 85 */
69 86 public function add_debug_menu() {
70 87 if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) {
@@ -102,9 +119,8 @@
102 119 <?php $this->render_url_testing_section(); ?>
103 120 <?php $this->render_configuration_status(); ?>
104 121 <?php $this->render_notification_endpoint_status(); ?>
105 122 <?php $this->render_api_connectivity_status(); ?>
106 - <?php $this->render_crawl_data_status(); ?>
107 123 <?php $this->render_processing_status(); ?>
108 124 <?php $this->render_debug_tools(); ?>
109 125 </div>
110 126 </div>
@@ -242,14 +258,14 @@
242 258 </div>
243 259
244 260 <div class="debug-item info">
245 261 <strong>Current User:</strong>
246 - <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>
247 263 </div>
248 264
249 265 <div class="debug-item info">
250 266 <strong>User Roles:</strong>
251 - <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>
252 268 </div>
253 269
254 270 <div class="debug-item success">
255 271 <strong>Debug Access Active</strong>
@@ -345,9 +361,9 @@
345 361 </div>
346 362
347 363 <div class="debug-item info">
348 364 <strong>Plugin Version:</strong>
349 - <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>
350 366 </div>
351 367 </div>
352 368 <?php
353 369 }
@@ -449,64 +465,13 @@
449 465 <?php
450 466 }
451 467
452 468 /**
453 - * Render crawl data status
454 - */
455 - private function render_crawl_data_status() {
456 - $crawl_data = get_option('metasync_otto_crawldata');
457 -
458 - ?>
459 - <div class="debug-section">
460 - <h3><span class="status-indicator <?php echo !empty($crawl_data) ? 'status-success' : 'status-warning'; ?>"></span>Crawl Data Status</h3>
461 -
462 - <div class="debug-item <?php echo !empty($crawl_data) ? 'success' : 'warning'; ?>">
463 - <strong>Crawl Data Available:</strong>
464 - <span class="debug-value"><?php echo !empty($crawl_data) ? 'Yes' : 'No'; ?></span>
465 - </div>
466 -
467 - <?php if (!empty($crawl_data)): ?>
468 - <div class="debug-item info">
469 - <strong>Domain:</strong>
470 - <span class="debug-value"><?php echo esc_html($crawl_data['domain'] ?? 'Not Set'); ?></span>
471 - </div>
472 -
473 - <div class="debug-item info">
474 - <strong>Total URLs Crawled:</strong>
475 - <span class="debug-value"><?php echo count($crawl_data['urls'] ?? []); ?></span>
476 - </div>
477 -
478 - <div class="debug-item info">
479 - <strong>Last Updated:</strong>
480 - <span class="debug-value"><?php echo $this->get_option_last_updated('metasync_otto_crawldata'); ?></span>
481 - </div>
482 -
483 - <div class="debug-item info">
484 - <strong>Sample URLs:</strong>
485 - <div class="debug-value">
486 - <?php
487 - $sample_urls = array_slice($crawl_data['urls'] ?? [], 0, 5);
488 - foreach ($sample_urls as $url) {
489 - echo esc_html($url) . '<br>';
490 - }
491 - if (count($crawl_data['urls'] ?? []) > 5) {
492 - echo '... and ' . (count($crawl_data['urls']) - 5) . ' more';
493 - }
494 - ?>
495 - </div>
496 - </div>
497 - <?php endif; ?>
498 - </div>
499 - <?php
500 - }
501 -
502 - /**
503 469 * Render processing status
504 470 */
505 471 private function render_processing_status() {
506 472 $current_url = $this->get_current_url();
507 - $otto_pixel = new Metasync_otto_pixel(Metasync::get_option('general')['otto_pixel_uuid'] ?? '');
508 - $is_crawled = $otto_pixel->is_url_crawled($current_url);
473 + $is_crawled = self::is_url_crawled($current_url);
509 474 $render_diagnostics = $this->get_render_strategy_diagnostics();
510 475
511 476 ?>
512 477 <div class="debug-section">
@@ -528,19 +493,19 @@
528 493 </div>
529 494
530 495 <div class="debug-item info">
531 496 <strong>Page Type:</strong>
532 - <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>
533 498 </div>
534 499
535 500 <div class="debug-item info">
536 501 <strong>Cache Status:</strong>
537 - <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>
538 503 </div>
539 504
540 505 <div class="debug-item info">
541 506 <strong>Processing Method:</strong>
542 - <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>
543 508 </div>
544 509
545 510 <?php if (!empty($render_diagnostics) && isset($render_diagnostics['available']) === false): ?>
546 511 <div class="debug-item info">
@@ -652,29 +617,8 @@
652 617 return !is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200;
653 618 }
654 619
655 620 /**
656 - * Get option last updated time
657 - */
658 - private function get_option_last_updated($option_name) {
659 - global $wpdb;
660 -
661 - $result = $wpdb->get_var($wpdb->prepare(
662 - "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s",
663 - $option_name
664 - ));
665 -
666 - if ($result) {
667 - $data = maybe_unserialize($result);
668 - if (isset($data['last_updated'])) {
669 - return date('Y-m-d H:i:s', $data['last_updated']);
670 - }
671 - }
672 -
673 - return 'Unknown';
674 - }
675 -
676 - /**
677 621 * Get current URL
678 622 */
679 623 private function get_current_url() {
680 624 $scheme = is_ssl() ? 'https' : 'http';
@@ -872,20 +816,23 @@
872 816 * AJAX handler for clearing OTTO cache
873 817 */
874 818 public function ajax_clear_otto_cache() {
875 819 check_ajax_referer('metasync_otto_debug', 'nonce');
876 -
820 +
877 821 if (!current_user_can('manage_options') || !self::is_debug_tools_enabled()) {
878 822 wp_die('Unauthorized');
879 823 }
880 -
881 - // 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.
882 829 delete_option('metasync_otto_crawldata');
883 -
830 +
884 831 // Clear any cached API responses
885 832 $general_options = Metasync::get_option('general');
886 833 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
887 -
834 +
888 835 if (!empty($otto_uuid)) {
889 836 delete_transient(Metasync_Heartbeat_Manager::public_hash_cache_key($otto_uuid));
890 837 }
891 838
@@ -978,9 +925,9 @@
978 925
979 926 wp_send_json_success($results);
980 927
981 928 } catch (Exception $e) {
982 - 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
983 930 wp_send_json_error('Exception: ' . $e->getMessage());
984 931 }
985 932 }
986 933
@@ -1085,27 +1032,27 @@
1085 1032 /**
1086 1033 * Test crawl status for URL
1087 1034 */
1088 1035 private function test_crawl_status($url) {
1089 - if (class_exists('Metasync_otto_pixel')) {
1090 - $otto_pixel = new Metasync_otto_pixel(false);
1091 - $is_crawled = $otto_pixel->is_url_crawled($url);
1092 -
1093 - // Get crawl data from options
1094 - $crawl_data = get_option('metasync_otto_crawldata');
1095 -
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 +
1096 1042 return array(
1097 1043 'status' => 'success',
1098 1044 'is_crawled' => $is_crawled,
1099 - 'crawl_data' => $crawl_data,
1100 - 'total_crawled_urls' => count($crawl_data['urls'] ?? array()),
1101 - '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
1102 1049 );
1103 1050 }
1104 -
1051 +
1105 1052 return array(
1106 1053 'status' => 'error',
1107 - 'message' => Metasync::get_whitelabel_otto_name() . ' pixel class not available'
1054 + 'message' => Metasync::get_whitelabel_otto_name() . ' job status class not available'
1108 1055 );
1109 1056 }
1110 1057
1111 1058 /**
@@ -1111,9 +1058,9 @@
1111 1058 /**
1112 1059 * Test page type detection
1113 1060 */
1114 1061 private function test_page_type_detection($url) {
1115 - $parsed_url = parse_url($url);
1062 + $parsed_url = wp_parse_url($url);
1116 1063 $path = $parsed_url['path'] ?? '/';
1117 1064
1118 1065 $detection = array(
1119 1066 'url' => $url,
@@ -1224,9 +1171,9 @@
1224 1171 'nonce_verified' => true
1225 1172 ));
1226 1173
1227 1174 } catch (Exception $e) {
1228 - 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
1229 1176 wp_send_json_error('Exception: ' . $e->getMessage());
1230 1177 }
1231 1178 }
1232 1179
@@ -1258,9 +1205,9 @@
1258 1205
1259 1206 // Test 2: Check if we can access Action Scheduler tables
1260 1207 global $wpdb;
1261 1208 $table_name = $wpdb->prefix . 'actionscheduler_actions';
1262 - $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
1263 1210
1264 1211 $results['tests']['table_access'] = array(
1265 1212 'table_exists' => $table_exists,
1266 1213 'table_name' => $table_name,
@@ -1268,9 +1215,9 @@
1268 1215 );
1269 1216
1270 1217 // Test 3: Try to insert a test record
1271 1218 if ($table_exists) {
1272 - $insert_result = $wpdb->insert(
1219 + $insert_result = $wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- admin debug tool — scratch diagnostics storage outside any WordPress API
1273 1220 $table_name,
1274 1221 array(
1275 1222 'hook' => 'metasync_debug_test',
1276 1223 'status' => 'pending',
@@ -1289,9 +1236,9 @@
1289 1236 );
1290 1237
1291 1238 // Clean up test record
1292 1239 if ($insert_result !== false && $wpdb->insert_id) {
1293 - $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
1294 1241 }
1295 1242 }
1296 1243
1297 1244 // Test 4: Check WordPress cron functionality
@@ -1303,9 +1250,9 @@
1303 1250
1304 1251 wp_send_json_success($results);
1305 1252
1306 1253 } catch (Exception $e) {
1307 - 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
1308 1255 wp_send_json_error('Exception: ' . $e->getMessage());
1309 1256 }
1310 1257 }
1311 1258 }