Plugin Directory

Changeset 3348358


Ignore:
Timestamp:
08/21/2025 09:26:20 PM (6 months ago)
Author:
helloextend
Message:

Updated to version 1.1.1 with bugs fixed for product and shipping protection

Location:
helloextend-protection/trunk
Files:
11 added
18 edited

Legend:

Unmodified
Added
Removed
  • helloextend-protection/trunk/admin/class-helloextend-protection-admin.php

    r3263092 r3348358  
    8888        add_action('admin_init', array($this, 'helloextend_protection_for_woocommerce_settings_page_init'));
    8989        add_action('admin_enqueue_scripts', 'helloextend_protection_style');
     90
     91        add_action('wp_ajax_helloextend_remove_ignored_category', array($this, 'helloextend_remove_ignored_category'), 10);
     92        add_action('wp_ajax_nopriv_helloextend_remove_ignored_category', array($this, 'helloextend_remove_ignored_category'), 10);
    9093
    9194        // add_action('admin_enqueue_scripts', 'helloextend_admin_enqueue_scripts');
     
    158161        $nonce             = wp_create_nonce('helloextend_sync_nonce');
    159162        $helloextend_sync_batch = $this->helloextend_protection_for_woocommerce_settings_catalog_sync_options['helloextend_sync_batch'];
     163        $debug_log_enabled = $this->helloextend_protection_for_woocommerce_settings_general_options['enable_helloextend_debug'];
    160164
    161165        wp_enqueue_script('helloextend_script');
    162166        wp_enqueue_script('helloextend_sync_script');
    163         wp_localize_script('helloextend_sync_script', 'ExtendWooCommerce', compact('store_id', 'ajaxurl', 'environment', 'nonce', 'helloextend_sync_batch'));
     167        wp_localize_script('helloextend_sync_script', 'ExtendWooCommerce', compact('store_id', 'ajaxurl', 'environment', 'nonce', 'helloextend_sync_batch', 'debug_log_enabled'));
    164168
    165169        /* end for sync */
     
    168172            wp_enqueue_script($this->helloextend_protection, plugin_dir_url(__FILE__) . 'js/helloextend-protection-admin.js', array('jquery'), $this->version, false);
    169173        }
     174
     175        $js_path = plugin_dir_path(__FILE__) . 'js/helloextend-protection-remove-ignored-category.js';
     176        $js_file_version = file_exists($js_path) ? filemtime($js_path) : $this->version;
     177        wp_enqueue_script('helloextend_remove_ignored_category_script', plugin_dir_url(__FILE__) . 'js/helloextend-protection-remove-ignored-category.js', array('jquery'), $js_file_version, true);
    170178    }
    171179
     
    238246                    'before_section' => '<div style="margin-top:40px;">',
    239247                    'after_section'  => '</div>', // html for after the section
     248                )
     249            );
     250
     251            add_settings_section(
     252                'helloextend_protection_for_woocommerce_settings_setting_section', //id
     253                'Product Protection Categories',
     254                array($this, 'helloextend_protection_for_woocommerce_settings_section_info'), // callback
     255                'helloextend-protection-for-woommerce-settings-aadmin-product-protection', //page
     256                array(
     257                    'before_section' => '<div style="margin-top: 40px;">',
     258                    'after_section' => '</div>'
    240259                )
    241260            );
     
    283302
    284303            add_settings_section(
     304                'helloextend_protection_for_woocommerce_settings_setting_section', //id
     305                'Product Protection Categories',
     306                array($this, 'helloextend_protection_for_woocommerce_settings_section_info'), // callback
     307                'helloextend-protection-for-woommerce-settings-aadmin-product-protection'
     308            );
     309
     310            add_settings_section(
    285311                'helloextend_setting_contract_section',
    286312                'Product Protection Contracts',
     
    371397        );
    372398
     399        // Ignored categories
     400        add_settings_field(
     401            'helloextend_ignored_categories',
     402            'Excluded Product Categories',
     403            array($this, 'helloextend_ignored_categories_callback'),
     404            'helloextend-protection-for-woocommerce-settings-admin-product-protection',
     405            'helloextend_protection_for_woocommerce_settings_setting_section'
     406        );
     407
     408        // Contracts
    373409        add_settings_field(
    374410            'helloextend_product_protection_contract_create', // id
     
    463499        );
    464500
    465         // add_settings_field(
    466         //     'enable_helloextend_sp', // id
    467         //     'Enable Shipping Protection', // title
    468         //     array( $this, 'enable_helloextend_sp_callback' ), // callback
    469         //     'helloextend-protection-for-woocommerce-settings-admin-shipping-protection', // page
    470         //     'helloextend_setting_shipping_protection_section' // section
    471         // );
     501        add_settings_field(
     502            'helloextend_sp_add_sku', // id
     503            'Display Shipping Protection as a Line Item in Cart', // title
     504            array($this, 'helloextend_sp_add_sku_callback'), // callback
     505            'helloextend-protection-for-woocommerce-settings-admin-shipping-protection', // page
     506            'helloextend_setting_shipping_protection_section' // section
     507        );
    472508
    473509        add_settings_field(
     
    561597            $settingsSP = [
    562598                'enable_helloextend_sp'               => '1',
     599                'helloextend_sp_add_sku'              => '1',
    563600                'enable_sp_offer_location'       => 'woocommerce_review_order_before_payment',
    564601                'enable_sp_offer_location_other' => '',
     
    638675        }
    639676
     677        if (isset($input['helloextend_sp_add_sku'])) {
     678            $sanitary_values['helloextend_sp_add_sku'] = $input['helloextend_sp_add_sku'];
     679        }
     680
    640681        if (isset($input['enable_helloextend_debug'])) {
    641682            $sanitary_values['enable_helloextend_debug'] = $input['enable_helloextend_debug'];
     
    763804            (isset($this->helloextend_protection_for_woocommerce_settings_shipping_protection_options['enable_helloextend_sp'])
    764805                && $this->helloextend_protection_for_woocommerce_settings_shipping_protection_options['enable_helloextend_sp'] === '1') ? 'checked' : ''
     806        );
     807    }
     808
     809    public function helloextend_sp_add_sku_callback()
     810    {
     811        printf(
     812            '<input type="checkbox" name="helloextend_protection_for_woocommerce_shipping_protection_settings[helloextend_sp_add_sku]" id="helloextend_sp_add_sku" value="1" %s> <label for="helloextend_sp_add_sku">Leave unchecked for Shipping Protection as a fee</label>',
     813            (isset($this->helloextend_protection_for_woocommerce_settings_shipping_protection_options['helloextend_sp_add_sku'])
     814                && $this->helloextend_protection_for_woocommerce_settings_shipping_protection_options['helloextend_sp_add_sku'] === '1') ? 'checked' : ''
    765815        );
    766816    }
     
    848898            (isset($this->helloextend_protection_for_woocommerce_settings_product_protection_options['helloextend_enable_modal_offers'])
    849899                && $this->helloextend_protection_for_woocommerce_settings_product_protection_options['helloextend_enable_modal_offers'] === '1') ? 'checked' : ''
     900        );
     901    }
     902
     903    public function helloextend_ignored_categories_callback()
     904    {
     905        $ignored_category_ids = (array) get_option('helloextend_protection_for_woocommerce_ignored_categories');
     906       
     907        global $wpdb;
     908        $query = "SELECT term_id, name FROM $wpdb->terms WHERE ";
     909
     910        foreach ($ignored_category_ids  as $category_id ) {
     911            $query = $query . sprintf("term_id = %d", $category_id);
     912
     913            if (next($ignored_category_ids)) {
     914                $query = $query . " OR ";
     915            }
     916        }
     917
     918        $ignored_category_results = $wpdb->get_results($wpdb->prepare(
     919            // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
     920            $query), "OBJECT");
     921       
     922        $ignored_categories_markup = "<div class=\"helloextend-ignored-categories-container\">";
     923        if (count($ignored_category_results) > 0) {
     924   
     925            foreach ($ignored_category_results as $category) {
     926                $ignored_categories_markup .= sprintf("<div class=\"helloextend-category-button button\" data-category-id=\"%d\">%s <a class=\"helloextend-category-remove\">&#10005;</a> </div>", $category->term_id, $category->name);
     927            }
     928   
     929        } else {
     930            $ignored_categories_markup .= "None";
     931        }
     932
     933        $ignored_categories_markup .= "<br><label>Product Protection offers may be disabled for a Product Category via the Category edit page</label></div>";
     934
     935        $allowed_categories_tags = array(
     936            'div' => array(
     937                'class' => true,
     938                'data-category-id' => true
     939            ),
     940            'a' => array(
     941                'class' => true
     942            ),
     943            'label' => true,
     944            'br' => true
     945        );
     946       
     947        printf(
     948            wp_kses($ignored_categories_markup, $allowed_categories_tags)
    850949        );
    851950    }
     
    12121311        echo '<hr>';
    12131312    }
     1313
     1314    function helloextend_remove_ignored_category()
     1315    {
     1316        if (isset($_POST["categoryId"])) {
     1317            $id_to_be_removed = sanitize_text_field(wp_unslash($_POST["categoryId"]));
     1318        } else {
     1319            $id_to_be_removed = null;
     1320        }
     1321
     1322        $ignored_category_ids = (array) get_option("helloextend_protection_for_woocommerce_ignored_categories");
     1323
     1324        $new_ignored_category_ids = array_filter($ignored_category_ids, function($item) use ($id_to_be_removed) {
     1325            return $item != $id_to_be_removed;
     1326        });
     1327
     1328        if (count($new_ignored_category_ids) < count($ignored_category_ids)) {
     1329            HelloExtend_Protection_Logger::helloextend_log_notice(sprintf("Category ID %d was removed from ignore list", $id_to_be_removed));;
     1330
     1331            update_option("helloextend_protection_for_woocommerce_ignored_categories", $new_ignored_category_ids);
     1332            wp_send_json_success(array( "deleted" => true ));
     1333        } else {
     1334            wp_send_json_error(array( "deteted" => false ));
     1335        }
     1336
     1337    }
    12141338}
  • helloextend-protection/trunk/admin/css/helloextend-protection-admin.css

    r3263092 r3348358  
    5353    transition: width 0.3s;
    5454}
     55
     56.helloextend-category-button {
     57    margin-right: 15px !important;
     58    margin-bottom: 5px !important;
     59    cursor: default !important;
     60}
     61
     62.helloextend-category-remove {
     63    color: black;
     64    padding-left: 10px;
     65    cursor: pointer;
     66}
  • helloextend-protection/trunk/admin/helloextend_logger_admin.php

    r3263092 r3348358  
    4747function helloextend_logger_log_table_scripts()
    4848{
    49     $lastmodtime= filemtime(HELLOEXTEND_LOGGER_URI . 'css/helloextend_logger.css');
     49    $css_path = HELLOEXTEND_LOGGER_DIR . 'css/helloextend_logger.css';
     50    $lastmodtime= file_exists($css_path) ? filemtime($css_path) : HELLOEXTEND_PROTECTION_VERSION;
    5051    wp_register_style('mainStyle', HELLOEXTEND_LOGGER_URI . 'css/helloextend_logger.css', array(), $lastmodtime);
    5152
  • helloextend-protection/trunk/admin/js/helloextend-protection-ignore-categories.js

    r3263092 r3348358  
    11(function( $ ) {
     2    // Set input value to currently displayed input
    23    $(document).ready(($) => {
    34        let isIgnored = $('input[name="helloextend-ignore-value"]').val() == 1;
     
    1011        });
    1112    });
     13
    1214})(jQuery);
  • helloextend-protection/trunk/helloextend-protection.php

    r3263092 r3348358  
    1010 *
    1111 * @link    http://extend.com
    12  * @since   1.0.0
     12 * @since   1.1.1
    1313 * @package HelloExtend_Protection
    1414 *
     
    4545 * Rename this for your plugin and update it as you release new versions.
    4646 */
    47 define('HELLOEXTEND_PROTECTION_VERSION', '1.0.0');
     47define('HELLOEXTEND_PROTECTION_VERSION', '1.1.0');
    4848define('HELLOEXTEND_PRODUCT_PROTECTION_SKU', 'helloextend-product-protection');
     49define('HELLOEXTEND_SHIPPING_PROTECTION_SKU', 'helloextend-shipping-protection');
    4950
    5051
     
    215216{
    216217    // Register stylesheets
    217     $lastmodtime= filemtime(HELLOEXTEND_PLUGIN_URL. 'css/helloextend.css');
     218    $css_path = HELLOEXTEND_PLUGIN_DIR . 'css/helloextend.css';
     219    $lastmodtime= file_exists($css_path) ? filemtime($css_path) : HELLOEXTEND_PROTECTION_VERSION;
    218220    wp_register_style('helloextend_protection_style',  HELLOEXTEND_PLUGIN_URL.'css/helloextend.css', array(), $lastmodtime);
    219221    wp_enqueue_style('helloextend_protection_style');
     
    298300        }
    299301
    300         // upload image and associate to product
    301302        try {
    302             $product_id     = $product->get_id();
    303             //check if image exists
    304             if (file_exists(plugin_dir_path('images/Extend_icon.png'))) {
    305 
    306                 $upload         = wc_rest_upload_image_from_url(HELLOEXTEND_PLUGIN_URL . '/images/Extend_icon.png');
     303            $product_id = $product->get_id();
     304            $image_path = HELLOEXTEND_PLUGIN_DIR . 'images/Extend_icon.png';
     305            $image_url  = HELLOEXTEND_PLUGIN_URL . 'images/Extend_icon.png';
     306
     307            if (file_exists($image_path)) {
     308                $upload = wc_rest_upload_image_from_url($image_url);
     309
    307310                if (is_wp_error($upload)) {
    308                     HelloExtend_Protection_Logger::helloextend_log_error('Could not upload extend logo from ' . HELLOEXTEND_PLUGIN_URL . '/images/Extend_icon.png : ' . $upload->get_error_message());
     311                    HelloExtend_Protection_Logger::helloextend_log_error('Could not upload Extend logo from ' . $image_url . ' : ' . $upload->get_error_message());
    309312                    return false;
    310313                }
     
    312315                $product_img_id = wc_rest_set_uploaded_image_as_attachment($upload, $product_id);
    313316                if (is_wp_error($product_img_id)) {
    314                     HelloExtend_Protection_Logger::helloextend_log_error('Could not retrieve product image id : ');
     317                    HelloExtend_Protection_Logger::helloextend_log_error('Could not retrieve product image ID.');
    315318                    return false;
    316319                }
    317320
    318                 //set the product image
    319321                set_post_thumbnail($product_id, $product_img_id);
    320322            } else {
    321                 HelloExtend_Protection_Logger::helloextend_log_error('Extend_icon file path incorrect: ' . HELLOEXTEND_PLUGIN_DIR.'/images/Extend_icon.png');
     323                HelloExtend_Protection_Logger::helloextend_log_error('Extend_icon file path incorrect: ' . $image_path);
    322324            }
    323325        } catch (\Exception $e) {
     
    325327        }
    326328    }
     329}
     330
     331function helloextend_get_or_create_shipping_protection_product($fee_amount) {
     332    $query = new WP_Query([
     333        'post_type'  => 'product',
     334        'meta_key'   => '_helloextend_shipping_protection_product',
     335        'meta_value' => '1',
     336        'post_status'=> 'any',
     337        'numberposts'=> 1
     338    ]);
     339
     340    if (!empty($query->posts)) {
     341        $product_id = $query->posts[0]->ID;
     342        update_post_meta($product_id, '_price', $fee_amount);
     343        update_post_meta($product_id, '_regular_price', $fee_amount);
     344        return $product_id;
     345    }
     346
     347    $product_id = wp_insert_post([
     348        'post_title'   => 'Extend Shipping Protection',
     349        'post_content' => 'Optional shipping protection offered at checkout.',
     350        'post_status'  => 'publish',
     351        'post_type'    => 'product',
     352    ]);
     353
     354    if (!is_wp_error($product_id)) {
     355        update_post_meta($product_id, '_virtual', 'yes');
     356        update_post_meta($product_id, '_price', $fee_amount);
     357        update_post_meta($product_id, '_regular_price', $fee_amount);
     358        update_post_meta($product_id, '_visibility', 'hidden');
     359        update_post_meta($product_id, '_catalog_visibility', 'hidden');
     360        update_post_meta($product_id, '_helloextend_shipping_protection_product', 1);
     361        update_post_meta($product_id, '_sku', HELLOEXTEND_SHIPPING_PROTECTION_SKU);
     362        wp_set_object_terms($product_id, 'simple', 'product_type');
     363
     364        // Upload image and associate to product
     365        $image_path = HELLOEXTEND_PLUGIN_DIR . 'images/Extend_shipping_icon.png';
     366        $image_url  = HELLOEXTEND_PLUGIN_URL . 'images/Extend_shipping_icon.png';
     367
     368        if (file_exists($image_path)) {
     369            $upload         = wc_rest_upload_image_from_url($image_url);
     370            if (is_wp_error($upload)) {
     371                HelloExtend_Protection_Logger::helloextend_log_error('Could not upload extend logo from ' . $image_url . $upload->get_error_message());
     372                return false;
     373            }
     374
     375            $product_img_id = wc_rest_set_uploaded_image_as_attachment($upload, $product_id);
     376            if (is_wp_error($product_img_id)) {
     377                HelloExtend_Protection_Logger::helloextend_log_error('Could not retrieve product image id : ');
     378                return false;
     379            }
     380
     381            //set the product image
     382            set_post_thumbnail($product_id, $product_img_id);
     383        } else {
     384            HelloExtend_Protection_Logger::helloextend_log_error('Extend_icon file path incorrect: ' . $image_path);
     385        }
     386
     387        return $product_id;
     388    }
     389
     390    return false;
    327391}
    328392
     
    401465function helloextend_set_shipping_fee()
    402466{
    403     if (is_admin() && !defined('DOING_AJAX') || !is_checkout()) {
     467    if ((is_admin() && !defined('DOING_AJAX')) || !is_checkout()) {
    404468        return;
    405469    }
    406470
    407     $fee_label  = __('Extend Shipping Protection', 'helloextend-protection');
    408 
    409     if (1 == WC()->session->get('shipping_fee')) {
    410 
    411         $fee_amount = WC()->session->get('shipping_fee_value');
    412 
    413         WC()->cart->add_fee($fee_label, $fee_amount);
    414     } elseif (1 == WC()->session->get('shipping_fee_remove')) {
    415         $fees = WC()->cart->get_fees();
    416         foreach ($fees as $key => $fee) {
    417             if ($fees[$key]->name == $fee_label) {
    418                 unset($fees[$key]);
    419             }
    420         }
    421         WC()->cart->fees_api()->set_fees($fees);
     471    $fee_label = __('Extend Shipping Protection', 'helloextend-protection');
     472    $shipping_fee = WC()->session->get('shipping_fee');
     473    $remove_fee = WC()->session->get('shipping_fee_remove');
     474    $fee_amount = WC()->session->get('shipping_fee_value');
     475
     476    $options = get_option('helloextend_protection_for_woocommerce_shipping_protection_settings');
     477    $add_as_sku = isset($options['helloextend_sp_add_sku']) && $options['helloextend_sp_add_sku'];
     478
     479    if ($shipping_fee == 1) {
     480        if ($add_as_sku) {
     481
     482            $product_id = helloextend_get_or_create_shipping_protection_product($fee_amount);
     483            if (!$product_id) {
     484                HelloExtend_Protection_Logger::helloextend_log_error('Could not create or retrieve shipping protection product');
     485                return;
     486            }
     487            // Avoid duplicate product in cart
     488            $already_in_cart = false;
     489            foreach (WC()->cart->get_cart() as $cart_item_key => $values) {
     490                if ($values['product_id'] == $product_id) {
     491                    $already_in_cart = true;
     492                    break;
     493                }
     494            }
     495
     496            if (!$already_in_cart) {
     497                WC()->cart->add_to_cart($product_id, 1);
     498            }
     499        } else {
     500            WC()->cart->add_fee($fee_label, $fee_amount);
     501        }
     502    } elseif ($remove_fee == 1) {
     503        if ($add_as_sku) {
     504            // Remove the product from cart
     505            foreach (WC()->cart->get_cart() as $cart_item_key => $values) {
     506                $product = $values['data'];
     507                if ($product && get_post_meta($product->get_id(), '_helloextend_shipping_protection_product', true)) {
     508                    WC()->cart->remove_cart_item($cart_item_key);
     509                }
     510            }
     511        } else {
     512            $fees = WC()->cart->get_fees();
     513            foreach ($fees as $key => $fee) {
     514                if ($fee->name == $fee_label) {
     515                    unset($fees[$key]);
     516                }
     517            }
     518            WC()->cart->fees_api()->set_fees($fees);
     519        }
     520
    422521        WC()->session->set('shipping_fee_remove', false);
    423522    }
    424523}
     524
    425525
    426526function helloextend_save_shipping_protection_quote_id($order_id)
     
    458558        }
    459559
    460         $token = HelloExtend_Protection_Global::get_helloextend_token();
     560        $token = HelloExtend_Protection_Global::helloextend_get_token();
    461561
    462562        // Get product object
    463563        if (method_exists($item, 'get_product')) {
    464564            $product = $item->get_product();
    465 
    466             // Check if the product SKU matches product protection
    467             if ($product->get_sku() === 'helloextend-product-protection') {
    468                 echo '<table cellspacing="0" class="display_meta"><tbody><tr><th>Extend Product Protection contracts : </th><th></th></tr>';
    469 
    470                 foreach ($contracts as $product_covered => $contract_id) {
    471                     if ($helloextend_meta_data['covered_product_id'] == $product_covered) {
    472                         echo '<tr><td><a href="' . esc_url($url . '?contractId=' . $contract_id . '&accessToken=' . $token) . '">' . esc_html($contract_id) . '</a></td></tr>';
     565            if ( $product && $product instanceof WC_Product ) {
     566                // Check if the product SKU matches product protection
     567                if ($product->get_sku() === HELLOEXTEND_PRODUCT_PROTECTION_SKU) {
     568                  echo '<table cellspacing="0" class="display_meta"><tbody><tr><th>Extend Product Protection contracts : </th><th></th></tr>';
     569
     570                    foreach ($contracts as $product_covered => $contract_id) {
     571                        if ( isset( $helloextend_meta_data['covered_product_id'] ) && $helloextend_meta_data['covered_product_id'] == $product_covered ) {
     572                            $link = add_query_arg(
     573                                array(
     574                                    'contractId'  => rawurlencode( $contract_id ),
     575                                    'accessToken' => rawurlencode( $token ),
     576                                    ),
     577                                $url
     578                                );
     579                            echo '<tr><td><a href="' . esc_url( $link ) . '">' . esc_html( $contract_id ) . '</a></td></tr>';
     580                        }
    473581                    }
     582                    echo '</tbody></table>';
    474583                }
    475                 echo '</tbody></table>';
    476584            }
    477585        }
     
    521629    </tr>
    522630    ';
    523     $js_file_version = filemtime(plugin_dir_url(__FILE__) . 'admin/js/helloextend-protection-ignore-categories.js');
     631    $js_path = HELLOEXTEND_PLUGIN_DIR . 'admin/js/helloextend-protection-ignore-categories.js';
     632    $js_file_version = file_exists($js_path) ? filemtime($js_path) : HELLOEXTEND_PROTECTION_VERSION;
    524633    wp_enqueue_script('helloextend_set_ignore_value_script', plugin_dir_url(__FILE__) . 'admin/js/helloextend-protection-ignore-categories.js' , array('jquery'), $js_file_version, true);
    525634
     
    548657        foreach ($ignored_categories as $category_id) {
    549658            if ($category_id !== $term_id) {
    550                 array_push($new_ignored_categories, $ignored_categories[$i]);
    551             }
    552         }
     659                array_push($new_ignored_categories, $category_id);
     660            }
     661        }
     662        HelloExtend_Protection_Logger::helloextend_log_notice(sprintf("Category ID %d was removed from ignore list", $term_id));
     663       
    553664        $ignored_categories = $new_ignored_categories;
    554665    } else if ($helloextend_ignore && !$category_in_array) {
     666       
     667        HelloExtend_Protection_Logger::helloextend_log_notice(sprintf("Category ID %d was added to ignore list", $term_id));
     668
    555669        array_push($ignored_categories, $term_id);
    556670    }
  • helloextend-protection/trunk/includes/class-helloextend-global.php

    r3263092 r3348358  
    117117
    118118            // retrieve id or sku based on settings, and default to id if sku is empty
    119             $sku         = $_woo_product->get_sku() <> '' ? $_woo_product->get_sku() : $cart_item['product_id'];
    120             $referenceId = $settings['helloextend_use_skus'] ? $sku : $cart_item['product_id'];
     119            $referenceId = $cart_item['product_id'];
    121120
    122121            // add sku to cart item and label it referenceId
     
    192191            $settings['enable_helloextend_sp'] = array_key_exists('enable_helloextend_sp', $helloextend_protection_shipping_protection_settings)
    193192                ? $helloextend_protection_shipping_protection_settings['enable_helloextend_sp'] : 0;
     193
     194            $settings['helloextend_sp_add_sku'] = array_key_exists('helloextend_sp_add_sku', $helloextend_protection_shipping_protection_settings)
     195                ? $helloextend_protection_shipping_protection_settings['helloextend_sp_add_sku'] : 0;
    194196
    195197            $settings['helloextend_sp_offer_location'] = array_key_exists('helloextend_sp_offer_location', $helloextend_protection_shipping_protection_settings)
     
    491493        $ignored_categories = (array) get_option('helloextend_protection_for_woocommerce_ignored_categories');
    492494
    493         // If ignored categories doesn't exist or is empty, return first category
     495        if (empty($categories) || !is_array($categories)) {
     496            return 'Uncategorized'; // or any safe fallback
     497        }
     498
    494499        if (is_null($ignored_categories) || count($ignored_categories) == 0) {
    495             return $categories[0]->name;
    496         }
    497 
    498         // Find the first category that is not ignored and return it
     500            return $categories[0]->name ?? 'Uncategorized';
     501        }
     502
    499503        foreach ($categories as $category) {
    500504            if (!in_array($category->term_id, $ignored_categories)) {
    501                 return $category->name;
     505                return $category->name ?? 'Uncategorized';
    502506            }
    503507        }
    504508
    505         // If all categories are ignored, return the first one in the array
    506         return $categories[0]->name;
     509        return $categories[0]->name ?? 'Uncategorized';
    507510    }
    508511}
  • helloextend-protection/trunk/includes/class-helloextend-protection-cart-offer.php

    r3263092 r3348358  
    193193            $item_id     = $cart_item['variation_id'] ? $cart_item['variation_id'] : $cart_item['product_id'];
    194194            $item_sku    = $cart_item['data']->get_sku() ? $cart_item['data']->get_sku() : $item_id;
    195             $referenceId = $this->settings['helloextend_use_skus'] ? $item_sku : $item_id;
     195            $referenceId = $item_id;
    196196            $categories  = get_the_terms($item_id, 'product_cat');
    197197            $category    = HelloExtend_Protection_Global::helloextend_get_first_valid_category($categories);
  • helloextend-protection/trunk/includes/class-helloextend-protection-i18n.php

    r3263097 r3348358  
    3333class Helloextend_Protection_i18n
    3434{
     35
    3536    /**
    3637     * Load the plugin text domain for translation.
  • helloextend-protection/trunk/includes/class-helloextend-protection-logger.php

    r3263092 r3348358  
    561561
    562562    }
     563
     564    public static function helloextend_logger_ajax_call()
     565    {
     566        $method = isset($_POST['method']) ? sanitize_text_field(wp_unslash($_POST['method'])) : null;
     567        $message = isset($_POST['message']) ? sanitize_text_field(wp_unslash($_POST['message'])) : null;
     568
     569        if ( $method == 'notice' ) {
     570            self::helloextend_log_notice($message);
     571        } else if ( $method == 'error' ) {
     572            self::helloextend_log_error( $message );
     573        } else if ( $method == 'debug' ) {
     574            self::helloextend_log_debug( $message );
     575        }
     576    }
    563577}
    564578
     
    577591add_action('wp_ajax_helloextend_logger_delete_single', array( $helloextendProtectionLogger, 'helloextend_logger_delete_single' ));
    578592
     593add_action('wp_ajax_nopriv_helloextend_logger_ajax_call', array( $helloextendProtectionLogger, 'helloextend_logger_ajax_call' ), 10);
     594add_action('wp_ajax_helloextend_logger_ajax_call', array( $helloextendProtectionLogger, 'helloextend_logger_ajax_call' ), 10);
  • helloextend-protection/trunk/includes/class-helloextend-protection-orders.php

    r3263092 r3348358  
    7373        // Hook the callback function to the order completed action
    7474        add_action('woocommerce_order_status_completed', [$this, 'create_update_order'], 10, 1);
     75
     76        // Hook the callback function to the order cancelled action
     77        add_action('woocommerce_order_status_cancelled', [$this, 'cancel_order'], 10, 1);
    7578    }
    7679
     
    173176        }
    174177        $order_data = $order->get_data();
     178        $items = $order->get_items();
     179        $product_id_array = array();
     180        foreach($items as $item){
     181            $product_id_array[] = $item->get_product_id();
     182        }
     183        $product_id_list = implode(',', $product_id_array);
    175184
    176185        // if contract creation is set to order create, call helloextend_get_plans_and_products
     
    198207        if ($shipping_protection_quote_id) {
    199208            // phpcs:disable WordPress.PHP.DevelopmentFunctions
    200             HelloExtend_Protection_Logger::helloextend_log_notice('Shipping Protection Meta Exists: ' . print_r($shipping_protection_quote_id, true));
     209            if ($this->settings['enable_helloextend_debug'] == 1) {
     210                HelloExtend_Protection_Logger::helloextend_log_debug(
     211                    'Shipping Protection Meta Exists: ' . (string) $shipping_protection_quote_id
     212                );
     213            }
    201214            // phpcs:enable
    202215
     216            // on order completion send shipmentInfo to activate the contract, otherwise send an empty array to create the contract
     217            $shipmentInfo = array();
     218            $store_raw_country = get_option('woocommerce_default_country');
     219            $split_country = explode(":", $store_raw_country);
     220            $store_country = $split_country[0];
     221            $store_state = $split_country[1];
     222            $called_action_hook = current_filter();
     223            if ($called_action_hook == 'woocommerce_order_status_completed') {
     224                $arg = array(
     225                    'limit'  => -1,
     226                    'status' => 'publish',
     227                    'return' => 'ids'
     228                );
     229                $shipmentInfo[] = array(
     230                    "shipmentDate" => time(),
     231                    "shippingProvider" => "custom",
     232                    "trackingId" => "woocommerce-shipping",
     233                    "productIds" => $product_id_list,
     234                    "destination" => array(
     235                        "address1" => $order_data['shipping']['address_1'],
     236                        "address2" => $order_data['shipping']['address_2'] ? $order_data['shipping']['address_2'] : null,
     237                        "city" => $order_data['shipping']['city'],
     238                        "companyName" => '',
     239                        "countryCode" => $order_data['shipping']['country'],
     240                        "personName" => $order_data['shipping']['first_name'] . ' ' . $order_data['shipping']['last_name'],
     241                        "phone" => '',
     242                        "postalCode" => $order_data['shipping']['postcode'],
     243                        "provinceCode" => $order_data['shipping']['state']
     244                    ),
     245                    "source" => array(
     246                        "address1" => get_option('woocommerce_store_address'),
     247                        "address2" => get_option('woocommerce_store_address_2'),
     248                        "city" => get_option('woocommerce_store_city'),
     249                        "companyName" => '',
     250                        "countryCode" => $store_country,
     251                        "personName" => '',
     252                        "phone" => get_option('woocommerce_store_phone'),
     253                        "postalCode" =>get_option('woocommerce_store_postcode'),
     254                        "provinceCode" => $store_state
     255                    )
     256                );
     257            }
    203258            // Push shipping protection line item into helloextend_line_items array
    204259            $helloextend_line_items[] = array(
    205260                'lineItemTransactionId' => $order_id . '-shipping',
    206261                'quoteId'               => $shipping_protection_quote_id,
    207                 'shipmentInfo'          => array(),
     262                'shipmentInfo'          => $shipmentInfo,
    208263            );
    209264        } else {
     
    251306        $token = HelloExtend_Protection_Global::helloextend_get_token();
    252307
    253         // Log the token
    254         if ($this->settings['enable_helloextend_debug'] == 1) {
    255             HelloExtend_Protection_Logger::helloextend_log_debug('Token: ' . $token);
     308        // If token exists, log successful token
     309        if ($this->settings['enable_helloextend_debug'] == 1 && $token) {
     310            HelloExtend_Protection_Logger::helloextend_log_debug('Access token created successfully');
     311        }
     312        // If token does not exist, log error
     313        if ($this->settings['enable_helloextend_debug'] == 1 && !$token) {
     314            HelloExtend_Protection_Logger::helloextend_log_error('Error:Access token was not created, exiting order creation');
     315            return;
    256316        }
    257317
     
    314374        }
    315375    }
     376
     377    /**
     378     * Cancel Orders/Contracts in Extend
     379     *
     380     * @param string $order_id The ID of the order.
     381     * @since 1.0.0
     382     */
     383    // Accept a WC_Order object or null.
     384    // Using `mixed` keeps compatibility with PHP <8 (no union types).
     385    public function cancel_order(string $order_id, $order = null) /* @param WC_Order|null $order */
     386    {
     387        $order = wc_get_order($order_id);
     388
     389        if ( ! $order instanceof WC_Order ) {
     390                HelloExtend_Protection_Logger::helloextend_log_error(
     391                    'Cannot cancel Extend order – WooCommerce order ' . $order_id . ' not found.'
     392                );
     393                return;
     394            }
     395
     396        // Get Token from Global function
     397        $token = HelloExtend_Protection_Global::helloextend_get_token();
     398
     399        // If token exists, log successful token
     400        if ($this->settings['enable_helloextend_debug'] == 1 && $token) {
     401            HelloExtend_Protection_Logger::helloextend_log_debug('Access token created successfully');
     402        }
     403        // If token does not exist, log error
     404        if ($this->settings['enable_helloextend_debug'] == 1 && !$token) {
     405            HelloExtend_Protection_Logger::helloextend_log_error('Error:Access token was not created, exiting order cancel');
     406            return;
     407        }
     408
     409        // GET the order uuid
     410        // {{API_HOST}}/orders/search?transactionId={{transactionId}}
     411        $request_args = array(
     412            'method'  => 'GET',
     413            'headers' => array(
     414                'Content-Type'          => 'application/json',
     415                'Accept'                => 'application/json; version=latest',
     416                'X-Extend-Access-Token' => $token,
     417            ),
     418        );
     419
     420        $endpoint = add_query_arg(
     421            array( 'transactionId' => (string) $order->get_id() ),
     422            $this->settings['api_host'] . '/orders/search'
     423        );
     424        $response = wp_remote_request( $endpoint, $request_args );
     425        if (is_wp_error($response)) {
     426            $error_message = $response->get_error_message();
     427            HelloExtend_Protection_Logger::helloextend_log_error(' Order ID ' . $order->get_id() . ' : GET request failed: ' . $error_message.', cannot cancel extend order');
     428        } else {
     429            $response_code = wp_remote_retrieve_response_code( $response );
     430            if ( $response_code >= 200 && $response_code < 300 ) {
     431                // if GET was successful retrieve the response and find order uuid
     432                $data               = json_decode( wp_remote_retrieve_body( $response ) );
     433                $extend_order_uuid  = null;
     434                if ( isset( $data->orders ) && is_array( $data->orders ) && ! empty( $data->orders[0]->id ) ) {
     435                    $extend_order_uuid = $data->orders[0]->id;
     436                }
     437                if ( $extend_order_uuid ) {
     438                    //POST cancel the order (uuid)
     439                    //{{API_HOST}}/orders/{{orderId}}/cancel
     440                    $cancel_request_args = array(
     441                        'method'  => 'POST',
     442                        'headers' => array(
     443                            'Content-Type'          => 'application/json',
     444                            'Accept'                => 'application/json; version=latest',
     445                            'X-Extend-Access-Token' => $token,
     446                        ),
     447                    );
     448                    $cancel_response      = wp_remote_request(
     449                        $this->settings['api_host'] . '/orders/' . $extend_order_uuid . '/cancel',
     450                        $cancel_request_args
     451                    );
     452                    $cancel_response_code = wp_remote_retrieve_response_code( $cancel_response );
     453                    if ( $cancel_response_code >= 200 && $cancel_response_code < 300 ) {
     454                        HelloExtend_Protection_Logger::helloextend_log_notice(
     455                            'Order ID ' . $order->get_id() . ' : Cancelled Extend order UUID: ' . $extend_order_uuid
     456                        );
     457                    } else {
     458                        HelloExtend_Protection_Logger::helloextend_log_error(
     459                            'Order ID ' . $order->get_id() . ' : Could not cancel Extend order (status ' .
     460                            $cancel_response_code . ')'
     461                        );
     462                    }
     463                }else{
     464                    return;
     465                }
     466
     467            } else {
     468                HelloExtend_Protection_Logger::helloextend_log_error(
     469                    'Order ID ' . $order->get_id() . ' : GET request returned status ' . $response_code
     470                );
     471                return;
     472            }
     473        }
     474    }
    316475}
  • helloextend-protection/trunk/includes/class-helloextend-protection-pdp-offer.php

    r3263092 r3348358  
    8888
    8989        // Variables that are passed to the PDP JS Script
    90         $helloextend_use_skus             = $this->settings['helloextend_use_skus'];
    9190        $id                          = $product->get_id();
    9291        $sku                         = $product->get_sku();
     
    109108                'helloextend_product_integration_script',
    110109                'ExtendProductIntegration',
    111                 compact('id', 'sku', 'first_category', 'price', 'type', 'env', 'helloextend_enabled', 'helloextend_pdp_offers_enabled', 'helloextend_modal_offers_enabled', 'helloextend_use_skus', 'atc_button_selector')
     110                compact('id', 'sku', 'first_category', 'price', 'type', 'env', 'helloextend_enabled', 'helloextend_pdp_offers_enabled', 'helloextend_modal_offers_enabled', 'atc_button_selector')
    112111            );
    113112            echo "<div class='helloextend-offer' data-extend='pdpOfferContainer' style='width: 100%;'></div>";
  • helloextend-protection/trunk/includes/class-helloextend-protection-shipping.php

    r3263092 r3348358  
    7676    /**
    7777     * This method adds to xml export an SKU tag in order to identify
    78      * Route Protection to ShipStation integration
     78     * Extend Protection to ShipStation integration
    7979     *
    8080     * @param  $order_xml
     
    108108        // add offer element
    109109        $enable_helloextend_sp          = $this->settings['enable_helloextend_sp'];
     110        $helloextend_sp_add_sku        = $this->settings['helloextend_sp_add_sku'];
    110111        $env                       = $this->settings['helloextend_environment'];
    111112        $cart_items                = WC()->cart->get_cart();
     
    117118            $product = $cart_item['data'];
    118119            if (! $product->is_virtual() ) {
    119                 $referenceId = ( $this->settings['helloextend_use_skus'] == 1 ) ? $product->get_sku() : $product->get_id();
     120                $referenceId = $product->get_id();
    120121                $items[]     = array(
    121122                 'referenceId'   => $referenceId,
     
    141142                'helloextend_shipping_integration_script',
    142143                'ExtendShippingIntegration',
    143                 compact('env', 'items', 'enable_helloextend_sp', 'ajax_url', 'update_order_review_nonce')
     144                compact('env', 'items', 'enable_helloextend_sp', 'helloextend_sp_add_sku', 'ajax_url', 'update_order_review_nonce')
    144145            );
    145146            echo '<tr><td colspan="2"><div id="helloextend-shipping-offer" style="height: 120px;"></div></td></tr>';
  • helloextend-protection/trunk/js/helloextend-cart-offers.js

    r3263092 r3348358  
    11// This script is used to handle the rendering and functionality of Extend offers in a WooCommerce cart.
    2 
    3 // Wait until the document is fully loaded before running the script.
    4 jQuery(document).ready(function() {
    5     // Check if necessary objects (ExtendWooCommerce and ExtendCartIntegration) exist.
    6     // If not, stop the execution of the script.
    7     if(!ExtendWooCommerce || !ExtendCartIntegration) {
    8         return;
    9     }
    10 
    11     // For each cart item:
    12     jQuery('.cart_item').each(function(ix, val){
    13         // Find the title and image of the product.
    14         var title = jQuery(val).find('.product-name');
    15         var image = jQuery(val).find('.product-thumbnail')
    16 
    17         // If the title includes 'Extend Protection Plan', disable pointer events for the image.
    18         // This could be used to prevent clicking on the image.
    19         if(title.text().indexOf('Extend Protection Plan') > -1){
    20             image.css('pointer-events', 'none')
    21         }
    22     })
    23 
    24     // For each Extend offer in the cart:
    25     document.querySelectorAll('.cart-extend-offer').forEach(function(val, ix){
    26         // Get the reference ID and quantity of the covered item
    27         let ref_id =  val.dataset.covered;
    28         let category = val.dataset.category;
    29         let qty = jQuery(val).parents('.cart_item').find('input.qty').val();
    30         let price = jQuery(val).parents('.cart_item').find('.product-price').text().trim().replace(/[$,]/g, '');
    31         let extendPrice = Math.round(parseFloat(price).toFixed(2) * 100);
    32 
    33         // If the warranty is already in the cart or if Extend offers are disabled, stop processing this item.
    34         if(ExtendWooCommerce.warrantyAlreadyInCart(ref_id, window.ExtendCartIntegration.cart) || ExtendCartIntegration.helloextend_enable_cart_offers !== '1'){
    35             return;
    36         }
    37 
    38         Extend.buttons.renderSimpleOffer(val, {
    39             referenceId: ref_id,
    40             price: extendPrice,
    41             category: category,
    42             onAddToCart: function({ plan, product }) {
    43 
    44                 // On adding to the cart, if both plan and product exist:
    45                 if (plan && product) {
    46                     // ExtendWooCommerce.extendAjaxLog('1 - OnAddToCart simple offer call with :', 'notice')
    47                     ExtendWooCommerce.extendAjaxLog(plan, 'notice');
    48                     ExtendWooCommerce.extendAjaxLog(product.toString(), 'notice');
    49 
    50                     // Create a copy of the plan, adding the reference ID of the covered product.
    51                     var planCopy = { ...plan, covered_product_id: ref_id }
    52 
    53                     var data = {
    54                         quantity: qty,
    55                         plan: planCopy
    56                     };
    57 
    58                     // Add the plan to the cart.
    59                     ExtendWooCommerce.addPlanToCart(data)
    60                         .then(() => {
    61                             // After adding the plan, enable the 'Update cart' button and trigger a click on it.
    62                             jQuery("[name='update_cart']").removeAttr('disabled');
    63                             jQuery("[name='update_cart']").trigger("click");
    64                         })
    65                 } else {
    66                     ExtendWooCommerce.extendAjaxLog('onAddToCart failed: plan or product missing', 'error');
    67                 }
    68             },
    69         });
    70     })
    71 });
    72 
    73 // When the cart totals are updated, re-render the Extend offers.
    74 jQuery(document.body).on('updated_cart_totals', function () {
     2(($) => {
    753
    764    // If necessary objects (ExtendWooCommerce and ExtendCartIntegration) do not exist, stop the execution of the script.
     
    797    }
    808
    81     // Iterate over each element with class 'cart-extend-offer'
    82     jQuery('.cart-extend-offer').each(function (ix, val) {
    83         let ref_id = jQuery(val).data('covered'); // Get the 'covered' data attribute value
    84         let category = val.dataset.category; // Get the 'category' data attribute value
    85         let qty = jQuery(val).parents('.cart_item').find('input.qty').val(); // Get the quantity value from the corresponding input field
    86         let price = jQuery(val).parents('.cart_item').find('.product-price').text().trim().replace(/[$,\.]/g, '')
    87         let extendPrice = parseFloat(price)
     9    const SELECTORS = {
     10        CART_ITEM: '.cart_item',
     11        TITLE: '.product-name',
     12        IMAGE: '.product-thumbnail',
     13        PRICE: '.product-price',
     14        QUANTITY: 'input.qty',
     15        EXTEND_OFFER: '.cart-extend-offer',
     16        UPDATE_CART: "[name='update_cart']"
     17    }
     18   
     19    /**
     20     * Renders the cart offer for a given offer container element and params
     21     * @param {HTMLElement} element Offer container element
     22     * @param {object} params Offer params: referenceId, price, category
     23     * @param {number} quantity Quantity of warranties to be added
     24     */
     25    function renderExtendOffer(element, params, quantity) {
     26       
     27        Extend.buttons.renderSimpleOffer(element, {
     28            ...params,
     29            onAddToCart: ({plan, product}) => {
     30                if (!plan || !product) {
     31                    ExtendWooCommerce.extendAjaxLog('error', 'SimpleOffer onAddToCart failed: plan or product missing');
     32                    return;
     33                }
     34               
     35                const data = {
     36                    quantity,
     37                    plan: {
     38                        ...plan,
     39                        covered_product_id: product.id
     40                    }
     41                };
     42               
     43                if (ExtendWooCommerce.debugLogEnabled)
     44                    ExtendWooCommerce.extendAjaxLog('debug', 'SimpleOffer add to cart with data: ', JSON.stringify(data));
     45               
     46                // Add the plan to the cart.
     47                ExtendWooCommerce.addPlanToCart(data).then(() => {
     48                    // After adding the plan, enable the 'Update cart' button and trigger a click on it.
     49                    $(SELECTORS.UPDATE_CART).removeAttr('disabled');
     50                    $(SELECTORS.UPDATE_CART).trigger("click");
     51                });
     52            }
     53        });
     54    }
     55   
     56    /**
     57     * Initializes cart offers
     58     * @param {Object} cart Cart object
     59     */
     60    function initCartOffers(cart) {
     61        $(SELECTORS.CART_ITEM).each((index, lineItemElement) => {
     62            const $lineItemElement = $(lineItemElement);
     63            const $title = $lineItemElement.find(SELECTORS.TITLE);
     64            const $image = $lineItemElement.find(SELECTORS.IMAGE);
     65           
     66            if ($title.text().toLowerCase().includes('extend protection plan')) {
     67                $image.css('pointer-events', 'none');
     68            } else {
     69                const $offer = $lineItemElement.find(SELECTORS.EXTEND_OFFER);
     70               
     71                const referenceId = $offer.data('covered');
     72               
     73                if (ExtendWooCommerce.warrantyAlreadyInCart(referenceId, cart ? cart : window.ExtendCartIntegration.cart)
     74                    || ExtendCartIntegration.helloextend_enable_cart_offers !== '1') {
     75                    return;
     76                }
     77               
     78                const category = $offer.data('category');
     79                const quantity = $lineItemElement.find(SELECTORS.QUANTITY).val();
     80               
     81                const [ dollars, cents = '00' ] = $lineItemElement.find(SELECTORS.PRICE).text().trim().replace(/[$,]/g, '').split('.');
     82                const normalizedCents = cents.padEnd(2, '0');
     83                const price = `${dollars}${normalizedCents}`;
     84               
     85                renderExtendOffer($offer[0], { referenceId, category, price }, quantity);
     86            }
     87        });
     88    }
     89   
     90    // Wait until the document is fully loaded before running the script.
     91    $(document).ready(() => {
     92        initCartOffers();
     93    });
     94   
     95    // When the cart totals are updated, re-render the Extend offers.
     96    $(document.body).on('updated_cart_totals', function () {
     97        ExtendWooCommerce.getCart().then(initCartOffers);
     98    });
    8899
    89         // Check if an Extend button instance exists for the current element
    90         if (Extend.buttons.instance('#' + val.id)) {
    91             Extend.buttons.instance('#' + val.id).destroy(); // Destroy the existing Extend button instance
    92         }
    93 
    94         // Retrieve the cart data from ExtendWooCommerce
    95         ExtendWooCommerce.getCart()
    96             .then(cart => {
    97 
    98                 // Check if the warranty is already in the cart or if Extend cart offers are disabled
    99                 if (ExtendWooCommerce.warrantyAlreadyInCart(ref_id, cart) || ExtendCartIntegration.helloextend_cart_offers_enabled === 'no') {
    100                     return; // Skip further processing
    101                 }
    102 
    103                 /** initialize offer */
    104 
    105                 // Render a simple offer using Extend.buttons.renderSimpleOffer()
    106                 Extend.buttons.renderSimpleOffer(val, {
    107                     referenceId: ref_id,
    108                     price: extendPrice,
    109                     category: category,
    110                     onAddToCart: function ({ plan, product }) {
    111 
    112                         if (plan && product) {
    113                             ExtendWooCommerce.extendAjaxLog('2 - OnAddToCart simple offer call with :', 'notice')
    114                             ExtendWooCommerce.extendAjaxLog(plan.toString(), 'notice');
    115                             ExtendWooCommerce.extendAjaxLog(product.toString(), 'notice');
    116 
    117                             var planCopy = { ...plan, covered_product_id: ref_id }; // Create a copy of the plan object with the 'covered_product_id' property set to ref_id
    118 
    119                             var data = {
    120                                 quantity: qty,
    121                                 plan: planCopy
    122                             };
    123 
    124                             // Add the plan to the cart using ExtendWooCommerce.addPlanToCart()
    125                             ExtendWooCommerce.addPlanToCart(data)
    126                                 .then(() => {
    127                                     // Enable the 'update_cart' button and trigger a click event
    128                                     jQuery("[name='update_cart']").removeAttr('disabled');
    129                                     jQuery("[name='update_cart']").trigger("click");
    130                                 });
    131                         }
    132                     },
    133                 });
    134             });
    135     });
    136 });
     100})(jQuery);
  • helloextend-protection/trunk/js/helloextend-global.js

    r3263092 r3348358  
    66            }
    77
    8             const { store_id: storeId, ajaxurl, environment  } = ExtendWooCommerce;
     8            const { store_id: storeId, ajaxurl, environment, debug_log_enabled: debugLogEnabled } = ExtendWooCommerce;
    99
    1010            Extend.config(
     
    2020                getCart,
    2121                warrantyAlreadyInCart,
    22                 extendAjaxLog
     22                extendAjaxLog,
     23                debugLogEnabled
    2324            }
    2425
     
    7071            }
    7172
    72             function extendAjaxLog(message , method)
     73            function extendAjaxLog(method, ...message)
    7374            {
    7475
     76                message = message.join(' ');
    7577                /* Now use an ajax call to write logs from js files... */
    7678                $.ajax(
  • helloextend-protection/trunk/js/helloextend-pdp-offers.js

    r3263092 r3348358  
    66
    77        // Deconstructs ExtendProductIntegration variables
    8         const { type: product_type, id: product_id, sku, first_category, price, helloextend_pdp_offers_enabled, helloextend_modal_offers_enabled, helloextend_use_skus, atc_button_selector } = ExtendProductIntegration;
     8        const { type: product_type, id: product_id, sku, first_category, price, helloextend_pdp_offers_enabled, helloextend_modal_offers_enabled, atc_button_selector } = ExtendProductIntegration;
    99
    1010        const $atcButton = jQuery(atc_button_selector)
    1111
     12        const quantity = parseInt(document.querySelector('input[name="quantity"]').value || 1)
     13
    1214        let supportedProductType = true;
    13         let reference_id = '';
     15        let reference_id = product_id;
    1416
    1517        // If PDP offers are not enabled, hide Extend offer div
     
    1921        }
    2022
    21         if (helloextend_use_skus == '1') {
    22             reference_id = sku;
    23         } else {
    24             reference_id = product_id;
    25         }
    26 
    2723        function handleAddToCartLogic(variation_id)  {
    2824
    2925            $atcButton.on('click', function extendHandler(e) {
    30                 e.preventDefault()
     26                e.preventDefault();
     27                e.stopImmediatePropagation();
    3128
    3229                let isDisabled = $atcButton.hasClass("disabled");
     
    4946                    var planCopy = { ...plan, covered_product_id: variation_id }
    5047                    var data = {
    51                         quantity: 1,
     48                        quantity: quantity,
    5249                        plan: planCopy,
    5350                        price: (plan.price / 100).toFixed(2)
    5451                    }
    5552                    ExtendWooCommerce.addPlanToCart(data)
    56 
    5753                        .then(() => {
    5854                            triggerAddToCart();
     
    6864                                    var planCopy = { ...plan, covered_product_id: variation_id }
    6965                                    var data = {
    70                                         quantity: 1,
     66                                        quantity: quantity,
    7167                                        plan: planCopy,
    7268                                        price: (plan.price / 100).toFixed(2)
  • helloextend-protection/trunk/js/helloextend-shipping-offers.js

    r3263092 r3348358  
    1010            {
    1111                // Deconstructs ExtendProductIntegration variables
    12                 const { env, items, enable_helloextend_sp, ajax_url, update_order_review_nonce } = ExtendShippingIntegration;
     12                const { env, items, enable_helloextend_sp, ajax_url, update_order_review_nonce, helloextend_sp_add_sku } = ExtendShippingIntegration;
    1313                let items_array = eval(items);
    1414
     
    4545                                        success: function () {
    4646                                            $('body').trigger('update_checkout');
     47
     48                                            // Need to trigger again for SP line item settings to get correct total
     49                                            if (helloextend_sp_add_sku) {
     50                                                setTimeout(() => {
     51                                                    $('body').trigger('update_checkout');
     52                                                }, 50);
     53                                            }
    4754                                        }
    4855                                    }
     
    6067                                        success: function () {
    6168                                            $('body').trigger('update_checkout');
     69
     70                                            // Need to trigger again for SP line item settings to get correct total
     71                                            if (helloextend_sp_add_sku) {
     72                                                setTimeout(() => {
     73                                                    $('body').trigger('update_checkout');
     74                                                }, 50);
     75                                            }
    6276                                        }
    6377                                    }
     
    7993                                        success: function () {
    8094                                            $('body').trigger('update_checkout');
     95
     96                                            // Need to trigger again for SP line item settings to get correct total
     97                                            if (helloextend_sp_add_sku) {
     98                                                setTimeout(() => {
     99                                                    $('body').trigger('update_checkout');
     100                                                }, 50);
     101                                            }
    81102                                        }
    82103                                    }
  • helloextend-protection/trunk/readme.txt

    r3263092 r3348358  
    55Tags: extend, protection, tracking
    66Requires at least: 4.0
    7 Tested up to: 6.7
    8 Stable tag: 1.0.0
     7Tested up to: 6.8
     8Stable tag: 1.1.1
    99Requires PHP: 7.4
    1010License: GPLv2 or later
     
    7979
    8080== Changelog ==
     81= 1.1.1 2025-08-01 =
     82 * Fix - When Shipping Protection as a line item is enabled, the cart total would not correctly update when selecting or deselecting - this has been fixed
     83 * Fix - Resolved an issue where the default add to cart behavior was not always prevented in the modal offer
     84 * Feature - Logs are now passed to the backend from the site. You can now view cart offer debug logs.
    8185
    82 = 1.0 =
     86= 1.1.0 2025-04-15 =
     87* Fix — PDP offers now pass correct quantity from input element. If the input element does not exists, it defaults to 1.
     88* Feature — Adds the ability to add Shipping Protection as a line item instead of a checkout fee.
     89
     90= 1.0.0 2025-03-27 =
    8391* Extend Protection For WooCommerce plugin launch.
    8492* Initial release. Supports product and shipping protection.
    8593
     94
Note: See TracChangeset for help on using the changeset viewer.