PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.21
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.21
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.6.21, 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>Debug Access Enabled!</strong></p>
393 <p>You now have access to the <?php echo esc_html($whitelabel_otto_name); ?> Debug page.</p>
394 </div>
395
396 <div class="card">
397 <h2>Next Steps</h2>
398 <ol>
399 <li><strong>Access Debug Page:</strong> The "<?php echo esc_html($whitelabel_otto_name); ?> Debug" menu should now be visible in the <?php echo esc_html(Metasync::get_effective_plugin_name()); ?> plugin menu</li>
400 <li><strong>Use Diagnostics:</strong> Click on "<?php echo esc_html($whitelabel_otto_name); ?> Debug" to access comprehensive diagnostic tools</li>
401 <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>
402 </ol>
403 </div>
404
405 <div class="card">
406 <h2>Access Information</h2>
407 <table class="form-table">
408 <tr>
409 <th scope="row">Magic Word</th>
410 <td><code>abracadabra@2020</code></td>
411 </tr>
412 <tr>
413 <th scope="row">Current User</th>
414 <td><?php echo esc_html($current_user->user_login); ?> (ID: <?php echo $current_user->ID; ?>)</td>
415 </tr>
416 <tr>
417 <th scope="row">Access Type</th>
418 <td>User Meta (persistent)</td>
419 </tr>
420 <tr>
421 <th scope="row">Debug Page URL</th>
422 <td><code><?php echo esc_html(admin_url('admin.php?page=' . Metasync_Admin::$page_slug . '-otto-debug')); ?></code></td>
423 </tr>
424 </table>
425 </div>
426
427 <div class="card">
428 <h2>Security Notes</h2>
429 <ul>
430 <li><strong>Persistent Access:</strong> This access is stored in your user profile and persists across sessions</li>
431 <li><strong>Magic Word:</strong> Keep the magic word <code>abracadabra@2020</code> confidential</li>
432 <li><strong>Developer Only:</strong> This debug page is intended for plugin developers only</li>
433 <li><strong>To Revoke Access:</strong> Use <code>Metasync_Otto_Debug::disable_developer_access(<?php echo $current_user->ID; ?>)</code></li>
434 </ul>
435 </div>
436
437 <div class="card">
438 <h2>Quick Access</h2>
439 <p>To access the debug page directly, use this URL:</p>
440 <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>
441
442 <p>Or add the magic word to any WordPress admin URL:</p>
443 <p><code>?metasync_debug=abracadabra@2020</code></p>
444 </div>
445
446 <style>
447 .card {
448 background: #fff;
449 border: 1px solid #ccd0d4;
450 border-radius: 4px;
451 padding: 20px;
452 margin: 20px 0;
453 box-shadow: 0 1px 1px rgba(0,0,0,.04);
454 }
455 .card h2 {
456 margin-top: 0;
457 color: #23282d;
458 border-bottom: 1px solid #eee;
459 padding-bottom: 10px;
460 }
461 .form-table th {
462 width: 200px;
463 }
464 </style>
465 </div>
466 <?php
467 }
468
469 /**
470 * Render developer access status section
471 */
472 private function render_developer_access_status() {
473 $current_user = wp_get_current_user();
474 $is_debug_enabled = $this->is_debug_access_enabled();
475 $debug_meta = get_user_meta($current_user->ID, 'metasync_debug_enabled', true);
476
477 ?>
478 <div class="debug-section">
479 <h3><span class="status-indicator <?php echo $is_debug_enabled ? 'status-success' : 'status-warning'; ?>"></span>Developer Access Status</h3>
480
481 <div class="debug-item <?php echo $is_debug_enabled ? 'success' : 'warning'; ?>">
482 <strong>Debug Access:</strong>
483 <span class="debug-value"><?php echo $is_debug_enabled ? 'Granted' : 'Not Granted'; ?></span>
484 </div>
485
486 <div class="debug-item info">
487 <strong>Current User:</strong>
488 <span class="debug-value"><?php echo esc_html($current_user->user_login); ?> (ID: <?php echo $current_user->ID; ?>)</span>
489 </div>
490
491 <div class="debug-item info">
492 <strong>User Roles:</strong>
493 <span class="debug-value"><?php echo implode(', ', $current_user->roles); ?></span>
494 </div>
495
496 <div class="debug-item info">
497 <strong>Email Domain:</strong>
498 <span class="debug-value"><?php echo esc_html(substr(strrchr($current_user->user_email, "@"), 1)); ?></span>
499 </div>
500
501 <div class="debug-item info">
502 <strong>Debug Meta:</strong>
503 <span class="debug-value"><?php echo $debug_meta ? esc_html($debug_meta) : 'Not Set'; ?></span>
504 </div>
505
506 <?php if (!$is_debug_enabled): ?>
507 <div class="debug-item warning">
508 <strong>Enable Debug Access:</strong>
509 <p><strong>Method 1 - Magic Word (Recommended):</strong></p>
510 <p>Add this parameter to any WordPress admin URL:</p>
511 <div class="debug-value">
512 <code>?metasync_debug=abracadabra@2020</code>
513 </div>
514 <p><strong>Example:</strong> <code><?php echo esc_html(admin_url('admin.php?metasync_debug=abracadabra@2020')); ?></code></p>
515
516 <p><strong>Method 2 - User Meta:</strong></p>
517 <p>Run this code in WordPress:</p>
518 <div class="debug-value">
519 <code>Metasync_Otto_Debug::enable_developer_access(<?php echo $current_user->ID; ?>);</code>
520 </div>
521
522 <p><strong>Method 3 - WordPress CLI:</strong></p>
523 <div class="debug-value">
524 <code>wp user meta update <?php echo $current_user->ID; ?> metasync_debug_enabled true</code>
525 </div>
526 </div>
527 <?php else: ?>
528 <div class="debug-item success">
529 <strong>Debug Access Active</strong>
530 <p>You have access to all <?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> debug tools and diagnostics.</p>
531 <p><strong>Magic Word:</strong> <code>abracadabra@2020</code></p>
532 <p><strong>Access URL:</strong> <code><?php echo esc_html(self::get_debug_access_url()); ?></code></p>
533 </div>
534 <?php endif; ?>
535 </div>
536 <?php
537 }
538
539 /**
540 * Render URL testing section
541 */
542 private function render_url_testing_section() {
543 $whitelabel_otto_name = Metasync::get_whitelabel_otto_name();
544 $site_url = get_site_url();
545 ?>
546 <div class="debug-section debug-tools">
547 <h3><span class="status-indicator status-info"></span>URL Testing & <?php echo esc_html($whitelabel_otto_name); ?> Emulation</h3>
548
549 <div class="debug-item info">
550 <strong>Test Specific URL:</strong>
551 <p>Enter any URL from your site to test <?php echo esc_html($whitelabel_otto_name); ?> functionality and check all diagnostic points.</p>
552 </div>
553
554 <div style="margin-bottom: 20px;">
555 <label for="test-url-input"><strong>URL to Test:</strong></label><br>
556 <input type="url" id="test-url-input" placeholder="<?php echo esc_attr($site_url); ?>/sample-page/" style="width: 100%; padding: 8px; margin: 5px 0;" />
557 <br>
558 <button id="test-specific-url" class="debug-button">Test URL & Check All Points</button>
559 <button id="emulate-otto-changes" class="debug-button">Emulate <?php echo esc_html($whitelabel_otto_name); ?> Changes</button>
560 <button id="simple-ajax-test" class="debug-button">Test AJAX Connection</button>
561 </div>
562
563 <div id="url-test-results" class="debug-results"></div>
564 <div id="emulation-results" class="debug-results"></div>
565
566 <div class="debug-item info">
567 <strong>What This Tests:</strong>
568 <ul style="margin-left: 20px;">
569 <li>URL accessibility and response</li>
570 <li><?php echo esc_html($whitelabel_otto_name); ?> API data for the specific URL</li>
571 <li>Crawl status and processing eligibility</li>
572 <li>Page type detection and exclusions</li>
573 <li><?php echo esc_html($whitelabel_otto_name); ?> recommendations and changes</li>
574 <li>Error simulation and validation</li>
575 </ul>
576 </div>
577
578 <div class="debug-item warning">
579 <strong>Database Permissions Check:</strong>
580 <p>Testing if Action Scheduler can schedule jobs...</p>
581 <button id="test-db-permissions" class="debug-button">Test Database Permissions</button>
582 <div id="db-permissions-results" class="debug-results"></div>
583 </div>
584 </div>
585 <?php
586 }
587
588 /**
589 * Render configuration status section
590 */
591 private function render_configuration_status() {
592 $whitelabel_otto_name = Metasync::get_whitelabel_otto_name();
593 $general_options = Metasync::get_option('general');
594
595 // OTTO SSR is always enabled by default
596 $otto_enabled = true;
597 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
598 $otto_disable_loggedin = $general_options['otto_disable_on_loggedin'] ?? false;
599
600 ?>
601 <div class="debug-section">
602 <h3><span class="status-indicator <?php echo !empty($otto_uuid) ? 'status-success' : 'status-error'; ?>"></span>Configuration Status</h3>
603
604 <div class="debug-item success">
605 <strong><?php echo esc_html($whitelabel_otto_name); ?> SSR Enabled:</strong>
606 <span class="debug-value">Yes (Always Active)</span>
607 </div>
608
609 <div class="debug-item <?php echo !empty($otto_uuid) ? 'success' : 'error'; ?>">
610 <strong><?php echo esc_html($whitelabel_otto_name); ?> UUID:</strong>
611 <span class="debug-value"><?php echo !empty($otto_uuid) ? esc_html($otto_uuid) : 'Not Set'; ?></span>
612 </div>
613
614 <div class="debug-item <?php echo $otto_disable_loggedin ? 'warning' : 'info'; ?>">
615 <strong>Disable for Logged-in Users:</strong>
616 <span class="debug-value"><?php echo $otto_disable_loggedin ? 'Yes' : 'No'; ?></span>
617 </div>
618
619 <div class="debug-item info">
620 <strong>Current User Logged In:</strong>
621 <span class="debug-value"><?php echo is_user_logged_in() ? 'Yes' : 'No'; ?></span>
622 </div>
623
624 <div class="debug-item info">
625 <strong>Plugin Version:</strong>
626 <span class="debug-value"><?php echo defined('METASYNC_VERSION') ? METASYNC_VERSION : 'Unknown'; ?></span>
627 </div>
628 </div>
629 <?php
630 }
631
632 /**
633 * Render notification endpoint status
634 */
635 private function render_notification_endpoint_status() {
636 $rest_url = rest_url('metasync/v1/otto_crawl_notify');
637 $site_url = get_site_url();
638
639 ?>
640 <div class="debug-section">
641 <h3><span class="status-indicator status-info"></span>Notification Endpoint Status</h3>
642
643 <div class="debug-item info">
644 <strong>REST API Base URL:</strong>
645 <span class="debug-value"><?php echo esc_html($site_url); ?></span>
646 </div>
647
648 <div class="debug-item info">
649 <strong><?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> Notification Endpoint:</strong>
650 <span class="debug-value"><?php echo esc_html($rest_url); ?></span>
651 </div>
652
653 <div class="debug-item <?php echo function_exists('rest_url') ? 'success' : 'error'; ?>">
654 <strong>REST API Available:</strong>
655 <span class="debug-value"><?php echo function_exists('rest_url') ? 'Yes' : 'No'; ?></span>
656 </div>
657
658 <div class="debug-item <?php echo $this->is_rest_endpoint_registered() ? 'success' : 'error'; ?>">
659 <strong>Endpoint Registered:</strong>
660 <span class="debug-value"><?php echo $this->is_rest_endpoint_registered() ? 'Yes' : 'No'; ?></span>
661 </div>
662
663 <div class="debug-item info">
664 <strong>Expected Method:</strong>
665 <span class="debug-value">POST</span>
666 </div>
667
668 <div class="debug-item info">
669 <strong>Expected JSON Fields:</strong>
670 <span class="debug-value">domain, urls</span>
671 </div>
672 </div>
673 <?php
674 }
675
676 /**
677 * Render API connectivity status
678 */
679 private function render_api_connectivity_status() {
680 $general_options = Metasync::get_option('general');
681 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
682
683 # Use endpoint manager to get the correct API URL
684 $api_url = class_exists('Metasync_Endpoint_Manager')
685 ? Metasync_Endpoint_Manager::get_endpoint('OTTO_URL_DETAILS')
686 : 'https://sa.searchatlas.com/api/v2/otto-url-details';
687 $test_url = add_query_arg(array(
688 'url' => get_site_url(),
689 'uuid' => $otto_uuid
690 ), $api_url);
691
692 ?>
693 <div class="debug-section">
694 <h3><span class="status-indicator status-info"></span>API Connectivity Status</h3>
695
696 <div class="debug-item info">
697 <strong><?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> API Endpoint:</strong>
698 <span class="debug-value"><?php echo esc_html($api_url); ?></span>
699 </div>
700
701 <div class="debug-item info">
702 <strong>Test URL:</strong>
703 <span class="debug-value"><?php echo esc_html($test_url); ?></span>
704 </div>
705
706 <div class="debug-item <?php echo $this->can_reach_otto_api() ? 'success' : 'error'; ?>">
707 <strong>API Reachable:</strong>
708 <span class="debug-value"><?php echo $this->can_reach_otto_api() ? 'Yes' : 'No'; ?></span>
709 </div>
710
711 <div class="debug-item info">
712 <strong>SSL Verification:</strong>
713 <span class="debug-value">Enabled</span>
714 </div>
715
716 <div class="debug-item info">
717 <strong>Timeout:</strong>
718 <span class="debug-value">30 seconds</span>
719 </div>
720
721 <div class="debug-item info">
722 <strong>User Agent:</strong>
723 <span class="debug-value">MetaSync-WordPress-Plugin/1.0</span>
724 </div>
725 </div>
726 <?php
727 }
728
729 /**
730 * Render crawl data status
731 */
732 private function render_crawl_data_status() {
733 $crawl_data = get_option('metasync_otto_crawldata');
734
735 ?>
736 <div class="debug-section">
737 <h3><span class="status-indicator <?php echo !empty($crawl_data) ? 'status-success' : 'status-warning'; ?>"></span>Crawl Data Status</h3>
738
739 <div class="debug-item <?php echo !empty($crawl_data) ? 'success' : 'warning'; ?>">
740 <strong>Crawl Data Available:</strong>
741 <span class="debug-value"><?php echo !empty($crawl_data) ? 'Yes' : 'No'; ?></span>
742 </div>
743
744 <?php if (!empty($crawl_data)): ?>
745 <div class="debug-item info">
746 <strong>Domain:</strong>
747 <span class="debug-value"><?php echo esc_html($crawl_data['domain'] ?? 'Not Set'); ?></span>
748 </div>
749
750 <div class="debug-item info">
751 <strong>Total URLs Crawled:</strong>
752 <span class="debug-value"><?php echo count($crawl_data['urls'] ?? []); ?></span>
753 </div>
754
755 <div class="debug-item info">
756 <strong>Last Updated:</strong>
757 <span class="debug-value"><?php echo $this->get_option_last_updated('metasync_otto_crawldata'); ?></span>
758 </div>
759
760 <div class="debug-item info">
761 <strong>Sample URLs:</strong>
762 <div class="debug-value">
763 <?php
764 $sample_urls = array_slice($crawl_data['urls'] ?? [], 0, 5);
765 foreach ($sample_urls as $url) {
766 echo esc_html($url) . '<br>';
767 }
768 if (count($crawl_data['urls'] ?? []) > 5) {
769 echo '... and ' . (count($crawl_data['urls']) - 5) . ' more';
770 }
771 ?>
772 </div>
773 </div>
774 <?php endif; ?>
775 </div>
776 <?php
777 }
778
779 /**
780 * Render processing status
781 */
782 private function render_processing_status() {
783 $current_url = $this->get_current_url();
784 $otto_pixel = new Metasync_otto_pixel(Metasync::get_option('general')['otto_pixel_uuid'] ?? '');
785 $is_crawled = $otto_pixel->is_url_crawled($current_url);
786 $render_diagnostics = $this->get_render_strategy_diagnostics();
787
788 ?>
789 <div class="debug-section">
790 <h3><span class="status-indicator <?php echo $is_crawled ? 'status-success' : 'status-warning'; ?>"></span>Processing Status</h3>
791
792 <div class="debug-item info">
793 <strong>Current URL:</strong>
794 <span class="debug-value"><?php echo esc_html($current_url); ?></span>
795 </div>
796
797 <div class="debug-item <?php echo $is_crawled ? 'success' : 'warning'; ?>">
798 <strong>URL Crawled by <?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?>:</strong>
799 <span class="debug-value"><?php echo $is_crawled ? 'Yes' : 'No'; ?></span>
800 </div>
801
802 <div class="debug-item <?php echo $this->is_otto_excluded() ? 'warning' : 'info'; ?>">
803 <strong><?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> Excluded:</strong>
804 <span class="debug-value"><?php echo $this->is_otto_excluded() ? 'Yes' : 'No'; ?></span>
805 </div>
806
807 <div class="debug-item info">
808 <strong>Page Type:</strong>
809 <span class="debug-value"><?php echo $this->get_page_type(); ?></span>
810 </div>
811
812 <div class="debug-item info">
813 <strong>Cache Status:</strong>
814 <span class="debug-value"><?php echo $this->get_cache_status(); ?></span>
815 </div>
816
817 <div class="debug-item info">
818 <strong>Processing Method:</strong>
819 <span class="debug-value"><?php echo $this->get_processing_method(); ?></span>
820 </div>
821
822 <?php if (!empty($render_diagnostics) && isset($render_diagnostics['available']) === false): ?>
823 <div class="debug-item info">
824 <strong>Render Strategy:</strong>
825 <div class="debug-value">
826 <ul style="margin: 5px 0 0 15px; padding: 0;">
827 <li><strong>PHP:</strong> <?php echo esc_html($render_diagnostics['php_version'] ?? 'Unknown'); ?></li>
828 <li><strong>WP:</strong> <?php echo esc_html($render_diagnostics['wp_version'] ?? 'Unknown'); ?></li>
829 <li><strong>Memory:</strong> <?php echo esc_html($render_diagnostics['memory_limit'] ?? 'Unknown'); ?> (used: <?php echo esc_html($render_diagnostics['memory_used'] ?? 'Unknown'); ?>)</li>
830 <li><strong>Buffer Level:</strong> <?php echo esc_html($render_diagnostics['buffer_level'] ?? 'Unknown'); ?></li>
831 <li><strong>Headers Sent:</strong> <?php echo ($render_diagnostics['headers_sent'] ?? false) ? 'Yes' : 'No'; ?></li>
832 </ul>
833 </div>
834 </div>
835
836 <div class="debug-item info">
837 <strong>Detected Plugins:</strong>
838 <div class="debug-value">
839 <?php
840 $plugins = $render_diagnostics['detected_plugins'] ?? [];
841 foreach ($plugins as $plugin => $active):
842 ?>
843 <span style="display: inline-block; margin: 2px 5px; padding: 2px 8px; background: <?php echo $active ? '#d4edda' : '#f8f9fa'; ?>; border-radius: 3px;">
844 <?php echo esc_html($plugin); ?>: <?php echo $active ? '✓' : '✗'; ?>
845 </span>
846 <?php endforeach; ?>
847 </div>
848 </div>
849
850 <div class="debug-item info">
851 <strong>Detected Hosts:</strong>
852 <div class="debug-value">
853 <?php
854 $hosts = $render_diagnostics['detected_hosts'] ?? [];
855 foreach ($hosts as $host => $detected):
856 ?>
857 <span style="display: inline-block; margin: 2px 5px; padding: 2px 8px; background: <?php echo $detected ? '#fff3cd' : '#f8f9fa'; ?>; border-radius: 3px;">
858 <?php echo esc_html($host); ?>: <?php echo $detected ? '✓' : '✗'; ?>
859 </span>
860 <?php endforeach; ?>
861 </div>
862 </div>
863 <?php endif; ?>
864 </div>
865 <?php
866 }
867
868 /**
869 * Render debug tools
870 */
871 private function render_debug_tools() {
872 ?>
873 <div class="debug-section debug-tools">
874 <h3><span class="status-indicator status-info"></span>Debug Tools</h3>
875
876 <div style="margin-bottom: 20px;">
877 <button id="test-otto-api" class="debug-button">Test API Connectivity</button>
878 <button id="test-notification-endpoint" class="debug-button">Test Notification Endpoint</button>
879 <button id="simulate-crawl" class="debug-button">Simulate Crawl Notification</button>
880 <button id="clear-otto-cache" class="debug-button danger">Clear <?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> Cache</button>
881 </div>
882
883 <div id="api-test-results" class="debug-results"></div>
884 <div id="notification-test-results" class="debug-results"></div>
885 <div id="crawl-simulate-results" class="debug-results"></div>
886 <div id="cache-clear-results" class="debug-results"></div>
887
888 <div class="debug-item info">
889 <strong>Note:</strong> These tools help diagnose <?php echo esc_html(Metasync::get_whitelabel_otto_name()); ?> issues. Use with caution in production environments.
890 </div>
891 </div>
892 <?php
893 }
894
895 /**
896 * Check if REST endpoint is registered
897 */
898 private function is_rest_endpoint_registered() {
899 $routes = rest_get_server()->get_routes();
900 return isset($routes['/metasync/v1/otto_crawl_notify']);
901 }
902
903 /**
904 * Check if OTTO API is reachable
905 */
906 private function can_reach_otto_api() {
907 $general_options = Metasync::get_option('general');
908 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
909
910 if (empty($otto_uuid)) {
911 return false;
912 }
913
914 # Use endpoint manager to get the correct API URL
915 $api_endpoint = class_exists('Metasync_Endpoint_Manager')
916 ? Metasync_Endpoint_Manager::get_endpoint('OTTO_URL_DETAILS')
917 : 'https://sa.searchatlas.com/api/v2/otto-url-details';
918
919 $api_url = add_query_arg(array(
920 'url' => get_site_url(),
921 'uuid' => $otto_uuid
922 ), $api_endpoint);
923
924 $response = wp_remote_get($api_url, array(
925 'timeout' => 10,
926 'sslverify' => true
927 ));
928
929 return !is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200;
930 }
931
932 /**
933 * Get option last updated time
934 */
935 private function get_option_last_updated($option_name) {
936 global $wpdb;
937
938 $result = $wpdb->get_var($wpdb->prepare(
939 "SELECT option_value FROM {$wpdb->options} WHERE option_name = %s",
940 $option_name
941 ));
942
943 if ($result) {
944 $data = maybe_unserialize($result);
945 if (isset($data['last_updated'])) {
946 return date('Y-m-d H:i:s', $data['last_updated']);
947 }
948 }
949
950 return 'Unknown';
951 }
952
953 /**
954 * Get current URL
955 */
956 private function get_current_url() {
957 $scheme = is_ssl() ? 'https' : 'http';
958 $host = $_SERVER['HTTP_HOST'] ?? '';
959 $uri = $_SERVER['REQUEST_URI'] ?? '';
960 return $scheme . '://' . $host . $uri;
961 }
962
963 /**
964 * Check if OTTO is excluded for current request
965 */
966 private function is_otto_excluded() {
967 // Check AJAX requests
968 if (wp_doing_ajax() || defined('DOING_AJAX') && DOING_AJAX) {
969 return true;
970 }
971
972 // Check WooCommerce pages
973 if (function_exists('is_woocommerce') && is_woocommerce()) {
974 return true;
975 }
976
977 // Check logged-in user exclusion
978 $general_options = Metasync::get_option('general');
979 if (!empty($general_options['otto_disable_on_loggedin']) &&
980 $general_options['otto_disable_on_loggedin'] === 'true' &&
981 is_user_logged_in()) {
982 return true;
983 }
984
985 return false;
986 }
987
988 /**
989 * Get page type
990 */
991 private function get_page_type() {
992 if (is_home()) return 'Home';
993 if (is_front_page()) return 'Front Page';
994 if (is_single()) return 'Single Post';
995 if (is_page()) return 'Page';
996 if (is_category()) return 'Category';
997 if (is_tag()) return 'Tag';
998 if (is_archive()) return 'Archive';
999 if (is_search()) return 'Search';
1000 if (is_404()) return '404';
1001 return 'Other';
1002 }
1003
1004 /**
1005 * Get cache status
1006 */
1007 private function get_cache_status() {
1008 // Cache is disabled in current implementation
1009 return 'Disabled (SSR Mode)';
1010 }
1011
1012 /**
1013 * Get processing method
1014 */
1015 private function get_processing_method() {
1016 // OTTO SSR is always enabled by default
1017 $otto_enabled = true;
1018
1019 if ($otto_enabled) {
1020 // Check which render strategy would be used
1021 if (class_exists('Metasync_Otto_Render_Strategy')) {
1022 $method = Metasync_Otto_Render_Strategy::determine_method();
1023 if ($method === Metasync_Otto_Render_Strategy::METHOD_BUFFER) {
1024 return 'Server-Side Rendering (SSR) - Output Buffer (Fast)';
1025 } elseif ($method === Metasync_Otto_Render_Strategy::METHOD_HTTP) {
1026 return 'Server-Side Rendering (SSR) - HTTP Request (Fallback)';
1027 }
1028 }
1029 return 'Server-Side Rendering (SSR)';
1030 } else {
1031 return 'Client-Side JavaScript';
1032 }
1033 }
1034
1035 /**
1036 * Get render strategy diagnostics
1037 */
1038 public function get_render_strategy_diagnostics() {
1039 if (!class_exists('Metasync_Otto_Render_Strategy')) {
1040 return array(
1041 'available' => false,
1042 'message' => 'Render Strategy class not loaded'
1043 );
1044 }
1045
1046 return Metasync_Otto_Render_Strategy::get_diagnostics();
1047 }
1048
1049 /**
1050 * AJAX handler for testing OTTO API
1051 */
1052 public function ajax_test_otto_api() {
1053 check_ajax_referer('metasync_otto_debug', 'nonce');
1054
1055 if (!Metasync::current_user_has_plugin_access()) {
1056 wp_die('Unauthorized');
1057 }
1058
1059 $general_options = Metasync::get_option('general');
1060 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
1061
1062 if (empty($otto_uuid)) {
1063 wp_send_json_error(Metasync::get_whitelabel_otto_name() . ' UUID not configured');
1064 }
1065
1066 $test_url = get_site_url();
1067
1068 # Use endpoint manager to get the correct API URL
1069 $api_endpoint = class_exists('Metasync_Endpoint_Manager')
1070 ? Metasync_Endpoint_Manager::get_endpoint('OTTO_URL_DETAILS')
1071 : 'https://sa.searchatlas.com/api/v2/otto-url-details';
1072
1073 $api_url = add_query_arg(array(
1074 'url' => $test_url,
1075 'uuid' => $otto_uuid
1076 ), $api_endpoint);
1077
1078 $response = wp_remote_get($api_url, array(
1079 'timeout' => 30,
1080 'sslverify' => true,
1081 'headers' => array(
1082 'User-Agent' => 'MetaSync-WordPress-Plugin/1.0'
1083 )
1084 ));
1085
1086 if (is_wp_error($response)) {
1087 wp_send_json_error(array(
1088 'error' => $response->get_error_message(),
1089 'url' => $api_url
1090 ));
1091 }
1092
1093 $response_code = wp_remote_retrieve_response_code($response);
1094 $body = wp_remote_retrieve_body($response);
1095
1096 wp_send_json_success(array(
1097 'response_code' => $response_code,
1098 'url' => $api_url,
1099 'body' => $body,
1100 'has_data' => !empty($body),
1101 'data_valid' => json_decode($body, true) !== null
1102 ));
1103 }
1104
1105 /**
1106 * AJAX handler for testing notification endpoint
1107 */
1108 public function ajax_test_notification_endpoint() {
1109 check_ajax_referer('metasync_otto_debug', 'nonce');
1110
1111 if (!Metasync::current_user_has_plugin_access()) {
1112 wp_die('Unauthorized');
1113 }
1114
1115 $endpoint_url = rest_url('metasync/v1/otto_crawl_notify');
1116
1117 $test_data = array(
1118 'domain' => get_site_url(),
1119 'urls' => array('/', '/about/', '/contact/')
1120 );
1121
1122 $response = wp_remote_post($endpoint_url, array(
1123 'headers' => array(
1124 'Content-Type' => 'application/json'
1125 ),
1126 'body' => json_encode($test_data),
1127 'timeout' => 30
1128 ));
1129
1130 if (is_wp_error($response)) {
1131 wp_send_json_error(array(
1132 'error' => $response->get_error_message(),
1133 'url' => $endpoint_url
1134 ));
1135 }
1136
1137 $response_code = wp_remote_retrieve_response_code($response);
1138 $body = wp_remote_retrieve_body($response);
1139
1140 wp_send_json_success(array(
1141 'response_code' => $response_code,
1142 'url' => $endpoint_url,
1143 'body' => $body,
1144 'test_data' => $test_data
1145 ));
1146 }
1147
1148 /**
1149 * AJAX handler for clearing OTTO cache
1150 */
1151 public function ajax_clear_otto_cache() {
1152 check_ajax_referer('metasync_otto_debug', 'nonce');
1153
1154 if (!Metasync::current_user_has_plugin_access()) {
1155 wp_die('Unauthorized');
1156 }
1157
1158 // Clear crawl data
1159 delete_option('metasync_otto_crawldata');
1160
1161 // Clear any cached API responses
1162 $general_options = Metasync::get_option('general');
1163 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
1164
1165 if (!empty($otto_uuid)) {
1166 delete_transient(Metasync_Heartbeat_Manager::public_hash_cache_key($otto_uuid));
1167 }
1168
1169 delete_transient('metasync_otto_js_detected');
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