PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.6.5
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.6.5
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.5, at admin/class-metasync-otto-debug.php

1,588 lines 59.5 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 MetaSync 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 $cache_key = 'metasync_public_hash_' . md5($otto_uuid);
1167 delete_transient($cache_key);
1168 }
1169
1170 wp_send_json_success(array(
1171 'message' => Metasync::get_whitelabel_otto_name() . ' cache cleared successfully',
1172 'cleared_items' => array(
1173 'crawl_data' => true,
1174 'api_cache' => true
1175 )
1176 ));
1177 }
1178
1179 /**
1180 * AJAX handler for simulating crawl notification
1181 */
1182 public function ajax_simulate_crawl_notification() {
1183 check_ajax_referer('metasync_otto_debug', 'nonce');
1184
1185 if (!Metasync::current_user_has_plugin_access()) {
1186 wp_die('Unauthorized');
1187 }
1188
1189 $general_options = Metasync::get_option('general');
1190 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
1191
1192 if (empty($otto_uuid)) {
1193 wp_send_json_error(Metasync::get_whitelabel_otto_name() . ' UUID not configured');
1194 }
1195
1196 // Simulate crawl notification
1197 $test_data = array(
1198 'domain' => get_site_url(),
1199 'urls' => array('/', '/about/', '/contact/', '/blog/')
1200 );
1201
1202 // Create a mock request object
1203 $request = new WP_REST_Request('POST', '/metasync/v1/otto_crawl_notify');
1204 $request->set_body(json_encode($test_data));
1205
1206 // Call the notification handler
1207 $response = metasync_otto_crawl_notify($request);
1208
1209 wp_send_json_success(array(
1210 'message' => 'Crawl notification simulated',
1211 'test_data' => $test_data,
1212 'response' => $response->get_data(),
1213 'response_code' => $response->get_status()
1214 ));
1215 }
1216
1217 /**
1218 * AJAX handler for testing specific URL
1219 */
1220 public function ajax_test_specific_url() {
1221 try {
1222 check_ajax_referer('metasync_otto_debug', 'nonce');
1223
1224 if (!Metasync::current_user_has_plugin_access()) {
1225 wp_die('Unauthorized');
1226 }
1227
1228 $test_url = sanitize_url($_POST['test_url'] ?? '');
1229
1230 if (empty($test_url)) {
1231 wp_send_json_error('No URL provided');
1232 }
1233
1234 $results = array(
1235 'test_url' => $test_url,
1236 'timestamp' => current_time('mysql'),
1237 'tests' => array()
1238 );
1239
1240 // Test 1: URL Accessibility
1241 $results['tests']['url_accessibility'] = $this->test_url_accessibility($test_url);
1242
1243 // Test 2: OTTO API Data
1244 $results['tests']['otto_api_data'] = $this->test_otto_api_for_url($test_url);
1245
1246 // Test 3: Crawl Status
1247 $results['tests']['crawl_status'] = $this->test_crawl_status($test_url);
1248
1249 // Test 4: Page Type Detection
1250 $results['tests']['page_type_detection'] = $this->test_page_type_detection($test_url);
1251
1252 // Test 5: Processing Eligibility
1253 $results['tests']['processing_eligibility'] = $this->test_processing_eligibility($test_url);
1254
1255 wp_send_json_success($results);
1256
1257 } catch (Exception $e) {
1258 error_log('MetaSync OTTO Debug: Exception in ajax_test_specific_url: ' . $e->getMessage());
1259 wp_send_json_error('Exception: ' . $e->getMessage());
1260 }
1261 }
1262
1263 /**
1264 * AJAX handler for emulating OTTO changes
1265 */
1266 public function ajax_emulate_otto_changes() {
1267 check_ajax_referer('metasync_otto_debug', 'nonce');
1268
1269 if (!Metasync::current_user_has_plugin_access()) {
1270 wp_die('Unauthorized');
1271 }
1272
1273 $test_url = sanitize_url($_POST['test_url'] ?? '');
1274
1275 if (empty($test_url)) {
1276 wp_send_json_error('No URL provided');
1277 }
1278
1279 $results = array(
1280 'test_url' => $test_url,
1281 'timestamp' => current_time('mysql'),
1282 'emulation' => array()
1283 );
1284
1285 // Emulate OTTO processing
1286 $results['emulation'] = $this->emulate_otto_processing($test_url);
1287
1288 wp_send_json_success($results);
1289 }
1290
1291 /**
1292 * Test URL accessibility
1293 */
1294 private function test_url_accessibility($url) {
1295 $response = wp_remote_get($url, array(
1296 'timeout' => 10,
1297 'user-agent' => 'MetaSync Debug Tool'
1298 ));
1299
1300 if (is_wp_error($response)) {
1301 return array(
1302 'status' => 'error',
1303 'message' => $response->get_error_message(),
1304 'accessible' => false
1305 );
1306 }
1307
1308 $status_code = wp_remote_retrieve_response_code($response);
1309 $body = wp_remote_retrieve_body($response);
1310
1311 return array(
1312 'status' => 'success',
1313 'status_code' => $status_code,
1314 'accessible' => $status_code === 200,
1315 'content_length' => strlen($body),
1316 'headers' => wp_remote_retrieve_headers($response)->getAll()
1317 );
1318 }
1319
1320 /**
1321 * Test OTTO API data for specific URL
1322 */
1323 private function test_otto_api_for_url($url) {
1324 $general_options = Metasync::get_option('general');
1325 $otto_uuid = $general_options['otto_pixel_uuid'] ?? '';
1326
1327 if (empty($otto_uuid)) {
1328 return array(
1329 'status' => 'error',
1330 'message' => Metasync::get_whitelabel_otto_name() . ' UUID not configured'
1331 );
1332 }
1333
1334 // Use the existing OTTO API function
1335 if (function_exists('metasync_fetch_otto_seo_data')) {
1336 $data = metasync_fetch_otto_seo_data($url, $otto_uuid);
1337
1338 if (is_wp_error($data)) {
1339 return array(
1340 'status' => 'error',
1341 'message' => $data->get_error_message(),
1342 'has_data' => false
1343 );
1344 }
1345
1346 return array(
1347 'status' => 'success',
1348 'has_data' => !empty($data),
1349 'data_keys' => array_keys($data ?? array()),
1350 'recommendations_count' => count($data['recommendations'] ?? array()),
1351 'sample_data' => array_slice($data ?? array(), 0, 3) // First 3 items for preview
1352 );
1353 }
1354
1355 return array(
1356 'status' => 'error',
1357 'message' => Metasync::get_whitelabel_otto_name() . ' API function not available'
1358 );
1359 }
1360
1361 /**
1362 * Test crawl status for URL
1363 */
1364 private function test_crawl_status($url) {
1365 if (class_exists('Metasync_otto_pixel')) {
1366 $otto_pixel = new Metasync_otto_pixel(false);
1367 $is_crawled = $otto_pixel->is_url_crawled($url);
1368
1369 // Get crawl data from options
1370 $crawl_data = get_option('metasync_otto_crawldata');
1371
1372 return array(
1373 'status' => 'success',
1374 'is_crawled' => $is_crawled,
1375 'crawl_data' => $crawl_data,
1376 'total_crawled_urls' => count($crawl_data['urls'] ?? array()),
1377 'domain' => $crawl_data['domain'] ?? 'Not set'
1378 );
1379 }
1380
1381 return array(
1382 'status' => 'error',
1383 'message' => Metasync::get_whitelabel_otto_name() . ' pixel class not available'
1384 );
1385 }
1386
1387 /**
1388 * Test page type detection
1389 */
1390 private function test_page_type_detection($url) {
1391 $parsed_url = parse_url($url);
1392 $path = $parsed_url['path'] ?? '/';
1393
1394 $detection = array(
1395 'url' => $url,
1396 'path' => $path,
1397 'is_ajax' => strpos($path, 'wp-admin/admin-ajax.php') !== false,
1398 'is_woocommerce' => function_exists('is_woocommerce') ? false : 'WooCommerce not available',
1399 'is_admin' => strpos($path, '/wp-admin/') !== false,
1400 'is_login' => strpos($path, '/wp-login.php') !== false,
1401 'is_cron' => strpos($path, '/wp-cron.php') !== false,
1402 'is_xmlrpc' => strpos($path, '/xmlrpc.php') !== false
1403 );
1404
1405 // Check if it's a WooCommerce page
1406 if (function_exists('is_woocommerce')) {
1407 // This would need to be tested with actual page context
1408 $detection['is_woocommerce'] = 'Requires page context to determine';
1409 }
1410
1411 return $detection;
1412 }
1413
1414 /**
1415 * Test processing eligibility
1416 */
1417 private function test_processing_eligibility($url) {
1418 $general_options = Metasync::get_option('general');
1419 // OTTO SSR is always enabled by default
1420 $otto_enabled = true;
1421 $disable_logged_in = $general_options['otto_disable_on_loggedin'] ?? false;
1422
1423 $eligibility = array(
1424 'otto_enabled' => $otto_enabled,
1425 'disable_logged_in' => $disable_logged_in,
1426 'user_logged_in' => is_user_logged_in(),
1427 'eligible_for_processing' => false,
1428 'exclusion_reasons' => array()
1429 );
1430
1431 // OTTO SSR is always enabled, so this check is no longer needed
1432
1433 if ($disable_logged_in && is_user_logged_in()) {
1434 $eligibility['exclusion_reasons'][] = 'User is logged in and ' . Metasync::get_whitelabel_otto_name() . ' disabled for logged-in users';
1435 }
1436
1437 $eligibility['eligible_for_processing'] = empty($eligibility['exclusion_reasons']);
1438
1439 return $eligibility;
1440 }
1441
1442 /**
1443 * Emulate OTTO processing
1444 */
1445 private function emulate_otto_processing($url) {
1446 $emulation = array(
1447 'url' => $url,
1448 'steps' => array(),
1449 'errors' => array(),
1450 'changes_applied' => array()
1451 );
1452
1453 // Step 1: Check if URL is crawled
1454 $emulation['steps']['check_crawled'] = $this->test_crawl_status($url);
1455
1456 // Step 2: Fetch OTTO data
1457 $emulation['steps']['fetch_otto_data'] = $this->test_otto_api_for_url($url);
1458
1459 // Step 3: Simulate HTML processing
1460 if (class_exists('Metasync_otto_html')) {
1461 try {
1462 $otto_html = new Metasync_otto_html(false);
1463 $emulation['steps']['html_processing'] = array(
1464 'status' => 'success',
1465 'message' => Metasync::get_whitelabel_otto_name() . ' HTML class available'
1466 );
1467
1468 // Simulate processing (without actually modifying files)
1469 $emulation['changes_applied'] = array(
1470 'header_changes' => 'Simulated header modifications',
1471 'body_changes' => 'Simulated body modifications',
1472 'footer_changes' => 'Simulated footer modifications'
1473 );
1474
1475 } catch (Exception $e) {
1476 $emulation['errors'][] = 'HTML processing error: ' . $e->getMessage();
1477 }
1478 } else {
1479 $emulation['errors'][] = Metasync::get_whitelabel_otto_name() . ' HTML class not available';
1480 }
1481
1482 return $emulation;
1483 }
1484
1485 /**
1486 * Simple AJAX test to verify basic functionality
1487 */
1488 public function ajax_simple_test() {
1489 try {
1490 check_ajax_referer('metasync_otto_debug', 'nonce');
1491
1492 if (!Metasync::current_user_has_plugin_access()) {
1493 wp_send_json_error('Unauthorized');
1494 }
1495
1496 wp_send_json_success(array(
1497 'message' => 'AJAX is working!',
1498 'timestamp' => current_time('mysql'),
1499 'user_id' => get_current_user_id(),
1500 'nonce_verified' => true
1501 ));
1502
1503 } catch (Exception $e) {
1504 error_log('MetaSync OTTO Debug: Exception in ajax_simple_test: ' . $e->getMessage());
1505 wp_send_json_error('Exception: ' . $e->getMessage());
1506 }
1507 }
1508
1509 /**
1510 * AJAX handler for testing database permissions
1511 */
1512 public function ajax_test_db_permissions() {
1513 try {
1514 check_ajax_referer('metasync_otto_debug', 'nonce');
1515
1516 if (!Metasync::current_user_has_plugin_access()) {
1517 wp_send_json_error('Unauthorized');
1518 }
1519
1520 $results = array(
1521 'timestamp' => current_time('mysql'),
1522 'tests' => array()
1523 );
1524
1525 // Test 1: Try to schedule a simple action
1526 $test_action = 'metasync_debug_test_action';
1527 $scheduled = wp_schedule_single_event(time() + 60, $test_action, array('test' => 'data'));
1528
1529 $results['tests']['action_scheduler'] = array(
1530 'can_schedule' => $scheduled !== false,
1531 'scheduled' => $scheduled,
1532 'message' => $scheduled !== false ? 'Action Scheduler working' : 'Action Scheduler failed - likely database permissions issue'
1533 );
1534
1535 // Test 2: Check if we can access Action Scheduler tables
1536 global $wpdb;
1537 $table_name = $wpdb->prefix . 'actionscheduler_actions';
1538 $table_exists = $wpdb->get_var("SHOW TABLES LIKE '$table_name'") == $table_name;
1539
1540 $results['tests']['table_access'] = array(
1541 'table_exists' => $table_exists,
1542 'table_name' => $table_name,
1543 'message' => $table_exists ? 'Action Scheduler table exists' : 'Action Scheduler table not found'
1544 );
1545
1546 // Test 3: Try to insert a test record
1547 if ($table_exists) {
1548 $insert_result = $wpdb->insert(
1549 $table_name,
1550 array(
1551 'hook' => 'metasync_debug_test',
1552 'status' => 'pending',
1553 'scheduled_date_gmt' => current_time('mysql', 1),
1554 'args' => json_encode(array('test' => true)),
1555 'schedule' => 'once'
1556 ),
1557 array('%s', '%s', '%s', '%s', '%s')
1558 );
1559
1560 $results['tests']['insert_test'] = array(
1561 'can_insert' => $insert_result !== false,
1562 'insert_id' => $wpdb->insert_id,
1563 'last_error' => $wpdb->last_error,
1564 'message' => $insert_result !== false ? 'Can insert records' : 'Cannot insert records - ' . $wpdb->last_error
1565 );
1566
1567 // Clean up test record
1568 if ($insert_result !== false && $wpdb->insert_id) {
1569 $wpdb->delete($table_name, array('ID' => $wpdb->insert_id));
1570 }
1571 }
1572
1573 // Test 4: Check WordPress cron functionality
1574 $cron_disabled = defined('DISABLE_WP_CRON') && DISABLE_WP_CRON;
1575 $results['tests']['wp_cron'] = array(
1576 'enabled' => !$cron_disabled,
1577 'message' => $cron_disabled ? 'WordPress cron is disabled' : 'WordPress cron is enabled'
1578 );
1579
1580 wp_send_json_success($results);
1581
1582 } catch (Exception $e) {
1583 error_log('MetaSync OTTO Debug: Exception in ajax_test_db_permissions: ' . $e->getMessage());
1584 wp_send_json_error('Exception: ' . $e->getMessage());
1585 }
1586 }
1587 }
1588