From 4a94037c528a353ee3201f80176afba948183de8 Mon Sep 17 00:00:00 2001 From: Paul Dechov Date: Mon, 29 Jul 2019 22:32:56 -0400 Subject: [PATCH 001/137] Replace update_checkout request on checkout page load with updated_checkout event --- assets/js/frontend/checkout.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/assets/js/frontend/checkout.js b/assets/js/frontend/checkout.js index 44dfefa228e..9ec82d1c6f6 100644 --- a/assets/js/frontend/checkout.js +++ b/assets/js/frontend/checkout.js @@ -135,7 +135,10 @@ jQuery( function( $ ) { } }, init_checkout: function() { - $( document.body ).trigger( 'update_checkout' ); + // Fire updated_checkout event after existing ready event handlers. + $( function() { + $( document.body ).trigger( 'updated_checkout' ); + } ); }, maybe_input_changed: function( e ) { if ( wc_checkout_form.dirtyInput ) { From 264556be91d9d1b596d588ef7f6bf5b37718a014 Mon Sep 17 00:00:00 2001 From: Paul Dechov Date: Mon, 29 Jul 2019 22:39:19 -0400 Subject: [PATCH 002/137] Call ship-to-different-address change handler manually in lieu of event trigger Avoids unnecessary update_checkout call on initialization. --- assets/js/frontend/checkout.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/assets/js/frontend/checkout.js b/assets/js/frontend/checkout.js index 9ec82d1c6f6..6df50100a3b 100644 --- a/assets/js/frontend/checkout.js +++ b/assets/js/frontend/checkout.js @@ -50,7 +50,7 @@ jQuery( function( $ ) { this.$checkout_form.on( 'change', '#ship-to-different-address input', this.ship_to_different_address ); // Trigger events - this.$checkout_form.find( '#ship-to-different-address input' ).change(); + this.ship_to_different_address(); this.init_payment_methods(); // Update on page load @@ -183,10 +183,11 @@ jQuery( function( $ ) { wc_checkout_form.trigger_update_checkout(); } }, - ship_to_different_address: function() { - $( 'div.shipping_address' ).hide(); - if ( $( this ).is( ':checked' ) ) { - $( 'div.shipping_address' ).slideDown(); + ship_to_different_address: function( e ) { + if ( $( '#ship-to-different-address input' ).is( ':checked' ) ) { + $( 'div.shipping_address' ).slideDown( e ? null : 0 ); + } else { + $( 'div.shipping_address' ).slideUp( e ? null : 0 ); } }, reset_update_checkout_timer: function() { From 429161e1c66cb04e864529b47f03a92e57033196 Mon Sep 17 00:00:00 2001 From: Paul Dechov Date: Tue, 30 Jul 2019 18:42:51 -0400 Subject: [PATCH 003/137] Add logic to initialize checkbox based on whether shipping address is different --- assets/js/frontend/checkout.js | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/assets/js/frontend/checkout.js b/assets/js/frontend/checkout.js index 6df50100a3b..ce994448ddd 100644 --- a/assets/js/frontend/checkout.js +++ b/assets/js/frontend/checkout.js @@ -50,7 +50,7 @@ jQuery( function( $ ) { this.$checkout_form.on( 'change', '#ship-to-different-address input', this.ship_to_different_address ); // Trigger events - this.ship_to_different_address(); + this.init_ship_to_different_address(); this.init_payment_methods(); // Update on page load @@ -183,11 +183,30 @@ jQuery( function( $ ) { wc_checkout_form.trigger_update_checkout(); } }, - ship_to_different_address: function( e ) { - if ( $( '#ship-to-different-address input' ).is( ':checked' ) ) { - $( 'div.shipping_address' ).slideDown( e ? null : 0 ); + init_ship_to_different_address: function() { + var $checkbox = $( '#ship-to-different-address input' ); + + if ( ! $checkbox.prop( 'checked' ) ) { + var $billing = $( 'div.woocommerce-billing-fields' ); + + var $differentFields = jQuery( 'div.shipping_address' ).find( 'input, select' ).filter( function() { + jQuery( this ).attr( 'id' ).replace( 'shipping', 'billing' ); + var id = jQuery( this ).attr( 'id' ).replace( 'shipping', 'billing' ); + return jQuery( this ).val() !== $billing.find( '#' + id ).val(); + } ); + + if ( $differentFields.length > 0 ) { + $checkbox.prop( 'checked', true ); + } + } + + $( 'div.shipping_address' ).toggle( $checkbox.prop( 'checked' ) ); + }, + ship_to_different_address: function() { + if ( $( this ).is( ':checked' ) ) { + $( 'div.shipping_address' ).slideDown(); } else { - $( 'div.shipping_address' ).slideUp( e ? null : 0 ); + $( 'div.shipping_address' ).slideUp(); } }, reset_update_checkout_timer: function() { From a646d96bec3768368be3524e85569bc76dedc3e2 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 31 Jul 2019 19:48:22 -0300 Subject: [PATCH 004/137] Make wc_format_decimal() strip multiple decimal separators --- includes/wc-formatting-functions.php | 1 + 1 file changed, 1 insertion(+) diff --git a/includes/wc-formatting-functions.php b/includes/wc-formatting-functions.php index f0cd54c647e..2fdd57b0739 100644 --- a/includes/wc-formatting-functions.php +++ b/includes/wc-formatting-functions.php @@ -293,6 +293,7 @@ function wc_format_decimal( $number, $dp = false, $trim_zeros = false ) { if ( ! is_float( $number ) ) { $number = str_replace( $decimals, '.', $number ); $number = preg_replace( '/[^0-9\.,-]/', '', wc_clean( $number ) ); + $number = preg_replace( '/\.+/', '.', $number ); } if ( false !== $dp ) { From 83c0e696374366207696d0c5fccd63963db2c5fb Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 31 Jul 2019 19:54:58 -0300 Subject: [PATCH 005/137] Update wc_format_decimal() tests to check for multiple decimals points --- includes/wc-formatting-functions.php | 2 ++ tests/unit-tests/formatting/functions.php | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/includes/wc-formatting-functions.php b/includes/wc-formatting-functions.php index 2fdd57b0739..e2677c4d57a 100644 --- a/includes/wc-formatting-functions.php +++ b/includes/wc-formatting-functions.php @@ -293,6 +293,8 @@ function wc_format_decimal( $number, $dp = false, $trim_zeros = false ) { if ( ! is_float( $number ) ) { $number = str_replace( $decimals, '.', $number ); $number = preg_replace( '/[^0-9\.,-]/', '', wc_clean( $number ) ); + + // Convert multiple dots to just one. $number = preg_replace( '/\.+/', '.', $number ); } diff --git a/tests/unit-tests/formatting/functions.php b/tests/unit-tests/formatting/functions.php index a2d9be890fe..3c61ee12da9 100644 --- a/tests/unit-tests/formatting/functions.php +++ b/tests/unit-tests/formatting/functions.php @@ -290,6 +290,9 @@ class WC_Tests_Formatting_Functions extends WC_Unit_Test_Case { // Given string. $this->assertEquals( '9.99', wc_format_decimal( '9.99' ) ); + // Given string with multiple decimals points. + $this->assertEquals( '9.99', wc_format_decimal( '9...99' ) ); + // Float. $this->assertEquals( '9.99', wc_format_decimal( 9.99 ) ); @@ -316,7 +319,10 @@ class WC_Tests_Formatting_Functions extends WC_Unit_Test_Case { update_option( 'woocommerce_price_thousand_sep', '.' ); // Given string. - $this->assertEquals( '9.99', wc_format_decimal( '9.99' ) ); + $this->assertEquals( '9.99', wc_format_decimal( '9,99' ) ); + + // Given string with multiple decimals points. + $this->assertEquals( '9.99', wc_format_decimal( '9,,,99' ) ); // Float. $this->assertEquals( '9.99', wc_format_decimal( 9.99 ) ); From 375b989322c7d8f45ae62cd5752f3f0630686d43 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 2 Aug 2019 13:58:02 -0300 Subject: [PATCH 006/137] Added validation for multiple decimal points --- assets/js/admin/woocommerce_admin.js | 12 +++++++++++- includes/admin/class-wc-admin-assets.php | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/assets/js/admin/woocommerce_admin.js b/assets/js/admin/woocommerce_admin.js index f9e88587d00..c4a2b09e6c1 100644 --- a/assets/js/admin/woocommerce_admin.js +++ b/assets/js/admin/woocommerce_admin.js @@ -78,22 +78,32 @@ }) .on( 'keyup', '.wc_input_price[type=text], .wc_input_decimal[type=text], .wc_input_country_iso[type=text], .wc-order-totals #refund_amount[type=text]', function() { - var regex, error; + var regex, error, decimalRegex; + var checkDecimalNumbers = false; if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) { + checkDecimalNumbers = true; regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.mon_decimal_point + ']+', 'gi' ); + decimalRegex = new RegExp( '[^\\' + woocommerce_admin.mon_decimal_point + ']', 'gi' ); error = 'i18n_mon_decimal_error'; } else if ( $( this ).is( '.wc_input_country_iso' ) ) { regex = new RegExp( '([^A-Z])+|(.){3,}', 'im' ); error = 'i18n_country_iso_error'; } else { + checkDecimalNumbers = true; regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.decimal_point + ']+', 'gi' ); + decimalRegex = new RegExp( '[^\\' + woocommerce_admin.decimal_point + ']', 'gi' ); error = 'i18n_decimal_error'; } var value = $( this ).val(); var newvalue = value.replace( regex, '' ); + // Check if newvalue have more than one decimal point. + if ( checkDecimalNumbers && 1 < newvalue.replace( decimalRegex, '' ).length ) { + newvalue = newvalue.replace( decimalRegex, '' ); + } + if ( value !== newvalue ) { $( document.body ).triggerHandler( 'wc_add_error_tip', [ $( this ), error ] ); } else { diff --git a/includes/admin/class-wc-admin-assets.php b/includes/admin/class-wc-admin-assets.php index 8a5c7b7f955..34defe99fc6 100644 --- a/includes/admin/class-wc-admin-assets.php +++ b/includes/admin/class-wc-admin-assets.php @@ -169,9 +169,9 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) : $params = array( /* translators: %s: decimal */ - 'i18n_decimal_error' => sprintf( __( 'Please enter in decimal (%s) format without thousand separators.', 'woocommerce' ), $decimal ), + 'i18n_decimal_error' => sprintf( __( 'Please enter with one decimal point (%s) without thousand separators.', 'woocommerce' ), $decimal ), /* translators: %s: price decimal separator */ - 'i18n_mon_decimal_error' => sprintf( __( 'Please enter in monetary decimal (%s) format without thousand separators and currency symbols.', 'woocommerce' ), wc_get_price_decimal_separator() ), + 'i18n_mon_decimal_error' => sprintf( __( 'Please enter with one monetary decimal point (%s) without thousand separators and currency symbols.', 'woocommerce' ), wc_get_price_decimal_separator() ), 'i18n_country_iso_error' => __( 'Please enter in country code with two capital letters.', 'woocommerce' ), 'i18n_sale_less_than_regular_error' => __( 'Please enter in a value less than the regular price.', 'woocommerce' ), 'i18n_delete_product_notice' => __( 'This product has produced sales and may be linked to existing orders. Are you sure you want to delete it?', 'woocommerce' ), From 2b0fc6f50a84234b6f717b84f8be2481bb500884 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Fri, 2 Aug 2019 14:02:33 -0300 Subject: [PATCH 007/137] Added sanitization for number of decimal points in JS --- assets/js/admin/woocommerce_admin.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/assets/js/admin/woocommerce_admin.js b/assets/js/admin/woocommerce_admin.js index c4a2b09e6c1..936bfe9a232 100644 --- a/assets/js/admin/woocommerce_admin.js +++ b/assets/js/admin/woocommerce_admin.js @@ -61,16 +61,20 @@ }) .on( 'change', '.wc_input_price[type=text], .wc_input_decimal[type=text], .wc-order-totals #refund_amount[type=text]', function() { - var regex; + var regex, decimalRegex, decimailPoint; if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) { - regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.mon_decimal_point + ']+', 'gi' ); + decimailPoint = woocommerce_admin.mon_decimal_point; + regex = new RegExp( '[^\-0-9\%\\' + decimailPoint + ']+', 'gi' ); + decimalRegex = new RegExp( '\\' + decimailPoint + '+', 'gi' ); } else { - regex = new RegExp( '[^\-0-9\%\\' + woocommerce_admin.decimal_point + ']+', 'gi' ); + decimailPoint = woocommerce_admin.decimal_point; + regex = new RegExp( '[^\-0-9\%\\' + decimailPoint + ']+', 'gi' ); + decimalRegex = new RegExp( '\\' + decimailPoint + '+', 'gi' ); } var value = $( this ).val(); - var newvalue = value.replace( regex, '' ); + var newvalue = value.replace( regex, '' ).replace( decimalRegex, decimailPoint ); if ( value !== newvalue ) { $( this ).val( newvalue ); From e15e51868c9b031a473ff7f1a36da94c6a6fabe8 Mon Sep 17 00:00:00 2001 From: Paul Dechov Date: Fri, 2 Aug 2019 18:10:47 -0400 Subject: [PATCH 008/137] Remove accidental jQuery references in favor of $ --- assets/js/frontend/checkout.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/assets/js/frontend/checkout.js b/assets/js/frontend/checkout.js index ce994448ddd..877d418ebcf 100644 --- a/assets/js/frontend/checkout.js +++ b/assets/js/frontend/checkout.js @@ -189,10 +189,11 @@ jQuery( function( $ ) { if ( ! $checkbox.prop( 'checked' ) ) { var $billing = $( 'div.woocommerce-billing-fields' ); - var $differentFields = jQuery( 'div.shipping_address' ).find( 'input, select' ).filter( function() { - jQuery( this ).attr( 'id' ).replace( 'shipping', 'billing' ); - var id = jQuery( this ).attr( 'id' ).replace( 'shipping', 'billing' ); - return jQuery( this ).val() !== $billing.find( '#' + id ).val(); + // Find shipping field values that diverge from billing. + var $differentFields = $( 'div.shipping_address' ).find( 'input, select' ).filter( function() { + $( this ).attr( 'id' ).replace( 'shipping', 'billing' ); + var id = $( this ).attr( 'id' ).replace( 'shipping', 'billing' ); + return $( this ).val() !== $billing.find( '#' + id ).val(); } ); if ( $differentFields.length > 0 ) { From 366681038ff0061f8b17598dd8dfe95c04dde02b Mon Sep 17 00:00:00 2001 From: johntendik Date: Tue, 10 Sep 2019 20:23:10 -0400 Subject: [PATCH 009/137] added unload event to prevent reload during checkout --- assets/js/frontend/checkout.js | 55 ++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/assets/js/frontend/checkout.js b/assets/js/frontend/checkout.js index 44dfefa228e..46df68759d9 100644 --- a/assets/js/frontend/checkout.js +++ b/assets/js/frontend/checkout.js @@ -41,10 +41,10 @@ jQuery( function( $ ) { this.$checkout_form.on( 'update', this.trigger_update_checkout ); // Inputs/selects which update totals - this.$checkout_form.on( 'change', 'select.shipping_method, input[name^="shipping_method"], #ship-to-different-address input, .update_totals_on_change select, .update_totals_on_change input[type="radio"], .update_totals_on_change input[type="checkbox"]', this.trigger_update_checkout ); + this.$checkout_form.on( 'change', 'select.shipping_method, input[name^="shipping_method"], #ship-to-different-address input, .update_totals_on_change select, .update_totals_on_change input[type="radio"], .update_totals_on_change input[type="checkbox"]', this.trigger_update_checkout ); // eslint-disable-line max-len this.$checkout_form.on( 'change', '.address-field select', this.input_changed ); - this.$checkout_form.on( 'change', '.address-field input.input-text, .update_totals_on_change input.input-text', this.maybe_input_changed ); - this.$checkout_form.on( 'keydown', '.address-field input.input-text, .update_totals_on_change input.input-text', this.queue_update_checkout ); + this.$checkout_form.on( 'change', '.address-field input.input-text, .update_totals_on_change input.input-text', this.maybe_input_changed ); // eslint-disable-line max-len + this.$checkout_form.on( 'keydown', '.address-field input.input-text, .update_totals_on_change input.input-text', this.queue_update_checkout ); // eslint-disable-line max-len // Address fields this.$checkout_form.on( 'change', '#ship-to-different-address input', this.ship_to_different_address ); @@ -207,7 +207,7 @@ jQuery( function( $ ) { event_type = e.type; if ( 'input' === event_type ) { - $parent.removeClass( 'woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email woocommerce-validated' ); + $parent.removeClass( 'woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email woocommerce-validated' ); // eslint-disable-line max-len } if ( 'validate' === event_type || 'change' === event_type ) { @@ -225,7 +225,7 @@ jQuery( function( $ ) { if ( validate_email ) { if ( $this.val() ) { /* https://stackoverflow.com/questions/2855865/jquery-validate-e-mail-address-regex */ - var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i); + var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i); // eslint-disable-line max-len if ( ! pattern.test( $this.val() ) ) { $parent.removeClass( 'woocommerce-validated' ).addClass( 'woocommerce-invalid woocommerce-invalid-email' ); @@ -235,7 +235,7 @@ jQuery( function( $ ) { } if ( validated ) { - $parent.removeClass( 'woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email' ).addClass( 'woocommerce-validated' ); + $parent.removeClass( 'woocommerce-invalid woocommerce-invalid-required-field woocommerce-invalid-email' ).addClass( 'woocommerce-validated' ); // eslint-disable-line max-len } } }, @@ -311,6 +311,7 @@ jQuery( function( $ ) { if ( false !== args.update_shipping_method ) { var shipping_methods = {}; + // eslint-disable-next-line max-len $( 'select.shipping_method, input[name^="shipping_method"][type="radio"]:checked, input[name^="shipping_method"][type="hidden"]' ).each( function() { shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val(); } ); @@ -395,7 +396,7 @@ jQuery( function( $ ) { // Add new errors returned by this event if ( data.messages ) { - $form.prepend( '
' + data.messages + '
' ); + $form.prepend( '
' + data.messages + '
' ); // eslint-disable-line max-len } else { $form.prepend( data ); } @@ -414,7 +415,27 @@ jQuery( function( $ ) { } }); - }, + }, + handleUnloadEvent: function( e ) { + // Modern browsers have their own standard generic messages that they will display. + // Confirm, alert, prompt or custom message are not allowed during the unload event + // Browsers will display their own standard messages + + // Check if the browser is Internet Explorer + if((navigator.userAgent.indexOf('MSIE') !== -1 ) || (!!document.documentMode)) { + // IE handles unload events differently than modern browsers + e.preventDefault(); + return undefined; + } + + return true; + }, + attachUnloadEventsOnSubmit: function() { + $( window ).on('beforeunload', this.handleUnloadEvent); + }, + detachUnloadEventsOnSubmit: function() { + $( window ).unbind('beforeunload', this.handleUnloadEvent); + }, blockOnSubmit: function( $form ) { var form_data = $form.data(); @@ -439,12 +460,16 @@ jQuery( function( $ ) { return false; } - // Trigger a handler to let gateways manipulate the checkout if needed + // Trigger a handler to let gateways manipulate the checkout if needed + // eslint-disable-next-line max-len if ( $form.triggerHandler( 'checkout_place_order' ) !== false && $form.triggerHandler( 'checkout_place_order_' + wc_checkout_form.get_payment_method() ) !== false ) { $form.addClass( 'processing' ); - wc_checkout_form.blockOnSubmit( $form ); + wc_checkout_form.blockOnSubmit( $form ); + + // Attach event to block reloading the page when the form has been submitted + wc_checkout_form.attachUnloadEventsOnSubmit(); // ajaxSetup is global, but we use it to ensure JSON is valid once returned. $.ajaxSetup( { @@ -481,6 +506,9 @@ jQuery( function( $ ) { data: $form.serialize(), dataType: 'json', success: function( result ) { + // Detach the unload handler that prevents a reload / redirect + wc_checkout_form.detachUnloadEventsOnSubmit(); + try { if ( 'success' === result.result ) { if ( -1 === result.redirect.indexOf( 'https://' ) || -1 === result.redirect.indexOf( 'http://' ) ) { @@ -509,11 +537,14 @@ jQuery( function( $ ) { if ( result.messages ) { wc_checkout_form.submit_error( result.messages ); } else { - wc_checkout_form.submit_error( '
' + wc_checkout_params.i18n_checkout_error + '
' ); + wc_checkout_form.submit_error( '
' + wc_checkout_params.i18n_checkout_error + '
' ); // eslint-disable-line max-len } } }, error: function( jqXHR, textStatus, errorThrown ) { + // Detach the unload handler that prevents a reload / redirect + wc_checkout_form.detachUnloadEventsOnSubmit(); + wc_checkout_form.submit_error( '
' + errorThrown + '
' ); } }); @@ -523,7 +554,7 @@ jQuery( function( $ ) { }, submit_error: function( error_message ) { $( '.woocommerce-NoticeGroup-checkout, .woocommerce-error, .woocommerce-message' ).remove(); - wc_checkout_form.$checkout_form.prepend( '
' + error_message + '
' ); + wc_checkout_form.$checkout_form.prepend( '
' + error_message + '
' ); // eslint-disable-line max-len wc_checkout_form.$checkout_form.removeClass( 'processing' ).unblock(); wc_checkout_form.$checkout_form.find( '.input-text, select, input:checkbox' ).trigger( 'validate' ).blur(); wc_checkout_form.scroll_to_notices(); From 0a9563dacd3a7d7ffa0933872b9187327194998c Mon Sep 17 00:00:00 2001 From: johntendik Date: Tue, 10 Sep 2019 20:43:13 -0400 Subject: [PATCH 010/137] fixing indentation --- assets/js/frontend/checkout.js | 58 +++++++++++++++++----------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/assets/js/frontend/checkout.js b/assets/js/frontend/checkout.js index 46df68759d9..a82298f13b5 100644 --- a/assets/js/frontend/checkout.js +++ b/assets/js/frontend/checkout.js @@ -311,7 +311,7 @@ jQuery( function( $ ) { if ( false !== args.update_shipping_method ) { var shipping_methods = {}; - // eslint-disable-next-line max-len + // eslint-disable-next-line max-len $( 'select.shipping_method, input[name^="shipping_method"][type="radio"]:checked, input[name^="shipping_method"][type="hidden"]' ).each( function() { shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val(); } ); @@ -415,27 +415,27 @@ jQuery( function( $ ) { } }); - }, - handleUnloadEvent: function( e ) { - // Modern browsers have their own standard generic messages that they will display. - // Confirm, alert, prompt or custom message are not allowed during the unload event - // Browsers will display their own standard messages + }, + handleUnloadEvent: function( e ) { + // Modern browsers have their own standard generic messages that they will display. + // Confirm, alert, prompt or custom message are not allowed during the unload event + // Browsers will display their own standard messages - // Check if the browser is Internet Explorer - if((navigator.userAgent.indexOf('MSIE') !== -1 ) || (!!document.documentMode)) { - // IE handles unload events differently than modern browsers - e.preventDefault(); - return undefined; - } + // Check if the browser is Internet Explorer + if((navigator.userAgent.indexOf('MSIE') !== -1 ) || (!!document.documentMode)) { + // IE handles unload events differently than modern browsers + e.preventDefault(); + return undefined; + } - return true; - }, - attachUnloadEventsOnSubmit: function() { - $( window ).on('beforeunload', this.handleUnloadEvent); - }, - detachUnloadEventsOnSubmit: function() { - $( window ).unbind('beforeunload', this.handleUnloadEvent); - }, + return true; + }, + attachUnloadEventsOnSubmit: function() { + $( window ).on('beforeunload', this.handleUnloadEvent); + }, + detachUnloadEventsOnSubmit: function() { + $( window ).unbind('beforeunload', this.handleUnloadEvent); + }, blockOnSubmit: function( $form ) { var form_data = $form.data(); @@ -460,16 +460,16 @@ jQuery( function( $ ) { return false; } - // Trigger a handler to let gateways manipulate the checkout if needed - // eslint-disable-next-line max-len + // Trigger a handler to let gateways manipulate the checkout if needed + // eslint-disable-next-line max-len if ( $form.triggerHandler( 'checkout_place_order' ) !== false && $form.triggerHandler( 'checkout_place_order_' + wc_checkout_form.get_payment_method() ) !== false ) { $form.addClass( 'processing' ); - wc_checkout_form.blockOnSubmit( $form ); + wc_checkout_form.blockOnSubmit( $form ); - // Attach event to block reloading the page when the form has been submitted - wc_checkout_form.attachUnloadEventsOnSubmit(); + // Attach event to block reloading the page when the form has been submitted + wc_checkout_form.attachUnloadEventsOnSubmit(); // ajaxSetup is global, but we use it to ensure JSON is valid once returned. $.ajaxSetup( { @@ -506,8 +506,8 @@ jQuery( function( $ ) { data: $form.serialize(), dataType: 'json', success: function( result ) { - // Detach the unload handler that prevents a reload / redirect - wc_checkout_form.detachUnloadEventsOnSubmit(); + // Detach the unload handler that prevents a reload / redirect + wc_checkout_form.detachUnloadEventsOnSubmit(); try { if ( 'success' === result.result ) { @@ -542,8 +542,8 @@ jQuery( function( $ ) { } }, error: function( jqXHR, textStatus, errorThrown ) { - // Detach the unload handler that prevents a reload / redirect - wc_checkout_form.detachUnloadEventsOnSubmit(); + // Detach the unload handler that prevents a reload / redirect + wc_checkout_form.detachUnloadEventsOnSubmit(); wc_checkout_form.submit_error( '
' + errorThrown + '
' ); } From 4d25b058c11a463464ac5c893e735924fcbad424 Mon Sep 17 00:00:00 2001 From: Nathan Dawson Date: Tue, 24 Sep 2019 23:41:57 +0200 Subject: [PATCH 011/137] Refine static homepage check to exclude blog archive queries. Fixes #24582 --- includes/class-wc-query.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-query.php b/includes/class-wc-query.php index 366c6a5b3fa..cd424cf7d44 100644 --- a/includes/class-wc-query.php +++ b/includes/class-wc-query.php @@ -234,7 +234,7 @@ class WC_Query { * @return bool */ private function is_showing_page_on_front( $q ) { - return $q->is_home() && 'page' === get_option( 'show_on_front' ); + return ( $q->is_home() && ! $q->is_posts_page ) && 'page' === get_option( 'show_on_front' ); } /** From 56bb0e1d3aa615393f464a57af762a713d532007 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Thu, 3 Oct 2019 10:52:41 -0300 Subject: [PATCH 012/137] Add subdivisions of Laos Based on https://github.com/unicode-org/cldr/blob/release-35-1/common/subdivisions/en.xml#L2690 --- i18n/states.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/i18n/states.php b/i18n/states.php index f90e11e213a..24fd0231a7b 100644 --- a/i18n/states.php +++ b/i18n/states.php @@ -698,6 +698,26 @@ return array( ), 'KR' => array(), 'KW' => array(), + 'LA' => array( + 'laat' => __( 'Attapeu', 'woocommerce' ), + 'labk' => __( 'Bokeo', 'woocommerce' ), + 'labl' => __( 'Bolikhamsai', 'woocommerce' ), + 'lach' => __( 'Champasak', 'woocommerce' ), + 'laho' => __( 'Houaphanh', 'woocommerce' ), + 'lakh' => __( 'Khammouane', 'woocommerce' ), + 'lalm' => __( 'Luang Namtha', 'woocommerce' ), + 'lalp' => __( 'Luang Prabang', 'woocommerce' ), + 'laou' => __( 'Oudomxay', 'woocommerce' ), + 'laph' => __( 'Phongsaly', 'woocommerce' ), + 'lasl' => __( 'Salavan', 'woocommerce' ), + 'lasv' => __( 'Savannakhet', 'woocommerce' ), + 'lavi' => __( 'Vientiane Province', 'woocommerce' ), + 'lavt' => __( 'Vientiane', 'woocommerce' ), + 'laxa' => __( 'Sainyabuli', 'woocommerce' ), + 'laxe' => __( 'Sekong', 'woocommerce' ), + 'laxi' => __( 'Xiangkhouang', 'woocommerce' ), + 'laxs' => __( 'Xaisomboun', 'woocommerce' ), + ), 'LB' => array(), 'LR' => array( // Liberia provinces. 'BM' => __( 'Bomi', 'woocommerce' ), From 9851b1f0f3dabc9b2e14fe0abc6278edd8d9240c Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Thu, 3 Oct 2019 21:19:52 -0300 Subject: [PATCH 013/137] DRY --- assets/js/admin/woocommerce_admin.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/assets/js/admin/woocommerce_admin.js b/assets/js/admin/woocommerce_admin.js index 936bfe9a232..fd5034073d0 100644 --- a/assets/js/admin/woocommerce_admin.js +++ b/assets/js/admin/woocommerce_admin.js @@ -61,18 +61,16 @@ }) .on( 'change', '.wc_input_price[type=text], .wc_input_decimal[type=text], .wc-order-totals #refund_amount[type=text]', function() { - var regex, decimalRegex, decimailPoint; + var regex, decimalRegex, + decimailPoint = woocommerce_admin.decimal_point; if ( $( this ).is( '.wc_input_price' ) || $( this ).is( '#refund_amount' ) ) { decimailPoint = woocommerce_admin.mon_decimal_point; - regex = new RegExp( '[^\-0-9\%\\' + decimailPoint + ']+', 'gi' ); - decimalRegex = new RegExp( '\\' + decimailPoint + '+', 'gi' ); - } else { - decimailPoint = woocommerce_admin.decimal_point; - regex = new RegExp( '[^\-0-9\%\\' + decimailPoint + ']+', 'gi' ); - decimalRegex = new RegExp( '\\' + decimailPoint + '+', 'gi' ); } + regex = new RegExp( '[^\-0-9\%\\' + decimailPoint + ']+', 'gi' ); + decimalRegex = new RegExp( '\\' + decimailPoint + '+', 'gi' ); + var value = $( this ).val(); var newvalue = value.replace( regex, '' ).replace( decimalRegex, decimailPoint ); From 388f15de9e16963aa9bd220009e35d3ce7f54a78 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Fri, 4 Oct 2019 10:33:39 -0300 Subject: [PATCH 014/137] Fix code for Laos subdivisions Remove 'la' prefix and make the code uppercase. --- i18n/states.php | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/i18n/states.php b/i18n/states.php index 24fd0231a7b..62144047341 100644 --- a/i18n/states.php +++ b/i18n/states.php @@ -699,24 +699,24 @@ return array( 'KR' => array(), 'KW' => array(), 'LA' => array( - 'laat' => __( 'Attapeu', 'woocommerce' ), - 'labk' => __( 'Bokeo', 'woocommerce' ), - 'labl' => __( 'Bolikhamsai', 'woocommerce' ), - 'lach' => __( 'Champasak', 'woocommerce' ), - 'laho' => __( 'Houaphanh', 'woocommerce' ), - 'lakh' => __( 'Khammouane', 'woocommerce' ), - 'lalm' => __( 'Luang Namtha', 'woocommerce' ), - 'lalp' => __( 'Luang Prabang', 'woocommerce' ), - 'laou' => __( 'Oudomxay', 'woocommerce' ), - 'laph' => __( 'Phongsaly', 'woocommerce' ), - 'lasl' => __( 'Salavan', 'woocommerce' ), - 'lasv' => __( 'Savannakhet', 'woocommerce' ), - 'lavi' => __( 'Vientiane Province', 'woocommerce' ), - 'lavt' => __( 'Vientiane', 'woocommerce' ), - 'laxa' => __( 'Sainyabuli', 'woocommerce' ), - 'laxe' => __( 'Sekong', 'woocommerce' ), - 'laxi' => __( 'Xiangkhouang', 'woocommerce' ), - 'laxs' => __( 'Xaisomboun', 'woocommerce' ), + 'AT' => __( 'Attapeu', 'woocommerce' ), + 'BK' => __( 'Bokeo', 'woocommerce' ), + 'BL' => __( 'Bolikhamsai', 'woocommerce' ), + 'CH' => __( 'Champasak', 'woocommerce' ), + 'HO' => __( 'Houaphanh', 'woocommerce' ), + 'KH' => __( 'Khammouane', 'woocommerce' ), + 'LM' => __( 'Luang Namtha', 'woocommerce' ), + 'LP' => __( 'Luang Prabang', 'woocommerce' ), + 'OU' => __( 'Oudomxay', 'woocommerce' ), + 'PH' => __( 'Phongsaly', 'woocommerce' ), + 'SL' => __( 'Salavan', 'woocommerce' ), + 'SV' => __( 'Savannakhet', 'woocommerce' ), + 'VI' => __( 'Vientiane Province', 'woocommerce' ), + 'VT' => __( 'Vientiane', 'woocommerce' ), + 'XA' => __( 'Sainyabuli', 'woocommerce' ), + 'XE' => __( 'Sekong', 'woocommerce' ), + 'XI' => __( 'Xiangkhouang', 'woocommerce' ), + 'XS' => __( 'Xaisomboun', 'woocommerce' ), ), 'LB' => array(), 'LR' => array( // Liberia provinces. From 34036d8f7deb520deda80a163c39876cbc42b7cb Mon Sep 17 00:00:00 2001 From: Jacob McKinney Date: Tue, 15 Oct 2019 22:11:44 -0500 Subject: [PATCH 015/137] Replaced call to func_get_args() in WC_Order_Factory::get_order() with a variable to store the original passed arguments. --- includes/class-wc-order-factory.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/includes/class-wc-order-factory.php b/includes/class-wc-order-factory.php index 9286334b75a..35cca1c0b98 100644 --- a/includes/class-wc-order-factory.php +++ b/includes/class-wc-order-factory.php @@ -22,6 +22,7 @@ class WC_Order_Factory { * @return WC_Order|bool */ public static function get_order( $order_id = false ) { + $passed_args = $order_id; $order_id = self::get_order_id( $order_id ); if ( ! $order_id ) { @@ -46,7 +47,7 @@ class WC_Order_Factory { try { return new $classname( $order_id ); } catch ( Exception $e ) { - wc_caught_exception( $e, __FUNCTION__, func_get_args() ); + wc_caught_exception( $e, __FUNCTION__, $passed_args ); return false; } } From 8ed29fad7fda45d446d76348ed47ec10db793744 Mon Sep 17 00:00:00 2001 From: Akshaya Rane Date: Mon, 21 Oct 2019 22:45:05 +0530 Subject: [PATCH 016/137] refs #24638 Fixed Stock status update on Bulk Edit --- includes/admin/class-wc-admin-post-types.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/includes/admin/class-wc-admin-post-types.php b/includes/admin/class-wc-admin-post-types.php index 3970426cace..041c99099c8 100644 --- a/includes/admin/class-wc-admin-post-types.php +++ b/includes/admin/class-wc-admin-post-types.php @@ -643,6 +643,12 @@ class WC_Admin_Post_Types { break; } } + else + { + //Reset values if Manage Stock status is disabled + $product->set_stock_quantity(''); + $product->set_manage_stock('no'); + } // Apply product type constraints to stock status. if ( $product->is_type( 'external' ) ) { From b8cdeb21649b6062595f79b04234452f5e80a16b Mon Sep 17 00:00:00 2001 From: Akshaya Rane Date: Tue, 22 Oct 2019 00:21:44 +0530 Subject: [PATCH 017/137] Fixed standards error --- includes/admin/class-wc-admin-post-types.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/includes/admin/class-wc-admin-post-types.php b/includes/admin/class-wc-admin-post-types.php index 041c99099c8..634494f4205 100644 --- a/includes/admin/class-wc-admin-post-types.php +++ b/includes/admin/class-wc-admin-post-types.php @@ -642,12 +642,10 @@ class WC_Admin_Post_Types { wc_update_product_stock( $product, $stock_amount, 'set', true ); break; } - } - else - { - //Reset values if Manage Stock status is disabled - $product->set_stock_quantity(''); - $product->set_manage_stock('no'); + } else { + // Reset values if Manage Stock status is disabled. + $product->set_stock_quantity( '' ); + $product->set_manage_stock( 'no' ); } // Apply product type constraints to stock status. From 19e3131d5e70eeaa3cf56ace773d497e0acef79c Mon Sep 17 00:00:00 2001 From: Akshaya Rane Date: Tue, 22 Oct 2019 10:56:08 +0530 Subject: [PATCH 018/137] Modified comment message --- includes/admin/class-wc-admin-post-types.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/class-wc-admin-post-types.php b/includes/admin/class-wc-admin-post-types.php index 634494f4205..99d3c6b6ccd 100644 --- a/includes/admin/class-wc-admin-post-types.php +++ b/includes/admin/class-wc-admin-post-types.php @@ -643,7 +643,7 @@ class WC_Admin_Post_Types { break; } } else { - // Reset values if Manage Stock status is disabled. + // Reset values if WooCommerce Setting - Manage Stock status is disabled. $product->set_stock_quantity( '' ); $product->set_manage_stock( 'no' ); } From 0fb01e6886a6ff6fcbe288b5bfdaa741850122de Mon Sep 17 00:00:00 2001 From: Dhaval Shah <30974879+dhavalgshah@users.noreply.github.com> Date: Sun, 27 Oct 2019 23:06:41 +0530 Subject: [PATCH 019/137] Rework confusing shipping message on cart page when calculator is disabled and no methods are available. (#24807) * Check if shipping calculator is enabled before showing related message in cart totals. Fixes #24674 * Check if on cart then is shipping calculator is enabled before showing related message. Fixes #24674 * Update no shipping available on cart message Fix #24674 --- templates/cart/cart-shipping.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/templates/cart/cart-shipping.php b/templates/cart/cart-shipping.php index 7e4efb7d1fe..b0c66a5d8e6 100644 --- a/templates/cart/cart-shipping.php +++ b/templates/cart/cart-shipping.php @@ -58,7 +58,11 @@ $calculator_text = ''; Date: Sun, 27 Oct 2019 14:38:47 -0300 Subject: [PATCH 020/137] Introduced woocommerce_shipping_not_enabled_on_cart_html filter --- templates/cart/cart-shipping.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/cart/cart-shipping.php b/templates/cart/cart-shipping.php index b0c66a5d8e6..1bad8799f88 100644 --- a/templates/cart/cart-shipping.php +++ b/templates/cart/cart-shipping.php @@ -59,7 +59,7 @@ $calculator_text = ''; Date: Sun, 27 Oct 2019 16:56:42 -0400 Subject: [PATCH 021/137] add password hover visibility on password inputs with javascript --- assets/css/woocommerce-layout.scss | 21 +++++++++++++++++++++ assets/js/frontend/woocommerce.js | 13 +++++++++++++ 2 files changed, 34 insertions(+) diff --git a/assets/css/woocommerce-layout.scss b/assets/css/woocommerce-layout.scss index 57332eede05..a44743938fc 100644 --- a/assets/css/woocommerce-layout.scss +++ b/assets/css/woocommerce-layout.scss @@ -352,6 +352,27 @@ .form-row-wide { clear: both; } + + .password-input { + display: flex; + flex-direction: column; + justify-content: center; + position: relative; + } + + .show-password-input { + position: absolute; + right: 0.7em; + top: 0.7em; + } + + .show-password-input::after { + @include iconafter( "\e010" ); // Icon styles and glyph + } + + .show-password-input:hover::after { + color: #e8e8e8; + } } #payment { diff --git a/assets/js/frontend/woocommerce.js b/assets/js/frontend/woocommerce.js index c05641f8642..a672d1a03af 100644 --- a/assets/js/frontend/woocommerce.js +++ b/assets/js/frontend/woocommerce.js @@ -78,4 +78,17 @@ jQuery( function( $ ) { }, 1000 ); } }; + + // Show password visiblity hover icon on woocommerce forms + $( '.woocommerce form input[type="password"]' ).wrap( '' ); + $( '.password-input' ).append( '' ); + + $( '.show-password-input' ).hover( + function() { + $( this ).siblings( array( 'input[name="password"]', 'input[type="password"]' ) ).prop( 'type', 'text' ); + }, + function() { + $( this ).siblings( array( 'input[name="password"]', 'input[type="password"]' ) ).prop( 'type', 'password' ); + } + ); }); From 925bad1faf943e04b03bd8e5279aba3f9fe353b2 Mon Sep 17 00:00:00 2001 From: BrandynL Date: Mon, 28 Oct 2019 09:35:39 -0400 Subject: [PATCH 022/137] convert array instance to shorthand syntax --- assets/js/frontend/woocommerce.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/frontend/woocommerce.js b/assets/js/frontend/woocommerce.js index a672d1a03af..84ec43b80ad 100644 --- a/assets/js/frontend/woocommerce.js +++ b/assets/js/frontend/woocommerce.js @@ -85,10 +85,10 @@ jQuery( function( $ ) { $( '.show-password-input' ).hover( function() { - $( this ).siblings( array( 'input[name="password"]', 'input[type="password"]' ) ).prop( 'type', 'text' ); + $( this ).siblings( ['input[name="password"]', 'input[type="password"]'] ).prop( 'type', 'text' ); }, function() { - $( this ).siblings( array( 'input[name="password"]', 'input[type="password"]' ) ).prop( 'type', 'password' ); + $( this ).siblings( ['input[name="password"]', 'input[type="password"]'] ).prop( 'type', 'password' ); } ); }); From 3ed614389fd8288f44e76c5ed650acc18defc7c5 Mon Sep 17 00:00:00 2001 From: BrandynL Date: Mon, 28 Oct 2019 09:56:20 -0400 Subject: [PATCH 023/137] change event to click for better mobile device support --- assets/css/woocommerce-layout.scss | 3 ++- assets/js/frontend/woocommerce.js | 12 +++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/assets/css/woocommerce-layout.scss b/assets/css/woocommerce-layout.scss index a44743938fc..2682e99d8f2 100644 --- a/assets/css/woocommerce-layout.scss +++ b/assets/css/woocommerce-layout.scss @@ -364,13 +364,14 @@ position: absolute; right: 0.7em; top: 0.7em; + cursor: pointer; } .show-password-input::after { @include iconafter( "\e010" ); // Icon styles and glyph } - .show-password-input:hover::after { + .show-password-input.display-password:after { color: #e8e8e8; } } diff --git a/assets/js/frontend/woocommerce.js b/assets/js/frontend/woocommerce.js index 84ec43b80ad..5891153545f 100644 --- a/assets/js/frontend/woocommerce.js +++ b/assets/js/frontend/woocommerce.js @@ -83,12 +83,14 @@ jQuery( function( $ ) { $( '.woocommerce form input[type="password"]' ).wrap( '' ); $( '.password-input' ).append( '' ); - $( '.show-password-input' ).hover( + $( '.show-password-input' ).click( function() { - $( this ).siblings( ['input[name="password"]', 'input[type="password"]'] ).prop( 'type', 'text' ); - }, - function() { - $( this ).siblings( ['input[name="password"]', 'input[type="password"]'] ).prop( 'type', 'password' ); + $( this ).toggleClass( 'display-password' ); + if ( $( this ).hasClass('display-password') ) { + $( this ).siblings( ['input[name="password"]', 'input[type="password"]'] ).prop('type', 'text'); + } else { + $( this ).siblings( 'input[name="password"]' ).prop('type', 'password'); + } } ); }); From 40faecc8e747b77ee82fe778ceeaa9de737607c1 Mon Sep 17 00:00:00 2001 From: Gerhard Date: Wed, 30 Oct 2019 15:17:31 +0200 Subject: [PATCH 024/137] Add show_invalid_variations_notice filter to hide the invalid variations notice. --- includes/admin/wc-admin-functions.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/includes/admin/wc-admin-functions.php b/includes/admin/wc-admin-functions.php index f802fc97f66..80169dda230 100644 --- a/includes/admin/wc-admin-functions.php +++ b/includes/admin/wc-admin-functions.php @@ -429,6 +429,11 @@ function wc_render_action_buttons( $actions ) { function wc_render_invalid_variation_notice( $product_object ) { global $wpdb; + // Give ability for extensions to hide this notice. + if ( ! apply_filters( 'show_invalid_variations_notice', true ) ) { + return; + } + $variation_ids = $product_object ? $product_object->get_children() : array(); if ( empty( $variation_ids ) ) { From 0cda53580f81c089f5f1fdfc000d1c9ee17ba69c Mon Sep 17 00:00:00 2001 From: Gerhard Date: Wed, 30 Oct 2019 15:37:04 +0200 Subject: [PATCH 025/137] Do not run send_frame_options_header when on the customizer --- includes/wc-template-functions.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/includes/wc-template-functions.php b/includes/wc-template-functions.php index 7d857c43fbd..00695aa7a03 100644 --- a/includes/wc-template-functions.php +++ b/includes/wc-template-functions.php @@ -80,7 +80,8 @@ add_action( 'template_redirect', 'wc_template_redirect' ); * @since 2.3.10 */ function wc_send_frame_options_header() { - if ( is_checkout() || is_account_page() ) { + + if ( ( is_checkout() || is_account_page() ) && ! is_customize_preview() ) { send_frame_options_header(); } } From 2340f269cf5067ca2bae577c0a450a20f5583961 Mon Sep 17 00:00:00 2001 From: Ian Jenkins Date: Wed, 30 Oct 2019 15:08:19 +0000 Subject: [PATCH 026/137] Add support for custom attributes to wc_placeholder_img(). When displaying a list of images you often want a specific class to be attached to each image, therefore you pass through a custom class using the attr parameter. Unfortunately this doesn't get passed through to a placeholder image should one be needed. This means that, for example, if you're custom class center an image or something, it won't be honoured for placeholders, which can lead to some wonky image listings. You can work around this currently by leverging the `woocommerce_product_get_image` filter, but it's a bit gnarly as you need to do some regexing or string splitting or something and checking class names and what not. This provides a much easier way, by supporting custom attrs on placeholder images as is the case for non placehodler images. --- includes/abstracts/abstract-wc-product.php | 2 +- includes/wc-product-functions.php | 25 ++++++++++++++++------ tests/unit-tests/product/data.php | 4 ++++ tests/unit-tests/product/functions.php | 4 ++++ 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/includes/abstracts/abstract-wc-product.php b/includes/abstracts/abstract-wc-product.php index 50437cb570e..504fc66d466 100644 --- a/includes/abstracts/abstract-wc-product.php +++ b/includes/abstracts/abstract-wc-product.php @@ -1859,7 +1859,7 @@ class WC_Product extends WC_Abstract_Legacy_Product { } if ( ! $image && $placeholder ) { - $image = wc_placeholder_img( $size ); + $image = wc_placeholder_img( $size, $attr ); } return apply_filters( 'woocommerce_product_get_image', $image, $this, $size, $attr, $placeholder, $image ); diff --git a/includes/wc-product-functions.php b/includes/wc-product-functions.php index 975ee6d9d57..3473da82697 100644 --- a/includes/wc-product-functions.php +++ b/includes/wc-product-functions.php @@ -288,26 +288,37 @@ function wc_placeholder_img_src( $size = 'woocommerce_thumbnail' ) { * * Uses wp_get_attachment_image if using an attachment ID @since 3.6.0 to handle responsiveness. * - * @param string $size Image size. + * @param string $size Image size. + * @param string|array $attr Optional. Attributes for the image markup. Default empty. * @return string */ -function wc_placeholder_img( $size = 'woocommerce_thumbnail' ) { +function wc_placeholder_img( $size = 'woocommerce_thumbnail', $attr = '' ) { $dimensions = wc_get_image_size( $size ); $placeholder_image = get_option( 'woocommerce_placeholder_image', 0 ); + $default_attr = array( + 'class' => 'woocommerce-placeholder wp-post-image', + 'alt' => __( 'Placeholder', 'woocommerce' ), + ); + + $attr = wp_parse_args( $attr, $default_attr ); + if ( wp_attachment_is_image( $placeholder_image ) ) { $image_html = wp_get_attachment_image( $placeholder_image, $size, false, - array( - 'alt' => __( 'Placeholder', 'woocommerce' ), - 'class' => 'woocommerce-placeholder wp-post-image', - ) + $attr ); } else { $image = wc_placeholder_img_src( $size ); - $image_html = '' . esc_attr__( 'Placeholder', 'woocommerce' ) . ''; + $hwstring = image_hwstring( $dimensions['width'], $dimensions['height'] ); + $attr = array_map( 'esc_attr', $attr ); + $image_html = rtrim( ' $value ) { + $image_html .= " $name=" . '"' . $value . '"'; + } + $image_html .= ' />'; } return apply_filters( 'woocommerce_placeholder_img', $image_html, $size, $dimensions ); diff --git a/tests/unit-tests/product/data.php b/tests/unit-tests/product/data.php index 86544dfe7b9..54c907e484b 100644 --- a/tests/unit-tests/product/data.php +++ b/tests/unit-tests/product/data.php @@ -324,6 +324,10 @@ class WC_Tests_Product_Data extends WC_Unit_Test_Case { $product = new WC_Product(); $this->assertContains( wc_placeholder_img_src(), $product->get_image() ); + + // Test custom class attribute is honoured. + $image = $product->get_image( 'woocommerce_thumbnail', array( 'class' => 'custom-class' ) ); + $this->assertContains( 'class="custom-class"', $image ); } /** diff --git a/tests/unit-tests/product/functions.php b/tests/unit-tests/product/functions.php index 01ea4e0b40e..14b9ec2ddca 100644 --- a/tests/unit-tests/product/functions.php +++ b/tests/unit-tests/product/functions.php @@ -885,6 +885,10 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case { */ public function test_wc_placeholder_img() { $this->assertTrue( (bool) strstr( wc_placeholder_img(), wc_placeholder_img_src() ) ); + + // Test custom class attribute is honoured. + $attr = array( 'class' => 'custom-class' ); + $this->assertContains( 'class="custom-class"', wc_placeholder_img( 'woocommerce_thumbnail', $attr ) ); } /** From d53b73b56cdb1803454bc18c7786372d8dbab7ef Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Thu, 7 Nov 2019 17:22:33 -0300 Subject: [PATCH 027/137] Added support for "pay button" feature --- .../abstracts/abstract-wc-payment-gateway.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/includes/abstracts/abstract-wc-payment-gateway.php b/includes/abstracts/abstract-wc-payment-gateway.php index 8e816d23e9b..7070ff435e3 100644 --- a/includes/abstracts/abstract-wc-payment-gateway.php +++ b/includes/abstracts/abstract-wc-payment-gateway.php @@ -131,6 +131,13 @@ abstract class WC_Payment_Gateway extends WC_Settings_API { */ public $new_method_label = ''; + /** + * Pay button ID if supported. + * + * @var string + */ + public $pay_button_id = ''; + /** * Contains a users saved tokens for this gateway. * @@ -317,6 +324,16 @@ abstract class WC_Payment_Gateway extends WC_Settings_API { return apply_filters( 'woocommerce_gateway_icon', $icon, $this->id ); } + /** + * Return the gateway's pay button ID. + * + * @since 3.9.0 + * @return string + */ + public function get_pay_button_id() { + return sanitize_html_class( $this->pay_button_id ); + } + /** * Set as current gateway. * From ced207633ca61eaa108a5988e9063da77302cbd3 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Thu, 7 Nov 2019 17:23:19 -0300 Subject: [PATCH 028/137] Added unit tests for pay button support --- .../framework/class-wc-mock-payment-gateway.php | 17 +++++++++++++++++ tests/unit-tests/gateways/gateways.php | 15 +++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/tests/framework/class-wc-mock-payment-gateway.php b/tests/framework/class-wc-mock-payment-gateway.php index ed11be78a67..478e16edb18 100644 --- a/tests/framework/class-wc-mock-payment-gateway.php +++ b/tests/framework/class-wc-mock-payment-gateway.php @@ -4,18 +4,35 @@ class WC_Mock_Payment_Gateway extends WC_Payment_Gateway { * Constructor for the gateway. */ public function __construct() { + $this->enabled = 'yes'; $this->id = 'mock'; $this->has_fields = false; $this->order_button_text = __( 'Proceed to PayPal', 'woocommerce' ); $this->method_title = 'Mock Gateway'; $this->method_description = 'Mock Gateway for unit tests'; + $this->pay_button_id = 'mock-pay-button'; $this->supports = array( 'products', + 'pay_button', ); // Load the settings. $this->init_form_fields(); $this->init_settings(); } + + /** + * Initialise Gateway Settings Form Fields. + */ + public function init_form_fields() { + $this->form_fields = array( + 'enabled' => array( + 'title' => '', + 'type' => 'checkbox', + 'label' => '', + 'default' => 'yes', + ), + ); + } } diff --git a/tests/unit-tests/gateways/gateways.php b/tests/unit-tests/gateways/gateways.php index f7ee8b0de8c..142d8257036 100644 --- a/tests/unit-tests/gateways/gateways.php +++ b/tests/unit-tests/gateways/gateways.php @@ -64,5 +64,20 @@ class WC_Tests_Gateways extends WC_Unit_Test_Case { $order->save(); $this->assertFalse( $gateway->can_refund_order( $order ) ); } + + /** + * Test WC_Payment_Gateway::get_pay_button_id(); + * + * @return void + */ + public function test_get_pay_button_id() { + $gateway = new WC_Mock_Payment_Gateway(); + + $this->assertEquals( $gateway->pay_button_id, $gateway->get_pay_button_id() ); + + $gateway->pay_button_id = 'new-pay-button'; + + $this->assertEquals( $gateway->pay_button_id, $gateway->get_pay_button_id() ); + } } From fdd391e10ece5ec4afbb1bbbd611c606313cc4f0 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Thu, 7 Nov 2019 17:23:38 -0300 Subject: [PATCH 029/137] Introduced wc_get_pay_buttons() function --- includes/wc-template-functions.php | 26 +++++++++++++++++ includes/wc-template-hooks.php | 7 +++++ tests/unit-tests/templates/functions.php | 36 ++++++++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/includes/wc-template-functions.php b/includes/wc-template-functions.php index 7d857c43fbd..a10313a807e 100644 --- a/includes/wc-template-functions.php +++ b/includes/wc-template-functions.php @@ -3664,3 +3664,29 @@ if ( ! function_exists( 'woocommerce_product_reviews_tab' ) ) { wc_deprecated_function( 'woocommerce_product_reviews_tab', '2.4' ); } } + +/** + * Display pay buttons HTML. + * + * @since 3.9.0 + */ +function wc_get_pay_buttons() { + $supported_gateways = array(); + $available_gateways = WC()->payment_gateways()->get_available_payment_gateways(); + + foreach ( $available_gateways as $gateway ) { + if ( $gateway->supports( 'pay_button' ) ) { + $supported_gateways[] = $gateway->get_pay_button_id(); + } + } + + if ( ! $supported_gateways ) { + return; + } + + echo '
'; + foreach ( $supported_gateways as $pay_button_id ) { + echo sprintf( '
', esc_attr( $pay_button_id ) ); + } + echo '
'; +} diff --git a/includes/wc-template-hooks.php b/includes/wc-template-hooks.php index cd7f3bce62b..f45ea6a2d49 100644 --- a/includes/wc-template-hooks.php +++ b/includes/wc-template-hooks.php @@ -207,6 +207,9 @@ add_action( 'woocommerce_product_additional_information', 'wc_display_product_at * @see woocommerce_checkout_coupon_form() * @see woocommerce_order_review() * @see woocommerce_checkout_payment() + * @see wc_checkout_privacy_policy_text() + * @see wc_terms_and_conditions_page_content() + * @see wc_get_pay_buttons() */ add_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_login_form', 10 ); add_action( 'woocommerce_before_checkout_form', 'woocommerce_checkout_coupon_form', 10 ); @@ -214,6 +217,7 @@ add_action( 'woocommerce_checkout_order_review', 'woocommerce_order_review', 10 add_action( 'woocommerce_checkout_order_review', 'woocommerce_checkout_payment', 20 ); add_action( 'woocommerce_checkout_terms_and_conditions', 'wc_checkout_privacy_policy_text', 20 ); add_action( 'woocommerce_checkout_terms_and_conditions', 'wc_terms_and_conditions_page_content', 30 ); +add_action( 'woocommerce_checkout_before_customer_details', 'wc_get_pay_buttons', 30 ); /** * Cart widget @@ -227,10 +231,13 @@ add_action( 'woocommerce_widget_shopping_cart_total', 'woocommerce_widget_shoppi * * @see woocommerce_cross_sell_display() * @see woocommerce_cart_totals() + * @see wc_get_pay_buttons() * @see woocommerce_button_proceed_to_checkout() + * @see wc_empty_cart_message() */ add_action( 'woocommerce_cart_collaterals', 'woocommerce_cross_sell_display' ); add_action( 'woocommerce_cart_collaterals', 'woocommerce_cart_totals', 10 ); +add_action( 'woocommerce_proceed_to_checkout', 'wc_get_pay_buttons', 10 ); add_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 ); add_action( 'woocommerce_cart_is_empty', 'wc_empty_cart_message', 10 ); diff --git a/tests/unit-tests/templates/functions.php b/tests/unit-tests/templates/functions.php index cf0a1c0ea16..5b1bbb49001 100644 --- a/tests/unit-tests/templates/functions.php +++ b/tests/unit-tests/templates/functions.php @@ -142,4 +142,40 @@ class WC_Tests_Template_Functions extends WC_Unit_Test_Case { $expected_html = ''; $this->assertEquals( $expected_html, $actual_html ); } + + /** + * Test test_wc_get_pay_buttons(). + */ + public function test_wc_get_pay_buttons() { + // Test default. + ob_start(); + wc_get_pay_buttons(); + $actual_html = ob_get_clean(); + + $this->assertEquals( '', $actual_html ); + + // Include a payment gateway that supports "pay button". + add_filter( + 'woocommerce_payment_gateways', + function( $gateways ) { + $gateways[] = 'WC_Mock_Payment_Gateway'; + + return $gateways; + } + ); + WC()->payment_gateways()->init(); + + // Test pay buttons HTML. + ob_start(); + wc_get_pay_buttons(); + $actual_html = ob_get_clean(); + + $gateway = new WC_Mock_Payment_Gateway(); + $expected_html = sprintf( + '
', + $gateway->get_pay_button_id() + ); + + $this->assertEquals( $expected_html, $actual_html ); + } } From 7024fc8483a2a0de0115e090ba83f08415d08e75 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Thu, 7 Nov 2019 20:23:30 -0300 Subject: [PATCH 030/137] Change notices to accept extra data --- includes/wc-notice-functions.php | 74 +++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/includes/wc-notice-functions.php b/includes/wc-notice-functions.php index db293034281..bef5038f9c6 100644 --- a/includes/wc-notice-functions.php +++ b/includes/wc-notice-functions.php @@ -59,17 +59,18 @@ function wc_has_notice( $message, $notice_type = 'success' ) { $notices = WC()->session->get( 'wc_notices', array() ); $notices = isset( $notices[ $notice_type ] ) ? $notices[ $notice_type ] : array(); - return array_search( $message, $notices, true ) !== false; + return array_search( $message, wp_list_pluck( $notices, 'notice' ), true ) !== false; } /** * Add and store a notice. * * @since 2.1 - * @param string $message The text to display in the notice. + * @param string $message The text to display in the notice. * @param string $notice_type Optional. The name of the notice type - either error, success or notice. + * @param array $data Optional notice data. */ -function wc_add_notice( $message, $notice_type = 'success' ) { +function wc_add_notice( $message, $notice_type = 'success', $data = array() ) { if ( ! did_action( 'woocommerce_init' ) ) { wc_doing_it_wrong( __FUNCTION__, __( 'This function should not be called before woocommerce_init.', 'woocommerce' ), '2.3' ); return; @@ -82,7 +83,10 @@ function wc_add_notice( $message, $notice_type = 'success' ) { $message = apply_filters( 'woocommerce_add_message', $message ); } - $notices[ $notice_type ][] = apply_filters( 'woocommerce_add_' . $notice_type, $message ); + $notices[ $notice_type ][] = array( + 'notice' => apply_filters( 'woocommerce_add_' . $notice_type, $message ), + 'data' => $data, + ); WC()->session->set( 'wc_notices', $notices ); } @@ -91,17 +95,17 @@ function wc_add_notice( $message, $notice_type = 'success' ) { * Set all notices at once. * * @since 2.6.0 - * @param mixed $notices Array of notices. + * @param array[] $notices Array of notices. */ function wc_set_notices( $notices ) { if ( ! did_action( 'woocommerce_init' ) ) { wc_doing_it_wrong( __FUNCTION__, __( 'This function should not be called before woocommerce_init.', 'woocommerce' ), '2.6' ); return; } + WC()->session->set( 'wc_notices', $notices ); } - /** * Unset all notices. * @@ -136,9 +140,19 @@ function wc_print_notices( $return = false ) { foreach ( $notice_types as $notice_type ) { if ( wc_notice_count( $notice_type ) > 0 ) { - wc_get_template( "notices/{$notice_type}.php", array( - 'messages' => array_filter( $all_notices[ $notice_type ] ), - ) ); + $messages = array(); + + foreach ( $all_notices[ $notice_type ] as $notice ) { + $messages[] = isset( $notice['notice'] ) ? $notice['notice'] : $notice; + } + + wc_get_template( + "notices/{$notice_type}.php", + array( + 'messages' => array_filter( $messages ), // @deprecated 3.9.0 + 'notices' => array_filter( $all_notices[ $notice_type ] ), + ) + ); } } @@ -150,7 +164,7 @@ function wc_print_notices( $return = false ) { return $notices; } - echo $notices; // WPCS: XSS ok. + echo $notices; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** @@ -159,15 +173,27 @@ function wc_print_notices( $return = false ) { * @since 2.1 * @param string $message The text to display in the notice. * @param string $notice_type Optional. The singular name of the notice type - either error, success or notice. + * @param array $data Optional notice data. @since 3.9.0. */ -function wc_print_notice( $message, $notice_type = 'success' ) { +function wc_print_notice( $message, $notice_type = 'success', $data = array() ) { if ( 'success' === $notice_type ) { $message = apply_filters( 'woocommerce_add_message', $message ); } - wc_get_template( "notices/{$notice_type}.php", array( - 'messages' => array( apply_filters( 'woocommerce_add_' . $notice_type, $message ) ), - ) ); + $message = apply_filters( 'woocommerce_add_' . $notice_type, $message ); + + wc_get_template( + "notices/{$notice_type}.php", + array( + 'messages' => array( $message ), // @deprecated 3.9.0 + 'notices' => array( + array( + 'notice' => $message, + 'data' => $data, + ), + ), + ) + ); } /** @@ -175,7 +201,7 @@ function wc_print_notice( $message, $notice_type = 'success' ) { * * @since 2.1 * @param string $notice_type Optional. The singular name of the notice type - either error, success or notice. - * @return array|mixed + * @return array[] */ function wc_get_notices( $notice_type = '' ) { if ( ! did_action( 'woocommerce_init' ) ) { @@ -217,7 +243,8 @@ function wc_add_wp_error_notices( $errors ) { * @return string */ function wc_kses_notice( $message ) { - return wp_kses( $message, + return wp_kses( + $message, array_replace_recursive( // phpcs:ignore PHPCompatibility.PHP.NewFunctions.array_replace_recursiveFound wp_kses_allowed_html( 'post' ), array( @@ -228,3 +255,18 @@ function wc_kses_notice( $message ) { ) ); } + +/** + * Get notice data attribute. + * + * @since 3.9.0 + * @param array $notice Notice data. + * @return string + */ +function wc_get_notice_data_attr( $notice ) { + if ( ! isset( $notice['data']['id'] ) ) { + return; + } + + return sprintf( ' data-element-id="%s"', esc_attr( $notice['data']['id'] ) ); +} From 08b761df4f7750c64ef562b1b68fcb648892a896 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Thu, 7 Nov 2019 20:24:37 -0300 Subject: [PATCH 031/137] Updated templates to handle new notices. --- templates/notices/error.php | 16 +++++++--------- templates/notices/notice.php | 16 +++++++--------- templates/notices/success.php | 16 +++++++--------- 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/templates/notices/error.php b/templates/notices/error.php index 2fdff091f6d..8bbeeb7adf3 100644 --- a/templates/notices/error.php +++ b/templates/notices/error.php @@ -10,26 +10,24 @@ * happen. When this occurs the version of the template file will be bumped and * the readme will list any important changes. * - * @see https://docs.woocommerce.com/document/template-structure/ - * @package WooCommerce/Templates - * @version 3.5.0 + * @see https://docs.woocommerce.com/document/template-structure/ + * @package WooCommerce/Templates + * @version 3.9.0 */ if ( ! defined( 'ABSPATH' ) ) { exit; } -if ( ! $messages ) { +if ( ! $notices ) { return; } ?> diff --git a/templates/notices/notice.php b/templates/notices/notice.php index 5272526b214..b300f8d10a9 100644 --- a/templates/notices/notice.php +++ b/templates/notices/notice.php @@ -10,25 +10,23 @@ * happen. When this occurs the version of the template file will be bumped and * the readme will list any important changes. * - * @see https://docs.woocommerce.com/document/template-structure/ - * @package WooCommerce/Templates - * @version 3.5.0 + * @see https://docs.woocommerce.com/document/template-structure/ + * @package WooCommerce/Templates + * @version 3.9.0 */ if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } -if ( ! $messages ) { +if ( ! $notices ) { return; } ?> - -
- + +
> +
diff --git a/templates/notices/success.php b/templates/notices/success.php index 146d61a583d..17b5fc19af5 100644 --- a/templates/notices/success.php +++ b/templates/notices/success.php @@ -10,25 +10,23 @@ * happen. When this occurs the version of the template file will be bumped and * the readme will list any important changes. * - * @see https://docs.woocommerce.com/document/template-structure/ - * @package WooCommerce/Templates - * @version 3.5.0 + * @see https://docs.woocommerce.com/document/template-structure/ + * @package WooCommerce/Templates + * @version 3.9.0 */ if ( ! defined( 'ABSPATH' ) ) { exit; } -if ( ! $messages ) { +if ( ! $notices ) { return; } ?> - -