Changeset 3257952
- Timestamp:
- 03/18/2025 04:06:12 PM (13 months ago)
- Location:
- ilachat/trunk
- Files:
-
- 4 added
- 8 edited
-
assets/css/ilachat-woocommerce.css (modified) (1 diff)
-
assets/js/ilachat-woocommerce.js (modified) (1 diff)
-
composer.json (modified) (1 diff)
-
composer.lock (added)
-
ilachat.php (modified) (4 diffs)
-
languages/ilachat.pot (modified) (4 diffs)
-
readme.txt (modified) (1 diff)
-
src/Integrations/Woocommerce.php (modified) (31 diffs)
-
templates/admin/wc-integration-page.php (modified) (3 diffs)
-
vendor/composer/InstalledVersions.php (added)
-
vendor/composer/installed.json (added)
-
vendor/composer/installed.php (added)
Legend:
- Unmodified
- Added
- Removed
-
ilachat/trunk/assets/css/ilachat-woocommerce.css
r3252285 r3257952 20 20 border-color: #b3d4ff transparent; 21 21 } 22 23 #ilachat-woocommerce-sync-products-wrapper .spinner { 24 float: unset; 25 vertical-align: middle; 26 margin-top: 1.125em; 27 } -
ilachat/trunk/assets/js/ilachat-woocommerce.js
r3252285 r3257952 126 126 } 127 127 128 class IlachatProductSync { 129 constructor() { 130 this.isSyncing = false; 131 this.isPaused = false; 132 this.currentOffset = 0; 133 this.button = document.getElementById('ilachat-woocommerce-sync-products'); 134 this.messageElem = document.getElementById('ilachat-woocommerce-sync-products-message'); 135 136 if (this.button) { 137 this.button.addEventListener('click', this.handleButtonClick.bind(this)); 138 } 139 } 140 141 handleButtonClick(e) { 142 e.preventDefault(); 143 if (!this.isSyncing) { 144 this.startSync(); 145 } else { 146 this.togglePause(); 147 } 148 } 149 150 startSync() { 151 this.isSyncing = true; 152 this.isPaused = false; 153 this.currentOffset = 0; 154 this.button.textContent = ilachat_woocommerce.texts.pause_sync; 155 156 // Add spinner element if not already present 157 if (!document.getElementById('ilachat-spinner')) { 158 const spinner = document.createElement('span'); 159 spinner.id = 'ilachat-spinner'; 160 spinner.className = 'spinner is-active'; 161 this.button.parentNode.insertBefore(spinner, this.button.nextSibling); 162 } 163 164 this.syncProducts(this.currentOffset); 165 } 166 167 togglePause() { 168 this.isPaused = !this.isPaused; 169 if (this.isPaused) { 170 this.button.textContent = ilachat_woocommerce.texts.resume_sync; 171 // Remove spinner when paused 172 const spinner = document.getElementById('ilachat-spinner'); 173 if (spinner) { 174 spinner.remove(); 175 } 176 } else { 177 this.button.textContent = ilachat_woocommerce.texts.pause_sync; 178 // Add spinner back if not present 179 if (!document.getElementById('ilachat-spinner')) { 180 const spinner = document.createElement('span'); 181 spinner.id = 'ilachat-spinner'; 182 spinner.className = 'spinner is-active'; 183 this.button.parentNode.insertBefore(spinner, this.button.nextSibling); 184 } 185 this.syncProducts(this.currentOffset); 186 } 187 } 188 189 syncProducts(offset) { 190 if (this.isPaused) { 191 return; 192 } 193 194 const formData = new FormData(); 195 formData.append('action', 'ilachat_sync_products'); 196 formData.append('security', ilachat_woocommerce.security); 197 formData.append('offset', offset); 198 199 fetch(ilachat_woocommerce.ajax_url, { 200 method: 'POST', 201 body: formData 202 }) 203 .then(response => response.json()) 204 .then(data => { 205 if (data.success) { 206 const responseData = data.data; 207 this.updateMessage(responseData.success, responseData.error); 208 209 // If there are more products to process, continue syncing 210 if (responseData.total > 0) { 211 this.currentOffset = responseData.offset; 212 this.syncProducts(this.currentOffset); 213 } else { 214 // Finished syncing; reset UI 215 this.resetSync(); 216 } 217 } else { 218 alert(ilachat_woocommerce.texts.error); 219 this.resetSync(); 220 } 221 }) 222 .catch(error => { 223 alert(ilachat_woocommerce.texts.error); 224 this.resetSync(); 225 }); 226 } 227 228 updateMessage(successCount, errorCount) { 229 if (this.messageElem) { 230 const spans = this.messageElem.querySelectorAll('span'); 231 if (spans.length >= 2) { 232 const currentSuccess = parseInt(spans[0].textContent) || 0; 233 const currentError = parseInt(spans[1].textContent) || 0; 234 const newSuccess = currentSuccess + successCount; 235 const newError = currentError + errorCount; 236 spans[0].textContent = newSuccess; 237 spans[1].textContent = newError; 238 } 239 this.messageElem.style.display = 'block'; 240 } 241 } 242 243 resetSync() { 244 this.button.textContent = ilachat_woocommerce.texts.sync_products; 245 const spinner = document.getElementById('ilachat-spinner'); 246 if (spinner) { 247 spinner.remove(); 248 } 249 this.isSyncing = false; 250 this.isPaused = false; 251 this.currentOffset = 0; 252 } 253 } 254 255 128 256 document.addEventListener('DOMContentLoaded', () => { 129 257 new IlachatOrderNotes(); 258 new IlachatProductSync(); 130 259 }); -
ilachat/trunk/composer.json
r3239636 r3257952 14 14 } 15 15 ], 16 "require": {} 16 "require": {}, 17 "config": { 18 "allow-plugins": { 19 "dealerdirect/phpcodesniffer-composer-installer": false 20 } 21 } 17 22 } -
ilachat/trunk/ilachat.php
r3252602 r3257952 12 12 * Plugin URI: https://ila.chat 13 13 * Description: Integrate ILACHAT with WordPress to add AI-powered chatbot and live chat for seamless customer support and engagement. 14 * Version: 1.1. 014 * Version: 1.1.1 15 15 * Requires at least: 6.2 16 16 * Requires PHP: 7.4.0 … … 45 45 46 46 // Define constants 47 define('ILACHAT_VERSION', '1.1. 0');47 define('ILACHAT_VERSION', '1.1.1'); 48 48 define('ILACHAT_ROOT', __FILE__); 49 49 define('ILACHAT_PATH', plugin_dir_path(ILACHAT_ROOT)); … … 55 55 56 56 // Define API URL 57 Define('ILACHAT_CONNECT_URL', 'https://app.ila.chat/user/dashboard/connect-services'); 58 Define('ILACHAT_VALIDATE_TOKEN_API', 'https://app.ila.chat/api/connect-services/wpp/valid-token'); 59 Define('ILACHAT_PLUGIN_UPDATE_API', 'https://app.ila.chat/api/connect-services/wpp/last-update'); 60 Define('ILACHAT_GET_WIDGET_API', 'https://app.ila.chat/api/connect-services/wpp/get-bot-details'); 61 Define('ILACHAT_SYNC_PRODUCT_API', 'https://app.ila.chat/api/connect-services/wpp/sync-product'); 62 Define('ILACHAT_SYNC_VARIABLE_LINK_API', 'https://app.ila.chat/api/connect-services/wpp/sync-variable-link'); 63 Define('ILACHAT_DISCONNECT_API', 'https://app.ila.chat/api/connect-services/wpp/disconnect'); 64 57 define('ILACHAT_CONNECT_URL', 'https://app.ila.chat/user/dashboard/connect-services'); 58 define('ILACHAT_VALIDATE_TOKEN_API', 'https://app.ila.chat/api/connect-services/wpp/valid-token'); 59 define('ILACHAT_PLUGIN_UPDATE_API', 'https://app.ila.chat/api/connect-services/wpp/last-update'); 60 define('ILACHAT_GET_WIDGET_API', 'https://app.ila.chat/api/connect-services/wpp/get-bot-details'); 61 define('ILACHAT_SYNC_PRODUCT_API', 'https://app.ila.chat/api/connect-services/wpp/sync-product'); 62 define('ILACHAT_SYNC_VARIABLE_LINK_API', 'https://app.ila.chat/api/connect-services/wpp/sync-variable-link'); 63 define('ILACHAT_DISCONNECT_API', 'https://app.ila.chat/api/connect-services/wpp/disconnect'); 65 64 66 65 // Include Composer autoload … … 79 78 function ilachat_init() 80 79 { 81 Plugin::run(); 80 if (class_exists(Plugin::class)) { 81 Plugin::run(); 82 } else { 83 error_log('ILACHAT Plugin class not found. Ensure the autoload file is loaded properly.'); 84 } 82 85 } 83 86 -
ilachat/trunk/languages/ilachat.pot
r3252598 r3257952 3 3 msgid "" 4 4 msgstr "" 5 "Project-Id-Version: ILACHAT - AI Chatbot & Live Chat 1.1. 0\n"5 "Project-Id-Version: ILACHAT - AI Chatbot & Live Chat 1.1.1\n" 6 6 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/ilachat\n" 7 7 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" … … 10 10 "Content-Type: text/plain; charset=UTF-8\n" 11 11 "Content-Transfer-Encoding: 8bit\n" 12 "POT-Creation-Date: 2025-03- 08T19:02:38+01:00\n"12 "POT-Creation-Date: 2025-03-18T17:00:24+01:00\n" 13 13 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 14 14 "X-Generator: WP-CLI 2.11.0\n" … … 80 80 msgstr "" 81 81 82 #: src/Integrations/Woocommerce.php:1 7083 #: src/Integrations/Woocommerce.php:1 7184 #: src/Integrations/Woocommerce.php:1 9685 #: templates/admin/wc-integration-page.php:5 482 #: src/Integrations/Woocommerce.php:161 83 #: src/Integrations/Woocommerce.php:162 84 #: src/Integrations/Woocommerce.php:187 85 #: templates/admin/wc-integration-page.php:51 86 86 msgid "WooCommerce Integration" 87 87 msgstr "" 88 88 89 #: src/Integrations/Woocommerce.php:3 5189 #: src/Integrations/Woocommerce.php:342 90 90 msgid "Order tracking is disabled" 91 91 msgstr "" 92 92 93 #: src/Integrations/Woocommerce.php:35 993 #: src/Integrations/Woocommerce.php:350 94 94 msgid "Order ID is required" 95 95 msgstr "" 96 96 97 #: src/Integrations/Woocommerce.php:3 6497 #: src/Integrations/Woocommerce.php:355 98 98 msgid "Order not found" 99 99 msgstr "" 100 100 101 #: src/Integrations/Woocommerce.php:36 9101 #: src/Integrations/Woocommerce.php:360 102 102 msgid "Invalid phone number" 103 103 msgstr "" 104 104 105 #: src/Integrations/Woocommerce.php:3 74105 #: src/Integrations/Woocommerce.php:365 106 106 msgid "Invalid email address" 107 107 msgstr "" 108 108 109 #: src/Integrations/Woocommerce.php:5 49110 #: src/Integrations/Woocommerce.php:6 20109 #: src/Integrations/Woocommerce.php:566 110 #: src/Integrations/Woocommerce.php:640 111 111 msgid "Please enter a note." 112 112 msgstr "" 113 113 114 #: src/Integrations/Woocommerce.php:5 50114 #: src/Integrations/Woocommerce.php:567 115 115 msgid "An error occurred while doing the request." 116 116 msgstr "" 117 117 118 #: src/Integrations/Woocommerce.php:5 51118 #: src/Integrations/Woocommerce.php:568 119 119 #: templates/admin/wc-order-notes.php:38 120 120 msgid "Delete note" 121 121 msgstr "" 122 122 123 #: src/Integrations/Woocommerce.php:5 52123 #: src/Integrations/Woocommerce.php:569 124 124 msgid "Are you sure you want to delete this note? This action cannot be undone." 125 125 msgstr "" 126 126 127 #: src/Integrations/Woocommerce.php:570 128 msgid "Pause sync" 129 msgstr "" 130 131 #: src/Integrations/Woocommerce.php:571 132 msgid "Resume sync" 133 msgstr "" 134 127 135 #: src/Integrations/Woocommerce.php:572 136 msgid "Sync Products" 137 msgstr "" 138 139 #: src/Integrations/Woocommerce.php:592 128 140 msgid "Ilachat Order Notes" 129 141 msgstr "" 130 142 131 #: src/Integrations/Woocommerce.php:6 15143 #: src/Integrations/Woocommerce.php:635 132 144 msgid "Invalid order." 133 145 msgstr "" 134 146 135 #: src/Integrations/Woocommerce.php:6 25147 #: src/Integrations/Woocommerce.php:645 136 148 msgid "Failed to add note." 137 149 msgstr "" 138 150 139 #: src/Integrations/Woocommerce.php: 695151 #: src/Integrations/Woocommerce.php:715 140 152 msgid "Failed to delete note." 141 153 msgstr "" 142 154 143 #: src/Integrations/Woocommerce.php:876 144 #: src/Integrations/Woocommerce.php:887 145 msgid "Failed to sync product with Ilachat." 146 msgstr "" 147 148 #: src/Integrations/Woocommerce.php:896 149 msgid "Product synced successfully with Ilachat." 150 msgstr "" 151 152 #: src/Integrations/Woocommerce.php:924 155 #: src/Integrations/Woocommerce.php:962 156 #: src/Integrations/Woocommerce.php:977 153 157 msgid "Sync with Ilachat" 154 158 msgstr "" 155 159 156 #: src/Integrations/Woocommerce.php:9 26160 #: src/Integrations/Woocommerce.php:964 157 161 msgid "Last synced:" 158 162 msgstr "" 163 164 #. translators: %s is the number of products successfully synced with Ilachat. 165 #: src/Integrations/Woocommerce.php:1043 166 msgid "Synced %s product with Ilachat." 167 msgid_plural "Synced %s products with Ilachat." 168 msgstr[0] "" 169 msgstr[1] "" 170 171 #. translators: %s is the number of products that failed to sync with Ilachat. 172 #: src/Integrations/Woocommerce.php:1057 173 msgid "Failed to sync %s product with Ilachat." 174 msgid_plural "Failed to sync %s products with Ilachat." 175 msgstr[0] "" 176 msgstr[1] "" 159 177 160 178 #: templates/admin/connect-page.php:28 … … 202 220 msgstr "" 203 221 204 #: templates/admin/wc-integration-page.php:5 7222 #: templates/admin/wc-integration-page.php:54 205 223 msgid "Enable the integration between Ilachat and WooCommerce." 206 224 msgstr "" 207 225 226 #: templates/admin/wc-integration-page.php:58 227 msgid "Product Sync" 228 msgstr "" 229 208 230 #: templates/admin/wc-integration-page.php:61 209 msgid "Product Sync" 231 msgid "Enable product synchronization with Ilachat." 232 msgstr "" 233 234 #: templates/admin/wc-integration-page.php:62 235 msgid "This will automatically sync your WooCommerce products with Ilachat whenever a product is updated." 210 236 msgstr "" 211 237 212 238 #: templates/admin/wc-integration-page.php:64 213 msgid " Enable product synchronization with Ilachat."239 msgid "Sync All Products Now" 214 240 msgstr "" 215 241 216 242 #: templates/admin/wc-integration-page.php:65 217 msgid "This will automatically sync your WooCommerce products with Ilachat whenever a product is updated." 218 msgstr "" 219 220 #: templates/admin/wc-integration-page.php:69 221 #: templates/admin/wc-integration-page.php:72 243 msgid "Click the button above to manually sync all products with Ilachat for the first time." 244 msgstr "" 245 246 #: templates/admin/wc-integration-page.php:67 247 msgid "Success:" 248 msgstr "" 249 250 #: templates/admin/wc-integration-page.php:67 251 msgid "Error:" 252 msgstr "" 253 254 #: templates/admin/wc-integration-page.php:74 255 #: templates/admin/wc-integration-page.php:77 222 256 msgid "Order Tracking" 223 257 msgstr "" 224 258 225 #: templates/admin/wc-integration-page.php: 75259 #: templates/admin/wc-integration-page.php:80 226 260 msgid "Enable order tracking through the REST API." 227 261 msgstr "" 228 262 229 #: templates/admin/wc-integration-page.php: 79263 #: templates/admin/wc-integration-page.php:84 230 264 msgid "Authorizations" 231 265 msgstr "" 232 266 233 #: templates/admin/wc-integration-page.php:8 2267 #: templates/admin/wc-integration-page.php:87 234 268 msgid "Validate the phone number during order tracking." 235 269 msgstr "" 236 270 237 #: templates/admin/wc-integration-page.php:8 4271 #: templates/admin/wc-integration-page.php:89 238 272 msgid "Validate the email address during order tracking." 239 273 msgstr "" 240 274 241 #: templates/admin/wc-integration-page.php: 89275 #: templates/admin/wc-integration-page.php:93 242 276 msgid "Allowed Order Data" 243 277 msgstr "" 244 278 245 #: templates/admin/wc-integration-page.php:9 3279 #: templates/admin/wc-integration-page.php:97 246 280 msgid "Billing Information" 247 281 msgstr "" 248 282 249 #: templates/admin/wc-integration-page.php:9 4283 #: templates/admin/wc-integration-page.php:98 250 284 msgid "Shipping Information" 251 285 msgstr "" 252 286 253 #: templates/admin/wc-integration-page.php:9 5287 #: templates/admin/wc-integration-page.php:99 254 288 msgid "Purchased Items Details" 255 289 msgstr "" 256 290 257 #: templates/admin/wc-integration-page.php: 96291 #: templates/admin/wc-integration-page.php:100 258 292 msgid "Order Notes" 259 293 msgstr "" 260 294 261 #: templates/admin/wc-integration-page.php:1 07295 #: templates/admin/wc-integration-page.php:111 262 296 msgid "Select the user order data fields to expose via the REST API." 263 297 msgstr "" 264 298 265 #: templates/admin/wc-integration-page.php:11 1299 #: templates/admin/wc-integration-page.php:115 266 300 msgid "Special Order Note" 267 301 msgstr "" 268 302 269 #: templates/admin/wc-integration-page.php:11 4303 #: templates/admin/wc-integration-page.php:118 270 304 msgid "Enable special order notes functionality." 271 305 msgstr "" 272 306 273 #: templates/admin/wc-integration-page.php:11 5307 #: templates/admin/wc-integration-page.php:119 274 308 msgid "This will add a special meta box to the order edit screen for adding additional notes exclusive to Ilachat." 275 309 msgstr "" 276 310 277 #: templates/admin/wc-integration-page.php:1 19278 #: templates/admin/wc-integration-page.php:12 2311 #: templates/admin/wc-integration-page.php:123 312 #: templates/admin/wc-integration-page.php:126 279 313 msgid "Order Statuses Description" 280 314 msgstr "" 281 315 282 #: templates/admin/wc-integration-page.php:1 28316 #: templates/admin/wc-integration-page.php:132 283 317 msgid "Provide a description for each order status." 284 318 msgstr "" -
ilachat/trunk/readme.txt
r3252599 r3257952 73 73 == Changelog == 74 74 75 = 1.1.1 = 76 * Fix for WooCommerce product syncing. 77 * Added bulk product syncing option. 78 * Minor bug fixes. 79 75 80 = 1.1.0 = 76 81 * Added WooCommerce integration: -
ilachat/trunk/src/Integrations/Woocommerce.php
r3252602 r3257952 49 49 add_action('updated_option', [$this, 'sync_variable_links_after_update'], 10, 3); 50 50 51 if (get_option('ilachat_woocommerce_integration_enabled' )) {51 if (get_option('ilachat_woocommerce_integration_enabled', 1)) { 52 52 add_action('rest_api_init', [$this, 'register_rest_routes']); 53 add_action('woocommerce_process_product_meta', [$this, ' sync_product'], 10, 2);53 add_action('woocommerce_process_product_meta', [$this, 'handle_sync_product'], 10, 2); 54 54 add_action('post_submitbox_misc_actions', [$this, 'add_product_sync_misc_actions']); 55 add_filter('bulk_actions-edit-product', [$this, 'add_bulk_actions']); 56 add_filter('handle_bulk_actions-edit-product', [$this, 'handle_bulk_actions'], 10, 3); 57 add_action('admin_notices', [$this, 'sync_product_admin_notice']); 58 add_action('wp_ajax_ilachat_sync_products', [$this, 'sync_products_ajax']); 55 59 $this->init_special_order_note(); 56 60 } … … 71 75 'ilachat_woocommerce_integration_enabled' => [ 72 76 'type' => 'boolean', 73 'default' => true,77 'default' => 1, 74 78 'sanitize_callback' => [$this, 'sanitize_boolean'], 75 79 ], 76 80 'ilachat_woocommerce_order_tracking_enabled' => [ 77 81 'type' => 'boolean', 78 'default' => true,82 'default' => 1, 79 83 'sanitize_callback' => [$this, 'sanitize_boolean'], 80 84 ], … … 86 90 'ilachat_woocommerce_order_check_phone_enabled' => [ 87 91 'type' => 'boolean', 88 'default' => true,92 'default' => 1, 89 93 'sanitize_callback' => [$this, 'sanitize_boolean'], 90 94 ], … … 96 100 'ilachat_woocommerce_order_check_email_enabled' => [ 97 101 'type' => 'boolean', 98 'default' => true,102 'default' => 1, 99 103 'sanitize_callback' => [$this, 'sanitize_boolean'], 100 104 ], 101 105 'ilachat_woocommerce_order_special_note' => [ 102 106 'type' => 'boolean', 103 'default' => true,107 'default' => 1, 104 108 'sanitize_callback' => [$this, 'sanitize_boolean'], 105 109 ], 106 110 'ilachat_woocommerce_product_sync_enabled' => [ 107 111 'type' => 'boolean', 108 'default' => false,112 'default' => 0, 109 113 'sanitize_callback' => [$this, 'sanitize_boolean'], 110 114 ], … … 114 118 register_setting('ilachat_woocommerce', $option, (array) $args); 115 119 116 // Set the default value if the option does not exist.117 if (get_option($option ) === false) {120 // Set default value only if the option doesn't exist. 121 if (get_option($option, null) === null && isset($args['default'])) { 118 122 update_option($option, $args['default']); 119 123 } … … 157 161 esc_html__('WooCommerce Integration', 'ilachat'), 158 162 esc_html__('WooCommerce Integration', 'ilachat'), 159 ' read',163 'manage_options', 160 164 'ilachat-woocommerce', 161 165 [$this, 'render_page'] … … 232 236 } 233 237 234 $integration_enabled = get_option('ilachat_woocommerce_integration_enabled', true);235 $order_tracking_enabled = get_option('ilachat_woocommerce_order_tracking_enabled', true);238 $integration_enabled = get_option('ilachat_woocommerce_integration_enabled', 1); 239 $order_tracking_enabled = get_option('ilachat_woocommerce_order_tracking_enabled', 1); 236 240 237 241 $rest_enabled = false; … … 240 244 } 241 245 242 $phone_required = (bool) get_option('ilachat_woocommerce_order_check_phone_enabled', false);243 $email_required = (bool) get_option('ilachat_woocommerce_order_check_email_enabled', false);246 $phone_required = (bool) get_option('ilachat_woocommerce_order_check_phone_enabled', 0); 247 $email_required = (bool) get_option('ilachat_woocommerce_order_check_email_enabled', 0); 244 248 245 249 $registered_route = rest_url('ilachat/v1/get-order-details'); … … 284 288 public function register_rest_routes() 285 289 { 286 $integration_enabled = get_option('ilachat_woocommerce_integration_enabled', true);287 $order_tracking_enabled = get_option('ilachat_woocommerce_order_tracking_enabled', true);290 $integration_enabled = get_option('ilachat_woocommerce_integration_enabled', 1); 291 $order_tracking_enabled = get_option('ilachat_woocommerce_order_tracking_enabled', 1); 288 292 if (! $integration_enabled || ! $order_tracking_enabled) { 289 293 return; 290 294 } 291 295 292 $phone_required = (bool) get_option('ilachat_woocommerce_order_check_phone_enabled', false);293 $email_required = (bool) get_option('ilachat_woocommerce_order_check_email_enabled', false);296 $phone_required = (bool) get_option('ilachat_woocommerce_order_check_phone_enabled', 0); 297 $email_required = (bool) get_option('ilachat_woocommerce_order_check_email_enabled', 0); 294 298 295 299 register_rest_route( … … 334 338 public function handle_get_order_details(WP_REST_Request $request) 335 339 { 336 $order_tracking_enabled = get_option('ilachat_woocommerce_order_tracking_enabled' );340 $order_tracking_enabled = get_option('ilachat_woocommerce_order_tracking_enabled', 1); 337 341 if (! $order_tracking_enabled) { 338 342 return new WP_Error('order_tracking_disabled', esc_html__('Order tracking is disabled', 'ilachat'), ['status' => 400]); … … 353 357 354 358 // Validate the phone number. 355 if (get_option('ilachat_woocommerce_order_check_phone_enabled' ) && $this->check_phone($order->get_billing_phone()) !== $this->check_phone($phone_number)) {359 if (get_option('ilachat_woocommerce_order_check_phone_enabled', 0) && $this->check_phone($order->get_billing_phone()) !== $this->check_phone($phone_number)) { 356 360 return new WP_Error('invalid_phone', esc_html__('Invalid phone number', 'ilachat'), ['status' => 400]); 357 361 } 358 362 359 363 // Validate the email address. 360 if (get_option('ilachat_woocommerce_order_check_email_enabled' ) && $order->get_billing_email() !== $email) {364 if (get_option('ilachat_woocommerce_order_check_email_enabled', 0) && $order->get_billing_email() !== $email) { 361 365 return new WP_Error('invalid_email', esc_html__('Invalid email address', 'ilachat'), ['status' => 400]); 362 366 } 367 368 $data = $this->get_order_details($order); 369 370 return new WP_REST_Response($data, 200); 371 } 372 373 /** 374 * Get order details. 375 * 376 * @param object $order 377 * @return array 378 */ 379 public function get_order_details($order) 380 { 381 if (! $order) { 382 return []; 383 } 384 385 $order_id = $order->get_id(); 363 386 364 387 $allowed_data = get_option('ilachat_woocommerce_order_allowed_data', ['billing', 'shipping', 'items']); … … 366 389 367 390 $data = [ 368 'order_id' => $order->get_id(), 369 'date_of_order_creation' => $this->get_date($order->get_date_created()), 370 'date_of_order_completion' => $this->get_date($order->get_date_completed()), 371 'order_total' => $order->get_total() . ' ' . get_woocommerce_currency_symbol($order->get_currency()), 372 'order_status' => wc_get_order_status_name($order->get_status()), 391 'order_id' => $order_id, 392 'date_of_order_creation' => $this->get_date( 393 ($order->get_date_paid() ? $order->get_date_paid()->date('Y-m-d H:i:s') : null) 394 ?: ($order->get_date_created() ? $order->get_date_created()->date('Y-m-d H:i:s') : null) 395 ), 396 'order_total' => $order->get_total() . ' ' . get_woocommerce_currency_symbol($order->get_currency()), 397 'order_status' => wc_get_order_status_name($order->get_status()), 373 398 ]; 374 399 … … 417 442 'ilachat_woocommerce_order_item_data', 418 443 [ 419 'item_name' => $item->get_name(),444 'item_name' => apply_filters('ilachat_woocommerce_order_item_name', $item->get_name(), $item, $order), 420 445 'item_quantity' => $item->get_quantity(), 421 'item_total' => $item->get_total() . ' ' . get_woocommerce_currency_symbol($order->get_currency()),446 'item_total' => apply_filters('ilachat_woocommerce_order_item_total', $item->get_total() . ' ' . get_woocommerce_currency_symbol($order->get_currency()), $item, $order), 422 447 ], 423 448 $item, … … 453 478 } 454 479 455 if ( get_option('ilachat_woocommerce_order_special_note')) {480 if (in_array('special_note', $allowed_data, true) && get_option('ilachat_woocommerce_order_special_note', 0)) { 456 481 $data['special_note'] = []; 457 482 $order_notes = $this->get_special_order_notes($order_id); … … 470 495 } 471 496 497 if ($order->get_status() === 'completed' && $order->get_date_completed()) { 498 $data['date_of_order_completion'] = $this->get_date($order->get_date_completed()->date('Y-m-d H:i:s')); 499 } 500 472 501 $data = apply_filters('ilachat_woocommerce_order_data', $data, $order); 473 502 $data = $this->array_filter_recursive($data); 474 503 475 return new WP_REST_Response($data, 200);504 return $data; 476 505 } 477 506 … … 502 531 public function init_special_order_note() 503 532 { 504 if (! get_option('ilachat_woocommerce_order_special_note')) { 533 add_filter('comments_clauses', [$this, 'exclude_special_order_notes']); 534 535 if (! (bool) get_option('ilachat_woocommerce_order_special_note', 0)) { 505 536 return; 506 537 } … … 510 541 add_action('wp_ajax_ilachat_delete_order_note', [$this, 'delete_special_order_note_ajax']); 511 542 add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts']); 512 add_filter('comments_clauses', [$this, 'exclude_special_order_notes'], 10, 1);513 543 } 514 544 … … 522 552 $screen = get_current_screen(); 523 553 $expected_screen = OrderUtil::custom_orders_table_usage_is_enabled() ? 'woocommerce_page_wc-orders' : 'shop_order'; 524 if ($screen->id !== $expected_screen ) {554 if ($screen->id !== $expected_screen && strpos($screen->id, 'ilachat') === false) { 525 555 return; 526 556 } … … 530 560 'ilachat_woocommerce', 531 561 [ 532 'security' => wp_create_nonce('ilachat- order-note'),562 'security' => wp_create_nonce('ilachat-woocommerce'), 533 563 'delete_security' => wp_create_nonce('ilachat-delete-order-note'), 534 564 'ajax_url' => admin_url('admin-ajax.php'), 535 565 'texts' => [ 536 'empty_note' => esc_html__('Please enter a note.', 'ilachat'), 537 'error' => esc_html__('An error occurred while doing the request.', 'ilachat'), 538 'delete_note' => esc_html__('Delete note', 'ilachat'), 539 'confirm_delete' => esc_html__('Are you sure you want to delete this note? This action cannot be undone.', 'ilachat'), 566 'empty_note' => esc_html__('Please enter a note.', 'ilachat'), 567 'error' => esc_html__('An error occurred while doing the request.', 'ilachat'), 568 'delete_note' => esc_html__('Delete note', 'ilachat'), 569 'confirm_delete' => esc_html__('Are you sure you want to delete this note? This action cannot be undone.', 'ilachat'), 570 'pause_sync' => esc_html__('Pause sync', 'ilachat'), 571 'resume_sync' => esc_html__('Resume sync', 'ilachat'), 572 'sync_products' => esc_html__('Sync Products', 'ilachat'), 540 573 ], 541 574 ] … … 594 627 public function add_special_order_note_ajax() 595 628 { 596 check_ajax_referer('ilachat- order-note', 'security');629 check_ajax_referer('ilachat-woocommerce', 'security'); 597 630 598 631 $order_id = isset($_POST['order_id']) ? absint($_POST['order_id']) : 0; … … 749 782 750 783 /** 751 * Sync product data with Ilachat.784 * Handle sync product data with Ilachat. 752 785 * 753 786 * @param int $post_id The product post ID. … … 755 788 * @return void 756 789 */ 757 public function sync_product($post_id, $post)790 public function handle_sync_product($post_id, $post) 758 791 { 759 792 if ( … … 777 810 } 778 811 812 $this->sync_product($product); 813 } 814 815 /** 816 * Sync product data with Ilachat. 817 * 818 * @param object $product 819 * @return bool 820 */ 821 public function sync_product($product) 822 { 823 if (! $product) { 824 return; 825 } 826 827 if ('publish' !== $product->get_status()) { 828 return; 829 } 830 779 831 $token = get_option('ilachat_token', ''); 780 832 if (empty($token)) { … … 782 834 } 783 835 836 $product_id = $product->get_id(); 837 838 $parent_image_id = (int) $product->get_image_id(); 839 784 840 $body = [ 785 'wp_product_id' => $post_id, 786 'name' => $product->get_name(), 787 'description' => wp_strip_all_tags($product->get_description()), 788 'link' => $product->get_permalink(), 841 'wp_product_id' => $product_id, 842 'name' => apply_filters('ilachat_woocommerce_sync_product_name', $product->get_name(), $product), 843 'description' => wp_strip_all_tags(apply_filters('ilachat_woocommerce_sync_product_description', $product->get_description(), $product)), 844 'link' => apply_filters('ilachat_woocommerce_sync_product_link', $product->get_permalink(), $product), 845 'image' => $parent_image_id ? wp_get_attachment_url($parent_image_id) : '', 789 846 ]; 790 847 791 848 // Add excerpt to the description. 792 $excerpt = $product->get_short_description();849 $excerpt = apply_filters('ilachat_woocommerce_sync_product_excerpt', $product->get_short_description(), $product); 793 850 if ($excerpt) { 794 851 $body['description'] = $excerpt . "\n" . $body['description']; … … 802 859 $attr_name = wc_attribute_label($attribute->get_name()); 803 860 $options_ids = $attribute->get_options(); 804 $attr_options = array();861 $attr_options = []; 805 862 806 863 foreach ($options_ids as $option_id) { … … 817 874 $attributes_str .= $attr_name . ': ' . implode(', ', $attr_options) . "\n"; 818 875 } 876 877 $attributes_str = apply_filters('ilachat_woocommerce_sync_product_attributes', $attributes_str, $product); 878 819 879 $body['description'] = $attributes_str . $body['description']; 820 880 … … 825 885 foreach ($product->get_children() as $variation_id) { 826 886 $variation = wc_get_product($variation_id); 887 888 if (! $variation) { 889 continue; 890 } 891 892 $variation_image_id = (int) $variation->get_image_id(); 893 827 894 $body['variations'][] = [ 828 'name' => $variation->get_name(),829 'price' => $variation->get_price() . ' ' . get_woocommerce_currency_symbol(),830 'description' => $variation->get_description() ?: '',895 'name' => apply_filters('ilachat_woocommerce_sync_product_variation_name', $variation->get_name(), $variation), 896 'price' => apply_filters('ilachat_woocommerce_sync_product_variation_price', $variation->get_price() . ' ' . get_woocommerce_currency_symbol(), $variation), 897 'description' => wp_strip_all_tags(apply_filters('ilachat_woocommerce_sync_product_variation_description', $variation->get_description(), $variation)), 831 898 'available' => $parent_available ? $variation->is_in_stock() : false, 832 'image' => $variation->get_image_id() ? wp_get_attachment_url($variation->get_image_id()) : wp_get_attachment_url($product->get_image_id()), 833 'link' => $variation->get_permalink(), 899 'image' => $variation_image_id !== $parent_image_id ? wp_get_attachment_url($variation_image_id) : '', 834 900 ]; 835 901 } 836 902 } elseif ($product->is_type('simple')) { 837 $body['variations'] []= [838 'name' => $product->get_name(),839 'price' => $product->get_price() . ' ' . get_woocommerce_currency_symbol(),840 'available' => $parent_available,841 'image' => $product->get_image_id() ? wp_get_attachment_url($product->get_image_id()) : '',842 'link' => $product->get_permalink(),903 $body['variations'] = [ 904 [ 905 'name' => apply_filters('ilachat_woocommerce_sync_product_variation_name', $product->get_name(), $product), 906 'price' => apply_filters('ilachat_woocommerce_sync_product_variation_price', $product->get_price() . ' ' . get_woocommerce_currency_symbol(), $product), 907 'available' => $parent_available, 908 ] 843 909 ]; 844 910 } … … 858 924 859 925 if (is_wp_error($response) || wp_remote_retrieve_response_code($response) !== 200) { 860 add_action( 861 'admin_notices', 862 function () { 863 echo '<div class="notice notice-error is-dismissible"><p>' . esc_html__('Failed to sync product with Ilachat.', 'ilachat') . '</p></div>'; 864 } 865 ); 866 return; 926 return false; 867 927 } 868 928 869 929 $response_body = json_decode(wp_remote_retrieve_body($response), true); 870 930 if (empty($response_body['status']) || 'success' !== $response_body['status']) { 871 add_action( 872 'admin_notices', 873 function () use ($response_body) { 874 echo '<div class="notice notice-error is-dismissible"><p>' . esc_html__('Failed to sync product with Ilachat.', 'ilachat') . '</p></div>'; 875 } 876 ); 877 return; 878 } 879 880 add_action( 881 'admin_notices', 882 function () { 883 echo '<div class="notice notice-success is-dismissible"><p>' . esc_html__('Product synced successfully with Ilachat.', 'ilachat') . '</p></div>'; 884 } 885 ); 886 update_post_meta($post_id, 'ilachat_synced', current_time('mysql')); 931 return false; 932 } 933 934 $product->update_meta_data('ilachat_synced', current_time('mysql')); 935 $product->save(); 936 937 return true; 887 938 } 888 939 … … 899 950 } 900 951 901 $product = wc_get_product($post->ID);952 $product = wc_get_product($post->ID); 902 953 if (! $product) { 903 954 return; … … 905 956 906 957 $last_synced = $product->get_meta('ilachat_synced', true); 907 $sync_active = get_option('ilachat_woocommerce_product_sync_enabled', false);958 $sync_active = get_option('ilachat_woocommerce_product_sync_enabled', 0); 908 959 909 960 echo '<div class="misc-pub-section misc-pub-ilachat">'; 910 961 wp_nonce_field('ilachat_sync_product', 'ilachat_sync_product_nonce'); 911 echo '<label><input type="checkbox" name="ilachat_sync_product" value="1" ' . checked($sync_active, true, false) . ' /> ' . esc_html__('Sync with Ilachat', 'ilachat') . '</label>';962 echo '<label><input type="checkbox" name="ilachat_sync_product" value="1" ' . checked($sync_active, 1, false) . ' /> ' . esc_html__('Sync with Ilachat', 'ilachat') . '</label>'; 912 963 if ($last_synced) { 913 964 echo '<p class="description">' . esc_html__('Last synced:', 'ilachat') . ' ' . esc_html($this->get_date($last_synced)) . '</p>'; 914 965 } 915 966 echo '</div>'; 967 } 968 969 /** 970 * Add a bulk action to sync products with Ilachat. 971 * 972 * @param array $bulk_actions The bulk actions. 973 * @return array The modified bulk actions. 974 */ 975 public function add_bulk_actions($bulk_actions) 976 { 977 $bulk_actions['ilachat_sync_products'] = esc_html__('Sync with Ilachat', 'ilachat'); 978 return $bulk_actions; 979 } 980 981 /** 982 * Handle the bulk action to sync products with Ilachat. 983 * 984 * @param string $redirect_to The redirect URL. 985 * @param string $action The bulk action. 986 * @param array $post_ids The post IDs. 987 * @return string The modified redirect URL. 988 */ 989 public function handle_bulk_actions($redirect_to, $action, $post_ids) 990 { 991 if ('ilachat_sync_products' !== $action) { 992 return $redirect_to; 993 } 994 995 $update_status = ['success' => 0, 'error' => 0]; 996 foreach ($post_ids as $post_id) { 997 $product = wc_get_product($post_id); 998 if ($product) { 999 if ($this->sync_product($product)) { 1000 $update_status['success']++; 1001 } else { 1002 $update_status['error']++; 1003 } 1004 } 1005 } 1006 1007 // Append nonce along with our custom query variables. 1008 $redirect_to = add_query_arg( 1009 [ 1010 'ilachat_sync_products' => 1, 1011 'success' => $update_status['success'], 1012 'error' => $update_status['error'], 1013 '_wpnonce' => wp_create_nonce('bulk-posts'), 1014 ], 1015 $redirect_to 1016 ); 1017 1018 return $redirect_to; 1019 } 1020 1021 /** 1022 * Display a notice after syncing products. 1023 * 1024 * @return void 1025 */ 1026 public function sync_product_admin_notice() 1027 { 1028 if (! isset($_GET['ilachat_sync_products'])) { 1029 return; 1030 } 1031 1032 // Verify nonce to ensure the notice is displayed only when coming from our bulk action. 1033 if (! isset($_GET['_wpnonce']) || ! wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])), 'bulk-posts')) { 1034 return; 1035 } 1036 1037 $success = isset($_GET['success']) ? absint($_GET['success']) : 0; 1038 $error = isset($_GET['error']) ? absint($_GET['error']) : 0; 1039 1040 if ($success > 0) { 1041 $message = sprintf( 1042 // translators: %s is the number of products successfully synced with Ilachat. 1043 _n( 1044 'Synced %s product with Ilachat.', 1045 'Synced %s products with Ilachat.', 1046 $success, 1047 'ilachat' 1048 ), 1049 number_format_i18n($success) 1050 ); 1051 echo '<div class="notice notice-success is-dismissible"><p>' . esc_html($message) . '</p></div>'; 1052 } 1053 1054 if ($error > 0) { 1055 $message = sprintf( 1056 // translators: %s is the number of products that failed to sync with Ilachat. 1057 _n( 1058 'Failed to sync %s product with Ilachat.', 1059 'Failed to sync %s products with Ilachat.', 1060 $error, 1061 'ilachat' 1062 ), 1063 number_format_i18n($error) 1064 ); 1065 echo '<div class="notice notice-error is-dismissible"><p>' . esc_html($message) . '</p></div>'; 1066 } 1067 } 1068 1069 /** 1070 * Ajax handler for syncing products with Ilachat. 1071 * 1072 * @return void 1073 */ 1074 public function sync_products_ajax() 1075 { 1076 check_ajax_referer('ilachat-woocommerce', 'security'); 1077 1078 $offset = isset($_POST['offset']) ? absint($_POST['offset']) : 0; 1079 1080 $products = wc_get_products( 1081 [ 1082 'limit' => 1, 1083 'offset' => $offset, 1084 'status' => ['publish'], 1085 'stock_status' => 'instock', 1086 ] 1087 ); 1088 1089 $total_products = count($products); 1090 1091 $success = 0; 1092 $error = 0; 1093 1094 foreach ($products as $product) { 1095 if ($product->is_type('variation') || $product->get_meta('ilachat_synced', true)) { 1096 continue; 1097 } 1098 if ($this->sync_product($product)) { 1099 $success++; 1100 } else { 1101 $error++; 1102 } 1103 } 1104 1105 $offset += $total_products; 1106 1107 $response = [ 1108 'success' => $success, 1109 'error' => $error, 1110 'offset' => $offset, 1111 'total' => $total_products, 1112 ]; 1113 1114 wp_send_json_success($response); 916 1115 } 917 1116 … … 959 1158 private function get_date($date) 960 1159 { 961 return date_i18n(get_option('date_format') . ' ' . get_option('time_format'), strtotime($date)); 1160 if (empty($date)) { 1161 return ''; 1162 } 1163 1164 $datetime = wc_string_to_datetime($date); 1165 return apply_filters('ilachat_woocommerce_get_date', $datetime ? $datetime->date_i18n(get_option('date_format') . ' ' . get_option('time_format')) : '-', $date); 962 1166 } 963 1167 -
ilachat/trunk/templates/admin/wc-integration-page.php
r3252598 r3257952 37 37 do_settings_sections('ilachat_woocommerce'); 38 38 39 // Retrieve current option values. 40 $integration_enabled = get_option('ilachat_woocommerce_integration_enabled'); 41 $order_tracking_enabled = get_option('ilachat_woocommerce_order_tracking_enabled'); 42 $order_additional_info = get_option('ilachat_woocommerce_order_additional_info'); 43 $order_allowed_data = get_option('ilachat_woocommerce_order_allowed_data', ['billing', 'shipping', 'items']); 44 $order_statuses_description = get_option('ilachat_woocommerce_order_statuses_description', []); 45 $order_check_phone_enabled = get_option('ilachat_woocommerce_order_check_phone_enabled'); 46 $order_check_email_enabled = get_option('ilachat_woocommerce_order_check_email_enabled'); 47 $order_special_note = get_option('ilachat_woocommerce_order_special_note'); 48 $product_sync_enabled = get_option('ilachat_woocommerce_product_sync_enabled'); 49 $order_statuses_json = ! empty($order_statuses_description) ? json_encode($order_statuses_description, JSON_PRETTY_PRINT) : ''; 39 $integration_enabled = get_option('ilachat_woocommerce_integration_enabled'); 40 $order_tracking_enabled = get_option('ilachat_woocommerce_order_tracking_enabled'); 41 $order_allowed_data = get_option('ilachat_woocommerce_order_allowed_data', ['billing', 'shipping', 'items']); 42 $order_statuses_description = get_option('ilachat_woocommerce_order_statuses_description', []); 43 $order_check_phone_enabled = get_option('ilachat_woocommerce_order_check_phone_enabled'); 44 $order_check_email_enabled = get_option('ilachat_woocommerce_order_check_email_enabled'); 45 $order_special_note = get_option('ilachat_woocommerce_order_special_note'); 46 $product_sync_enabled = get_option('ilachat_woocommerce_product_sync_enabled'); 50 47 ?> 51 48 … … 64 61 <label for="ilachat_woocommerce_product_sync_enabled"><?php esc_html_e('Enable product synchronization with Ilachat.', 'ilachat'); ?></label> 65 62 <p class="description"><?php esc_html_e('This will automatically sync your WooCommerce products with Ilachat whenever a product is updated.', 'ilachat'); ?></p> 63 <div style="margin-top:1em" id="ilachat-woocommerce-sync-products-wrapper"> 64 <button type="button" class="button button-secondary" id="ilachat-woocommerce-sync-products" style="margin-top:1em"><?php esc_html_e('Sync All Products Now', 'ilachat'); ?></button> 65 <p class="description"><?php esc_html_e('Click the button above to manually sync all products with Ilachat for the first time.', 'ilachat'); ?></p> 66 <p id="ilachat-woocommerce-sync-products-message" style="display:none"> 67 <strong><?php esc_html_e('Success:', 'ilachat'); ?></strong> <span>0</span> <strong><?php esc_html_e('Error:', 'ilachat'); ?></strong> <span>0</span> 68 </p> 69 </div> 66 70 </td> 67 71 </tr> 68 72 </table> 73 69 74 <h2><?php esc_html_e('Order Tracking', 'ilachat'); ?></h2> 70 75 <table class="form-table"> … … 80 85 <td> 81 86 <input type="checkbox" name="ilachat_woocommerce_order_check_phone_enabled" value="1" <?php checked($order_check_phone_enabled, 1); ?> id="ilachat_woocommerce_order_check_phone_enabled" /> 82 <label for="ilachat_woocommerce_order_check_phone_enabled"><?php esc_html_e('Validate the phone number during order tracking.', 'ilachat'); ?></label>< /br>87 <label for="ilachat_woocommerce_order_check_phone_enabled"><?php esc_html_e('Validate the phone number during order tracking.', 'ilachat'); ?></label><br> 83 88 <input type="checkbox" name="ilachat_woocommerce_order_check_email_enabled" value="1" <?php checked($order_check_email_enabled, 1); ?> id="ilachat_woocommerce_order_check_email_enabled" /> 84 89 <label for="ilachat_woocommerce_order_check_email_enabled"><?php esc_html_e('Validate the email address during order tracking.', 'ilachat'); ?></label> 85 86 90 </td> 87 91 </tr>
Note: See TracChangeset
for help on using the changeset viewer.