Changeset 3402172
- Timestamp:
- 11/25/2025 03:29:10 AM (3 months ago)
- Location:
- nudgify
- Files:
-
- 3 edited
- 56 copied
-
tags/1.3.12 (copied) (copied from nudgify/trunk)
-
tags/1.3.12/includes/functions.php (copied) (copied from nudgify/trunk/includes/functions.php)
-
tags/1.3.12/includes/options.php (copied) (copied from nudgify/trunk/includes/options.php)
-
tags/1.3.12/includes/settings.php (copied) (copied from nudgify/trunk/includes/settings.php)
-
tags/1.3.12/nudgify.php (copied) (copied from nudgify/trunk/nudgify.php) (2 diffs)
-
tags/1.3.12/readme.txt (copied) (copied from nudgify/trunk/readme.txt)
-
tags/1.3.12/sentry/NudgifySentryBreadcrumb.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryBreadcrumb.php)
-
tags/1.3.12/sentry/NudgifySentryBreadcrumbLogger.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryBreadcrumbLogger.php)
-
tags/1.3.12/sentry/NudgifySentryBrowserContext.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryBrowserContext.php)
-
tags/1.3.12/sentry/NudgifySentryBufferedEventCapture.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryBufferedEventCapture.php)
-
tags/1.3.12/sentry/NudgifySentryClient.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryClient.php)
-
tags/1.3.12/sentry/NudgifySentryClientExtension.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryClientExtension.php)
-
tags/1.3.12/sentry/NudgifySentryClientIPDetector.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryClientIPDetector.php)
-
tags/1.3.12/sentry/NudgifySentryClientSniffer.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryClientSniffer.php)
-
tags/1.3.12/sentry/NudgifySentryDSN.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryDSN.php)
-
tags/1.3.12/sentry/NudgifySentryDirectEventCapture.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryDirectEventCapture.php)
-
tags/1.3.12/sentry/NudgifySentryEnvironmentReporter.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryEnvironmentReporter.php)
-
tags/1.3.12/sentry/NudgifySentryEvent.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryEvent.php)
-
tags/1.3.12/sentry/NudgifySentryEventCapture.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryEventCapture.php)
-
tags/1.3.12/sentry/NudgifySentryExceptionList.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryExceptionList.php)
-
tags/1.3.12/sentry/NudgifySentryExceptionReporter.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryExceptionReporter.php)
-
tags/1.3.12/sentry/NudgifySentryLevel.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryLevel.php)
-
tags/1.3.12/sentry/NudgifySentryOSContext.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryOSContext.php)
-
tags/1.3.12/sentry/NudgifySentryRequest.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryRequest.php)
-
tags/1.3.12/sentry/NudgifySentryRequestReporter.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryRequestReporter.php)
-
tags/1.3.12/sentry/NudgifySentryRuntimeContext.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryRuntimeContext.php)
-
tags/1.3.12/sentry/NudgifySentryStackTrace.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryStackTrace.php)
-
tags/1.3.12/sentry/autoload.php (copied) (copied from nudgify/trunk/sentry/autoload.php)
-
tags/1.3.14 (copied) (copied from nudgify/trunk)
-
tags/1.3.14/includes/functions.php (copied) (copied from nudgify/trunk/includes/functions.php)
-
tags/1.3.14/includes/options.php (copied) (copied from nudgify/trunk/includes/options.php) (4 diffs)
-
tags/1.3.14/includes/settings.php (copied) (copied from nudgify/trunk/includes/settings.php)
-
tags/1.3.14/nudgify.php (copied) (copied from nudgify/trunk/nudgify.php) (12 diffs)
-
tags/1.3.14/readme.txt (copied) (copied from nudgify/trunk/readme.txt) (2 diffs)
-
tags/1.3.14/sentry/NudgifySentryBreadcrumb.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryBreadcrumb.php)
-
tags/1.3.14/sentry/NudgifySentryBreadcrumbLogger.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryBreadcrumbLogger.php)
-
tags/1.3.14/sentry/NudgifySentryBrowserContext.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryBrowserContext.php)
-
tags/1.3.14/sentry/NudgifySentryBufferedEventCapture.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryBufferedEventCapture.php)
-
tags/1.3.14/sentry/NudgifySentryClient.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryClient.php)
-
tags/1.3.14/sentry/NudgifySentryClientExtension.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryClientExtension.php)
-
tags/1.3.14/sentry/NudgifySentryClientIPDetector.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryClientIPDetector.php)
-
tags/1.3.14/sentry/NudgifySentryClientSniffer.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryClientSniffer.php)
-
tags/1.3.14/sentry/NudgifySentryDSN.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryDSN.php)
-
tags/1.3.14/sentry/NudgifySentryDirectEventCapture.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryDirectEventCapture.php)
-
tags/1.3.14/sentry/NudgifySentryEnvironmentReporter.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryEnvironmentReporter.php)
-
tags/1.3.14/sentry/NudgifySentryEvent.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryEvent.php)
-
tags/1.3.14/sentry/NudgifySentryEventCapture.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryEventCapture.php)
-
tags/1.3.14/sentry/NudgifySentryExceptionList.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryExceptionList.php)
-
tags/1.3.14/sentry/NudgifySentryExceptionReporter.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryExceptionReporter.php)
-
tags/1.3.14/sentry/NudgifySentryLevel.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryLevel.php)
-
tags/1.3.14/sentry/NudgifySentryOSContext.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryOSContext.php)
-
tags/1.3.14/sentry/NudgifySentryRequest.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryRequest.php)
-
tags/1.3.14/sentry/NudgifySentryRequestReporter.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryRequestReporter.php)
-
tags/1.3.14/sentry/NudgifySentryRuntimeContext.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryRuntimeContext.php)
-
tags/1.3.14/sentry/NudgifySentryStackTrace.php (copied) (copied from nudgify/trunk/sentry/NudgifySentryStackTrace.php)
-
tags/1.3.14/sentry/autoload.php (copied) (copied from nudgify/trunk/sentry/autoload.php)
-
trunk/includes/options.php (modified) (4 diffs)
-
trunk/nudgify.php (modified) (12 diffs)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
nudgify/tags/1.3.12/nudgify.php
r3399921 r3402172 163 163 } 164 164 165 // JSON encode for safe JavaScript output 166 $uuid = wp_json_encode($uuid); 167 $url = wp_json_encode(NUDGIFY_PIXEL_BASE.'/pixel.js'); 165 // These will be properly escaped with esc_js() when output 166 $url = NUDGIFY_PIXEL_BASE.'/pixel.js'; 168 167 169 168 $pixelData = []; … … 231 230 echo '(function(w){' . "\n"; 232 231 echo ' var k="nudgify",n=w[k]||(w[k]={});' . "\n"; 233 echo ' n.uuid=' . esc_js($uuid) . ';' . "\n";232 echo ' n.uuid=' . wp_json_encode($uuid) . ';' . "\n"; 234 233 echo ' var d=document,s=d.createElement("script");' . "\n"; 235 echo ' s.src=' . esc_js($url) . ';' . "\n";234 echo ' s.src=' . wp_json_encode($url) . ';' . "\n"; 236 235 echo ' s.async=1;' . "\n"; 237 236 echo ' s.charset="utf-8";' . "\n"; -
nudgify/tags/1.3.14/includes/options.php
r3399921 r3402172 93 93 <h2>Sync orders</h2> 94 94 <?php echo wp_kses_post(nudgify_feedback_message('manualsync')); ?> 95 <form action="<?php echo esc_url(admin_url('admin .php')); ?>" method="post" id="nudgify-form-manualsync">95 <form action="<?php echo esc_url(admin_url('admin-post.php')); ?>" method="post" id="nudgify-form-manualsync"> 96 96 <input type="hidden" name="action" value="<?php echo esc_attr(NudgifyOptions::DO_MANUAL_SYNC); ?>" /> 97 97 <input type="hidden" name="nudgify_manual_sync_nonce" value="<?php echo esc_attr(wp_create_nonce('nudgify_manual_sync_nonce')); ?>" /> … … 103 103 <p class="description"> 104 104 This will send the last 30 orders to Nudgify 105 </p> 106 </td> 107 </tr> 108 <tr> 109 <td colspan="2"> 110 <p style="background: #f0f0f1; padding: 10px; border-left: 4px solid #2271b1;"> 111 <strong>Debug Info:</strong><br> 112 Action: <code><?php echo esc_html(NudgifyOptions::DO_MANUAL_SYNC); ?></code><br> 113 Form submits to: <code><?php echo esc_html(admin_url('admin-post.php')); ?></code><br> 114 Expected URL: <code><?php echo esc_html(admin_url('admin-post.php?action=' . NudgifyOptions::DO_MANUAL_SYNC)); ?></code> 105 115 </p> 106 116 </td> … … 151 161 var buttonText = button.val(); 152 162 var feedback = form.find('.nudgify-feedback'); 153 163 164 // Get the action value from hidden input 165 var actionValue = form.find('input[name="action"]').val(); 166 var ajaxEndpoint = window.ajaxurl || '<?php echo esc_js(admin_url('admin-ajax.php')); ?>'; 167 var ajaxUrl = ajaxEndpoint + '?action=' + actionValue; 168 169 console.log('[Nudgify AJAX] Submitting to:', ajaxUrl); 170 console.log('[Nudgify AJAX] Form data:', form.serialize()); 171 154 172 jQuery.ajax({ 155 173 type: "POST", 156 url: form.attr('action'),174 url: ajaxUrl, 157 175 data: form.serialize(), 158 176 beforeSend: function() { … … 162 180 }, 163 181 success: function(data) { 182 console.log('[Nudgify AJAX] Success response:', data); 164 183 button.prop('disabled', false); 165 184 button.val(buttonText); 166 185 feedback.html(data); 186 }, 187 error: function(xhr, status, error) { 188 console.error('[Nudgify AJAX] Error:', status, error); 189 console.error('[Nudgify AJAX] Response:', xhr.responseText); 190 button.prop('disabled', false); 191 button.val(buttonText); 192 feedback.html('<div class="notice notice-error"><p>Error: ' + error + '</p></div>'); 167 193 } 168 194 }); -
nudgify/tags/1.3.14/nudgify.php
r3399921 r3402172 5 5 Description: Install Nudgify on your WordPress website in less then 10 seconds. Integrate unique tracking code of Nudgify into every page of your website in one click. 6 6 Author: Nudgify 7 Version: 1.3.1 27 Version: 1.3.14 8 8 Author URI: https://nudgify.com 9 9 License: GPLv2 … … 13 13 defined('ABSPATH') or exit('Restricted access!'); 14 14 15 define('NUDGIFY_PLUGIN_VERSION', '1.3.1 2');15 define('NUDGIFY_PLUGIN_VERSION', '1.3.14'); 16 16 define('NUDGIFY_PLUGIN_SLUG', 'nudgify'); 17 17 define('NUDGIFY_PLUGIN_URL', plugin_dir_url(__FILE__)); … … 91 91 add_action('update_option_'.NudgifyOptions::SITE_KEY, [$this, 'connect'], 999, 0); 92 92 add_action('update_option_'.NudgifyOptions::API_TOKEN, [$this, 'connect'], 999, 0); 93 94 add_action('admin_action_'.NudgifyOptions::DO_MANUAL_SYNC, [$this, 'sync_orders_manually']); 95 add_action('admin_post_'.NudgifyOptions::DO_MANUAL_SYNC, [$this, 'sync_orders_manually']); 96 add_action('wp_ajax_'.NudgifyOptions::DO_MANUAL_SYNC, [$this, 'sync_orders_manually']); 93 97 } 94 98 95 99 public function init_woocommerce_orders() 96 100 { 101 // Log whether WooCommerce is detected using WooCommerce logger 102 if (function_exists('wc_get_logger')) { 103 $logger = wc_get_logger(); 104 $logger->info('init_woocommerce_orders called', ['source' => 'nudgify-init']); 105 $logger->info('WooCommerce enabled: ' . (nudgify_woocommerce_enabled() ? 'YES' : 'NO'), ['source' => 'nudgify-init']); 106 $logger->info('class_exists(WooCommerce): ' . (class_exists('WooCommerce') ? 'YES' : 'NO'), ['source' => 'nudgify-init']); 107 $logger->info('function_exists(WC): ' . (function_exists('WC') ? 'YES' : 'NO'), ['source' => 'nudgify-init']); 108 } 109 97 110 if (! nudgify_woocommerce_enabled()) { 98 return; 99 } 100 101 add_action('admin_action_'.NudgifyOptions::DO_MANUAL_SYNC, [$this, 'sync_orders_manually']); 111 if (function_exists('wc_get_logger')) { 112 $logger = wc_get_logger(); 113 $logger->error('Exiting init_woocommerce_orders - WooCommerce not enabled', ['source' => 'nudgify-init']); 114 } 115 return; 116 } 117 118 if (function_exists('wc_get_logger')) { 119 $logger = wc_get_logger(); 120 $logger->info('Registering WooCommerce hooks...', ['source' => 'nudgify-init']); 121 $logger->info('Registering Nudgify WooCommerce hooks', ['source' => 'nudgify-init']); 122 $logger->info('Manual sync action: admin_post_' . NudgifyOptions::DO_MANUAL_SYNC, ['source' => 'nudgify-init']); 123 $logger->info('About to register action: admin_post_' . NudgifyOptions::DO_MANUAL_SYNC, ['source' => 'nudgify-init']); 124 } 125 102 126 add_action('woocommerce_new_order', [$this, 'post_woocommerce_order']); 103 127 add_action('woocommerce_add_to_cart', [$this, 'post_woocommerce_add_to_cart'], 10, 6); … … 163 187 } 164 188 165 // JSON encode for safe JavaScript output 166 $uuid = wp_json_encode($uuid); 167 $url = wp_json_encode(NUDGIFY_PIXEL_BASE.'/pixel.js'); 189 // These will be properly escaped with esc_js() when output 190 $url = NUDGIFY_PIXEL_BASE.'/pixel.js'; 168 191 169 192 $pixelData = []; … … 231 254 echo '(function(w){' . "\n"; 232 255 echo ' var k="nudgify",n=w[k]||(w[k]={});' . "\n"; 233 echo ' n.uuid=' . esc_js($uuid) . ';' . "\n";256 echo ' n.uuid=' . wp_json_encode($uuid) . ';' . "\n"; 234 257 echo ' var d=document,s=d.createElement("script");' . "\n"; 235 echo ' s.src=' . esc_js($url) . ';' . "\n";258 echo ' s.src=' . wp_json_encode($url) . ';' . "\n"; 236 259 echo ' s.async=1;' . "\n"; 237 260 echo ' s.charset="utf-8";' . "\n"; … … 388 411 } 389 412 413 private function log_sync($level, $message, $context = []) 414 { 415 if (function_exists('wc_get_logger')) { 416 $logger = wc_get_logger(); 417 $context['source'] = 'nudgify-manual-sync'; 418 $logger->log($level, $message, $context); 419 } 420 } 421 390 422 public function sync_orders_manually() 391 423 { 424 $this->log_sync('info', 'Starting manual order sync...'); 425 392 426 if (! current_user_can('manage_options')) { 427 $this->log_sync('error', 'User does not have manage_options capability'); 393 428 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '419')); 394 429 … … 399 434 400 435 if (! wp_verify_nonce($nonce, 'nudgify_manual_sync_nonce')) { 436 $this->log_sync('error', 'Nonce verification failed'); 401 437 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '419')); 402 438 403 439 exit(); 404 440 } 441 442 $this->log_sync('info', 'Nonce verified successfully'); 405 443 406 444 $enabled = get_option(NudgifyOptions::ENABLED, true); … … 408 446 $apiToken = get_option(NudgifyOptions::API_TOKEN); 409 447 448 $this->log_sync('info', 'Settings check', [ 449 'enabled' => $enabled ? 'Yes' : 'No', 450 'site_key' => $siteKey ? 'Present' : 'Missing', 451 'api_token' => $apiToken ? 'Present' : 'Missing' 452 ]); 453 410 454 if (! (nudgify_woocommerce_enabled() && $enabled)) { 455 $this->log_sync('error', 'WooCommerce not enabled or Nudgify disabled'); 411 456 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '423')); 412 457 … … 415 460 416 461 if (! ($siteKey && $apiToken)) { 462 $this->log_sync('error', 'Missing Site Key or API Token'); 417 463 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '424')); 418 464 … … 428 474 return ! in_array($status, ['wc-refunded', 'wc-cancelled']); 429 475 }); 476 477 $this->log_sync('info', 'Accepted order statuses: ' . implode(', ', $acceptedStatuses)); 430 478 431 479 $orders = wc_get_orders([ … … 436 484 ]); 437 485 486 $this->log_sync('info', 'Found ' . count($orders) . ' orders to sync'); 487 438 488 foreach ($orders as $order) { 439 489 // guard agains OrderRefund or OrderCancelled 440 490 if (! method_exists($order, 'get_billing_last_name')) { 491 $this->log_sync('warning', 'Skipping order ID ' . $order->get_id() . ' - missing get_billing_last_name method'); 441 492 continue; 442 493 } … … 446 497 447 498 $data['orders'][] = $orderData; 448 } 499 $this->log_sync('debug', 'Prepared order ID: ' . $order->get_id()); 500 } 501 502 $this->log_sync('info', 'Sending ' . count($data['orders']) . ' orders to Nudgify API', [ 503 'endpoint' => NUDGIFY_ENDPOINT_SYNC, 504 'order_count' => count($data['orders']) 505 ]); 449 506 450 507 $response = $this->post(NUDGIFY_ENDPOINT_SYNC, $data, $apiToken); 508 509 $this->log_sync('info', 'API Response received', [ 510 'code' => $response['code'], 511 'successful' => $response['successful'] ? 'Yes' : 'No' 512 ]); 513 514 if (isset($response['message'])) { 515 $this->log_sync('info', 'API Response Message: ' . $response['message']); 516 } 451 517 452 518 if ($response['successful']) { 453 519 update_option(NudgifyOptions::CONNECTED, 1); 454 } 455 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '200')); 520 $this->log_sync('info', 'SUCCESS: Orders synced successfully'); 521 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '200')); 522 } else { 523 $this->log_sync('error', 'FAILED: Orders sync failed', [ 524 'code' => $response['code'], 525 'message' => isset($response['message']) ? $response['message'] : 'No message' 526 ]); 527 echo wp_kses_post(nudgify_build_feedback_message('manualsync', $response['code'])); 528 } 456 529 457 530 exit(); -
nudgify/tags/1.3.14/readme.txt
r3399921 r3402172 5 5 Requires at least: 4.6 6 6 Tested up to: 6.8 7 Stable tag: 1.3.1 27 Stable tag: 1.3.14 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 122 122 123 123 Our pricing is per website. That means that you can add as many websites to your Nudgify account as you like, and multiply your plan price by the number of websites you have, e.g. if you use our Lite plan on 2 websites, it will cost 2x $0.99 = $1.98/month. 124 -
nudgify/trunk/includes/options.php
r3399921 r3402172 93 93 <h2>Sync orders</h2> 94 94 <?php echo wp_kses_post(nudgify_feedback_message('manualsync')); ?> 95 <form action="<?php echo esc_url(admin_url('admin .php')); ?>" method="post" id="nudgify-form-manualsync">95 <form action="<?php echo esc_url(admin_url('admin-post.php')); ?>" method="post" id="nudgify-form-manualsync"> 96 96 <input type="hidden" name="action" value="<?php echo esc_attr(NudgifyOptions::DO_MANUAL_SYNC); ?>" /> 97 97 <input type="hidden" name="nudgify_manual_sync_nonce" value="<?php echo esc_attr(wp_create_nonce('nudgify_manual_sync_nonce')); ?>" /> … … 103 103 <p class="description"> 104 104 This will send the last 30 orders to Nudgify 105 </p> 106 </td> 107 </tr> 108 <tr> 109 <td colspan="2"> 110 <p style="background: #f0f0f1; padding: 10px; border-left: 4px solid #2271b1;"> 111 <strong>Debug Info:</strong><br> 112 Action: <code><?php echo esc_html(NudgifyOptions::DO_MANUAL_SYNC); ?></code><br> 113 Form submits to: <code><?php echo esc_html(admin_url('admin-post.php')); ?></code><br> 114 Expected URL: <code><?php echo esc_html(admin_url('admin-post.php?action=' . NudgifyOptions::DO_MANUAL_SYNC)); ?></code> 105 115 </p> 106 116 </td> … … 151 161 var buttonText = button.val(); 152 162 var feedback = form.find('.nudgify-feedback'); 153 163 164 // Get the action value from hidden input 165 var actionValue = form.find('input[name="action"]').val(); 166 var ajaxEndpoint = window.ajaxurl || '<?php echo esc_js(admin_url('admin-ajax.php')); ?>'; 167 var ajaxUrl = ajaxEndpoint + '?action=' + actionValue; 168 169 console.log('[Nudgify AJAX] Submitting to:', ajaxUrl); 170 console.log('[Nudgify AJAX] Form data:', form.serialize()); 171 154 172 jQuery.ajax({ 155 173 type: "POST", 156 url: form.attr('action'),174 url: ajaxUrl, 157 175 data: form.serialize(), 158 176 beforeSend: function() { … … 162 180 }, 163 181 success: function(data) { 182 console.log('[Nudgify AJAX] Success response:', data); 164 183 button.prop('disabled', false); 165 184 button.val(buttonText); 166 185 feedback.html(data); 186 }, 187 error: function(xhr, status, error) { 188 console.error('[Nudgify AJAX] Error:', status, error); 189 console.error('[Nudgify AJAX] Response:', xhr.responseText); 190 button.prop('disabled', false); 191 button.val(buttonText); 192 feedback.html('<div class="notice notice-error"><p>Error: ' + error + '</p></div>'); 167 193 } 168 194 }); -
nudgify/trunk/nudgify.php
r3399921 r3402172 5 5 Description: Install Nudgify on your WordPress website in less then 10 seconds. Integrate unique tracking code of Nudgify into every page of your website in one click. 6 6 Author: Nudgify 7 Version: 1.3.1 27 Version: 1.3.14 8 8 Author URI: https://nudgify.com 9 9 License: GPLv2 … … 13 13 defined('ABSPATH') or exit('Restricted access!'); 14 14 15 define('NUDGIFY_PLUGIN_VERSION', '1.3.1 2');15 define('NUDGIFY_PLUGIN_VERSION', '1.3.14'); 16 16 define('NUDGIFY_PLUGIN_SLUG', 'nudgify'); 17 17 define('NUDGIFY_PLUGIN_URL', plugin_dir_url(__FILE__)); … … 91 91 add_action('update_option_'.NudgifyOptions::SITE_KEY, [$this, 'connect'], 999, 0); 92 92 add_action('update_option_'.NudgifyOptions::API_TOKEN, [$this, 'connect'], 999, 0); 93 94 add_action('admin_action_'.NudgifyOptions::DO_MANUAL_SYNC, [$this, 'sync_orders_manually']); 95 add_action('admin_post_'.NudgifyOptions::DO_MANUAL_SYNC, [$this, 'sync_orders_manually']); 96 add_action('wp_ajax_'.NudgifyOptions::DO_MANUAL_SYNC, [$this, 'sync_orders_manually']); 93 97 } 94 98 95 99 public function init_woocommerce_orders() 96 100 { 101 // Log whether WooCommerce is detected using WooCommerce logger 102 if (function_exists('wc_get_logger')) { 103 $logger = wc_get_logger(); 104 $logger->info('init_woocommerce_orders called', ['source' => 'nudgify-init']); 105 $logger->info('WooCommerce enabled: ' . (nudgify_woocommerce_enabled() ? 'YES' : 'NO'), ['source' => 'nudgify-init']); 106 $logger->info('class_exists(WooCommerce): ' . (class_exists('WooCommerce') ? 'YES' : 'NO'), ['source' => 'nudgify-init']); 107 $logger->info('function_exists(WC): ' . (function_exists('WC') ? 'YES' : 'NO'), ['source' => 'nudgify-init']); 108 } 109 97 110 if (! nudgify_woocommerce_enabled()) { 98 return; 99 } 100 101 add_action('admin_action_'.NudgifyOptions::DO_MANUAL_SYNC, [$this, 'sync_orders_manually']); 111 if (function_exists('wc_get_logger')) { 112 $logger = wc_get_logger(); 113 $logger->error('Exiting init_woocommerce_orders - WooCommerce not enabled', ['source' => 'nudgify-init']); 114 } 115 return; 116 } 117 118 if (function_exists('wc_get_logger')) { 119 $logger = wc_get_logger(); 120 $logger->info('Registering WooCommerce hooks...', ['source' => 'nudgify-init']); 121 $logger->info('Registering Nudgify WooCommerce hooks', ['source' => 'nudgify-init']); 122 $logger->info('Manual sync action: admin_post_' . NudgifyOptions::DO_MANUAL_SYNC, ['source' => 'nudgify-init']); 123 $logger->info('About to register action: admin_post_' . NudgifyOptions::DO_MANUAL_SYNC, ['source' => 'nudgify-init']); 124 } 125 102 126 add_action('woocommerce_new_order', [$this, 'post_woocommerce_order']); 103 127 add_action('woocommerce_add_to_cart', [$this, 'post_woocommerce_add_to_cart'], 10, 6); … … 163 187 } 164 188 165 // JSON encode for safe JavaScript output 166 $uuid = wp_json_encode($uuid); 167 $url = wp_json_encode(NUDGIFY_PIXEL_BASE.'/pixel.js'); 189 // These will be properly escaped with esc_js() when output 190 $url = NUDGIFY_PIXEL_BASE.'/pixel.js'; 168 191 169 192 $pixelData = []; … … 231 254 echo '(function(w){' . "\n"; 232 255 echo ' var k="nudgify",n=w[k]||(w[k]={});' . "\n"; 233 echo ' n.uuid=' . esc_js($uuid) . ';' . "\n";256 echo ' n.uuid=' . wp_json_encode($uuid) . ';' . "\n"; 234 257 echo ' var d=document,s=d.createElement("script");' . "\n"; 235 echo ' s.src=' . esc_js($url) . ';' . "\n";258 echo ' s.src=' . wp_json_encode($url) . ';' . "\n"; 236 259 echo ' s.async=1;' . "\n"; 237 260 echo ' s.charset="utf-8";' . "\n"; … … 388 411 } 389 412 413 private function log_sync($level, $message, $context = []) 414 { 415 if (function_exists('wc_get_logger')) { 416 $logger = wc_get_logger(); 417 $context['source'] = 'nudgify-manual-sync'; 418 $logger->log($level, $message, $context); 419 } 420 } 421 390 422 public function sync_orders_manually() 391 423 { 424 $this->log_sync('info', 'Starting manual order sync...'); 425 392 426 if (! current_user_can('manage_options')) { 427 $this->log_sync('error', 'User does not have manage_options capability'); 393 428 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '419')); 394 429 … … 399 434 400 435 if (! wp_verify_nonce($nonce, 'nudgify_manual_sync_nonce')) { 436 $this->log_sync('error', 'Nonce verification failed'); 401 437 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '419')); 402 438 403 439 exit(); 404 440 } 441 442 $this->log_sync('info', 'Nonce verified successfully'); 405 443 406 444 $enabled = get_option(NudgifyOptions::ENABLED, true); … … 408 446 $apiToken = get_option(NudgifyOptions::API_TOKEN); 409 447 448 $this->log_sync('info', 'Settings check', [ 449 'enabled' => $enabled ? 'Yes' : 'No', 450 'site_key' => $siteKey ? 'Present' : 'Missing', 451 'api_token' => $apiToken ? 'Present' : 'Missing' 452 ]); 453 410 454 if (! (nudgify_woocommerce_enabled() && $enabled)) { 455 $this->log_sync('error', 'WooCommerce not enabled or Nudgify disabled'); 411 456 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '423')); 412 457 … … 415 460 416 461 if (! ($siteKey && $apiToken)) { 462 $this->log_sync('error', 'Missing Site Key or API Token'); 417 463 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '424')); 418 464 … … 428 474 return ! in_array($status, ['wc-refunded', 'wc-cancelled']); 429 475 }); 476 477 $this->log_sync('info', 'Accepted order statuses: ' . implode(', ', $acceptedStatuses)); 430 478 431 479 $orders = wc_get_orders([ … … 436 484 ]); 437 485 486 $this->log_sync('info', 'Found ' . count($orders) . ' orders to sync'); 487 438 488 foreach ($orders as $order) { 439 489 // guard agains OrderRefund or OrderCancelled 440 490 if (! method_exists($order, 'get_billing_last_name')) { 491 $this->log_sync('warning', 'Skipping order ID ' . $order->get_id() . ' - missing get_billing_last_name method'); 441 492 continue; 442 493 } … … 446 497 447 498 $data['orders'][] = $orderData; 448 } 499 $this->log_sync('debug', 'Prepared order ID: ' . $order->get_id()); 500 } 501 502 $this->log_sync('info', 'Sending ' . count($data['orders']) . ' orders to Nudgify API', [ 503 'endpoint' => NUDGIFY_ENDPOINT_SYNC, 504 'order_count' => count($data['orders']) 505 ]); 449 506 450 507 $response = $this->post(NUDGIFY_ENDPOINT_SYNC, $data, $apiToken); 508 509 $this->log_sync('info', 'API Response received', [ 510 'code' => $response['code'], 511 'successful' => $response['successful'] ? 'Yes' : 'No' 512 ]); 513 514 if (isset($response['message'])) { 515 $this->log_sync('info', 'API Response Message: ' . $response['message']); 516 } 451 517 452 518 if ($response['successful']) { 453 519 update_option(NudgifyOptions::CONNECTED, 1); 454 } 455 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '200')); 520 $this->log_sync('info', 'SUCCESS: Orders synced successfully'); 521 echo wp_kses_post(nudgify_build_feedback_message('manualsync', '200')); 522 } else { 523 $this->log_sync('error', 'FAILED: Orders sync failed', [ 524 'code' => $response['code'], 525 'message' => isset($response['message']) ? $response['message'] : 'No message' 526 ]); 527 echo wp_kses_post(nudgify_build_feedback_message('manualsync', $response['code'])); 528 } 456 529 457 530 exit(); -
nudgify/trunk/readme.txt
r3399921 r3402172 5 5 Requires at least: 4.6 6 6 Tested up to: 6.8 7 Stable tag: 1.3.1 27 Stable tag: 1.3.14 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 122 122 123 123 Our pricing is per website. That means that you can add as many websites to your Nudgify account as you like, and multiply your plan price by the number of websites you have, e.g. if you use our Lite plan on 2 websites, it will cost 2x $0.99 = $1.98/month. 124
Note: See TracChangeset
for help on using the changeset viewer.