PluginProbe
AI Chatbot for WooCommerce & Live Chat – onWebChat / 3.5.5
AI Chatbot for WooCommerce & Live Chat – onWebChat v3.5.5
3.10.0 3.9.2 3.9.3 3.9.1 3.9.0 3.8.4 3.8.2 3.8.1 3.8.0 3.7.2 3.7.1 3.7.0 3.6.0 3.5.5 trunk 1.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.2 1.0.3 1.0.4 1.0.5 All 49 releases
onwebchat / admin / tabs / woocommerce.php

woocommerce.php in AI Chatbot for WooCommerce & Live Chat – onWebChat 3.5.5, at admin/tabs/woocommerce.php

602 lines 27.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WooCommerce Tab - Product Sync Settings
4 */
5
6 if (!defined('ABSPATH')) {
7 exit;
8 }
9
10 function onwebchat_woocommerce_tab() {
11
12 // Handle form submissions
13 onwebchat_handle_woocommerce_actions();
14
15 // Get current settings
16 $sync_enabled = get_option('onwebchat_wc_sync_enabled', false);
17 $sync_mode = get_option('onwebchat_wc_sync_mode', 'short_fallback_full');
18 $include_price = get_option('onwebchat_wc_sync_include_price', false);
19 $secret = get_option('onwebchat_wc_sync_secret', '');
20
21 // Get sync status
22 $sync_status = array(
23 'last_sync' => get_option('onwebchat_wc_last_bulk_sync', 0),
24 'in_progress' => get_option('onwebchat_wc_bulk_in_progress', false),
25 'done' => get_option('onwebchat_wc_bulk_done', 0),
26 'total' => get_option('onwebchat_wc_bulk_total', 0),
27 'last_sync_start' => get_option('onwebchat_wc_last_sync_start', 0),
28 );
29
30 // Calculate cooldown status
31 $cooldown_period = 5 * 60; // 5 minutes // 5min // 5 * 60 //also in the file woocommerce-sync.php
32 $time_since_last_sync = time() - $sync_status['last_sync_start'];
33 $is_in_cooldown = ($time_since_last_sync < $cooldown_period) && $sync_status['last_sync_start'] > 0;
34 $cooldown_remaining = $is_in_cooldown ? ceil(($cooldown_period - $time_since_last_sync) / 60) : 0;
35
36 ?>
37
38 <?php if (isset($_GET['wc_saved']) && $_GET['wc_saved'] == '1'): ?>
39 <div class="notice notice-success is-dismissible">
40 <p><strong>WooCommerce settings saved successfully!</strong></p>
41 </div>
42 <?php endif; ?>
43
44 <?php
45 // Check for authentication errors
46 $auth_error = get_transient('onwebchat_wc_auth_error');
47 if ($auth_error):
48 ?>
49 <div class="notice notice-error is-dismissible">
50 <p><strong>⚠️ WooCommerce Sync Authentication Error:</strong></p>
51 <p><?php echo esc_html($auth_error); ?></p>
52 <p>This usually happens when:</p>
53 <ul style="list-style: disc; margin-left: 20px;">
54 <li>You're trying to connect the plugin to a different onWebChat account</li>
55 </ul>
56 <p><strong>Solution:</strong> Please enter your onWebChat account credentials again in the "Connect WooCommerce Sync" section below and click "Connect WooCommerce Sync" button to reconnect.</p>
57 </div>
58 <?php endif; ?>
59
60 <h2>WooCommerce Product Sync</h2>
61 <p>
62 Let your AI chatbot understand your WooCommerce products.
63 When enabled, products are automatically synced and kept up to date, allowing the AI to answer product-related questions accurately.
64 </p>
65
66 <?php if (empty($secret)): ?>
67 <!-- Authentication required section -->
68 <div class="notice notice-warning" style="margin: 15px 0; padding: 15px;">
69 <h3 style="margin-top: 0;">🔐 Connect WooCommerce Sync</h3>
70 <p>
71 To enable WooCommerce sync, please enter your onWebChat account credentials below.
72 </p>
73 <p style="color: #666; font-size: 13px;">
74 <!-- <strong>💡 Tip:</strong> If you originally connected using email/password in the <a href="?page=onwebchat_settings&tab=general">General tab</a>,
75 try unlinking and re-linking your account there. WooCommerce sync will be connected automatically! -->
76 </p>
77
78 <table class="form-table" style="margin-bottom: 0;">
79 <tr>
80 <th scope="row"><label for="onwebchat_wc_email">Email</label></th>
81 <td>
82 <input type="email"
83 id="onwebchat_wc_email"
84 class="regular-text"
85 placeholder="your@email.com"
86 value="<?php echo esc_attr(get_option('onwebchat_plugin_option_user', '')); ?>">
87 </td>
88 </tr>
89 <tr>
90 <th scope="row"><label for="onwebchat_wc_password">Password</label></th>
91 <td>
92 <input type="password"
93 id="onwebchat_wc_password"
94 class="regular-text"
95 placeholder="Your onWebChat password">
96 </td>
97 </tr>
98 </table>
99
100 <p style="margin-top: 15px;">
101 <button type="button" id="onwebchat_wc_connect" class="button button-primary">
102 Connect WooCommerce Sync
103 </button>
104 <span id="onwebchat_wc_connect_status" style="margin-left: 10px;"></span>
105 </p>
106 </div>
107
108 <script type="text/javascript">
109 jQuery(document).ready(function($) {
110 $('#onwebchat_wc_connect').on('click', function() {
111 var email = $('#onwebchat_wc_email').val();
112 var password = $('#onwebchat_wc_password').val();
113
114 if (!email || !password) {
115 alert('Please enter both email and password.');
116 return;
117 }
118
119 var $btn = $(this);
120 var $status = $('#onwebchat_wc_connect_status');
121
122 $btn.prop('disabled', true).text('Connecting...');
123 $status.html('');
124
125 $.ajax({
126 url: ajaxurl,
127 type: 'POST',
128 data: {
129 action: 'onwebchat_wc_connect',
130 email: email,
131 password: password,
132 nonce: '<?php echo wp_create_nonce('onwebchat_wc_sync_nonce'); ?>'
133 },
134 success: function(response) {
135 if (response.success) {
136 $status.html('<span style="color: green;">✓ Connected successfully!</span>');
137 setTimeout(function() {
138 location.reload();
139 }, 1000);
140 } else {
141 $status.html('<span style="color: red;">✗ ' + response.data + '</span>');
142 $btn.prop('disabled', false).text('Connect WooCommerce Sync');
143 }
144 },
145 error: function() {
146 $status.html('<span style="color: red;">✗ Connection error. Please try again.</span>');
147 $btn.prop('disabled', false).text('Connect WooCommerce Sync');
148 }
149 });
150 });
151 });
152 </script>
153
154 <?php else: ?>
155 <!-- Connected - show settings -->
156
157 <form action="admin.php?page=onwebchat_settings&tab=woocommerce" method="post">
158 <input type="hidden" name="action" value="save_wc_sync">
159 <?php wp_nonce_field('onwebchat_wc_sync_nonce'); ?>
160
161 <table class="form-table">
162 <tr>
163 <th scope="row" style="line-height: 1 !important;">
164 <label for="onwebchat_wc_sync_enabled">Enable Product Sync</label>
165 </th>
166 <td>
167 <label for="onwebchat_wc_sync_enabled">
168 <input type="checkbox"
169 id="onwebchat_wc_sync_enabled"
170 name="onwebchat_wc_sync_enabled"
171 value="1"
172 <?php checked($sync_enabled, true); ?>>
173 Automatically sync products to onWebChat for AI training
174 </label>
175 <p id="onwebchat_wc_sync_status" style="margin: 8px 0 0 0; font-size: 13px; min-height: 20px; visibility: hidden; opacity: 0;">
176 </p>
177 </td>
178 </tr>
179
180 <tr style="display: none;">
181 <th scope="row">
182 <label for="onwebchat_wc_sync_mode">Description Mode</label>
183 </th>
184 <td>
185 <select id="onwebchat_wc_sync_mode" name="onwebchat_wc_sync_mode" style="width: 350px;">
186 <option value="short_only" <?php selected($sync_mode, 'short_only'); ?>>
187 Short description only
188 </option>
189 <option value="short_fallback_full" <?php selected($sync_mode, 'short_fallback_full'); ?>>
190 Short description (fallback to full)
191 </option>
192 </select>
193 <p class="description">
194 Choose how product descriptions are synced for AI training
195 </p>
196 </td>
197 </tr>
198
199 <tr style="display: none">
200 <th scope="row">
201 <label for="onwebchat_wc_sync_include_price">Include Pricing</label>
202 </th>
203 <td>
204 <label for="onwebchat_wc_sync_include_price">
205 <input type="checkbox"
206 id="onwebchat_wc_sync_include_price"
207 name="onwebchat_wc_sync_include_price"
208 value="1"
209 <?php checked($include_price, true); ?>>
210 Include product prices in sync data
211 </label>
212 </td>
213 </tr>
214
215
216 <?php if (!empty($secret)): ?>
217 <tr style="display: none;">
218 <th scope="row">Connection Status</th>
219 <td>
220 <span style="color: green; font-weight: bold;"> Connected</span>
221 <code style="background: #f5f5f5; padding: 8px 12px; border-radius: 4px; display: inline-block; font-size: 11px; margin-left: 10px;">
222 <?php echo esc_html(substr($secret, 0, 8) . '...' . substr($secret, -4)); ?>
223 </code>
224 <button type="button"
225 id="onwebchat_regenerate_secret"
226 class="button"
227 style="margin-left: 10px;">
228 Disconnect & Reconnect
229 </button>
230 <p class="description">
231 WooCommerce sync is securely connected. Click "Disconnect & Reconnect" to re-authenticate.
232 </p>
233 </td>
234 </tr>
235 <?php endif; ?>
236 </table>
237 </form>
238
239 <hr>
240
241 <h2>Bulk Sync Status</h2>
242
243 <div id="onwebchat_sync_status_display" style="background: #f9f9f9; padding: 20px; border-radius: 8px; max-width: 800px; margin-top: 15px;">
244 <?php if ($sync_status['in_progress']): ?>
245 <p style="margin: 0 0 10px 0;">
246 <strong> Sync in progress:</strong>
247 <?php echo esc_html($sync_status['done']); ?> / <?php echo esc_html($sync_status['total']); ?> products synced
248 </p>
249 <div style="background: #fff; border: 1px solid #ddd; border-radius: 4px; height: 20px; overflow: hidden;">
250 <div style="background: #2271b1; height: 100%; width: <?php echo $sync_status['total'] > 0 ? ($sync_status['done'] / $sync_status['total'] * 100) : 0; ?>%; transition: width 0.3s;"></div>
251 </div>
252 <?php elseif ($sync_status['last_sync'] > 0): ?>
253 <p id="onwebchat_last_sync_info" style="margin: 0;">
254 <strong> Last bulk sync:</strong>
255 <?php echo esc_html(human_time_diff($sync_status['last_sync'], current_time('timestamp')) . ' ago'); ?>
256 </p>
257 <p id="onwebchat_total_synced_info" style="margin: 10px 0 0 0; color: #666;">
258 Total products synced: <?php echo esc_html($sync_status['total']); ?>
259 </p>
260 <?php else: ?>
261 <p style="margin: 0; color: #666;">
262 No bulk sync has been performed yet.
263 </p>
264 <?php endif; ?>
265
266 <?php if (!$is_in_cooldown): ?>
267 <p style="margin-top: 15px;">
268 <button type="button"
269 id="onwebchat_sync_now"
270 class="button button-primary"
271 <?php echo $sync_status['in_progress'] ? 'disabled' : ''; ?>>
272 <?php echo $sync_status['in_progress'] ? 'Sync in Progress...' : 'Sync All Products Now'; ?>
273 </button>
274 </p>
275 <?php endif; ?>
276
277 <p class="description onwebchat-sync-description" style="margin-top: 10px;">
278 <?php if ($is_in_cooldown): ?>
279 <?php if ($sync_enabled): ?>
280 Bulk sync was completed recently. Your products are already up to date, and any new or updated products will be synced automatically.
281 <?php else: ?>
282 Bulk sync was completed recently. Your products are already up to date. Please enable "Automatically sync products to onWebChat for AI training" above to keep all your products synced automatically.
283 <?php endif; ?>
284 <?php else: ?>
285 Click to sync all existing products. This process runs in the background and may take several minutes depending on your product count.
286 <?php endif; ?>
287 </p>
288
289 <?php
290 // Show reset button if sync appears stuck (done >= total OR in progress for more than 3 minutes)
291 $stuck_sync = $sync_status['in_progress'] && (
292 $sync_status['done'] >= $sync_status['total'] ||
293 (time() - $sync_status['last_sync_start'] > 180)
294 );
295 if ($stuck_sync):
296 ?>
297 <p style="margin-top: 10px;">
298 <button type="button"
299 id="onwebchat_manual_process_batch"
300 class="button button-secondary"
301 style="margin-right: 10px;">
302 Process Batch Manually
303 </button>
304 <button type="button"
305 id="onwebchat_reset_sync_status"
306 class="button">
307 Mark Sync as Complete
308 </button>
309 <span class="description" style="margin-left: 10px;">
310 If sync appears stuck, try processing manually or reset status.
311 </span>
312 </p>
313 <?php endif; ?>
314 </div>
315
316 <script type="text/javascript">
317 jQuery(document).ready(function($) {
318 // Cooldown timer - reload page when cooldown expires
319 <?php if ($is_in_cooldown): ?>
320 var cooldownSeconds = <?php echo ($cooldown_period - $time_since_last_sync); ?>;
321 setTimeout(function() {
322 location.reload();
323 }, cooldownSeconds * 1000);
324 <?php endif; ?>
325
326 // Sync enabled checkbox - save immediately via AJAX
327 $('#onwebchat_wc_sync_enabled').on('change', function() {
328 var $checkbox = $(this);
329 var $status = $('#onwebchat_wc_sync_status');
330 var $syncDescription = $('.onwebchat-sync-description');
331 var isEnabled = $checkbox.is(':checked');
332
333 // Disable checkbox while saving
334 $checkbox.prop('disabled', true);
335
336 $.ajax({
337 url: ajaxurl,
338 type: 'POST',
339 data: {
340 action: 'onwebchat_wc_save_sync_enabled',
341 sync_enabled: isEnabled ? '1' : '0',
342 nonce: '<?php echo wp_create_nonce('onwebchat_wc_sync_nonce'); ?>'
343 },
344 success: function(response) {
345 if (response.success) {
346 if (response.data.enabled) {
347 $status.html('<span style="color: green;">�
348 WooCommerce product sync enabled</span>');
349 // Update the sync description text if in cooldown
350 if ($syncDescription.length) {
351 var currentText = $syncDescription.text().trim();
352 if (currentText.includes('Bulk sync was completed recently')) {
353 $syncDescription.text('Bulk sync was completed recently. Your products are already up to date, and any new or updated products will be synced automatically.');
354 }
355 }
356 } else {
357 $status.html('<span style="color: #d63638;"> WooCommerce product sync disabled</span>');
358 // Update the sync description text if in cooldown
359 if ($syncDescription.length) {
360 var currentText = $syncDescription.text().trim();
361 if (currentText.includes('Bulk sync was completed recently')) {
362 $syncDescription.text('Bulk sync was completed recently. Your products are already up to date. Please enable "Automatically sync products to onWebChat for AI training" above to keep all your products synced automatically.');
363 }
364 }
365 }
366 // Ensure status is visible and fade in smoothly
367 $status.css('visibility', 'visible').css('opacity', 1);
368 // Hide it after 2.5 seconds with fade out
369 setTimeout(function() {
370 $status.animate({opacity: 0}, 300, function() {
371 $status.css('visibility', 'hidden');
372 });
373 }, 1700);
374 } else {
375 // Revert checkbox on error
376 $checkbox.prop('checked', !isEnabled);
377 alert('Error: ' + (response.data || 'Failed to save setting'));
378 }
379 $checkbox.prop('disabled', false);
380 },
381 error: function() {
382 // Revert checkbox on error
383 $checkbox.prop('checked', !isEnabled);
384 alert('An error occurred. Please try again.');
385 $checkbox.prop('disabled', false);
386 }
387 });
388 });
389
390 // Sync now button
391 $('#onwebchat_sync_now').on('click', function() {
392 if ($(this).prop('disabled')) {
393 return;
394 }
395
396 if (!confirm('Sync all published products with onWebChat to train your AI chatbot?')) {
397 return;
398 }
399
400 var $btn = $(this);
401 $btn.prop('disabled', true).text('Syncing products...');
402
403 // Hide the "Last sync" info while syncing
404 $('#onwebchat_last_sync_info').hide();
405 $('#onwebchat_total_synced_info').hide();
406
407 // Show initial syncing message with progress bar
408 $('#onwebchat_sync_status_display').html(
409 '<p style="margin: 0 0 10px 0;"><strong>⏳ Sync in progress:</strong> <span id="sync_progress_text">0 / ? products synced</span></p>' +
410 '<div style="background: #fff; border: 1px solid #ddd; border-radius: 4px; height: 20px; overflow: hidden;">' +
411 '<div id="sync_progress_bar" style="background: #2271b1; height: 100%; width: 0%; transition: width 0.3s;"></div>' +
412 '</div>' +
413 '<p style="margin: 10px 0 0 0; color: #666;">Please wait, this may take several minutes.</p>'
414 );
415
416 // Start polling for progress updates
417 var progressInterval = setInterval(function() {
418 $.ajax({
419 url: ajaxurl,
420 type: 'POST',
421 data: {
422 action: 'onwebchat_wc_get_sync_status',
423 nonce: '<?php echo wp_create_nonce('onwebchat_wc_sync_nonce'); ?>'
424 },
425 success: function(statusResponse) {
426 if (statusResponse.success && statusResponse.data.in_progress) {
427 var done = statusResponse.data.done || 0;
428 var total = statusResponse.data.total || 0;
429 var percentage = total > 0 ? Math.round((done / total) * 100) : 0;
430
431 $('#sync_progress_text').text(done + ' / ' + total + ' products synced');
432 $('#sync_progress_bar').css('width', percentage + '%');
433 }
434 }
435 });
436 }, 2000); // Poll every 2 seconds
437
438 $.ajax({
439 url: ajaxurl,
440 type: 'POST',
441 timeout: 120000, // 2 minute timeout for large syncs
442 data: {
443 action: 'onwebchat_wc_sync_now',
444 nonce: '<?php echo wp_create_nonce('onwebchat_wc_sync_nonce'); ?>'
445 },
446 success: function(response) {
447 clearInterval(progressInterval); // Stop polling
448
449 if (response.success) {
450 var result = response.data.result;
451 var stats = result.stats;
452 var msg = 'Sync completed!\n\n' +
453 'Products processed: ' + result.done + '/' + response.data.total + '\n' +
454 'Created: ' + stats.created + '\n' +
455 'Updated: ' + stats.updated + '\n' +
456 'Unchanged: ' + stats.skipped + '\n' +
457 'Errors: ' + stats.errors;
458 alert(msg);
459 location.reload();
460 } else {
461 alert('Error: ' + response.data);
462 $btn.prop('disabled', false).text('Sync All Products Now');
463 }
464 },
465 error: function(xhr, status, error) {
466 clearInterval(progressInterval); // Stop polling
467 alert('An error occurred: ' + error + '. Please try again.');
468 $btn.prop('disabled', false).text('Sync All Products Now');
469 }
470 });
471 });
472
473 // Manual process batch button (for debugging stuck syncs)
474 $('#onwebchat_manual_process_batch').on('click', function() {
475 var $btn = $(this);
476 $btn.prop('disabled', true).text('Processing...');
477
478 $.ajax({
479 url: ajaxurl,
480 type: 'POST',
481 data: {
482 action: 'onwebchat_wc_manual_process_batch',
483 nonce: '<?php echo wp_create_nonce('onwebchat_wc_sync_nonce'); ?>'
484 },
485 success: function(response) {
486 if (response.success) {
487 alert('Batch processed. Check console/logs for details.');
488 location.reload();
489 } else {
490 alert('Error: ' + response.data);
491 $btn.prop('disabled', false).text('Process Batch Manually');
492 }
493 },
494 error: function() {
495 alert('An error occurred. Please try again.');
496 $btn.prop('disabled', false).text('Process Batch Manually');
497 }
498 });
499 });
500
501 // Reset sync status button
502 $('#onwebchat_reset_sync_status').on('click', function() {
503 if (!confirm('Mark sync as complete? This will reset the progress indicator.')) {
504 return;
505 }
506
507 var $btn = $(this);
508 $btn.prop('disabled', true).text('Resetting...');
509
510 $.ajax({
511 url: ajaxurl,
512 type: 'POST',
513 data: {
514 action: 'onwebchat_wc_reset_sync_status',
515 nonce: '<?php echo wp_create_nonce('onwebchat_wc_sync_nonce'); ?>'
516 },
517 success: function(response) {
518 if (response.success) {
519 location.reload();
520 } else {
521 alert('Error: ' + response.data);
522 $btn.prop('disabled', false).text('Mark Sync as Complete');
523 }
524 },
525 error: function() {
526 alert('An error occurred. Please try again.');
527 $btn.prop('disabled', false).text('Mark Sync as Complete');
528 }
529 });
530 });
531
532 // Regenerate secret button (now "Disconnect" button)
533 $('#onwebchat_regenerate_secret').on('click', function() {
534 if (!confirm('This will disconnect WooCommerce sync. You will need to re-authenticate with your credentials. Continue?')) {
535 return;
536 }
537
538 var $btn = $(this);
539 $btn.prop('disabled', true).text('Disconnecting...');
540
541 $.ajax({
542 url: ajaxurl,
543 type: 'POST',
544 data: {
545 action: 'onwebchat_wc_regenerate_secret',
546 nonce: '<?php echo wp_create_nonce('onwebchat_wc_sync_nonce'); ?>'
547 },
548 success: function(response) {
549 if (response.success) {
550 alert('WooCommerce sync disconnected. Please re-authenticate to continue syncing.');
551 location.reload();
552 } else {
553 alert('Error: ' + response.data);
554 $btn.prop('disabled', false).text('Disconnect & Reconnect');
555 }
556 },
557 error: function() {
558 alert('An error occurred. Please try again.');
559 $btn.prop('disabled', false).text('Disconnect & Reconnect');
560 }
561 });
562 });
563 });
564 </script>
565
566 <?php endif; // End if secret exists ?>
567
568 <?php
569 }
570
571 /**
572 * Handle form submissions for WooCommerce tab
573 */
574 function onwebchat_handle_woocommerce_actions() {
575
576 if (isset($_POST["action"]) && $_POST["action"] == "save_wc_sync") {
577
578 if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'onwebchat_wc_sync_nonce')) {
579 wp_die('Sorry, your nonce did not verify.');
580 }
581
582 if (!current_user_can('manage_options')) {
583 wp_die('Insufficient permissions.');
584 }
585
586 // Save settings
587 $sync_enabled = isset($_POST["onwebchat_wc_sync_enabled"]) ? true : false;
588 $sync_mode = isset($_POST["onwebchat_wc_sync_mode"]) ? sanitize_text_field($_POST["onwebchat_wc_sync_mode"]) : 'short_fallback_full';
589 $include_price = isset($_POST["onwebchat_wc_sync_include_price"]) ? true : false;
590
591 update_option('onwebchat_wc_sync_enabled', $sync_enabled);
592 update_option('onwebchat_wc_sync_mode', $sync_mode);
593 update_option('onwebchat_wc_sync_include_price', $include_price);
594
595 // Secret is now obtained via authenticated connection, not auto-generated
596
597 wp_redirect(admin_url('admin.php?page=onwebchat_settings&tab=woocommerce&wc_saved=1'));
598 exit;
599 }
600 }
601
602