PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.5.23
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.5.23
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 2.6.4 2.6.3 2.5.23 All 138 releases
metasync / admin / class-metasync-otto-debug.php

class-metasync-otto-debug.php in Search Atlas SEO – OTTO AI SEO Automation for WordPress 2.5.23, at admin/class-metasync-otto-debug.php

1,589 lines 59.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * OTTO Debug Page for MetaSync Plugin
4 *
5 * This class provides comprehensive diagnostics for OTTO functionality
6 * to help developers troubleshoot why OTTO changes are not being applied.
7 *
8 * @package MetaSync
9 * @subpackage MetaSync/admin
10 * @since 1.0.0
11 */
12
13 // Prevent direct access
14 if (!defined('ABSPATH')) {
15 exit;
16 }
17
18 class Metasync_Otto_Debug {
19
20 /**
21 * The plugin name
22 */
23 private $plugin_name;
24
25 /**
26 * The plugin version
27 */
28 private $version;
29
30 /**
31 * Constructor
32 */
33 public function __construct($plugin_name, $version) {
34 $this->plugin_name = $plugin_name;
35 $this->version = $version;
36
37 // Add admin menu
38 add_action('admin_menu', array($this, 'add_debug_menu'));
39
40 // Add magic word handler
41 add_action('admin_init', array($this, 'handle_magic_word_access'));
42
43 // Add AJAX handlers
44 add_action('wp_ajax_metasync_otto_debug_test_api', array($this, 'ajax_test_otto_api'));
45 add_action('wp_ajax_metasync_otto_debug_test_notification', array($this, 'ajax_test_notification_endpoint'));
46 add_action('wp_ajax_metasync_otto_debug_clear_cache', array($this, 'ajax_clear_otto_cache'));
47 add_action('wp_ajax_metasync_otto_debug_simulate_crawl', array($this, 'ajax_simulate_crawl_notification'));
48 add_action('wp_ajax_metasync_otto_debug_test_url', array($this, 'ajax_test_specific_url'));
49 add_action('wp_ajax_metasync_otto_debug_emulate_changes', array($this, 'ajax_emulate_otto_changes'));
50 add_action('wp_ajax_metasync_otto_debug_simple_test', array($this, 'ajax_simple_test'));
51 add_action('wp_ajax_metasync_otto_debug_test_db_permissions', array($this, 'ajax_test_db_permissions'));
52 }
53
54
55 /**
56 * Add debug menu (developer only - hidden by default)
57 */
58 public function add_debug_menu() {
59 // Check if user has developer capabilities
60 if (!Metasync::current_user_has_plugin_access()) {
61 return;
62 }
63
64 // Check if debug access is enabled via magic word
65 if (!$this->is_debug_access_enabled()) {
66 return;
67 }
68
69 $menu_slug = Metasync_Admin::$page_slug;
70
71 add_submenu_page(
72 $menu_slug,
73 Metasync::get_whitelabel_otto_name() . ' Debug',
74 Metasync::get_whitelabel_otto_name() . ' Debug',
75 'manage_options',
76 $menu_slug . '-otto-debug',
77 array($this, 'create_debug_page')
78 );
79 }
80
81 /**
82 * Add magic word handler for direct access
83 */
84 public function handle_magic_word_access() {
85 // Check if magic word is provided
86 if (isset($_GET['metasync_debug']) && $_GET['metasync_debug'] === 'abracadabra@2020') {
87 // Enable debug access via user meta (persistent, no sessions needed)
88 $current_user = wp_get_current_user();
89 if ($current_user && $current_user->ID) {
90 update_user_meta($current_user->ID, 'metasync_debug_enabled', 'true');
91 }
92
93 // Redirect to admin with debug access enabled
94 $redirect_url = admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-otto-debug');
95 wp_redirect($redirect_url);
96 exit;
97 }
98 }
99
100 /**
101 * Check if debug access is enabled via magic word system
102 * Hidden from regular users, only accessible with secret key
103 */
104 private function is_debug_access_enabled() {
105 // Magic word for developer access
106 $magic_word = 'abracadabra@2020';
107
108 // Check if magic word is provided in URL parameter
109 if (isset($_GET['metasync_debug']) && $_GET['metasync_debug'] === $magic_word) {
110 // Enable debug access via user meta (persistent, no sessions needed)
111 $current_user = wp_get_current_user();
112 if ($current_user && $current_user->ID) {
113 update_user_meta($current_user->ID, 'metasync_debug_enabled', 'true');
114 }
115 return true;
116 }
117
118 // Check if debug access is enabled via user meta (for persistent access)
119 $current_user = wp_get_current_user();
120 if ($current_user && $current_user->ID) {
121 $debug_enabled = get_user_meta($current_user->ID, 'metasync_debug_enabled', true);
122 if ($debug_enabled === 'true') {
123 return true;
124 }
125 }
126
127 return false;
128 }
129
130 /**
131 * Check if current user is a developer
132 * Multiple methods to identify developers without requiring WP_DEBUG
133 */
134 private function is_developer_user($user) {
135 // Method 1: Check for specific user meta
136 $is_developer = get_user_meta($user->ID, 'metasync_developer', true);
137 if ($is_developer === 'true') {
138 return true;
139 }
140
141 // Method 2: Check for specific user roles
142 $developer_roles = array('administrator', 'developer', 'super_admin');
143 $user_roles = $user->roles;
144
145 foreach ($developer_roles as $role) {
146 if (in_array($role, $user_roles)) {
147 return true;
148 }
149 }
150
151 // Method 3: Check for specific capabilities
152 if ($user->has_cap('manage_options') && $user->has_cap('edit_plugins')) {
153 return true;
154 }
155
156 // Method 4: Check for specific email domains (optional)
157 $email_domain = substr(strrchr($user->user_email, "@"), 1);
158 $developer_domains = array('searchatlas.com', 'yourcompany.com'); // Add your company domains
159
160 if (in_array($email_domain, $developer_domains)) {
161 return true;
162 }
163
164 // Method 5: Check for specific username patterns
165 $username_patterns = array('/^dev_/', '/^admin_/', '/^support_/');
166 foreach ($username_patterns as $pattern) {
167 if (preg_match($pattern, $user->user_login)) {
168 return true;
169 }
170 }
171
172 return false;
173 }
174
175 /**
176 * Helper function to enable developer access for a specific user
177 * Call this function to grant debug access to a user
178 *
179 * Usage: Metasync_Otto_Debug::enable_developer_access($user_id);
180 */
181 public static function enable_developer_access($user_id) {
182 update_user_meta($user_id, 'metasync_debug_enabled', 'true');
183 }
184
185 /**
186 * Helper function to disable developer access for a specific user
187 *
188 * Usage: Metasync_Otto_Debug::disable_developer_access($user_id);
189 */
190 public static function disable_developer_access($user_id) {
191 delete_user_meta($user_id, 'metasync_debug_enabled');
192 }
193
194 /**
195 * Get the magic word for debug access
196 *
197 * Usage: Metasync_Otto_Debug::get_magic_word();
198 */
199 public static function get_magic_word() {
200 return 'abracadabra@2020';
201 }
202
203 /**
204 * Generate debug access URL
205 *
206 * Usage: Metasync_Otto_Debug::get_debug_access_url();
207 */
208 public static function get_debug_access_url() {
209 $admin_url = admin_url('admin.php');
210 $magic_word = self::get_magic_word();
211 return add_query_arg('metasync_debug', $magic_word, $admin_url);
212 }
213
214 /**
215 * Quick enable debug access for current user
216 *
217 * Usage: Metasync_Otto_Debug::quick_enable_debug();
218 */
219 public static function quick_enable_debug() {
220 $current_user = wp_get_current_user();
221 if ($current_user && $current_user->ID) {
222 update_user_meta($current_user->ID, 'metasync_debug_enabled', 'true');
223 return true;
224 }
225 return false;
226 }
227
228 /**
229 * Create the debug page
230 */
231 public function create_debug_page() {
232 // Check if this is a magic word access request
233 if (isset($_GET['metasync_debug']) && $_GET['metasync_debug'] === 'abracadabra@2020') {
234 // Enable debug access via user meta (persistent, no sessions needed)
235 $current_user = wp_get_current_user();
236 if ($current_user && $current_user->ID) {
237 update_user_meta($current_user->ID, 'metasync_debug_enabled', 'true');
238 }
239
240 // Show access granted message
241 $this->show_access_granted_page();
242 return;
243 }
244
245 $whitelabel_otto_name = Metasync::get_whitelabel_otto_name();
246 ?>
247 <div class="wrap metasync-otto-debug">
248 <h1><?php echo esc_html($whitelabel_otto_name); ?> Debug & Diagnostics</h1>
249 <p class="description">Comprehensive diagnostics for <?php echo esc_html($whitelabel_otto_name); ?> functionality. This page helps identify why <?php echo esc_html($whitelabel_otto_name); ?> changes may not be applied.</p>
250
251 <div class="metasync-debug-container">
252 <?php $this->render_developer_access_status(); ?>
253 <?php $this->render_url_testing_section(); ?>
254 <?php $this->render_configuration_status(); ?>
255 <?php $this->render_notification_endpoint_status(); ?>
256 <?php $this->render_api_connectivity_status(); ?>
257 <?php $this->render_crawl_data_status(); ?>
258 <?php $this->render_processing_status(); ?>
259 <?php $this->render_debug_tools(); ?>
260 </div>
261 </div>
262
263 <style>
264 .metasync-debug-container {
265 display: grid;
266 grid-template-columns: 1fr 1fr;
267 gap: 20px;
268 margin-top: 20px;
269 }
270
271 .debug-section {
272 background: #fff;
273 border: 1px solid #ccd0d4;
274 border-radius: 4px;
275 padding: 20px;
276 box-shadow: 0 1px 1px rgba(0,0,0,.04);
277 }
278
279 .debug-section h3 {
280 margin-top: 0;
281 color: #23282d;
282 border-bottom: 1px solid #eee;
283 padding-bottom: 10px;
284 }
285
286 .status-indicator {
287 display: inline-block;
288 width: 12px;
289 height: 12px;
290 border-radius: 50%;
291 margin-right: 8px;
292 }
293
294 .status-success { background-color: #46b450; }
295 .status-warning { background-color: #ffb900; }
296 .status-error { background-color: #dc3232; }
297 .status-info { background-color: #00a0d2; }
298
299 .debug-item {
300 margin: 10px 0;
301 padding: 8px;
302 background: #f9f9f9;
303 border-left: 4px solid #ddd;
304 }
305
306 .debug-item.success { border-left-color: #46b450; }
307 .debug-item.warning { border-left-color: #ffb900; }
308 .debug-item.error { border-left-color: #dc3232; }
309 .debug-item.info { border-left-color: #00a0d2; }
310
311 .debug-value {
312 font-family: monospace;
313 background: #fff;
314 padding: 4px 8px;
315 border: 1px solid #ddd;
316 border-radius: 3px;
317 word-break: break-all;
318 }
319
320 .debug-tools {
321 grid-column: 1 / -1;
322 }
323
324 .debug-button {
325 background: #0073aa;
326 color: white;
327 border: none;
328 padding: 8px 16px;
329 border-radius: 3px;
330 cursor: pointer;
331 margin: 5px;
332 }
333
334 .debug-button:hover {
335 background: #005a87;
336 }
337
338 .debug-button.danger {
339 background: #dc3232;
340 }
341
342 .debug-button.danger:hover {
343 background: #a00;
344 }
345
346 .debug-results {
347 margin-top: 15px;
348 padding: 15px;
349 background: #f1f1f1;
350 border-radius: 3px;
351 display: none;
352 }
353
354 .debug-results.show {
355 display: block;
356 }
357
358 .debug-results .error {
359 background: #f8d7da;
360 border: 1px solid #f5c6cb;
361 color: #721c24;
362 padding: 10px;
363 border-radius: 4px;
364 margin: 10px 0;
365 }
366
367 .json-output {
368 background: #fff;
369 border: 1px solid #ddd;
370 padding: 10px;
371 border-radius: 3px;
372 font-family: monospace;
373 white-space: pre-wrap;
374 max-height: 300px;
375 overflow-y: auto;
376 }
377 </style>
378 <?php
379 }
380
381 /**
382 * Show access granted page
383 */
384 private function show_access_granted_page() {
385 $whitelabel_otto_name = Metasync::get_whitelabel_otto_name();
386 $current_user = wp_get_current_user();
387 ?>
388 <div class="wrap">
389 <h1>🔑 <?php echo esc_html($whitelabel_otto_name); ?> Debug Access Granted</h1>
390
391 <div class="notice notice-success">
392 <p><strong>�
393 Debug Access Enabled!</strong></p>
394 <p>You now have access to the <?php echo esc_html($whitelabel_otto_name); ?> Debug page.</p>
395 </div>
396
397 <div class="card">
398 <h2>🎯 Next Steps</h2>
399 <ol>
400 <li><strong>Access Debug Page:</strong> The "<?php echo esc_html($whitelabel_otto_name); ?> Debug" menu should now be visible in the MetaSync plugin menu</li>
401 <li><strong>Use Diagnostics:</strong> Click on "<?php echo esc_html($whitelabel_otto_name); ?> Debug" to access comprehensive diagnostic tools</li>
402 <li><strong>Troubleshoot Issues:</strong> Use the debug tools to identify why <?php echo esc_html($whitelabel_otto_name); ?> changes may not be applied</li>
403 </ol>
404 </div>
405
406 <div class="card">
407 <h2>🔧 Access Information</h2>
408 <table class="form-table">
409 <tr>
410 <th scope="row">Magic Word</th>
411 <td><code>abracadabra@2020</code></td>
412 </tr>
413 <tr>
414 <th scope="row">Current User</th>
415 <td><?php echo esc_html($current_user->user_login); ?> (ID: <?php echo $current_user->ID; ?>)</td>
416 </tr>
417 <tr>
418 <th scope="row">Access Type</th>
419 <td>User Meta (persistent)</td>
420 </tr>
421 <tr>
422 <th scope="row">Debug Page URL</th>
423 <td><code><?php echo esc_html(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-otto-debug')); ?></code></td>
424 </tr>
425 </table>
426 </div>
427
428 <div class="card">
429 <h2>🔒 Security Notes</h2>
430 <ul>
431 <li><strong>Persistent Access:</strong> This access is stored in your user profile and persists across sessions</li>
432 <li><strong>Magic Word:</strong> Keep the magic word <code>abracadabra@2020</code> confidential</li>
433 <li><strong>Developer Only:</strong> This debug page is intended for plugin developers only</li>
434 <li><strong>To Revoke Access:</strong> Use <code>Metasync_Otto_Debug::disable_developer_access(<?php echo $current_user->ID; ?>)</code></li>
435 </ul>
436 </div>
437
438 <div class="card">
439 <h2>🚀 Quick Access</h2>
440 <p>To access the debug page directly, use this URL:</p>
441 <p><a href="<?php echo esc_url(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-otto-debug')); ?>" class="button button-primary">Open <?php echo esc_html($whitelabel_otto_name); ?> Debug Page</a></p>
442
443 <p>Or add the magic word to any WordPress admin URL:</p>
444 <p><code>?metasync_debug=abracadabra@2020</code></p>
445 </div>
446
447 <style>
448 .card {
449 background: #fff;
450 border: 1px solid #ccd0d4;
451 border-radius: 4px;
452 padding: 20px;
453 margin: 20px 0;
454 box-shadow: 0 1px 1px rgba(0,0,0,.04);
455 }
456 .card h2 {
457 margin-top: 0;
458 color: #23282d;
459 border-bottom: 1px solid #eee;
460 padding-bottom: 10px;
461 }
462 .form-table th {
463 width: 200px;
464 }
465 </style>
466 </div>
467 <?php
468 }
469
470 /**
471 * Render developer access status section
472 */
473 private function render_developer_access_status() {
474 $current_user = wp_get_current_user();
475 $is_debug_enabled = $this->is_debug_access_enabled();
476 $debug_meta = get_user_meta($current_user->ID, 'metasync_debug_enabled', true);
477
478 ?>
479 <div class="debug-section">
480 <h3><span class="status-indicator <?php echo $is_debug_enabled ? 'status-success' : 'status-warning'; ?>"></span>Developer Access Status</h3>
481
482 <div class="debug-item <?php echo $is_debug_enabled ? 'success' : 'warning'; ?>">
483 <strong>Debug Access:</strong>
484 <span class="debug-value"><?php echo $is_debug_enabled ? 'Granted' : 'Not Granted'; ?></span>
485 </div>
486
487 <div class="debug-item info">
488 <strong>Current User:</strong>
489 <span class="debug-value"><?php echo esc_html($current_user->user_login); ?> (ID: <?php echo $current_user->ID; ?>)</span>
490 </div>
491
492 <div class="debug-item info">
493 <strong>User Roles:</strong>
494 <span class="debug-value"><?php echo implode(', ', $current_user->roles); ?></span>
495 </div>
496
497 <div class="debug-item info">
498 <strong>Email Domain:</strong>
499 <span class="debug-value"><?php echo esc_html(substr(strrchr($current_user->user_email, "@"), 1)); ?></span>
500 </div>
501
502 <div class="debug-item info">
503 <strong>Debug Meta:</strong>
504 <span class="debug-value"><?php echo $debug_meta ? esc_html($debug_meta) : 'Not Set'; ?></span>
505 </div>
506
507 <?php if (!$is_debug_enabled): ?>
508 <div class="debug-item warning">
509 <strong>Enable Debug Access:</strong>
510 <p><strong>Method 1 - Magic Word (Recommended):</strong></p>
511 <p>Add this parameter to any WordPress admin URL:</p>
512 <div class="debug-value">
513 <code>?metasync_debug=abracadabra@2020</code>
514 </div>
515 <p><strong>Example:</strong> <code><?php echo esc_html(admin_url('admin.php?metasync_debug=abracadabra@2020')); ?></code></p>
516
517 <p><strong>Method 2 - User Meta:</strong></p>
518 <p>Run this code in WordPress:</p>
519 <div class="debug-value">
520 <code>Metasync_Otto_Debug::enable_developer_access(<?php echo $current_user->ID; ?>);</code>
521 </div>
522
523 <p><strong>Method 3 - WordPress CLI:</strong></p>
524 <div class="debug-value">
525 <code>wp user meta update <?php echo $current_user->ID; ?> metasync_debug_enabled true</code>
526 </div>
527 </div>
528 <?php else: ?>
529 <div class="debug-item success">
530 <strong>Debug Access Active</strong>
531 <p>You have access to all <?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> debug tools and diagnostics.</p>
532 <p><strong>Magic Word:</strong> <code>abracadabra@2020</code></p>
533 <p><strong>Access URL:</strong> <code><?php echo esc_html(self::get_debug_access_url()); ?></code></p>
534 </div>
535 <?php endif; ?>
536 </div>
537 <?php
538 }
539
540 /**
541 * Render URL testing section
542 */
543 private function render_url_testing_section() {
544 $whitelabel_otto_name = Metasync::get_whitelabel_otto_name();
545 $site_url = get_site_url();
546 ?>
547 <div class="debug-section debug-tools">
548 <h3><span class="status-indicator status-info"></span>URL Testing & <?php echo esc_html($whitelabel_otto_name); ?> Emulation</h3>
549
550 <div class="debug-item info">
551 <strong>Test Specific URL:</strong>
552 <p>Enter any URL from your site to test <?php echo esc_html($whitelabel_otto_name); ?> functionality and check all diagnostic points.</p>
553 </div>
554
555 <div style="margin-bottom: 20px;">
556 <label for="test-url-input"><strong>URL to Test:</strong></label><br>
557 <input type="url" id="test-url-input" placeholder="<?php echo esc_attr($site_url); ?>/sample-page/" style="width: 100%; padding: 8px; margin: 5px 0;" />
558 <br>
559 <button id="test-specific-url" class="debug-button">Test URL & Check All Points</button>
560 <button id="emulate-otto-changes" class="debug-button">Emulate <?php echo esc_html($whitelabel_otto_name); ?> Changes</button>
561 <button id="simple-ajax-test" class="debug-button">Test AJAX Connection</button>
562 </div>
563
564 <div id="url-test-results" class="debug-results"></div>
565 <div id="emulation-results" class="debug-results"></div>
566
567 <div class="debug-item info">
568 <strong>What This Tests:</strong>
569 <ul style="margin-left: 20px;">
570 <li>URL accessibility and response</li>
571 <li><?php echo esc_html($whitelabel_otto_name); ?> API data for the specific URL</li>
572 <li>Crawl status and processing eligibility</li>
573 <li>Page type detection and exclusions</li>
574 <li><?php echo esc_html($whitelabel_otto_name); ?> recommendations and changes</li>
575 <li>Error simulation and validation</li>
576 </ul>
577 </div>
578
579 <div class="debug-item warning">
580 <strong>Database Permissions Check:</strong>
581 <p>Testing if Action Scheduler can schedule jobs...</p>
582 <button id="test-db-permissions" class="debug-button">Test Database Permissions</button>
583 <div id="db-permissions-results" class="debug-results"></div>
584 </div>
585 </div>
586 <?php
587 }
588
589 /**
590 * Render configuration status section
591 */
592 private function render_configuration_status() {
593 $whitelabel_otto_name = Metasync::get_whitelabel_otto_name();
594 $general_options = Metasync::get_option('general');
595
596 // OTTO SSR is always enabled by default
597 $otto_enabled = true;
598 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
599 $otto_disable_loggedin = $general_options['otto_disable_on_loggedin'] ?? false;
600
601 ?>
602 <div class="debug-section">
603 <h3><span class="status-indicator <?php echo !empty($otto_uuid) ? 'status-success' : 'status-error'; ?>"></span>Configuration Status</h3>
604
605 <div class="debug-item success">
606 <strong><?php echo esc_html($whitelabel_otto_name); ?> SSR Enabled:</strong>
607 <span class="debug-value">Yes (Always Active)</span>
608 </div>
609
610 <div class="debug-item <?php echo !empty($otto_uuid) ? 'success' : 'error'; ?>">
611 <strong><?php echo esc_html($whitelabel_otto_name); ?> UUID:</strong>
612 <span class="debug-value"><?php echo !empty($otto_uuid) ? esc_html($otto_uuid) : 'Not Set'; ?></span>
613 </div>
614
615 <div class="debug-item <?php echo $otto_disable_loggedin ? 'warning' : 'info'; ?>">
616 <strong>Disable for Logged-in Users:</strong>
617 <span class="debug-value"><?php echo $otto_disable_loggedin ? 'Yes' : 'No'; ?></span>
618 </div>
619
620 <div class="debug-item info">
621 <strong>Current User Logged In:</strong>
622 <span class="debug-value"><?php echo is_user_logged_in() ? 'Yes' : 'No'; ?></span>
623 </div>
624
625 <div class="debug-item info">
626 <strong>Plugin Version:</strong>
627 <span class="debug-value"><?php echo defined('METASYNC_VERSION') ? METASYNC_VERSION : 'Unknown'; ?></span>
628 </div>
629 </div>
630 <?php
631 }
632
633 /**
634 * Render notification endpoint status
635 */
636 private function render_notification_endpoint_status() {
637 $rest_url = rest_url('metasync/v1/otto_crawl_notify');
638 $site_url = get_site_url();
639
640 ?>
641 <div class="debug-section">
642 <h3><span class="status-indicator status-info"></span>Notification Endpoint Status</h3>
643
644 <div class="debug-item info">
645 <strong>REST API Base URL:</strong>
646 <span class="debug-value"><?php echo esc_html($site_url); ?></span>
647 </div>
648
649 <div class="debug-item info">
650 <strong><?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> Notification Endpoint:</strong>
651 <span class="debug-value"><?php echo esc_html($rest_url); ?></span>
652 </div>
653
654 <div class="debug-item <?php echo function_exists('rest_url') ? 'success' : 'error'; ?>">
655 <strong>REST API Available:</strong>
656 <span class="debug-value"><?php echo function_exists('rest_url') ? 'Yes' : 'No'; ?></span>
657 </div>
658
659 <div class="debug-item <?php echo $this->is_rest_endpoint_registered() ? 'success' : 'error'; ?>">
660 <strong>Endpoint Registered:</strong>
661 <span class="debug-value"><?php echo $this->is_rest_endpoint_registered() ? 'Yes' : 'No'; ?></span>
662 </div>
663
664 <div class="debug-item info">
665 <strong>Expected Method:</strong>
666 <span class="debug-value">POST</span>
667 </div>
668
669 <div class="debug-item info">
670 <strong>Expected JSON Fields:</strong>
671 <span class="debug-value">domain, urls</span>
672 </div>
673 </div>
674 <?php
675 }
676
677 /**
678 * Render API connectivity status
679 */
680 private function render_api_connectivity_status() {
681 $general_options = Metasync::get_option('general');
682 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
683
684 # Use endpoint manager to get the correct API URL
685 $api_url = class_exists('Metasync_Endpoint_Manager')
686 ? Metasync_Endpoint_Manager::get_endpoint('OTTO_URL_DETAILS')
687 : 'https://sa.searchatlas.com/api/v2/otto-url-details';
688 $test_url = add_query_arg(array(
689 'url' => get_site_url(),
690 'uuid' => $otto_uuid
691 ), $api_url);
692
693 ?>
694 <div class="debug-section">
695 <h3><span class="status-indicator status-info"></span>API Connectivity Status</h3>
696
697 <div class="debug-item info">
698 <strong><?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> API Endpoint:</strong>
699 <span class="debug-value"><?php echo esc_html($api_url); ?></span>
700 </div>
701
702 <div class="debug-item info">
703 <strong>Test URL:</strong>
704 <span class="debug-value"><?php echo esc_html($test_url); ?></span>
705 </div>
706
707 <div class="debug-item <?php echo $this->can_reach_otto_api() ? 'success' : 'error'; ?>">
708 <strong>API Reachable:</strong>
709 <span class="debug-value"><?php echo $this->can_reach_otto_api() ? 'Yes' : 'No'; ?></span>
710 </div>
711
712 <div class="debug-item info">
713 <strong>SSL Verification:</strong>
714 <span class="debug-value">Enabled</span>
715 </div>
716
717 <div class="debug-item info">
718 <strong>Timeout:</strong>
719 <span class="debug-value">30 seconds</span>
720 </div>
721
722 <div class="debug-item info">
723 <strong>User Agent:</strong>
724 <span class="debug-value">MetaSync-WordPress-Plugin/1.0</span>
725 </div>
726 </div>
727 <?php
728 }
729
730 /**
731 * Render crawl data status
732 */
733 private function render_crawl_data_status() {
734 $crawl_data = get_option('metasync_otto_crawldata');
735
736 ?>
737 <div class="debug-section">
738 <h3><span class="status-indicator <?php echo !empty($crawl_data) ? 'status-success' : 'status-warning'; ?>"></span>Crawl Data Status</h3>
739
740 <div class="debug-item <?php echo !empty($crawl_data) ? 'success' : 'warning'; ?>">
741 <strong>Crawl Data Available:</strong>
742 <span class="debug-value"><?php echo !empty($crawl_data) ? 'Yes' : 'No'; ?></span>
743 </div>
744
745 <?php if (!empty($crawl_data)): ?>
746 <div class="debug-item info">
747 <strong>Domain:</strong>
748 <span class="debug-value"><?php echo esc_html($crawl_data['domain'] ?? 'Not Set'); ?></span>
749 </div>
750
751 <div class="debug-item info">
752 <strong>Total URLs Crawled:</strong>
753 <span class="debug-value"><?php echo count($crawl_data['urls'] ?? []); ?></span>
754 </div>
755
756 <div class="debug-item info">
757 <strong>Last Updated:</strong>
758 <span class="debug-value"><?php echo $this->get_option_last_updated('metasync_otto_crawldata'); ?></span>
759 </div>
760
761 <div class="debug-item info">
762 <strong>Sample URLs:</strong>
763 <div class="debug-value">
764 <?php
765 $sample_urls = array_slice($crawl_data['urls'] ?? [], 0, 5);
766 foreach ($sample_urls as $url) {
767 echo esc_html($url) . '<br>';
768 }
769 if (count($crawl_data['urls'] ?? []) > 5) {
770 echo '... and ' . (count($crawl_data['urls']) - 5) . ' more';
771 }
772 ?>
773 </div>
774 </div>
775 <?php endif; ?>
776 </div>
777 <?php
778 }
779
780 /**
781 * Render processing status
782 */
783 private function render_processing_status() {
784 $current_url = $this->get_current_url();
785 $otto_pixel = new Metasync_otto_pixel(Metasync::get_option('general')['otto_pixel_uuid'] ?? '');
786 $is_crawled = $otto_pixel->is_url_crawled($current_url);
787 $render_diagnostics = $this->get_render_strategy_diagnostics();
788
789 ?>
790 <div class="debug-section">
791 <h3><span class="status-indicator <?php echo $is_crawled ? 'status-success' : 'status-warning'; ?>"></span>Processing Status</h3>
792
793 <div class="debug-item info">
794 <strong>Current URL:</strong>
795 <span class="debug-value"><?php echo esc_html($current_url); ?></span>
796 </div>
797
798 <div class="debug-item <?php echo $is_crawled ? 'success' : 'warning'; ?>">
799 <strong>URL Crawled by <?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?>:</strong>
800 <span class="debug-value"><?php echo $is_crawled ? 'Yes' : 'No'; ?></span>
801 </div>
802
803 <div class="debug-item <?php echo $this->is_otto_excluded() ? 'warning' : 'info'; ?>">
804 <strong><?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> Excluded:</strong>
805 <span class="debug-value"><?php echo $this->is_otto_excluded() ? 'Yes' : 'No'; ?></span>
806 </div>
807
808 <div class="debug-item info">
809 <strong>Page Type:</strong>
810 <span class="debug-value"><?php echo $this->get_page_type(); ?></span>
811 </div>
812
813 <div class="debug-item info">
814 <strong>Cache Status:</strong>
815 <span class="debug-value"><?php echo $this->get_cache_status(); ?></span>
816 </div>
817
818 <div class="debug-item info">
819 <strong>Processing Method:</strong>
820 <span class="debug-value"><?php echo $this->get_processing_method(); ?></span>
821 </div>
822
823 <?php if (!empty($render_diagnostics) && isset($render_diagnostics['available']) === false): ?>
824 <div class="debug-item info">
825 <strong>Render Strategy:</strong>
826 <div class="debug-value">
827 <ul style="margin: 5px 0 0 15px; padding: 0;">
828 <li><strong>PHP:</strong> <?php echo esc_html($render_diagnostics['php_version'] ?? 'Unknown'); ?></li>
829 <li><strong>WP:</strong> <?php echo esc_html($render_diagnostics['wp_version'] ?? 'Unknown'); ?></li>
830 <li><strong>Memory:</strong> <?php echo esc_html($render_diagnostics['memory_limit'] ?? 'Unknown'); ?> (used: <?php echo esc_html($render_diagnostics['memory_used'] ?? 'Unknown'); ?>)</li>
831 <li><strong>Buffer Level:</strong> <?php echo esc_html($render_diagnostics['buffer_level'] ?? 'Unknown'); ?></li>
832 <li><strong>Headers Sent:</strong> <?php echo ($render_diagnostics['headers_sent'] ?? false) ? 'Yes' : 'No'; ?></li>
833 </ul>
834 </div>
835 </div>
836
837 <div class="debug-item info">
838 <strong>Detected Plugins:</strong>
839 <div class="debug-value">
840 <?php
841 $plugins = $render_diagnostics['detected_plugins'] ?? [];
842 foreach ($plugins as $plugin => $active):
843 ?>
844 <span style="display: inline-block; margin: 2px 5px; padding: 2px 8px; background: <?php echo $active ? '#d4edda' : '#f8f9fa'; ?>; border-radius: 3px;">
845 <?php echo esc_html($plugin); ?>: <?php echo $active ? '✓' : '✗'; ?>
846 </span>
847 <?php endforeach; ?>
848 </div>
849 </div>
850
851 <div class="debug-item info">
852 <strong>Detected Hosts:</strong>
853 <div class="debug-value">
854 <?php
855 $hosts = $render_diagnostics['detected_hosts'] ?? [];
856 foreach ($hosts as $host => $detected):
857 ?>
858 <span style="display: inline-block; margin: 2px 5px; padding: 2px 8px; background: <?php echo $detected ? '#fff3cd' : '#f8f9fa'; ?>; border-radius: 3px;">
859 <?php echo esc_html($host); ?>: <?php echo $detected ? '✓' : '✗'; ?>
860 </span>
861 <?php endforeach; ?>
862 </div>
863 </div>
864 <?php endif; ?>
865 </div>
866 <?php
867 }
868
869 /**
870 * Render debug tools
871 */
872 private function render_debug_tools() {
873 ?>
874 <div class="debug-section debug-tools">
875 <h3><span class="status-indicator status-info"></span>Debug Tools</h3>
876
877 <div style="margin-bottom: 20px;">
878 <button id="test-otto-api" class="debug-button">Test API Connectivity</button>
879 <button id="test-notification-endpoint" class="debug-button">Test Notification Endpoint</button>
880 <button id="simulate-crawl" class="debug-button">Simulate Crawl Notification</button>
881 <button id="clear-otto-cache" class="debug-button danger">Clear <?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> Cache</button>
882 </div>
883
884 <div id="api-test-results" class="debug-results"></div>
885 <div id="notification-test-results" class="debug-results"></div>
886 <div id="crawl-simulate-results" class="debug-results"></div>
887 <div id="cache-clear-results" class="debug-results"></div>
888
889 <div class="debug-item info">
890 <strong>Note:</strong> These tools help diagnose <?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> issues. Use with caution in production environments.
891 </div>
892 </div>
893 <?php
894 }
895
896 /**
897 * Check if REST endpoint is registered
898 */
899 private function is_rest_endpoint_registered() {
900 $routes = rest_get_server()->get_routes();
901 return isset($routes['/metasync/v1/otto_crawl_notify']);
902 }
903
904 /**
905 * Check if OTTO API is reachable
906 */
907 private function can_reach_otto_api() {
908 $general_options = Metasync::get_option('general');
909 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
910
911 if (empty($otto_uuid)) {
912 return false;
913 }
914
915 # Use endpoint manager to get the correct API URL
916 $api_endpoint = class_exists('Metasync_Endpoint_Manager')
917 ? Metasync_Endpoint_Manager::get_endpoint('OTTO_URL_DETAILS')
918 : 'https://sa.searchatlas.com/api/v2/otto-url-details';
919
920 $api_url = add_query_arg(array(
921 'url' => get_site_url(),
922 'uuid' => $otto_uuid
923 ), $api_endpoint);
924
925 $response = wp_remote_get($api_url, array(
926 'timeout' => 10,
927 'sslverify' => true
928 ));
929
930 return !is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200;
931 }
932
933 /**
934 * Get option last updated time
935 */
936 private function get_option_last_updated($option_name) {
937 global $wpdb;
938
939 $result = $wpdb->get_var($wpdb->prepare(
940 "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s",
941 $option_name
942 ));
943
944 if ($result) {
945 $data = maybe_unserialize($result);
946 if (isset($data['last_updated'])) {
947 return date('Y-m-d H:i:s', $data['last_updated']);
948 }
949 }
950
951 return 'Unknown';
952 }
953
954 /**
955 * Get current URL
956 */
957 private function get_current_url() {
958 $scheme = is_ssl() ? 'https' : 'http';
959 $host = $_SERVER['HTTP_HOST'] ?? '';
960 $uri = $_SERVER['REQUEST_URI'] ?? '';
961 return $scheme . '://' . $host . $uri;
962 }
963
964 /**
965 * Check if OTTO is excluded for current request
966 */
967 private function is_otto_excluded() {
968 // Check AJAX requests
969 if (wp_doing_ajax() || defined('DOING_AJAX') && DOING_AJAX) {
970 return true;
971 }
972
973 // Check WooCommerce pages
974 if (function_exists('is_woocommerce') && is_woocommerce()) {
975 return true;
976 }
977
978 // Check logged-in user exclusion
979 $general_options = Metasync::get_option('general');
980 if (!empty($general_options['otto_disable_on_loggedin']) &&
981 $general_options['otto_disable_on_loggedin'] === 'true' &&
982 is_user_logged_in()) {
983 return true;
984 }
985
986 return false;
987 }
988
989 /**
990 * Get page type
991 */
992 private function get_page_type() {
993 if (is_home()) return 'Home';
994 if (is_front_page()) return 'Front Page';
995 if (is_single()) return 'Single Post';
996 if (is_page()) return 'Page';
997 if (is_category()) return 'Category';
998 if (is_tag()) return 'Tag';
999 if (is_archive()) return 'Archive';
1000 if (is_search()) return 'Search';
1001 if (is_404()) return '404';
1002 return 'Other';
1003 }
1004
1005 /**
1006 * Get cache status
1007 */
1008 private function get_cache_status() {
1009 // Cache is disabled in current implementation
1010 return 'Disabled (SSR Mode)';
1011 }
1012
1013 /**
1014 * Get processing method
1015 */
1016 private function get_processing_method() {
1017 // OTTO SSR is always enabled by default
1018 $otto_enabled = true;
1019
1020 if ($otto_enabled) {
1021 // Check which render strategy would be used
1022 if (class_exists('Metasync_Otto_Render_Strategy')) {
1023 $method = Metasync_Otto_Render_Strategy::determine_method();
1024 if ($method === Metasync_Otto_Render_Strategy::METHOD_BUFFER) {
1025 return 'Server-Side Rendering (SSR) - Output Buffer (Fast)';
1026 } elseif ($method === Metasync_Otto_Render_Strategy::METHOD_HTTP) {
1027 return 'Server-Side Rendering (SSR) - HTTP Request (Fallback)';
1028 }
1029 }
1030 return 'Server-Side Rendering (SSR)';
1031 } else {
1032 return 'Client-Side JavaScript';
1033 }
1034 }
1035
1036 /**
1037 * Get render strategy diagnostics
1038 */
1039 public function get_render_strategy_diagnostics() {
1040 if (!class_exists('Metasync_Otto_Render_Strategy')) {
1041 return array(
1042 'available' => false,
1043 'message' => 'Render Strategy class not loaded'
1044 );
1045 }
1046
1047 return Metasync_Otto_Render_Strategy::get_diagnostics();
1048 }
1049
1050 /**
1051 * AJAX handler for testing OTTO API
1052 */
1053 public function ajax_test_otto_api() {
1054 check_ajax_referer('metasync_otto_debug', 'nonce');
1055
1056 if (!Metasync::current_user_has_plugin_access()) {
1057 wp_die('Unauthorized');
1058 }
1059
1060 $general_options = Metasync::get_option('general');
1061 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
1062
1063 if (empty($otto_uuid)) {
1064 wp_send_json_error(Metasync::get_whitelabel_otto_name() . ' UUID not configured');
1065 }
1066
1067 $test_url = get_site_url();
1068
1069 # Use endpoint manager to get the correct API URL
1070 $api_endpoint = class_exists('Metasync_Endpoint_Manager')
1071 ? Metasync_Endpoint_Manager::get_endpoint('OTTO_URL_DETAILS')
1072 : 'https://sa.searchatlas.com/api/v2/otto-url-details';
1073
1074 $api_url = add_query_arg(array(
1075 'url' => $test_url,
1076 'uuid' => $otto_uuid
1077 ), $api_endpoint);
1078
1079 $response = wp_remote_get($api_url, array(
1080 'timeout' => 30,
1081 'sslverify' => true,
1082 'headers' => array(
1083 'User-Agent' => 'MetaSync-WordPress-Plugin/1.0'
1084 )
1085 ));
1086
1087 if (is_wp_error($response)) {
1088 wp_send_json_error(array(
1089 'error' => $response->get_error_message(),
1090 'url' => $api_url
1091 ));
1092 }
1093
1094 $response_code = wp_remote_retrieve_response_code($response);
1095 $body = wp_remote_retrieve_body($response);
1096
1097 wp_send_json_success(array(
1098 'response_code' => $response_code,
1099 'url' => $api_url,
1100 'body' => $body,
1101 'has_data' => !empty($body),
1102 'data_valid' => json_decode($body, true) !== null
1103 ));
1104 }
1105
1106 /**
1107 * AJAX handler for testing notification endpoint
1108 */
1109 public function ajax_test_notification_endpoint() {
1110 check_ajax_referer('metasync_otto_debug', 'nonce');
1111
1112 if (!Metasync::current_user_has_plugin_access()) {
1113 wp_die('Unauthorized');
1114 }
1115
1116 $endpoint_url = rest_url('metasync/v1/otto_crawl_notify');
1117
1118 $test_data = array(
1119 'domain' => get_site_url(),
1120 'urls' => array('/', '/about/', '/contact/')
1121 );
1122
1123 $response = wp_remote_post($endpoint_url, array(
1124 'headers' => array(
1125 'Content-Type' => 'application/json'
1126 ),
1127 'body' => json_encode($test_data),
1128 'timeout' => 30
1129 ));
1130
1131 if (is_wp_error($response)) {
1132 wp_send_json_error(array(
1133 'error' => $response->get_error_message(),
1134 'url' => $endpoint_url
1135 ));
1136 }
1137
1138 $response_code = wp_remote_retrieve_response_code($response);
1139 $body = wp_remote_retrieve_body($response);
1140
1141 wp_send_json_success(array(
1142 'response_code' => $response_code,
1143 'url' => $endpoint_url,
1144 'body' => $body,
1145 'test_data' => $test_data
1146 ));
1147 }
1148
1149 /**
1150 * AJAX handler for clearing OTTO cache
1151 */
1152 public function ajax_clear_otto_cache() {
1153 check_ajax_referer('metasync_otto_debug', 'nonce');
1154
1155 if (!Metasync::current_user_has_plugin_access()) {
1156 wp_die('Unauthorized');
1157 }
1158
1159 // Clear crawl data
1160 delete_option('metasync_otto_crawldata');
1161
1162 // Clear any cached API responses
1163 $general_options = Metasync::get_option('general');
1164 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
1165
1166 if (!empty($otto_uuid)) {
1167 $cache_key = 'metasync_public_hash_' . md5($otto_uuid);
1168 delete_transient($cache_key);
1169 }
1170
1171 wp_send_json_success(array(
1172 'message' => Metasync::get_whitelabel_otto_name() . ' cache cleared successfully',
1173 'cleared_items' => array(
1174 'crawl_data' => true,
1175 'api_cache' => true
1176 )
1177 ));
1178 }
1179
1180 /**
1181 * AJAX handler for simulating crawl notification
1182 */
1183 public function ajax_simulate_crawl_notification() {
1184 check_ajax_referer('metasync_otto_debug', 'nonce');
1185
1186 if (!Metasync::current_user_has_plugin_access()) {
1187 wp_die('Unauthorized');
1188 }
1189
1190 $general_options = Metasync::get_option('general');
1191 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
1192
1193 if (empty($otto_uuid)) {
1194 wp_send_json_error(Metasync::get_whitelabel_otto_name() . ' UUID not configured');
1195 }
1196
1197 // Simulate crawl notification
1198 $test_data = array(
1199 'domain' => get_site_url(),
1200 'urls' => array('/', '/about/', '/contact/', '/blog/')
1201 );
1202
1203 // Create a mock request object
1204 $request = new WP_REST_Request('POST', '/metasync/v1/otto_crawl_notify');
1205 $request->set_body(json_encode($test_data));
1206
1207 // Call the notification handler
1208 $response = metasync_otto_crawl_notify($request);
1209
1210 wp_send_json_success(array(
1211 'message' => 'Crawl notification simulated',
1212 'test_data' => $test_data,
1213 'response' => $response->get_data(),
1214 'response_code' => $response->get_status()
1215 ));
1216 }
1217
1218 /**
1219 * AJAX handler for testing specific URL
1220 */
1221 public function ajax_test_specific_url() {
1222 try {
1223 check_ajax_referer('metasync_otto_debug', 'nonce');
1224
1225 if (!Metasync::current_user_has_plugin_access()) {
1226 wp_die('Unauthorized');
1227 }
1228
1229 $test_url = sanitize_url($_POST['test_url'] ?? '');
1230
1231 if (empty($test_url)) {
1232 wp_send_json_error('No URL provided');
1233 }
1234
1235 $results = array(
1236 'test_url' => $test_url,
1237 'timestamp' => current_time('mysql'),
1238 'tests' => array()
1239 );
1240
1241 // Test 1: URL Accessibility
1242 $results['tests']['url_accessibility'] = $this->test_url_accessibility($test_url);
1243
1244 // Test 2: OTTO API Data
1245 $results['tests']['otto_api_data'] = $this->test_otto_api_for_url($test_url);
1246
1247 // Test 3: Crawl Status
1248 $results['tests']['crawl_status'] = $this->test_crawl_status($test_url);
1249
1250 // Test 4: Page Type Detection
1251 $results['tests']['page_type_detection'] = $this->test_page_type_detection($test_url);
1252
1253 // Test 5: Processing Eligibility
1254 $results['tests']['processing_eligibility'] = $this->test_processing_eligibility($test_url);
1255
1256 wp_send_json_success($results);
1257
1258 } catch (Exception $e) {
1259 error_log('MetaSync OTTO Debug: Exception in ajax_test_specific_url: ' . $e->getMessage());
1260 wp_send_json_error('Exception: ' . $e->getMessage());
1261 }
1262 }
1263
1264 /**
1265 * AJAX handler for emulating OTTO changes
1266 */
1267 public function ajax_emulate_otto_changes() {
1268 check_ajax_referer('metasync_otto_debug', 'nonce');
1269
1270 if (!Metasync::current_user_has_plugin_access()) {
1271 wp_die('Unauthorized');
1272 }
1273
1274 $test_url = sanitize_url($_POST['test_url'] ?? '');
1275
1276 if (empty($test_url)) {
1277 wp_send_json_error('No URL provided');
1278 }
1279
1280 $results = array(
1281 'test_url' => $test_url,
1282 'timestamp' => current_time('mysql'),
1283 'emulation' => array()
1284 );
1285
1286 // Emulate OTTO processing
1287 $results['emulation'] = $this->emulate_otto_processing($test_url);
1288
1289 wp_send_json_success($results);
1290 }
1291
1292 /**
1293 * Test URL accessibility
1294 */
1295 private function test_url_accessibility($url) {
1296 $response = wp_remote_get($url, array(
1297 'timeout' => 10,
1298 'user-agent' => 'MetaSync Debug Tool'
1299 ));
1300
1301 if (is_wp_error($response)) {
1302 return array(
1303 'status' => 'error',
1304 'message' => $response->get_error_message(),
1305 'accessible' => false
1306 );
1307 }
1308
1309 $status_code = wp_remote_retrieve_response_code($response);
1310 $body = wp_remote_retrieve_body($response);
1311
1312 return array(
1313 'status' => 'success',
1314 'status_code' => $status_code,
1315 'accessible' => $status_code === 200,
1316 'content_length' => strlen($body),
1317 'headers' => wp_remote_retrieve_headers($response)->getAll()
1318 );
1319 }
1320
1321 /**
1322 * Test OTTO API data for specific URL
1323 */
1324 private function test_otto_api_for_url($url) {
1325 $general_options = Metasync::get_option('general');
1326 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
1327
1328 if (empty($otto_uuid)) {
1329 return array(
1330 'status' => 'error',
1331 'message' => Metasync::get_whitelabel_otto_name() . ' UUID not configured'
1332 );
1333 }
1334
1335 // Use the existing OTTO API function
1336 if (function_exists('metasync_fetch_otto_seo_data')) {
1337 $data = metasync_fetch_otto_seo_data($url, $otto_uuid);
1338
1339 if (is_wp_error($data)) {
1340 return array(
1341 'status' => 'error',
1342 'message' => $data->get_error_message(),
1343 'has_data' => false
1344 );
1345 }
1346
1347 return array(
1348 'status' => 'success',
1349 'has_data' => !empty($data),
1350 'data_keys' => array_keys($data ?? array()),
1351 'recommendations_count' => count($data['recommendations'] ?? array()),
1352 'sample_data' => array_slice($data ?? array(), 0, 3) // First 3 items for preview
1353 );
1354 }
1355
1356 return array(
1357 'status' => 'error',
1358 'message' => Metasync::get_whitelabel_otto_name() . ' API function not available'
1359 );
1360 }
1361
1362 /**
1363 * Test crawl status for URL
1364 */
1365 private function test_crawl_status($url) {
1366 if (class_exists('Metasync_otto_pixel')) {
1367 $otto_pixel = new Metasync_otto_pixel(false);
1368 $is_crawled = $otto_pixel->is_url_crawled($url);
1369
1370 // Get crawl data from options
1371 $crawl_data = get_option('metasync_otto_crawldata');
1372
1373 return array(
1374 'status' => 'success',
1375 'is_crawled' => $is_crawled,
1376 'crawl_data' => $crawl_data,
1377 'total_crawled_urls' => count($crawl_data['urls'] ?? array()),
1378 'domain' => $crawl_data['domain'] ?? 'Not set'
1379 );
1380 }
1381
1382 return array(
1383 'status' => 'error',
1384 'message' => Metasync::get_whitelabel_otto_name() . ' pixel class not available'
1385 );
1386 }
1387
1388 /**
1389 * Test page type detection
1390 */
1391 private function test_page_type_detection($url) {
1392 $parsed_url = parse_url($url);
1393 $path = $parsed_url['path'] ?? '/';
1394
1395 $detection = array(
1396 'url' => $url,
1397 'path' => $path,
1398 'is_ajax' => strpos($path, 'wp-admin/admin-ajax.php') !== false,
1399 'is_woocommerce' => function_exists('is_woocommerce') ? false : 'WooCommerce not available',
1400 'is_admin' => strpos($path, '/wp-admin/') !== false,
1401 'is_login' => strpos($path, '/wp-login.php') !== false,
1402 'is_cron' => strpos($path, '/wp-cron.php') !== false,
1403 'is_xmlrpc' => strpos($path, '/xmlrpc.php') !== false
1404 );
1405
1406 // Check if it's a WooCommerce page
1407 if (function_exists('is_woocommerce')) {
1408 // This would need to be tested with actual page context
1409 $detection['is_woocommerce'] = 'Requires page context to determine';
1410 }
1411
1412 return $detection;
1413 }
1414
1415 /**
1416 * Test processing eligibility
1417 */
1418 private function test_processing_eligibility($url) {
1419 $general_options = Metasync::get_option('general');
1420 // OTTO SSR is always enabled by default
1421 $otto_enabled = true;
1422 $disable_logged_in = $general_options['otto_disable_on_loggedin'] ?? false;
1423
1424 $eligibility = array(
1425 'otto_enabled' => $otto_enabled,
1426 'disable_logged_in' => $disable_logged_in,
1427 'user_logged_in' => is_user_logged_in(),
1428 'eligible_for_processing' => false,
1429 'exclusion_reasons' => array()
1430 );
1431
1432 // OTTO SSR is always enabled, so this check is no longer needed
1433
1434 if ($disable_logged_in && is_user_logged_in()) {
1435 $eligibility['exclusion_reasons'][] = 'User is logged in and ' . Metasync::get_whitelabel_otto_name() . ' disabled for logged-in users';
1436 }
1437
1438 $eligibility['eligible_for_processing'] = empty($eligibility['exclusion_reasons']);
1439
1440 return $eligibility;
1441 }
1442
1443 /**
1444 * Emulate OTTO processing
1445 */
1446 private function emulate_otto_processing($url) {
1447 $emulation = array(
1448 'url' => $url,
1449 'steps' => array(),
1450 'errors' => array(),
1451 'changes_applied' => array()
1452 );
1453
1454 // Step 1: Check if URL is crawled
1455 $emulation['steps']['check_crawled'] = $this->test_crawl_status($url);
1456
1457 // Step 2: Fetch OTTO data
1458 $emulation['steps']['fetch_otto_data'] = $this->test_otto_api_for_url($url);
1459
1460 // Step 3: Simulate HTML processing
1461 if (class_exists('Metasync_otto_html')) {
1462 try {
1463 $otto_html = new Metasync_otto_html(false);
1464 $emulation['steps']['html_processing'] = array(
1465 'status' => 'success',
1466 'message' => Metasync::get_whitelabel_otto_name() . ' HTML class available'
1467 );
1468
1469 // Simulate processing (without actually modifying files)
1470 $emulation['changes_applied'] = array(
1471 'header_changes' => 'Simulated header modifications',
1472 'body_changes' => 'Simulated body modifications',
1473 'footer_changes' => 'Simulated footer modifications'
1474 );
1475
1476 } catch (Exception $e) {
1477 $emulation['errors'][] = 'HTML processing error: ' . $e->getMessage();
1478 }
1479 } else {
1480 $emulation['errors'][] = Metasync::get_whitelabel_otto_name() . ' HTML class not available';
1481 }
1482
1483 return $emulation;
1484 }
1485
1486 /**
1487 * Simple AJAX test to verify basic functionality
1488 */
1489 public function ajax_simple_test() {
1490 try {
1491 check_ajax_referer('metasync_otto_debug', 'nonce');
1492
1493 if (!Metasync::current_user_has_plugin_access()) {
1494 wp_send_json_error('Unauthorized');
1495 }
1496
1497 wp_send_json_success(array(
1498 'message' => 'AJAX is working!',
1499 'timestamp' => current_time('mysql'),
1500 'user_id' => get_current_user_id(),
1501 'nonce_verified' => true
1502 ));
1503
1504 } catch (Exception $e) {
1505 error_log('MetaSync OTTO Debug: Exception in ajax_simple_test: ' . $e->getMessage());
1506 wp_send_json_error('Exception: ' . $e->getMessage());
1507 }
1508 }
1509
1510 /**
1511 * AJAX handler for testing database permissions
1512 */
1513 public function ajax_test_db_permissions() {
1514 try {
1515 check_ajax_referer('metasync_otto_debug', 'nonce');
1516
1517 if (!Metasync::current_user_has_plugin_access()) {
1518 wp_send_json_error('Unauthorized');
1519 }
1520
1521 $results = array(
1522 'timestamp' => current_time('mysql'),
1523 'tests' => array()
1524 );
1525
1526 // Test 1: Try to schedule a simple action
1527 $test_action = 'metasync_debug_test_action';
1528 $scheduled = wp_schedule_single_event(time() + 60, $test_action, array('test' => 'data'));
1529
1530 $results['tests']['action_scheduler'] = array(
1531 'can_schedule' => $scheduled !== false,
1532 'scheduled' => $scheduled,
1533 'message' => $scheduled !== false ? 'Action Scheduler working' : 'Action Scheduler failed - likely database permissions issue'
1534 );
1535
1536 // Test 2: Check if we can access Action Scheduler tables
1537 global $wpdb;
1538 $table_name = $wpdb->prefix . 'actionscheduler_actions';
1539 $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name;
1540
1541 $results['tests']['table_access'] = array(
1542 'table_exists' => $table_exists,
1543 'table_name' => $table_name,
1544 'message' => $table_exists ? 'Action Scheduler table exists' : 'Action Scheduler table not found'
1545 );
1546
1547 // Test 3: Try to insert a test record
1548 if ($table_exists) {
1549 $insert_result = $wpdb->insert(
1550 $table_name,
1551 array(
1552 'hook' => 'metasync_debug_test',
1553 'status' => 'pending',
1554 'scheduled_date_gmt' => current_time('mysql', 1),
1555 'args' => json_encode(array('test' => true)),
1556 'schedule' => 'once'
1557 ),
1558 array('%s', '%s', '%s', '%s', '%s')
1559 );
1560
1561 $results['tests']['insert_test'] = array(
1562 'can_insert' => $insert_result !== false,
1563 'insert_id' => $wpdb->insert_id,
1564 'last_error' => $wpdb->last_error,
1565 'message' => $insert_result !== false ? 'Can insert records' : 'Cannot insert records - ' . $wpdb->last_error
1566 );
1567
1568 // Clean up test record
1569 if ($insert_result !== false && $wpdb->insert_id) {
1570 $wpdb->delete($table_name, array('ID' => $wpdb->insert_id));
1571 }
1572 }
1573
1574 // Test 4: Check WordPress cron functionality
1575 $cron_disabled = defined('DISABLE_WP_CRON') && DISABLE_WP_CRON;
1576 $results['tests']['wp_cron'] = array(
1577 'enabled' => !$cron_disabled,
1578 'message' => $cron_disabled ? 'WordPress cron is disabled' : 'WordPress cron is enabled'
1579 );
1580
1581 wp_send_json_success($results);
1582
1583 } catch (Exception $e) {
1584 error_log('MetaSync OTTO Debug: Exception in ajax_test_db_permissions: ' . $e->getMessage());
1585 wp_send_json_error('Exception: ' . $e->getMessage());
1586 }
1587 }
1588 }
1589