Plugin Directory

Changeset 3257952


Ignore:
Timestamp:
03/18/2025 04:06:12 PM (13 months ago)
Author:
ilachat
Message:

Initial v1.1.1 update

Location:
ilachat/trunk
Files:
4 added
8 edited

Legend:

Unmodified
Added
Removed
  • ilachat/trunk/assets/css/ilachat-woocommerce.css

    r3252285 r3257952  
    2020  border-color: #b3d4ff transparent;
    2121}
     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  
    126126}
    127127
     128class 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
    128256document.addEventListener('DOMContentLoaded', () => {
    129257    new IlachatOrderNotes();
     258    new IlachatProductSync();
    130259});
  • ilachat/trunk/composer.json

    r3239636 r3257952  
    1414        }
    1515    ],
    16     "require": {}
     16    "require": {},
     17    "config": {
     18        "allow-plugins": {
     19            "dealerdirect/phpcodesniffer-composer-installer": false
     20        }
     21    }
    1722}
  • ilachat/trunk/ilachat.php

    r3252602 r3257952  
    1212 * Plugin URI: https://ila.chat
    1313 * Description: Integrate ILACHAT with WordPress to add AI-powered chatbot and live chat for seamless customer support and engagement.
    14  * Version: 1.1.0
     14 * Version: 1.1.1
    1515 * Requires at least: 6.2
    1616 * Requires PHP: 7.4.0
     
    4545
    4646// Define constants
    47 define('ILACHAT_VERSION', '1.1.0');
     47define('ILACHAT_VERSION', '1.1.1');
    4848define('ILACHAT_ROOT', __FILE__);
    4949define('ILACHAT_PATH', plugin_dir_path(ILACHAT_ROOT));
     
    5555
    5656// 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 
     57define('ILACHAT_CONNECT_URL', 'https://app.ila.chat/user/dashboard/connect-services');
     58define('ILACHAT_VALIDATE_TOKEN_API', 'https://app.ila.chat/api/connect-services/wpp/valid-token');
     59define('ILACHAT_PLUGIN_UPDATE_API', 'https://app.ila.chat/api/connect-services/wpp/last-update');
     60define('ILACHAT_GET_WIDGET_API', 'https://app.ila.chat/api/connect-services/wpp/get-bot-details');
     61define('ILACHAT_SYNC_PRODUCT_API', 'https://app.ila.chat/api/connect-services/wpp/sync-product');
     62define('ILACHAT_SYNC_VARIABLE_LINK_API', 'https://app.ila.chat/api/connect-services/wpp/sync-variable-link');
     63define('ILACHAT_DISCONNECT_API', 'https://app.ila.chat/api/connect-services/wpp/disconnect');
    6564
    6665// Include Composer autoload
     
    7978function ilachat_init()
    8079{
    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    }
    8285}
    8386
  • ilachat/trunk/languages/ilachat.pot

    r3252598 r3257952  
    33msgid ""
    44msgstr ""
    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"
    66"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/ilachat\n"
    77"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
     
    1010"Content-Type: text/plain; charset=UTF-8\n"
    1111"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"
    1313"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
    1414"X-Generator: WP-CLI 2.11.0\n"
     
    8080msgstr ""
    8181
    82 #: src/Integrations/Woocommerce.php:170
    83 #: src/Integrations/Woocommerce.php:171
    84 #: src/Integrations/Woocommerce.php:196
    85 #: templates/admin/wc-integration-page.php:54
     82#: 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
    8686msgid "WooCommerce Integration"
    8787msgstr ""
    8888
    89 #: src/Integrations/Woocommerce.php:351
     89#: src/Integrations/Woocommerce.php:342
    9090msgid "Order tracking is disabled"
    9191msgstr ""
    9292
    93 #: src/Integrations/Woocommerce.php:359
     93#: src/Integrations/Woocommerce.php:350
    9494msgid "Order ID is required"
    9595msgstr ""
    9696
    97 #: src/Integrations/Woocommerce.php:364
     97#: src/Integrations/Woocommerce.php:355
    9898msgid "Order not found"
    9999msgstr ""
    100100
    101 #: src/Integrations/Woocommerce.php:369
     101#: src/Integrations/Woocommerce.php:360
    102102msgid "Invalid phone number"
    103103msgstr ""
    104104
    105 #: src/Integrations/Woocommerce.php:374
     105#: src/Integrations/Woocommerce.php:365
    106106msgid "Invalid email address"
    107107msgstr ""
    108108
    109 #: src/Integrations/Woocommerce.php:549
    110 #: src/Integrations/Woocommerce.php:620
     109#: src/Integrations/Woocommerce.php:566
     110#: src/Integrations/Woocommerce.php:640
    111111msgid "Please enter a note."
    112112msgstr ""
    113113
    114 #: src/Integrations/Woocommerce.php:550
     114#: src/Integrations/Woocommerce.php:567
    115115msgid "An error occurred while doing the request."
    116116msgstr ""
    117117
    118 #: src/Integrations/Woocommerce.php:551
     118#: src/Integrations/Woocommerce.php:568
    119119#: templates/admin/wc-order-notes.php:38
    120120msgid "Delete note"
    121121msgstr ""
    122122
    123 #: src/Integrations/Woocommerce.php:552
     123#: src/Integrations/Woocommerce.php:569
    124124msgid "Are you sure you want to delete this note? This action cannot be undone."
    125125msgstr ""
    126126
     127#: src/Integrations/Woocommerce.php:570
     128msgid "Pause sync"
     129msgstr ""
     130
     131#: src/Integrations/Woocommerce.php:571
     132msgid "Resume sync"
     133msgstr ""
     134
    127135#: src/Integrations/Woocommerce.php:572
     136msgid "Sync Products"
     137msgstr ""
     138
     139#: src/Integrations/Woocommerce.php:592
    128140msgid "Ilachat Order Notes"
    129141msgstr ""
    130142
    131 #: src/Integrations/Woocommerce.php:615
     143#: src/Integrations/Woocommerce.php:635
    132144msgid "Invalid order."
    133145msgstr ""
    134146
    135 #: src/Integrations/Woocommerce.php:625
     147#: src/Integrations/Woocommerce.php:645
    136148msgid "Failed to add note."
    137149msgstr ""
    138150
    139 #: src/Integrations/Woocommerce.php:695
     151#: src/Integrations/Woocommerce.php:715
    140152msgid "Failed to delete note."
    141153msgstr ""
    142154
    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
    153157msgid "Sync with Ilachat"
    154158msgstr ""
    155159
    156 #: src/Integrations/Woocommerce.php:926
     160#: src/Integrations/Woocommerce.php:964
    157161msgid "Last synced:"
    158162msgstr ""
     163
     164#. translators: %s is the number of products successfully synced with Ilachat.
     165#: src/Integrations/Woocommerce.php:1043
     166msgid "Synced %s product with Ilachat."
     167msgid_plural "Synced %s products with Ilachat."
     168msgstr[0] ""
     169msgstr[1] ""
     170
     171#. translators: %s is the number of products that failed to sync with Ilachat.
     172#: src/Integrations/Woocommerce.php:1057
     173msgid "Failed to sync %s product with Ilachat."
     174msgid_plural "Failed to sync %s products with Ilachat."
     175msgstr[0] ""
     176msgstr[1] ""
    159177
    160178#: templates/admin/connect-page.php:28
     
    202220msgstr ""
    203221
    204 #: templates/admin/wc-integration-page.php:57
     222#: templates/admin/wc-integration-page.php:54
    205223msgid "Enable the integration between Ilachat and WooCommerce."
    206224msgstr ""
    207225
     226#: templates/admin/wc-integration-page.php:58
     227msgid "Product Sync"
     228msgstr ""
     229
    208230#: templates/admin/wc-integration-page.php:61
    209 msgid "Product Sync"
     231msgid "Enable product synchronization with Ilachat."
     232msgstr ""
     233
     234#: templates/admin/wc-integration-page.php:62
     235msgid "This will automatically sync your WooCommerce products with Ilachat whenever a product is updated."
    210236msgstr ""
    211237
    212238#: templates/admin/wc-integration-page.php:64
    213 msgid "Enable product synchronization with Ilachat."
     239msgid "Sync All Products Now"
    214240msgstr ""
    215241
    216242#: 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
     243msgid "Click the button above to manually sync all products with Ilachat for the first time."
     244msgstr ""
     245
     246#: templates/admin/wc-integration-page.php:67
     247msgid "Success:"
     248msgstr ""
     249
     250#: templates/admin/wc-integration-page.php:67
     251msgid "Error:"
     252msgstr ""
     253
     254#: templates/admin/wc-integration-page.php:74
     255#: templates/admin/wc-integration-page.php:77
    222256msgid "Order Tracking"
    223257msgstr ""
    224258
    225 #: templates/admin/wc-integration-page.php:75
     259#: templates/admin/wc-integration-page.php:80
    226260msgid "Enable order tracking through the REST API."
    227261msgstr ""
    228262
    229 #: templates/admin/wc-integration-page.php:79
     263#: templates/admin/wc-integration-page.php:84
    230264msgid "Authorizations"
    231265msgstr ""
    232266
    233 #: templates/admin/wc-integration-page.php:82
     267#: templates/admin/wc-integration-page.php:87
    234268msgid "Validate the phone number during order tracking."
    235269msgstr ""
    236270
    237 #: templates/admin/wc-integration-page.php:84
     271#: templates/admin/wc-integration-page.php:89
    238272msgid "Validate the email address during order tracking."
    239273msgstr ""
    240274
    241 #: templates/admin/wc-integration-page.php:89
     275#: templates/admin/wc-integration-page.php:93
    242276msgid "Allowed Order Data"
    243277msgstr ""
    244278
    245 #: templates/admin/wc-integration-page.php:93
     279#: templates/admin/wc-integration-page.php:97
    246280msgid "Billing Information"
    247281msgstr ""
    248282
    249 #: templates/admin/wc-integration-page.php:94
     283#: templates/admin/wc-integration-page.php:98
    250284msgid "Shipping Information"
    251285msgstr ""
    252286
    253 #: templates/admin/wc-integration-page.php:95
     287#: templates/admin/wc-integration-page.php:99
    254288msgid "Purchased Items Details"
    255289msgstr ""
    256290
    257 #: templates/admin/wc-integration-page.php:96
     291#: templates/admin/wc-integration-page.php:100
    258292msgid "Order Notes"
    259293msgstr ""
    260294
    261 #: templates/admin/wc-integration-page.php:107
     295#: templates/admin/wc-integration-page.php:111
    262296msgid "Select the user order data fields to expose via the REST API."
    263297msgstr ""
    264298
    265 #: templates/admin/wc-integration-page.php:111
     299#: templates/admin/wc-integration-page.php:115
    266300msgid "Special Order Note"
    267301msgstr ""
    268302
    269 #: templates/admin/wc-integration-page.php:114
     303#: templates/admin/wc-integration-page.php:118
    270304msgid "Enable special order notes functionality."
    271305msgstr ""
    272306
    273 #: templates/admin/wc-integration-page.php:115
     307#: templates/admin/wc-integration-page.php:119
    274308msgid "This will add a special meta box to the order edit screen for adding additional notes exclusive to Ilachat."
    275309msgstr ""
    276310
    277 #: templates/admin/wc-integration-page.php:119
    278 #: templates/admin/wc-integration-page.php:122
     311#: templates/admin/wc-integration-page.php:123
     312#: templates/admin/wc-integration-page.php:126
    279313msgid "Order Statuses Description"
    280314msgstr ""
    281315
    282 #: templates/admin/wc-integration-page.php:128
     316#: templates/admin/wc-integration-page.php:132
    283317msgid "Provide a description for each order status."
    284318msgstr ""
  • ilachat/trunk/readme.txt

    r3252599 r3257952  
    7373== Changelog ==
    7474
     75= 1.1.1 =
     76* Fix for WooCommerce product syncing.
     77* Added bulk product syncing option.
     78* Minor bug fixes.
     79
    7580= 1.1.0 =
    7681* Added WooCommerce integration:
  • ilachat/trunk/src/Integrations/Woocommerce.php

    r3252602 r3257952  
    4949        add_action('updated_option', [$this, 'sync_variable_links_after_update'], 10, 3);
    5050
    51         if (get_option('ilachat_woocommerce_integration_enabled')) {
     51        if (get_option('ilachat_woocommerce_integration_enabled', 1)) {
    5252            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);
    5454            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']);
    5559            $this->init_special_order_note();
    5660        }
     
    7175            'ilachat_woocommerce_integration_enabled' => [
    7276                'type'              => 'boolean',
    73                 'default'           => true,
     77                'default'           => 1,
    7478                'sanitize_callback' => [$this, 'sanitize_boolean'],
    7579            ],
    7680            'ilachat_woocommerce_order_tracking_enabled' => [
    7781                'type'              => 'boolean',
    78                 'default'           => true,
     82                'default'           => 1,
    7983                'sanitize_callback' => [$this, 'sanitize_boolean'],
    8084            ],
     
    8690            'ilachat_woocommerce_order_check_phone_enabled' => [
    8791                'type'              => 'boolean',
    88                 'default'           => true,
     92                'default'           => 1,
    8993                'sanitize_callback' => [$this, 'sanitize_boolean'],
    9094            ],
     
    96100            'ilachat_woocommerce_order_check_email_enabled' => [
    97101                'type'              => 'boolean',
    98                 'default'           => true,
     102                'default'           => 1,
    99103                'sanitize_callback' => [$this, 'sanitize_boolean'],
    100104            ],
    101105            'ilachat_woocommerce_order_special_note' => [
    102106                'type'              => 'boolean',
    103                 'default'           => true,
     107                'default'           => 1,
    104108                'sanitize_callback' => [$this, 'sanitize_boolean'],
    105109            ],
    106110            'ilachat_woocommerce_product_sync_enabled' => [
    107111                'type'              => 'boolean',
    108                 'default'           => false,
     112                'default'           => 0,
    109113                'sanitize_callback' => [$this, 'sanitize_boolean'],
    110114            ],
     
    114118            register_setting('ilachat_woocommerce', $option, (array) $args);
    115119
    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'])) {
    118122                update_option($option, $args['default']);
    119123            }
     
    157161            esc_html__('WooCommerce Integration', 'ilachat'),
    158162            esc_html__('WooCommerce Integration', 'ilachat'),
    159             'read',
     163            'manage_options',
    160164            'ilachat-woocommerce',
    161165            [$this, 'render_page']
     
    232236        }
    233237
    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);
    236240
    237241        $rest_enabled = false;
     
    240244        }
    241245
    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);
    244248
    245249        $registered_route = rest_url('ilachat/v1/get-order-details');
     
    284288    public function register_rest_routes()
    285289    {
    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);
    288292        if (! $integration_enabled || ! $order_tracking_enabled) {
    289293            return;
    290294        }
    291295
    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);
    294298
    295299        register_rest_route(
     
    334338    public function handle_get_order_details(WP_REST_Request $request)
    335339    {
    336         $order_tracking_enabled = get_option('ilachat_woocommerce_order_tracking_enabled');
     340        $order_tracking_enabled = get_option('ilachat_woocommerce_order_tracking_enabled', 1);
    337341        if (! $order_tracking_enabled) {
    338342            return new WP_Error('order_tracking_disabled', esc_html__('Order tracking is disabled', 'ilachat'), ['status' => 400]);
     
    353357
    354358        // 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)) {
    356360            return new WP_Error('invalid_phone', esc_html__('Invalid phone number', 'ilachat'), ['status' => 400]);
    357361        }
    358362
    359363        // 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) {
    361365            return new WP_Error('invalid_email', esc_html__('Invalid email address', 'ilachat'), ['status' => 400]);
    362366        }
     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();
    363386
    364387        $allowed_data = get_option('ilachat_woocommerce_order_allowed_data', ['billing', 'shipping', 'items']);
     
    366389
    367390        $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()),
    373398        ];
    374399
     
    417442                    'ilachat_woocommerce_order_item_data',
    418443                    [
    419                         'item_name'     => $item->get_name(),
     444                        'item_name'     => apply_filters('ilachat_woocommerce_order_item_name', $item->get_name(), $item, $order),
    420445                        '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),
    422447                    ],
    423448                    $item,
     
    453478        }
    454479
    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)) {
    456481            $data['special_note'] = [];
    457482            $order_notes          = $this->get_special_order_notes($order_id);
     
    470495        }
    471496
     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
    472501        $data = apply_filters('ilachat_woocommerce_order_data', $data, $order);
    473502        $data = $this->array_filter_recursive($data);
    474503
    475         return new WP_REST_Response($data, 200);
     504        return $data;
    476505    }
    477506
     
    502531    public function init_special_order_note()
    503532    {
    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)) {
    505536            return;
    506537        }
     
    510541        add_action('wp_ajax_ilachat_delete_order_note', [$this, 'delete_special_order_note_ajax']);
    511542        add_action('admin_enqueue_scripts', [$this, 'enqueue_scripts']);
    512         add_filter('comments_clauses', [$this, 'exclude_special_order_notes'], 10, 1);
    513543    }
    514544
     
    522552        $screen          = get_current_screen();
    523553        $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) {
    525555            return;
    526556        }
     
    530560            'ilachat_woocommerce',
    531561            [
    532                 'security'        => wp_create_nonce('ilachat-order-note'),
     562                'security'        => wp_create_nonce('ilachat-woocommerce'),
    533563                'delete_security' => wp_create_nonce('ilachat-delete-order-note'),
    534564                'ajax_url'        => admin_url('admin-ajax.php'),
    535565                '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'),
    540573                ],
    541574            ]
     
    594627    public function add_special_order_note_ajax()
    595628    {
    596         check_ajax_referer('ilachat-order-note', 'security');
     629        check_ajax_referer('ilachat-woocommerce', 'security');
    597630
    598631        $order_id = isset($_POST['order_id']) ? absint($_POST['order_id']) : 0;
     
    749782
    750783    /**
    751      * Sync product data with Ilachat.
     784     * Handle sync product data with Ilachat.
    752785     *
    753786     * @param int    $post_id The product post ID.
     
    755788     * @return void
    756789     */
    757     public function sync_product($post_id, $post)
     790    public function handle_sync_product($post_id, $post)
    758791    {
    759792        if (
     
    777810        }
    778811
     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
    779831        $token = get_option('ilachat_token', '');
    780832        if (empty($token)) {
     
    782834        }
    783835
     836        $product_id = $product->get_id();
     837
     838        $parent_image_id = (int) $product->get_image_id();
     839
    784840        $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) : '',
    789846        ];
    790847
    791848        // 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);
    793850        if ($excerpt) {
    794851            $body['description'] = $excerpt . "\n" . $body['description'];
     
    802859                $attr_name = wc_attribute_label($attribute->get_name());
    803860                $options_ids = $attribute->get_options();
    804                 $attr_options = array();
     861                $attr_options = [];
    805862
    806863                foreach ($options_ids as $option_id) {
     
    817874            $attributes_str .= $attr_name . ': ' . implode(', ', $attr_options) . "\n";
    818875        }
     876
     877        $attributes_str = apply_filters('ilachat_woocommerce_sync_product_attributes', $attributes_str, $product);
     878
    819879        $body['description'] = $attributes_str . $body['description'];
    820880
     
    825885            foreach ($product->get_children() as $variation_id) {
    826886                $variation = wc_get_product($variation_id);
     887
     888                if (! $variation) {
     889                    continue;
     890                }
     891
     892                $variation_image_id = (int) $variation->get_image_id();
     893
    827894                $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)),
    831898                    '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) : '',
    834900                ];
    835901            }
    836902        } 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                ]
    843909            ];
    844910        }
     
    858924
    859925        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;
    867927        }
    868928
    869929        $response_body = json_decode(wp_remote_retrieve_body($response), true);
    870930        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;
    887938    }
    888939
     
    899950        }
    900951
    901         $product     = wc_get_product($post->ID);
     952        $product = wc_get_product($post->ID);
    902953        if (! $product) {
    903954            return;
     
    905956
    906957        $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);
    908959
    909960        echo '<div class="misc-pub-section misc-pub-ilachat">';
    910961        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>';
    912963        if ($last_synced) {
    913964            echo '<p class="description">' . esc_html__('Last synced:', 'ilachat') . ' ' . esc_html($this->get_date($last_synced)) . '</p>';
    914965        }
    915966        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);
    9161115    }
    9171116
     
    9591158    private function get_date($date)
    9601159    {
    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);
    9621166    }
    9631167
  • ilachat/trunk/templates/admin/wc-integration-page.php

    r3252598 r3257952  
    3737        do_settings_sections('ilachat_woocommerce');
    3838
    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');
    5047        ?>
    5148
     
    6461                    <label for="ilachat_woocommerce_product_sync_enabled"><?php esc_html_e('Enable product synchronization with Ilachat.', 'ilachat'); ?></label>
    6562                    <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>
    6670                </td>
    6771            </tr>
    6872        </table>
     73
    6974        <h2><?php esc_html_e('Order Tracking', 'ilachat'); ?></h2>
    7075        <table class="form-table">
     
    8085                <td>
    8186                    <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>
    8388                    <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" />
    8489                    <label for="ilachat_woocommerce_order_check_email_enabled"><?php esc_html_e('Validate the email address during order tracking.', 'ilachat'); ?></label>
    85 
    8690                </td>
    8791            </tr>
Note: See TracChangeset for help on using the changeset viewer.