From cd443581cfbad571787af10ab0f4a6bdb6a7a25f Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Wed, 4 Nov 2020 12:39:45 +0100 Subject: [PATCH 001/368] Fix code sniffer errors --- includes/customizer/class-wc-shop-customizer.php | 2 +- includes/theme-support/class-wc-twenty-nineteen.php | 2 +- includes/wc-core-functions.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/customizer/class-wc-shop-customizer.php b/includes/customizer/class-wc-shop-customizer.php index dd966b8de39..90af6a94c0b 100644 --- a/includes/customizer/class-wc-shop-customizer.php +++ b/includes/customizer/class-wc-shop-customizer.php @@ -769,7 +769,7 @@ class WC_Shop_Customizer { ); } else { $choose_pages = array( - 'woocommerce_terms_page_id' => __( 'Terms and conditions', 'woocommerce' ), + 'woocommerce_terms_page_id' => __( 'Terms and conditions', 'woocommerce' ), ); } $pages = get_pages( diff --git a/includes/theme-support/class-wc-twenty-nineteen.php b/includes/theme-support/class-wc-twenty-nineteen.php index 47c1aff660c..9d1f44cc64c 100644 --- a/includes/theme-support/class-wc-twenty-nineteen.php +++ b/includes/theme-support/class-wc-twenty-nineteen.php @@ -48,7 +48,7 @@ class WC_Twenty_Nineteen { // Tweak Twenty Nineteen features. add_action( 'wp', array( __CLASS__, 'tweak_theme_features' ) ); - // Color scheme CSS + // Color scheme CSS. add_filter( 'twentynineteen_custom_colors_css', array( __CLASS__, 'custom_colors_css' ), 10, 3 ); } diff --git a/includes/wc-core-functions.php b/includes/wc-core-functions.php index 097770fede8..34b225af008 100644 --- a/includes/wc-core-functions.php +++ b/includes/wc-core-functions.php @@ -390,7 +390,7 @@ function wc_locate_template( $template_name, $template_path = '', $default_path // Look within passed path within the theme - this is priority. if ( false !== strpos( $template_name, 'product_cat' ) || false !== strpos( $template_name, 'product_tag' ) ) { $cs_template = str_replace( '_', '-', $template_name ); - $template = locate_template( + $template = locate_template( array( trailingslashit( $template_path ) . $cs_template, $cs_template, From d620f1d2321785f52926e067df348cb52f547c75 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Wed, 4 Nov 2020 12:56:42 +0100 Subject: [PATCH 002/368] Fix #25900 - image size customisation controls not shown - Added the `ThemeSupport class`, with methods to add and get theme support options. - It also has a new `add_default_options` method that adds the options under a `_defaults` key. - The `WC_Twenty_*` classes now use `ThemeSupport` instead of the `add_theme_support` function to define image and thumbnail sizes. - The values are defined as default options. - The `WC_Shop_Customizer` class now uses `ThemeSupport` instead of `wc_get_theme_support` to check if image and thumbnail sizes UI should be rendered. - The check is made excluding default values. With these changes the UI to change the image and thumbnail sizes is hidden only if the options are added as non-defaults elsewhere. Additional changes: - The code of the `wc_get_theme_support` function is replaced with a simple call to `get_option` in `ThemeSupport`. - Added the utility class `ArrayUtil`. --- .../customizer/class-wc-shop-customizer.php | 19 +- .../theme-support/class-wc-twenty-eleven.php | 5 +- .../theme-support/class-wc-twenty-fifteen.php | 5 +- .../class-wc-twenty-fourteen.php | 5 +- .../class-wc-twenty-nineteen.php | 4 +- .../class-wc-twenty-seventeen.php | 4 +- .../theme-support/class-wc-twenty-sixteen.php | 5 +- .../theme-support/class-wc-twenty-ten.php | 5 +- .../class-wc-twenty-thirteen.php | 5 +- .../theme-support/class-wc-twenty-twelve.php | 5 +- .../theme-support/class-wc-twenty-twenty.php | 4 +- includes/wc-core-functions.php | 34 +-- src/Container.php | 4 +- .../ThemeManagementServiceProvider.php | 31 +++ src/ThemeManagement/ThemeSupport.php | 118 ++++++++ src/Utilities/ArrayUtil.php | 48 ++++ tests/legacy/bootstrap.php | 9 +- .../class-wc-shop-customizer-test.php | 59 ++++ .../php/src/ThemeSupport/ThemeSupportTest.php | 254 ++++++++++++++++++ tests/php/src/Utilities/ArrayUtilTest.php | 66 +++++ 20 files changed, 631 insertions(+), 58 deletions(-) create mode 100644 src/Internal/DependencyManagement/ServiceProviders/ThemeManagementServiceProvider.php create mode 100644 src/ThemeManagement/ThemeSupport.php create mode 100644 src/Utilities/ArrayUtil.php create mode 100644 tests/php/includes/customizer/class-wc-shop-customizer-test.php create mode 100644 tests/php/src/ThemeSupport/ThemeSupportTest.php create mode 100644 tests/php/src/Utilities/ArrayUtilTest.php diff --git a/includes/customizer/class-wc-shop-customizer.php b/includes/customizer/class-wc-shop-customizer.php index 90af6a94c0b..1a42c04b10c 100644 --- a/includes/customizer/class-wc-shop-customizer.php +++ b/includes/customizer/class-wc-shop-customizer.php @@ -6,6 +6,8 @@ * @package WooCommerce */ +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; + defined( 'ABSPATH' ) || exit; /** @@ -13,10 +15,19 @@ defined( 'ABSPATH' ) || exit; */ class WC_Shop_Customizer { + /** + * Holds the instance of ThemeSupport to use. + * + * @var ThemeSupport $theme_support The instance of ThemeSupport to use. + */ + private $theme_support; + /** * Constructor. */ public function __construct() { + $this->theme_support = wc_get_container()->get( ThemeSupport::class ); + add_action( 'customize_register', array( $this, 'add_sections' ) ); add_action( 'customize_controls_print_styles', array( $this, 'add_styles' ) ); add_action( 'customize_controls_print_scripts', array( $this, 'add_scripts' ), 30 ); @@ -545,11 +556,11 @@ class WC_Shop_Customizer { ) ); - if ( ! wc_get_theme_support( 'single_image_width' ) ) { + if ( ! $this->theme_support->has_option( 'single_image_width', false ) ) { $wp_customize->add_setting( 'woocommerce_single_image_width', array( - 'default' => 600, + 'default' => $this->theme_support->get_option( 'single_image_width', 600 ), 'type' => 'option', 'capability' => 'manage_woocommerce', 'sanitize_callback' => 'absint', @@ -573,11 +584,11 @@ class WC_Shop_Customizer { ); } - if ( ! wc_get_theme_support( 'thumbnail_image_width' ) ) { + if ( ! $this->theme_support->has_option( 'thumbnail_image_width', false ) ) { $wp_customize->add_setting( 'woocommerce_thumbnail_image_width', array( - 'default' => 300, + 'default' => $this->theme_support->get_option( 'thumbnail_image_width', 300 ), 'type' => 'option', 'capability' => 'manage_woocommerce', 'sanitize_callback' => 'absint', diff --git a/includes/theme-support/class-wc-twenty-eleven.php b/includes/theme-support/class-wc-twenty-eleven.php index fb06a7a84dc..9bb77c9e70e 100644 --- a/includes/theme-support/class-wc-twenty-eleven.php +++ b/includes/theme-support/class-wc-twenty-eleven.php @@ -6,6 +6,8 @@ * @package WooCommerce\Classes */ +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; + defined( 'ABSPATH' ) || exit; /** @@ -29,8 +31,7 @@ class WC_Twenty_Eleven { add_theme_support( 'wc-product-gallery-zoom' ); add_theme_support( 'wc-product-gallery-lightbox' ); add_theme_support( 'wc-product-gallery-slider' ); - add_theme_support( - 'woocommerce', + wc_get_container()->get( ThemeSupport::class )->add_default_options( array( 'thumbnail_image_width' => 150, 'single_image_width' => 300, diff --git a/includes/theme-support/class-wc-twenty-fifteen.php b/includes/theme-support/class-wc-twenty-fifteen.php index 83e1930cf93..828b2ed6d61 100644 --- a/includes/theme-support/class-wc-twenty-fifteen.php +++ b/includes/theme-support/class-wc-twenty-fifteen.php @@ -7,6 +7,8 @@ * @package WooCommerce\Classes */ +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; + defined( 'ABSPATH' ) || exit; /** @@ -30,8 +32,7 @@ class WC_Twenty_Fifteen { add_theme_support( 'wc-product-gallery-zoom' ); add_theme_support( 'wc-product-gallery-lightbox' ); add_theme_support( 'wc-product-gallery-slider' ); - add_theme_support( - 'woocommerce', + wc_get_container()->get( ThemeSupport::class )->add_default_options( array( 'thumbnail_image_width' => 200, 'single_image_width' => 350, diff --git a/includes/theme-support/class-wc-twenty-fourteen.php b/includes/theme-support/class-wc-twenty-fourteen.php index ce04395299d..e068e57c96c 100644 --- a/includes/theme-support/class-wc-twenty-fourteen.php +++ b/includes/theme-support/class-wc-twenty-fourteen.php @@ -7,6 +7,8 @@ * @package WooCommerce\Classes */ +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; + defined( 'ABSPATH' ) || exit; /** @@ -30,8 +32,7 @@ class WC_Twenty_Fourteen { add_theme_support( 'wc-product-gallery-zoom' ); add_theme_support( 'wc-product-gallery-lightbox' ); add_theme_support( 'wc-product-gallery-slider' ); - add_theme_support( - 'woocommerce', + wc_get_container()->get( ThemeSupport::class )->add_default_options( array( 'thumbnail_image_width' => 150, 'single_image_width' => 300, diff --git a/includes/theme-support/class-wc-twenty-nineteen.php b/includes/theme-support/class-wc-twenty-nineteen.php index 9d1f44cc64c..795fa079208 100644 --- a/includes/theme-support/class-wc-twenty-nineteen.php +++ b/includes/theme-support/class-wc-twenty-nineteen.php @@ -7,6 +7,7 @@ */ use Automattic\Jetpack\Constants; +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; defined( 'ABSPATH' ) || exit; @@ -37,8 +38,7 @@ class WC_Twenty_Nineteen { add_theme_support( 'wc-product-gallery-zoom' ); add_theme_support( 'wc-product-gallery-lightbox' ); add_theme_support( 'wc-product-gallery-slider' ); - add_theme_support( - 'woocommerce', + wc_get_container()->get( ThemeSupport::class )->add_default_options( array( 'thumbnail_image_width' => 300, 'single_image_width' => 450, diff --git a/includes/theme-support/class-wc-twenty-seventeen.php b/includes/theme-support/class-wc-twenty-seventeen.php index 2093d2200e7..6fff3aab843 100644 --- a/includes/theme-support/class-wc-twenty-seventeen.php +++ b/includes/theme-support/class-wc-twenty-seventeen.php @@ -7,6 +7,7 @@ */ use Automattic\Jetpack\Constants; +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; defined( 'ABSPATH' ) || exit; @@ -30,8 +31,7 @@ class WC_Twenty_Seventeen { add_theme_support( 'wc-product-gallery-zoom' ); add_theme_support( 'wc-product-gallery-lightbox' ); add_theme_support( 'wc-product-gallery-slider' ); - add_theme_support( - 'woocommerce', + wc_get_container()->get( ThemeSupport::class )->add_default_options( array( 'thumbnail_image_width' => 250, 'single_image_width' => 350, diff --git a/includes/theme-support/class-wc-twenty-sixteen.php b/includes/theme-support/class-wc-twenty-sixteen.php index c9681fa5e98..1dc0b137e7f 100644 --- a/includes/theme-support/class-wc-twenty-sixteen.php +++ b/includes/theme-support/class-wc-twenty-sixteen.php @@ -6,6 +6,8 @@ * @package WooCommerce\Classes */ +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; + defined( 'ABSPATH' ) || exit; /** @@ -29,8 +31,7 @@ class WC_Twenty_Sixteen { add_theme_support( 'wc-product-gallery-zoom' ); add_theme_support( 'wc-product-gallery-lightbox' ); add_theme_support( 'wc-product-gallery-slider' ); - add_theme_support( - 'woocommerce', + wc_get_container()->get( ThemeSupport::class )->add_default_options( array( 'thumbnail_image_width' => 250, 'single_image_width' => 400, diff --git a/includes/theme-support/class-wc-twenty-ten.php b/includes/theme-support/class-wc-twenty-ten.php index 8a9262e6191..67f14aeab94 100644 --- a/includes/theme-support/class-wc-twenty-ten.php +++ b/includes/theme-support/class-wc-twenty-ten.php @@ -6,6 +6,8 @@ * @package WooCommerce\Classes */ +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; + defined( 'ABSPATH' ) || exit; /** @@ -29,8 +31,7 @@ class WC_Twenty_Ten { add_theme_support( 'wc-product-gallery-zoom' ); add_theme_support( 'wc-product-gallery-lightbox' ); add_theme_support( 'wc-product-gallery-slider' ); - add_theme_support( - 'woocommerce', + wc_get_container()->get( ThemeSupport::class )->add_default_options( array( 'thumbnail_image_width' => 200, 'single_image_width' => 300, diff --git a/includes/theme-support/class-wc-twenty-thirteen.php b/includes/theme-support/class-wc-twenty-thirteen.php index 4e80b3e27c6..eac4e70130f 100644 --- a/includes/theme-support/class-wc-twenty-thirteen.php +++ b/includes/theme-support/class-wc-twenty-thirteen.php @@ -7,6 +7,8 @@ * @package WooCommerce\Classes */ +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; + defined( 'ABSPATH' ) || exit; /** @@ -30,8 +32,7 @@ class WC_Twenty_Thirteen { add_theme_support( 'wc-product-gallery-zoom' ); add_theme_support( 'wc-product-gallery-lightbox' ); add_theme_support( 'wc-product-gallery-slider' ); - add_theme_support( - 'woocommerce', + wc_get_container()->get( ThemeSupport::class )->add_default_options( array( 'thumbnail_image_width' => 200, 'single_image_width' => 300, diff --git a/includes/theme-support/class-wc-twenty-twelve.php b/includes/theme-support/class-wc-twenty-twelve.php index 116dabea432..a5e7315c911 100644 --- a/includes/theme-support/class-wc-twenty-twelve.php +++ b/includes/theme-support/class-wc-twenty-twelve.php @@ -7,6 +7,8 @@ * @package WooCommerce\Classes */ +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; + defined( 'ABSPATH' ) || exit; /** @@ -30,8 +32,7 @@ class WC_Twenty_Twelve { add_theme_support( 'wc-product-gallery-zoom' ); add_theme_support( 'wc-product-gallery-lightbox' ); add_theme_support( 'wc-product-gallery-slider' ); - add_theme_support( - 'woocommerce', + wc_get_container()->get( ThemeSupport::class )->add_default_options( array( 'thumbnail_image_width' => 200, 'single_image_width' => 300, diff --git a/includes/theme-support/class-wc-twenty-twenty.php b/includes/theme-support/class-wc-twenty-twenty.php index 47296f639ab..f2327680da0 100644 --- a/includes/theme-support/class-wc-twenty-twenty.php +++ b/includes/theme-support/class-wc-twenty-twenty.php @@ -7,6 +7,7 @@ */ use Automattic\Jetpack\Constants; +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; defined( 'ABSPATH' ) || exit; @@ -37,8 +38,7 @@ class WC_Twenty_Twenty { add_theme_support( 'wc-product-gallery-zoom' ); add_theme_support( 'wc-product-gallery-lightbox' ); add_theme_support( 'wc-product-gallery-slider' ); - add_theme_support( - 'woocommerce', + wc_get_container()->get( ThemeSupport::class )->add_default_options( array( 'thumbnail_image_width' => 450, 'single_image_width' => 600, diff --git a/includes/wc-core-functions.php b/includes/wc-core-functions.php index 34b225af008..604fa4ce103 100644 --- a/includes/wc-core-functions.php +++ b/includes/wc-core-functions.php @@ -9,6 +9,7 @@ */ use Automattic\Jetpack\Constants; +use Automattic\WooCommerce\ThemeManagement\ThemeSupport; use Automattic\WooCommerce\Utilities\NumberUtil; if ( ! defined( 'ABSPATH' ) ) { @@ -879,38 +880,7 @@ function wc_mail( $to, $subject, $message, $headers = "Content-Type: text/html\r * @return mixed Value of prop(s). */ function wc_get_theme_support( $prop = '', $default = null ) { - $theme_support = get_theme_support( 'woocommerce' ); - $theme_support = is_array( $theme_support ) ? $theme_support[0] : false; - - if ( ! $theme_support ) { - return $default; - } - - if ( $prop ) { - $prop_stack = explode( '::', $prop ); - $prop_key = array_shift( $prop_stack ); - - if ( isset( $theme_support[ $prop_key ] ) ) { - $value = $theme_support[ $prop_key ]; - - if ( count( $prop_stack ) ) { - foreach ( $prop_stack as $prop_key ) { - if ( is_array( $value ) && isset( $value[ $prop_key ] ) ) { - $value = $value[ $prop_key ]; - } else { - $value = $default; - break; - } - } - } - } else { - $value = $default; - } - - return $value; - } - - return $theme_support; + return wc_get_container()->get( ThemeSupport::class )->get_option( $prop, $default ); } /** diff --git a/src/Container.php b/src/Container.php index 4291867682b..91986c21a74 100644 --- a/src/Container.php +++ b/src/Container.php @@ -6,12 +6,13 @@ namespace Automattic\WooCommerce; use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\ProxiesServiceProvider; +use Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders\ThemeManagementServiceProvider; use Automattic\WooCommerce\Internal\DependencyManagement\ExtendedContainer; /** * PSR11 compliant dependency injection container for WooCommerce. * - * Classes in the `src` directory should specify dependencies from that directory via constructor arguments + * Classes in the `src` directory should specify dependencies from that directory via an 'init' method having arguments * with type hints. If an instance of the container itself is needed, the type hint to use is \Psr\Container\ContainerInterface. * * Classes in the `src` directory should interact with anything outside (especially code in the `includes` directory @@ -33,6 +34,7 @@ final class Container implements \Psr\Container\ContainerInterface { */ private $service_providers = array( ProxiesServiceProvider::class, + ThemeManagementServiceProvider::class, ); /** diff --git a/src/Internal/DependencyManagement/ServiceProviders/ThemeManagementServiceProvider.php b/src/Internal/DependencyManagement/ServiceProviders/ThemeManagementServiceProvider.php new file mode 100644 index 00000000000..9ae7f90d848 --- /dev/null +++ b/src/Internal/DependencyManagement/ServiceProviders/ThemeManagementServiceProvider.php @@ -0,0 +1,31 @@ +share_with_auto_arguments( ThemeSupport::class ); + } +} diff --git a/src/ThemeManagement/ThemeSupport.php b/src/ThemeManagement/ThemeSupport.php new file mode 100644 index 00000000000..82c6bff089a --- /dev/null +++ b/src/ThemeManagement/ThemeSupport.php @@ -0,0 +1,118 @@ +legacy_proxy = $legacy_proxy; + } + + /** + * Adds theme support options for the current theme. + * + * @param array $options The options to be added. + */ + public function add_options( $options ) { + $this->legacy_proxy->call_function( 'add_theme_support', 'woocommerce', $options ); + } + + /** + * Adds default theme support options for the current theme. + * + * @param array $options The options to be added. + */ + public function add_default_options( $options ) { + $default_options = $this->get_option( self::DEFAULTS_KEY, array() ); + $default_options = array_merge( $default_options, $options ); + $this->add_options( array( self::DEFAULTS_KEY => $default_options ) ); + } + + /** + * Gets "theme support" options from the current theme, if set. + * + * @param string $option_name Option name, possibly nested (key::subkey), to get specific value. Blank to get all the existing options as an array. + * @param mixed $default_value Value to return if the specified option doesn't exist. + * @return mixed The retrieved option or the default value. + */ + public function get_option( $option_name = '', $default_value = null ) { + $theme_support_options = $this->get_all_options(); + + if ( ! $theme_support_options ) { + return $default_value; + } + + if ( $option_name ) { + $value = ArrayUtil::get_nested_value( $theme_support_options, $option_name ); + if ( is_null( $value ) ) { + $value = ArrayUtil::get_nested_value( $theme_support_options, self::DEFAULTS_KEY . '::' . $option_name, $default_value ); + } + return $value; + } + + return $theme_support_options; + } + + /** + * Checks whether a given theme support option has been defined. + * + * @param string $option_name The (possibly nested) name of the option to check. + * @param bool $include_defaults True to include the default values in the check, false otherwise. + * + * @return bool True if the specified theme support option has been defined, false otherwise. + */ + public function has_option( $option_name, $include_defaults = true ) { + $theme_support_options = $this->get_all_options(); + + if ( ! $theme_support_options ) { + return false; + } + + $value = ArrayUtil::get_nested_value( $theme_support_options, $option_name ); + if ( ! is_null( $value ) ) { + return true; + } + + if ( ! $include_defaults ) { + return false; + } + $value = ArrayUtil::get_nested_value( $theme_support_options, self::DEFAULTS_KEY . '::' . $option_name ); + return ! is_null( $value ); + } + + /** + * Get all the defined theme support options for the 'woocommerce' feature. + * + * @return array An array with all the theme support options defined for the 'woocommerce' feature, or false if nothing has been defined for that feature. + */ + private function get_all_options() { + $theme_support = $this->legacy_proxy->call_function( 'get_theme_support', 'woocommerce' ); + return is_array( $theme_support ) ? $theme_support[0] : false; + } +} diff --git a/src/Utilities/ArrayUtil.php b/src/Utilities/ArrayUtil.php new file mode 100644 index 00000000000..b381dbef86a --- /dev/null +++ b/src/Utilities/ArrayUtil.php @@ -0,0 +1,48 @@ + [ 'bar' => [ 'fizz' => 'buzz' ] ] ] the value for key 'foo::bar::fizz' would be 'buzz'. + * + * @param array $array The array to get the value from. + * @param string $key The complete key hierarchy, using '::' as separator. + * @param mixed $default The value to return if the key doesn't exist in the array. + * + * @return mixed The retrieved value, or the supplied default value. + * @throws \Exception $array is not an array. + */ + public static function get_nested_value( array $array, string $key, $default = null ) { + $key_stack = explode( '::', $key ); + $subkey = array_shift( $key_stack ); + + if ( isset( $array[ $subkey ] ) ) { + $value = $array[ $subkey ]; + + if ( count( $key_stack ) ) { + foreach ( $key_stack as $subkey ) { + if ( is_array( $value ) && isset( $value[ $subkey ] ) ) { + $value = $value[ $subkey ]; + } else { + $value = $default; + break; + } + } + } + } else { + $value = $default; + } + + return $value; + } +} + diff --git a/tests/legacy/bootstrap.php b/tests/legacy/bootstrap.php index bfbcd11edeb..62d93d87254 100644 --- a/tests/legacy/bootstrap.php +++ b/tests/legacy/bootstrap.php @@ -103,7 +103,14 @@ class WC_Unit_Tests_Bootstrap { * @throws Exception Error when initializing one of the hacks. */ private function initialize_code_hacker() { - CodeHacker::initialize( array( __DIR__ . '/../../includes/' ) ); + $wp_dir = getenv( 'WP_TESTS_WP_DIR' ) ? getenv( 'WP_TESTS_WP_DIR' ) : sys_get_temp_dir() . '/wordpress'; + CodeHacker::initialize( + array( + $this->plugin_dir . '/includes/', + $wp_dir . '/wp-includes/class-wp-customize-manager.php', + ) + ); + $replaceable_functions = include_once __DIR__ . '/mockable-functions.php'; if ( ! empty( $replaceable_functions ) ) { FunctionsMockerHack::initialize( $replaceable_functions ); diff --git a/tests/php/includes/customizer/class-wc-shop-customizer-test.php b/tests/php/includes/customizer/class-wc-shop-customizer-test.php new file mode 100644 index 00000000000..c1c73f66c56 --- /dev/null +++ b/tests/php/includes/customizer/class-wc-shop-customizer-test.php @@ -0,0 +1,59 @@ +createMock( WP_Customize_Manager::class ); + $added_settings = array(); + $added_controls = array(); + + $add_setting_callback = function( $id, $args = array() ) use ( &$added_settings ) { + array_push( $added_settings, $id ); + }; + $add_control_callback = function( $id, $args = array() ) use ( &$added_controls ) { + array_push( $added_controls, $id ); + }; + $customize_manager->method( 'add_setting' )->will( $this->returnCallback( $add_setting_callback ) ); + $customize_manager->method( 'add_control' )->will( $this->returnCallback( $add_control_callback ) ); + + $theme_support = $this->get_instance_of( ThemeSupport::class ); + $add_support_method = $add_explicit_theme_support ? 'add_options' : 'add_default_options'; + $theme_support->$add_support_method( array( $option_name => 1234 ) ); + + $sut = $this->get_legacy_instance_of( WC_Shop_Customizer::class ); + $sut->add_sections( $customize_manager ); + + $this->assertEquals( $expected_to_have_added_customization, in_array( 'woocommerce_' . $option_name, $added_settings, true ) ); + $this->assertEquals( $expected_to_have_added_customization, in_array( 'woocommerce_' . $option_name, $added_controls, true ) ); + } +} diff --git a/tests/php/src/ThemeSupport/ThemeSupportTest.php b/tests/php/src/ThemeSupport/ThemeSupportTest.php new file mode 100644 index 00000000000..3b3a5f9304f --- /dev/null +++ b/tests/php/src/ThemeSupport/ThemeSupportTest.php @@ -0,0 +1,254 @@ +sut = $this->get_instance_of( ThemeSupport::class ); + remove_theme_support( 'woocommerce' ); + } + + /** + * @testdox add_options should add the supplied options under the 'woocommerce' feature. + */ + public function test_add_options() { + $actual_added_feature = null; + $actual_added_options = null; + + $this->register_legacy_proxy_function_mocks( + array( + 'add_theme_support' => function( $feature, ...$args ) use ( &$actual_added_feature, &$actual_added_options ) { + $actual_added_feature = $feature; + $actual_added_options = $args; + }, + ) + ); + + $options = array( 'foo' => 'bar' ); + $this->sut->add_options( $options ); + + $this->assertEquals( 'woocommerce', $actual_added_feature ); + $this->assertEquals( $options, $actual_added_options[0] ); + + $this->reset_legacy_proxy_mocks(); + + $this->sut->add_options( $options ); + + $actual_retrieved_options = get_theme_support( 'woocommerce' )[0]; + $this->assertEquals( $options, $actual_retrieved_options ); + } + + /** + * @testdox add_default_options should add the supplied options under the 'woocommerce' feature on a '_defaults' key. + */ + public function test_2_add_default_options() { + $actual_added_options = array(); + + $this->register_legacy_proxy_function_mocks( + array( + 'add_theme_support' => function( $feature, ...$args ) use ( &$actual_added_options ) { + array_push( $actual_added_options, $args ); + }, + ) + ); + + $this->sut->add_default_options( array( 'foo' => 'bar' ) ); + $this->sut->add_default_options( array( 'fizz' => 'buzz' ) ); + + $expected_added_options = array( + array( + array( + ThemeSupport::DEFAULTS_KEY => + array( + 'foo' => 'bar', + ), + ), + ), + array( + array( + ThemeSupport::DEFAULTS_KEY => + array( + 'fizz' => 'buzz', + ), + ), + ), + ); + + $this->assertEquals( $expected_added_options, $actual_added_options ); + + $this->reset_legacy_proxy_mocks(); + + $this->sut->add_default_options( array( 'foo' => 'bar' ) ); + $this->sut->add_default_options( array( 'fizz' => 'buzz' ) ); + + $actual_retrieved_options = get_theme_support( 'woocommerce' )[0]; + $expected_retrieved_options = array( + ThemeSupport::DEFAULTS_KEY => array( + 'foo' => 'bar', + 'fizz' => 'buzz', + ), + ); + $this->assertEquals( $expected_retrieved_options, $actual_retrieved_options ); + } + + /** + * @testdox add_default_options should add the supplied options under the 'woocommerce' feature on a '_defaults' key. + */ + public function test_add_default_options() { + $this->sut->add_default_options( array( 'foo' => 'bar' ) ); + $this->sut->add_default_options( array( 'fizz' => 'buzz' ) ); + + $actual = get_theme_support( 'woocommerce' )[0]; + $expected = array( + ThemeSupport::DEFAULTS_KEY => array( + 'foo' => 'bar', + 'fizz' => 'buzz', + ), + ); + $this->assertEquals( $expected, $actual ); + } + + /** + * @testdox get_option should return all the options under the 'woocommerce' feature when invoked with blank option name. + */ + public function test_get_option_with_no_option_name() { + $options = array( 'foo' => 'bar' ); + $this->sut->add_options( $options ); + + $actual = $this->sut->get_option(); + $this->assertEquals( $options, $actual ); + } + + /** + * @testdox get_option should return null if no 'woocommerce' feature exists and no default value is supplied. + */ + public function test_get_option_with_no_option_name_when_no_options_exist_and_no_default_value_supplied() { + $actual = $this->sut->get_option(); + $this->assertNull( $actual ); + } + + /** + * @testdox get_option should return the supplied default value if no 'woocommerce' feature exists. + */ + public function test_get_option_with_no_option_name_when_no_options_exist_and_default_value_supplied() { + $actual = $this->sut->get_option( '', 'DEFAULT' ); + $this->assertEquals( 'DEFAULT', $actual ); + } + + /** + * @testdox get_theme_support should return the value of the requested option if it exists. + */ + public function test_get_theme_support_with_option_name() { + $options = array( 'foo' => array( 'bar' => 'fizz' ) ); + $this->sut->add_options( $options ); + + $actual = $this->sut->get_option( 'foo::bar' ); + $this->assertEquals( 'fizz', $actual ); + } + + /** + * @testdox get_option should return null if the requested option doesn't exist and no default value is supplied. + */ + public function test_get_option_with_option_name_when_option_does_not_exist_and_no_default_value_supplied() { + $options = array( 'foo' => array( 'bar' => 'fizz' ) ); + $this->sut->add_options( $options ); + + $actual = $this->sut->get_option( 'buzz' ); + $this->assertNull( $actual ); + } + + /** + * @testdox get_option should return the supplied default value if the requested option doesn't exist. + */ + public function test_get_option_with_option_name_when_option_does_not_exist_and_default_value_supplied() { + $options = array( 'foo' => array( 'bar' => 'fizz' ) ); + $this->sut->add_options( $options ); + + $actual = $this->sut->get_option( 'buzz', 'DEFAULT' ); + $this->assertEquals( 'DEFAULT', $actual ); + } + + /** + * @testdox get_option should return the value of the requested option if it has been defined as a default. + */ + public function test_get_option_with_option_name_and_option_defined_as_default() { + $options = array( 'foo' => array( 'bar' => 'fizz' ) ); + $this->sut->add_default_options( $options ); + + $actual = $this->sut->get_option( 'foo::bar' ); + $this->assertEquals( 'fizz', $actual ); + } + + /** + * @testdox has_option should return false if no 'woocommerce' feature exists. + * + * @testWith [true] + * [false] + * + * @param bool $include_defaults Whether to include defaults in the search or not. + */ + public function test_has_option_when_no_woocommerce_feature_is_defined( $include_defaults ) { + $this->assertFalse( $this->sut->has_option( 'foo::bar', $include_defaults ) ); + } + + /** + * @testdox has_option should return false if the specified option has not been defined. + * + * @testWith [true] + * [false] + * + * @param bool $include_defaults Whether to include defaults in the search or not. + */ + public function test_has_option_when_option_is_not_defined( $include_defaults ) { + $this->sut->add_options( array( 'foo' => 'bar' ) ); + $this->assertFalse( $this->sut->has_option( 'fizz::buzz', $include_defaults ) ); + } + + /** + * @testdox has_option should return true if the specified option has been defined. + * + * @testWith [true] + * [false] + * + * @param bool $include_defaults Whether to include defaults in the search or not. + */ + public function test_has_option_when_option_is_defined( $include_defaults ) { + $this->sut->add_options( array( 'foo' => 'bar' ) ); + $this->assertTrue( $this->sut->has_option( 'foo', $include_defaults ) ); + } + + /** + * @testdox If an option has been defined as a default, has_theme_support should return true if $include_defaults is passed as true, should return false otherwise. + * + * @testWith [true, true] + * [false, false] + * + * @param bool $include_defaults Whether to include defaults in the search or not. + * @param bool $expected_result The expected return value from the tested method. + */ + public function test_has_option_when_option_is_defined_as_default( $include_defaults, $expected_result ) { + $this->sut->add_default_options( array( 'foo' => 'bar' ) ); + $this->assertEquals( $expected_result, $this->sut->has_option( 'foo', $include_defaults ) ); + } +} diff --git a/tests/php/src/Utilities/ArrayUtilTest.php b/tests/php/src/Utilities/ArrayUtilTest.php new file mode 100644 index 00000000000..77f225942ac --- /dev/null +++ b/tests/php/src/Utilities/ArrayUtilTest.php @@ -0,0 +1,66 @@ + 'buzz' ); + $actual = ArrayUtil::get_nested_value( $array, $key ); + + $this->assertNull( $actual ); + } + + /** + * @testdox `get_nested_value` should return the supplied default value if the requested key doesn't exist. + * + * @testWith ["foo"] + * ["foo::bar"] + * + * @param string $key The key to test. + */ + public function test_get_nested_value_returns_supplied_default_if_non_existing_key( $key ) { + $array = array( 'fizz' => 'buzz' ); + $actual = ArrayUtil::get_nested_value( $array, $key, 'DEFAULT' ); + + $this->assertEquals( 'DEFAULT', $actual ); + } + + /** + * @testdox `get_nested_value` should return the proper value when a simple key is passed. + */ + public function test_get_nested_value_works_for_simple_keys() { + $array = array( 'foo' => 'bar' ); + $actual = ArrayUtil::get_nested_value( $array, 'foo' ); + + $this->assertEquals( 'bar', $actual ); + } + + /** + * @testdox `get_nested_value` should return the proper value when a nested key is passed. + */ + public function test_get_nested_value_works_for_nested_keys() { + $array = array( + 'foo' => array( + 'bar' => array( + 'fizz' => 'buzz', + ), + ), + ); + $actual = ArrayUtil::get_nested_value( $array, 'foo::bar::fizz' ); + + $this->assertEquals( 'buzz', $actual ); + } +} From 1075382575298ad03d3963870b45e8ed4caa94a0 Mon Sep 17 00:00:00 2001 From: OlegApanovich Date: Thu, 19 Nov 2020 00:31:51 +0200 Subject: [PATCH 003/368] Fix filter woocommerce_shipping_rate_cost backwards compatible with cart taxes #28008 --- includes/class-wc-tax.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/includes/class-wc-tax.php b/includes/class-wc-tax.php index f80a7d8422d..b8fe9f72f1e 100644 --- a/includes/class-wc-tax.php +++ b/includes/class-wc-tax.php @@ -82,7 +82,13 @@ class WC_Tax { * @return array */ public static function calc_shipping_tax( $price, $rates ) { + // Backwards compatible from WC_Shipping_Rate::get_cost(). + if ( has_filter( 'woocommerce_shipping_rate_cost' ) ) { + $rate = new WC_Shipping_Rate(); + $price = $rate->get_cost(); + } $taxes = self::calc_exclusive_tax( $price, $rates ); + return apply_filters( 'woocommerce_calc_shipping_tax', $taxes, $price, $rates ); } From 142fafc60eb0c266357c0c8772061ce942e8e77b Mon Sep 17 00:00:00 2001 From: jjchrisdiehl Date: Tue, 26 Jan 2021 09:42:05 -0500 Subject: [PATCH 004/368] Adding Venezuelan states --- i18n/states.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/i18n/states.php b/i18n/states.php index cda1e51e4aa..25fdd505ba8 100644 --- a/i18n/states.php +++ b/i18n/states.php @@ -1735,6 +1735,33 @@ return array( 'AE' => __( 'Armed Forces (AE)', 'woocommerce' ), 'AP' => __( 'Armed Forces (AP)', 'woocommerce' ), ), + 'VE' => array( // Venezuela States. Ref: https://en.wikipedia.org/wiki/ISO_3166-2:VE + 'W' => __( 'Dependencias Federales', 'woocommerce' ), + 'A' => __( 'Distrito Capital', 'woocommerce' ), + 'Z' => __( 'Amazonas', 'woocommerce' ), + 'B' => __( 'Anzoátegui', 'woocommerce' ), + 'C' => __( 'Apure', 'woocommerce' ), + 'D' => __( 'Aragua', 'woocommerce' ), + 'E' => __( 'Barinas', 'woocommerce' ), + 'F' => __( 'Bolívar', 'woocommerce' ), + 'G' => __( 'Carabobo', 'woocommerce' ), + 'H' => __( 'Cojedes', 'woocommerce' ), + 'Y' => __( 'Delta Amacuro', 'woocommerce' ), + 'I' => __( 'Falcón', 'woocommerce' ), + 'J' => __( 'Guárico', 'woocommerce' ), + 'K' => __( 'Lara', 'woocommerce' ), + 'L' => __( 'Mérida', 'woocommerce' ), + 'M' => __( 'Miranda', 'woocommerce' ), + 'N' => __( 'Monagas', 'woocommerce' ), + 'O' => __( 'Nueva Esparta', 'woocommerce' ), + 'P' => __( 'Portuguesa', 'woocommerce' ), + 'R' => __( 'Sucre', 'woocommerce' ), + 'S' => __( 'Táchira', 'woocommerce' ), + 'T' => __( 'Trujillo', 'woocommerce' ), + 'X' => __( 'La Guaira', 'woocommerce' ), + 'U' => __( 'Yaracuy', 'woocommerce' ), + 'V' => __( 'Zulia', 'woocommerce' ), + ), 'VN' => array(), 'YT' => array(), 'ZA' => array( // South African states. From 9a8cbfbd73d78820d88a91582a6b170a5bac45b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rio=20Valney?= Date: Tue, 16 Feb 2021 14:49:25 -0300 Subject: [PATCH 005/368] Support to optgroups on select from Settings API Add the optgroups support to single select from Settings API. The multiselect input already has this feature. --- includes/abstracts/abstract-wc-settings-api.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/includes/abstracts/abstract-wc-settings-api.php b/includes/abstracts/abstract-wc-settings-api.php index f33a62365fc..095403d65c0 100644 --- a/includes/abstracts/abstract-wc-settings-api.php +++ b/includes/abstracts/abstract-wc-settings-api.php @@ -696,6 +696,7 @@ abstract class WC_Settings_API { ); $data = wp_parse_args( $data, $defaults ); + $value = $this->get_option( $key ); ob_start(); ?> @@ -708,7 +709,15 @@ abstract class WC_Settings_API { get_description_html( $data ); // WPCS: XSS ok. ?> From 323fc329599f6e0f843f802a0ff63ed1385ea208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rio=20Valney?= Date: Tue, 16 Feb 2021 15:01:07 -0300 Subject: [PATCH 006/368] Added esc_attr to selected like before --- includes/abstracts/abstract-wc-settings-api.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/abstracts/abstract-wc-settings-api.php b/includes/abstracts/abstract-wc-settings-api.php index 095403d65c0..35bdbe522b7 100644 --- a/includes/abstracts/abstract-wc-settings-api.php +++ b/includes/abstracts/abstract-wc-settings-api.php @@ -712,11 +712,11 @@ abstract class WC_Settings_API { $option_value_inner ) : ?> - + - + From 7a892f61d28f1c10ad198f3626bc12e5b0211958 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Wed, 3 Mar 2021 19:52:29 -0400 Subject: [PATCH 007/368] update shared objects among models - add optional defaultKey, defaultValue to meta data - move REST _links object to model shared - add _links collection to coupons --- tests/e2e/api/src/models/coupons/coupon.ts | 11 +++ .../src/models/products/abstract/common.ts | 8 +-- .../api/src/models/products/abstract/data.ts | 8 +-- .../api/src/models/products/shared/classes.ts | 56 --------------- .../e2e/api/src/models/products/variation.ts | 8 +-- tests/e2e/api/src/models/shared-types.ts | 70 +++++++++++++++++++ .../repositories/rest/coupons/transformer.ts | 1 + tests/e2e/api/src/repositories/rest/shared.ts | 7 ++ 8 files changed, 101 insertions(+), 68 deletions(-) diff --git a/tests/e2e/api/src/models/coupons/coupon.ts b/tests/e2e/api/src/models/coupons/coupon.ts index a0ee904de29..20e3f42ee9b 100644 --- a/tests/e2e/api/src/models/coupons/coupon.ts +++ b/tests/e2e/api/src/models/coupons/coupon.ts @@ -12,6 +12,7 @@ import { import { CouponUpdateParams, } from './shared'; +import { ObjectLinks } from '../shared-types'; /** * The parameters embedded in this generic can be used in the ModelRepository in order to give @@ -222,6 +223,16 @@ export class Coupon extends Model { */ public readonly usedBy: Array = []; + /** + * The coupon's links. + * + * @type {ReadonlyArray.} + */ + public readonly links: ObjectLinks = { + collection: [ { href: '' } ], + self: [ { href: '' } ], + }; + /** * Creates a new coupon instance with the given properties * diff --git a/tests/e2e/api/src/models/products/abstract/common.ts b/tests/e2e/api/src/models/products/abstract/common.ts index 88601fa6ad0..4f9833f8eab 100644 --- a/tests/e2e/api/src/models/products/abstract/common.ts +++ b/tests/e2e/api/src/models/products/abstract/common.ts @@ -3,9 +3,9 @@ import { ModelID } from '../../model'; import { CatalogVisibility, ProductTerm, - ProductLinks, ProductAttribute, } from '../shared'; +import { ObjectLinks } from '../../shared-types'; /** * The common parameters that all products can use in search. @@ -137,11 +137,11 @@ export abstract class AbstractProduct extends AbstractProductData { public readonly attributes: readonly ProductAttribute[] = []; /** - * The products links. + * The product's links. * - * @type {ReadonlyArray.} + * @type {ReadonlyArray.} */ - public readonly links: ProductLinks = { + public readonly links: ObjectLinks = { collection: [ { href: '' } ], self: [ { href: '' } ], }; diff --git a/tests/e2e/api/src/models/products/abstract/data.ts b/tests/e2e/api/src/models/products/abstract/data.ts index 0d1b83cb37e..e76c1c7d9d8 100644 --- a/tests/e2e/api/src/models/products/abstract/data.ts +++ b/tests/e2e/api/src/models/products/abstract/data.ts @@ -1,6 +1,6 @@ import { Model } from '../../model'; -import { MetaData, PostStatus } from '../../shared-types'; -import { ProductImage, ProductLinks } from '../shared'; +import { MetaData, PostStatus, ObjectLinks } from '../../shared-types'; +import { ProductImage } from '../shared'; /** * Base product data. @@ -93,9 +93,9 @@ export abstract class AbstractProductData extends Model { /** * The product data links. * - * @type {ReadonlyArray.} + * @type {ReadonlyArray.} */ - public readonly links: ProductLinks = { + public readonly links: ObjectLinks = { collection: [ { href: '' } ], self: [ { href: '' } ], }; diff --git a/tests/e2e/api/src/models/products/shared/classes.ts b/tests/e2e/api/src/models/products/shared/classes.ts index 7343c594352..c08e0a20b70 100644 --- a/tests/e2e/api/src/models/products/shared/classes.ts +++ b/tests/e2e/api/src/models/products/shared/classes.ts @@ -208,59 +208,3 @@ export class ProductImage { Object.assign( this, properties ); } } - -/** - * A product link item. - */ -class ProductLinkItem { - /** - * The options which are available for the attribute. - * - * @type {ReadonlyArray.} - */ - public readonly href: string = ''; - - /** - * Creates a new product link item. - * - * @param {Partial.} properties The properties to set. - */ - public constructor( properties?: Partial< ProductLinkItem > ) { - Object.assign( this, properties ); - } -} - -/** - * A product's links. - */ -export class ProductLinks { - /** - * The collection containing the product. - * - * @type {ReadonlyArray.} - */ - public readonly collection: readonly ProductLinkItem[] = []; - - /** - * Self referential link to the product. - * - * @type {ReadonlyArray.} - */ - public readonly self: readonly ProductLinkItem[] = []; - - /** - * The link to the parent. - * - * @type {ReadonlyArray.} - */ - public readonly up?: readonly ProductLinkItem[] = []; - - /** - * Creates a new product link list. - * - * @param {Partial.} properties The properties to set. - */ - public constructor( properties?: Partial< ProductLinks > ) { - Object.assign( this, properties ); - } -} diff --git a/tests/e2e/api/src/models/products/variation.ts b/tests/e2e/api/src/models/products/variation.ts index 78e8580c2fa..beb1bad8071 100644 --- a/tests/e2e/api/src/models/products/variation.ts +++ b/tests/e2e/api/src/models/products/variation.ts @@ -15,13 +15,13 @@ import { ProductPriceUpdateParams, ProductSalesTaxUpdateParams, ProductShippingUpdateParams, - ProductLinks, Taxability, ProductDownload, StockStatus, BackorderStatus, ProductDefaultAttribute, } from './shared'; +import { ObjectLinks } from '../shared-types'; import { CreatesChildModels, DeletesChildModels, @@ -149,11 +149,11 @@ export class ProductVariation extends AbstractProductData implements public readonly shippingClassId: number = 0; /** - * The variation links. + * The variation's links. * - * @type {ReadonlyArray.} + * @type {ReadonlyArray.} */ - public readonly links: ProductLinks = { + public readonly links: ObjectLinks = { collection: [ { href: '' } ], self: [ { href: '' } ], up: [ { href: '' } ], diff --git a/tests/e2e/api/src/models/shared-types.ts b/tests/e2e/api/src/models/shared-types.ts index 5f64fff0b72..d041f3c48c8 100644 --- a/tests/e2e/api/src/models/shared-types.ts +++ b/tests/e2e/api/src/models/shared-types.ts @@ -35,6 +35,20 @@ export class MetaData extends Model { */ public readonly value: any = ''; + /** + * The key of the metadata. + * + * @type {string} + */ + public readonly displayKey?: string = ''; + + /** + * The value of the metadata. + * + * @type {*} + */ + public readonly displayValue?: string = ''; + /** * Creates a new metadata. * @@ -45,3 +59,59 @@ export class MetaData extends Model { Object.assign( this, properties ); } } + +/** + * An object link item. + */ +class LinkItem { + /** + * The href of the link. + * + * @type {ReadonlyArray.} + */ + public readonly href: string = ''; + + /** + * Creates a new product link item. + * + * @param {Partial.} properties The properties to set. + */ + public constructor( properties?: Partial< LinkItem > ) { + Object.assign( this, properties ); + } +} + +/** + * An object's links. + */ +export class ObjectLinks { + /** + * The collection containing the object. + * + * @type {ReadonlyArray.} + */ + public readonly collection: readonly LinkItem[] = []; + + /** + * Self referential link to the object. + * + * @type {ReadonlyArray.} + */ + public readonly self: readonly LinkItem[] = []; + + /** + * The link to the parent object. + * + * @type {ReadonlyArray.} + */ + public readonly up?: readonly LinkItem[] = []; + + /** + * Creates a new product link list. + * + * @param {Partial.} properties The properties to set. + */ + public constructor( properties?: Partial< ObjectLinks > ) { + Object.assign( this, properties ); + } +} diff --git a/tests/e2e/api/src/repositories/rest/coupons/transformer.ts b/tests/e2e/api/src/repositories/rest/coupons/transformer.ts index b3827471242..8e0c7d85eb9 100644 --- a/tests/e2e/api/src/repositories/rest/coupons/transformer.ts +++ b/tests/e2e/api/src/repositories/rest/coupons/transformer.ts @@ -57,6 +57,7 @@ export function createCouponTransformer(): ModelTransformer< Coupon > { maximumAmount: 'maximum_amount', emailRestrictions: 'email_restrictions', usedBy: 'used_by', + links: '_links', }, ), ], diff --git a/tests/e2e/api/src/repositories/rest/shared.ts b/tests/e2e/api/src/repositories/rest/shared.ts index 1d52d73ec3d..3c4e976d177 100644 --- a/tests/e2e/api/src/repositories/rest/shared.ts +++ b/tests/e2e/api/src/repositories/rest/shared.ts @@ -16,6 +16,7 @@ import { CreateChildFn, ModelTransformer, IgnorePropertyTransformation, + KeyChangeTransformation, // @ts-ignore ModelParentID, } from '../../framework'; @@ -34,6 +35,12 @@ export function createMetaDataTransformer(): ModelTransformer< MetaData > { return new ModelTransformer( [ new IgnorePropertyTransformation( [ 'id' ] ), + new KeyChangeTransformation< MetaData >( + { + displayKey: 'display_key', + displayValue: 'display_value', + }, + ), ], ); } From 03c60b988b086b15e23e8760e9c67eb9a65a33b9 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Fri, 5 Mar 2021 10:39:35 -0400 Subject: [PATCH 008/368] add order classes --- tests/e2e/api/src/models/orders/index.ts | 1 + .../api/src/models/orders/shared/classes.ts | 412 ++++++++++++++++++ .../e2e/api/src/models/orders/shared/index.ts | 2 + .../e2e/api/src/models/orders/shared/types.ts | 3 + 4 files changed, 418 insertions(+) create mode 100644 tests/e2e/api/src/models/orders/index.ts create mode 100644 tests/e2e/api/src/models/orders/shared/classes.ts create mode 100644 tests/e2e/api/src/models/orders/shared/index.ts create mode 100644 tests/e2e/api/src/models/orders/shared/types.ts diff --git a/tests/e2e/api/src/models/orders/index.ts b/tests/e2e/api/src/models/orders/index.ts new file mode 100644 index 00000000000..c3da79f741b --- /dev/null +++ b/tests/e2e/api/src/models/orders/index.ts @@ -0,0 +1 @@ +export * from './shared'; diff --git a/tests/e2e/api/src/models/orders/shared/classes.ts b/tests/e2e/api/src/models/orders/shared/classes.ts new file mode 100644 index 00000000000..3852519b94c --- /dev/null +++ b/tests/e2e/api/src/models/orders/shared/classes.ts @@ -0,0 +1,412 @@ +import { MetaData } from '../../shared-types'; +import { Model } from '../../model'; +import { TaxStatus } from './types'; + +/** + * Order item meta. + */ +export class OrderItemMeta extends Model { + /** + * The meta data the order item. + * + * @type {ReadonlyArray.} + */ + public readonly metaData: MetaData[] = []; +} + +/** + * Order line item tax entry. + */ +export class OrderItemTax extends Model { + /** + * The total tax for this tax rate on this item. + * + * @type {string} + */ + public readonly total: string = ''; + + /** + * The subtotal tax for this tax rate on this item. + * + * @type {string} + */ + public readonly subtotal: string = ''; +} + +/** + * An order address. + */ +export class OrderAddress { + /** + * The first name of the person in the address. + * + * @type {string} + */ + public readonly firstName: string = ''; + + /** + * The last name of the person in the address. + * + * @type {string} + */ + public readonly lastName: string = ''; + + /** + * The company name of the person in the address. + * + * @type {string} + */ + public readonly companyName: string = ''; + + /** + * The first address line in the address. + * + * @type {string} + */ + public readonly address1: string = ''; + + /** + * The second address line in the address. + * + * @type {string} + */ + public readonly address2: string = ''; + + /** + * The city in the address. + * + * @type {string} + */ + public readonly city: string = ''; + + /** + * The state in the address. + * + * @type {string} + */ + public readonly state: string = ''; + + /** + * The postal code in the address. + * + * @type {string} + */ + public readonly postCode: string = ''; + + /** + * The country code for the address. + * + * @type {string} + */ + public readonly countryCode: string = ''; + + /** + * The email address of the person in the address. + * + * @type {string} + */ + public readonly email: string = ''; + + /** + * The phone number of the person in the address. + * + * @type {string} + */ + public readonly phone: string = ''; +} + +/** + * Order Line Item + */ +export class OrderLineItem extends OrderItemMeta { + /** + * The name of the product. + * + * @type {string} + */ + public readonly name: string = ''; + + /** + * The ID of the product. + * + * @type {number} + */ + public readonly ProductId: number = -1; + + /** + * The ID of the product variation. + * + * @type {number} + */ + public readonly variationId: number = 0; + + /** + * The quantity of the product. + * + * @type {number} + */ + public readonly quantity: number = -1; + + /** + * The tax class for the product. + * + * @type {string} + */ + public readonly taxClass: string = ''; + + /** + * The subtotal for the product. + * + * @type {string} + */ + public readonly subtotal: string = ''; + + /** + * The subtotal tax for the product. + * + * @type {string} + */ + public readonly subtotalTax: string = ''; + + /** + * The total for the product including adjusments. + * + * @type {string} + */ + public readonly total: string = ''; + + /** + * The total tax for the product including adjusments. + * + * @type {string} + */ + public readonly totalTax: string = ''; + + /** + * The taxes applied to the product. + * + * @type {ReadonlyArray.} + */ + public readonly taxes: OrderItemTax[] = []; + + /** + * The product SKU. + * + * @type {string} + */ + public readonly sku: string = ''; + + /** + * The price of the product. + * + * @type {number} + */ + public readonly price: number = -1; + + /** + * The name of the parent product. + * + * @type {string|null} + */ + public readonly parentName: string | null = null; +} + +/** + * Order Tax Rate + */ +export class OrderTaxRate extends Model { + /** + * The tax rate code. + * + * @type {string} + */ + public readonly rateCode: string = ''; + + /** + * The tax rate id. + * + * @type {number} + */ + public readonly rateId: number = 0; + + /** + * The tax label. + * + * @type {string} + */ + public readonly label: string = ''; + + /** + * Flag indicating whether it's a compound tax rate. + * + * @type {boolean} + */ + public readonly compoundRate: boolean = false; + + /** + * The total tax for this rate code. + * + * @type {string} + */ + public readonly taxTotal: string = ''; + + /** + * The total shipping tax for this rate code. + * + * @type {string} + */ + public readonly shippingTaxTotal: string = ''; + + /** + * The tax rate as a percentage. + * + * @type {number} + */ + public readonly ratePercent: number = 0; +} + +/** + * Order shipping line + */ +export class OrderShippingLine extends OrderItemMeta { + /** + * The shipping method title. + * + * @type {string} + */ + public readonly methodTitle: string = ''; + + /** + * The shipping method id. + * + * @type {string} + */ + public readonly methodId: string = ''; + + /** + * The shipping method instance id. + * + * @type {string} + */ + public readonly instanceId: string = ''; + + /** + * The total shipping amount for this method. + * + * @type {string} + */ + public readonly total: string = ''; + + /** + * The total tax amount for this shipping method. + * + * @type {string} + */ + public readonly totalTax: string = ''; + + /** + * The taxes applied to this shipping method. + * + * @type {ReadonlyArray.} + */ + public readonly taxes: OrderItemTax[] = []; +} + +/** + * Order fee line + */ +export class OrderFeeLine extends OrderItemMeta { + /** + * The name of the fee. + * + * @type {string} + */ + public readonly name: string = ''; + + /** + * The tax class of the fee. + * + * @type {string} + */ + public readonly taxClass: string = ''; + + /** + * The tax status of the fee. + * + * @type {TaxStatus} + */ + public readonly taxStatus: TaxStatus = ''; + + /** + * The total amount for this fee. + * + * @type {string} + */ + public readonly amount: string = ''; + + /** + * The display total amount for this fee. + * + * @type {string} + */ + public readonly total: string = ''; + + /** + * The total tax amount for this fee. + * + * @type {string} + */ + public readonly totalTax: string = ''; + + /** + * The taxes applied to this fee. + * + * @type {ReadonlyArray.} + */ + public readonly taxes: OrderItemTax[] = []; +} + +/** + * Order coupon line + */ +export class OrderCouponLine extends OrderItemMeta { + /** + * The coupon code + * + * @type {string} + */ + public readonly code: string = ''; + + /** + * The discount amount. + * + * @type {string} + */ + public readonly discount: string = ''; + + /** + * The discount tax. + * + * @type {string} + */ + public readonly discountTax: string = ''; +} + +/** + * Order refund line + */ +export class OrderRefundLine extends Model { + /** + * The reason for giving the refund. + * + * @type {string} + */ + public readonly reason: string = ''; + + /** + * The total amount of the refund. + * + * @type {string} + */ + public readonly total: string = ''; +} diff --git a/tests/e2e/api/src/models/orders/shared/index.ts b/tests/e2e/api/src/models/orders/shared/index.ts new file mode 100644 index 00000000000..15eb796c953 --- /dev/null +++ b/tests/e2e/api/src/models/orders/shared/index.ts @@ -0,0 +1,2 @@ +export * from './classes'; +export * from './types'; diff --git a/tests/e2e/api/src/models/orders/shared/types.ts b/tests/e2e/api/src/models/orders/shared/types.ts new file mode 100644 index 00000000000..4e987c99d24 --- /dev/null +++ b/tests/e2e/api/src/models/orders/shared/types.ts @@ -0,0 +1,3 @@ + +//@todo: complete this type +export type TaxStatus = 'taxable' | string; From b05a97e2c069f3dffbc23e576bbd9529eb729343 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Sun, 7 Mar 2021 23:06:48 -0400 Subject: [PATCH 009/368] add order types --- .../e2e/api/src/models/orders/shared/types.ts | 67 ++++++++++++++++++- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/tests/e2e/api/src/models/orders/shared/types.ts b/tests/e2e/api/src/models/orders/shared/types.ts index 4e987c99d24..adeba0128c4 100644 --- a/tests/e2e/api/src/models/orders/shared/types.ts +++ b/tests/e2e/api/src/models/orders/shared/types.ts @@ -1,3 +1,66 @@ +/** + * An order's status. + * + * @typedef OrderStatus + */ +export type OrderStatus = 'pending' | 'processing' | 'complete' | 'on-hold' | 'refunded' + | 'cancelled' | 'failed' | 'trash' | string; -//@todo: complete this type -export type TaxStatus = 'taxable' | string; +/** + * An fee's tax status. + * + * @typedef TaxStatus + */ +export type TaxStatus = 'taxable' | 'none'; + +/** + * Base order properties + */ +export type OrderDataUpdateParams = 'id' | 'parentId' | 'status' | 'currency' | 'version' + | 'pricesIncludeTax' | 'discountTotal' | 'discountTax' | 'shippingTotal' | 'shippingTax' + | 'cartTax' | 'customerId' | 'orderKey' | 'paymentMethod' | 'paymentMethodTitle' + | 'transactionId' | 'customerIpAddress' | 'customerUserAgent' | 'createdVia' | 'datePaid' + | 'customerNote' | 'dateCompleted' | 'cartHash' | 'orderNumber' | 'currencySymbol'; + +/** + * Common total properties + */ +export type OrderTotalUpdateParams = 'total' | 'totalTax'; + +/** + * Order address properties + */ +export type OrderAddressUpdateParams = 'firstName' | 'lastName' | 'companyName' | 'address1' + | 'address2' | 'city' | 'state' | 'postCode' | 'countryCode' | 'email' | 'phone'; + +/** + * Line item properties + */ +export type OrderLineItemUpdateParams = 'name' | 'ProductId' | 'variationId' | 'quantity' + | 'taxClass' | 'subtotal' | 'subtotalTax' | 'sku' | 'price' | 'parentName'; + +/** + * Tax rate properties + */ +export type OrderTaxUpdateParams = 'rateCode' | 'rateId' | 'label' | 'compoundRate' + | 'taxTotal' | 'shippingTaxTotal' | 'ratePercent'; + +/** + * Order shipping properties + */ +export type OrderShippingUpdateParams = 'methodTitle' | 'methodId' | 'instanceId'; + +/** + * Order fee properties + */ +export type OrderFeeUpdateParams = 'name' | 'taxClass' | 'taxStatus' | 'amount'; + +/** + * Order coupon properties + */ +export type OrderCouponUpdateParams = 'code' | 'discount' | 'discountTax'; + +/** + * Order refund properties + */ +export type OrderRefundUpdateParams = 'reason' | 'total'; From 1664ece7eb3ff04a76ad97d53b579772768d013a Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Mon, 8 Mar 2021 09:59:46 -0400 Subject: [PATCH 010/368] use valid tax status on fees --- tests/e2e/api/src/models/orders/shared/classes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/api/src/models/orders/shared/classes.ts b/tests/e2e/api/src/models/orders/shared/classes.ts index 3852519b94c..c506f6563cc 100644 --- a/tests/e2e/api/src/models/orders/shared/classes.ts +++ b/tests/e2e/api/src/models/orders/shared/classes.ts @@ -335,7 +335,7 @@ export class OrderFeeLine extends OrderItemMeta { * * @type {TaxStatus} */ - public readonly taxStatus: TaxStatus = ''; + public readonly taxStatus: TaxStatus = 'taxable'; /** * The total amount for this fee. From 5b02c440d7adaeefdbf4d77d8d2f965993af3615 Mon Sep 17 00:00:00 2001 From: Jacob Arriola Date: Mon, 8 Mar 2021 10:38:23 -0800 Subject: [PATCH 011/368] New filter: stock check message Adds a new filter to allow customization of the stock check message when a product is out of stock, but accounting for what's already in the cart. It mimics the existing woocommerce_cart_product_not_enough_stock_message filter. --- includes/class-wc-cart.php | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/includes/class-wc-cart.php b/includes/class-wc-cart.php index 1103ee053e5..966a5bb7fdf 100644 --- a/includes/class-wc-cart.php +++ b/includes/class-wc-cart.php @@ -1218,15 +1218,30 @@ class WC_Cart extends WC_Legacy_Cart { $products_qty_in_cart = $this->get_cart_item_quantities(); if ( isset( $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ] ) && ! $product_data->has_enough_stock( $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ] + $quantity ) ) { - throw new Exception( - sprintf( - '%s %s', - wc_get_cart_url(), - __( 'View cart', 'woocommerce' ), - /* translators: 1: quantity in stock 2: current quantity */ - sprintf( __( 'You cannot add that amount to the cart — we have %1$s in stock and you already have %2$s in your cart.', 'woocommerce' ), wc_format_stock_quantity_for_display( $product_data->get_stock_quantity(), $product_data ), wc_format_stock_quantity_for_display( $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ], $product_data ) ) - ) + $stock_quantity = $product_data->get_stock_quantity(); + $stock_quantity_in_cart = $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ]; + + $message = printf( + '%s %s', + wc_get_cart_url(), + __( 'View cart', 'woocommerce' ), + /* translators: 1: quantity in stock 2: current quantity */ + sprintf( __( 'You cannot add that amount to the cart — we have %1$s in stock and you already have %2$s in your cart.', 'woocommerce' ), wc_format_stock_quantity_for_display( $stock_quantity, $product_data ), wc_format_stock_quantity_for_display( $stock_quantity_in_cart, $product_data ) ) ); + + /** + * Filters message about product not having enough stock accounting for what's already in the cart. + * + * @param string $message Message. + * @param WC_Product $product_data Product data. + * @param int $stock_quantity Quantity remaining. + * @param int $stock_quantity_in_cart + * + * @since 5.0.0 + */ + $message = apply_filters( 'woocommerce_cart_product_not_enough_stock_already_in_cart_message', $message, $product_data, $stock_quantity, $stock_quantity_in_cart ); + + throw new Exception( $message ); } } From f6b4614225ea8645ed9949b17201ecb7e78aee16 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 9 Mar 2021 16:57:08 -0300 Subject: [PATCH 012/368] Return 0 if order isn't available --- includes/abstracts/abstract-wc-payment-gateway.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/includes/abstracts/abstract-wc-payment-gateway.php b/includes/abstracts/abstract-wc-payment-gateway.php index fe29740e569..3dcc281464d 100644 --- a/includes/abstracts/abstract-wc-payment-gateway.php +++ b/includes/abstracts/abstract-wc-payment-gateway.php @@ -262,7 +262,9 @@ abstract class WC_Payment_Gateway extends WC_Settings_API { // Gets order total from "pay for order" page. if ( 0 < $order_id ) { $order = wc_get_order( $order_id ); - $total = (float) $order->get_total(); + if ( $order ) { + $total = (float) $order->get_total(); + } // Gets order total from cart/checkout. } elseif ( 0 < WC()->cart->total ) { From 1fc1b604b9c0fddda6cdd8e674f4ebaf43a755e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Rey=20L=C3=B3pez?= Date: Wed, 10 Mar 2021 11:52:01 +0000 Subject: [PATCH 013/368] IE 11 compatibility for the site tracking enable function --- includes/tracks/class-wc-site-tracking.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/tracks/class-wc-site-tracking.php b/includes/tracks/class-wc-site-tracking.php index 74e06215985..e924d250448 100644 --- a/includes/tracks/class-wc-site-tracking.php +++ b/includes/tracks/class-wc-site-tracking.php @@ -104,7 +104,7 @@ class WC_Site_Tracking { ?> diff --git a/includes/admin/class-wc-admin-pointers.php b/includes/admin/class-wc-admin-pointers.php index 1ca73026713..c846276edde 100644 --- a/includes/admin/class-wc-admin-pointers.php +++ b/includes/admin/class-wc-admin-pointers.php @@ -254,12 +254,12 @@ class WC_Admin_Pointers { button2 = $( '' + next + '' ), wrapper = $( '
' ); - button.bind( 'click.pointer', function(e) { + button.on( 'click.pointer', function(e) { e.preventDefault(); t.element.pointer('destroy'); }); - button2.bind( 'click.pointer', function(e) { + button2.on( 'click.pointer', function(e) { e.preventDefault(); t.element.pointer('close'); }); diff --git a/includes/admin/plugin-updates/class-wc-plugins-screen-updates.php b/includes/admin/plugin-updates/class-wc-plugins-screen-updates.php index 5920fb52616..edc091946dc 100644 --- a/includes/admin/plugin-updates/class-wc-plugins-screen-updates.php +++ b/includes/admin/plugin-updates/class-wc-plugins-screen-updates.php @@ -157,7 +157,7 @@ class WC_Plugins_Screen_Updates extends WC_Plugin_Updates { $update_link.removeClass( 'wc-thickbox open-plugin-details-modal' ); $update_link.addClass( 'update-link' ); $update_link.attr( 'href', update_url ); - $update_link.click(); + $update_link.trigger( 'click' ); }); $( '#wc_untested_extensions_modal .cancel' ).on( 'click', function( evt ) { diff --git a/includes/admin/plugin-updates/class-wc-updates-screen-updates.php b/includes/admin/plugin-updates/class-wc-updates-screen-updates.php index 7d2cbb9de8d..233a7bfa897 100644 --- a/includes/admin/plugin-updates/class-wc-updates-screen-updates.php +++ b/includes/admin/plugin-updates/class-wc-updates-screen-updates.php @@ -69,7 +69,7 @@ class WC_Updates_Screen_Updates extends WC_Plugin_Updates { } var $checkbox = $( 'input[value="woocommerce/woocommerce.php"]' ); if ( $checkbox.prop( 'checked' ) ) { - $( '#wc-upgrade-warning' ).click(); + $( '#wc-upgrade-warning' ).trigger( 'click' ); } } diff --git a/includes/admin/reports/class-wc-report-coupon-usage.php b/includes/admin/reports/class-wc-report-coupon-usage.php index 01c83d84198..7d1a55c3d19 100644 --- a/includes/admin/reports/class-wc-report-coupon-usage.php +++ b/includes/admin/reports/class-wc-report-coupon-usage.php @@ -343,9 +343,9 @@ class WC_Report_Coupon_Usage extends WC_Admin_Report { } ); jQuery( '.section' ).slideUp( 100, function() { coupon_codes ) ) : ?> - jQuery( '.section_title:eq(1)' ).click(); + jQuery( '.section_title:eq(1)' ).trigger( 'click' ); - jQuery( '.section_title:eq(0)' ).click(); + jQuery( '.section_title:eq(0)' ).trigger( 'click' ); } ); @@ -551,7 +551,7 @@ class WC_Report_Coupon_Usage extends WC_Admin_Report { } ); - jQuery('.chart-placeholder').resize(); + jQuery('.chart-placeholder').trigger( 'resize' ); } drawGraph(); diff --git a/includes/admin/reports/class-wc-report-customers.php b/includes/admin/reports/class-wc-report-customers.php index 0096a73f993..5cff075d2d3 100644 --- a/includes/admin/reports/class-wc-report-customers.php +++ b/includes/admin/reports/class-wc-report-customers.php @@ -155,7 +155,7 @@ class WC_Report_Customers extends WC_Admin_Report { } ); - jQuery('.chart-placeholder.customers_vs_guests').resize(); + jQuery('.chart-placeholder.customers_vs_guests').trigger( 'resize' ); }); product_ids ) ) : ?> - jQuery( '.section_title:eq(1)' ).click(); + jQuery( '.section_title:eq(1)' ).trigger( 'click' ); } ); @@ -610,7 +610,7 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report { } ); - jQuery('.chart-placeholder').resize(); + jQuery('.chart-placeholder').trigger( 'resize' ); } drawGraph(); diff --git a/includes/admin/settings/views/html-webhooks-edit.php b/includes/admin/settings/views/html-webhooks-edit.php index eaaf56dd984..760d96fd92d 100644 --- a/includes/admin/settings/views/html-webhooks-edit.php +++ b/includes/admin/settings/views/html-webhooks-edit.php @@ -221,6 +221,6 @@ if ( ! defined( 'ABSPATH' ) ) { if ( 'action' === current ) { action_event_field.show(); } - }).change(); + }).trigger( 'change' ); }); diff --git a/includes/customizer/class-wc-shop-customizer.php b/includes/customizer/class-wc-shop-customizer.php index f17cac7dfea..bf86e7f9e55 100644 --- a/includes/customizer/class-wc-shop-customizer.php +++ b/includes/customizer/class-wc-shop-customizer.php @@ -128,7 +128,7 @@ class WC_Shop_Customizer { } ); wp.customize.bind( 'ready', function() { // Ready? - $( '.woocommerce-cropping-control' ).find( 'input:checked' ).change(); + $( '.woocommerce-cropping-control' ).find( 'input:checked' ).trigger( 'change' ); } ); wp.customize( 'woocommerce_demo_store', function( setting ) { diff --git a/includes/emails/class-wc-email.php b/includes/emails/class-wc-email.php index d5accd8347a..a74305413b6 100644 --- a/includes/emails/class-wc-email.php +++ b/includes/emails/class-wc-email.php @@ -1029,7 +1029,7 @@ class WC_Email extends WC_Settings_API { Date: Thu, 4 Feb 2021 13:21:44 -0800 Subject: [PATCH 252/368] Fix deprecated jQuery removeClass function --- assets/js/admin/meta-boxes-product.js | 14 ++++++++++---- assets/js/admin/meta-boxes.js | 14 +++++++++++++- assets/js/admin/wc-setup.js | 9 ++++++++- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/assets/js/admin/meta-boxes-product.js b/assets/js/admin/meta-boxes-product.js index 6e058abbfe7..e9cad28e4c6 100644 --- a/assets/js/admin/meta-boxes-product.js +++ b/assets/js/admin/meta-boxes-product.js @@ -34,17 +34,23 @@ jQuery( function( $ ) { } $( function() { - // Prevent inputs in meta box headings opening/closing contents. - $( '#woocommerce-product-data' ).find( '.hndle' ).off( 'click.postboxes' ); + var woocommerce_product_data = $( '#woocommerce-product-data' ); - $( '#woocommerce-product-data' ).on( 'click', '.hndle', function( event ) { + // Prevent inputs in meta box headings opening/closing contents. + woocommerce_product_data.find( '.hndle' ).off( 'click.postboxes' ); + + woocommerce_product_data.on( 'click', '.hndle', function( event ) { // If the user clicks on some form input inside the h3 the box should not be toggled. if ( $( event.target ).filter( 'input, option, label, select' ).length ) { return; } - $( '#woocommerce-product-data' ).toggleClass( 'closed' ); + if ( woocommerce_product_data.hasClass( 'closed' ) ) { + woocommerce_product_data.removeClass( 'closed' ); + } else { + woocommerce_product_data.addClass( 'closed' ); + } }); }); diff --git a/assets/js/admin/meta-boxes.js b/assets/js/admin/meta-boxes.js index 1f82968994f..a815b38315c 100644 --- a/assets/js/admin/meta-boxes.js +++ b/assets/js/admin/meta-boxes.js @@ -17,7 +17,19 @@ jQuery( function ( $ ) { runTipTip(); $( '.wc-metaboxes-wrapper' ).on( 'click', '.wc-metabox > h3', function() { - $( this ).parent( '.wc-metabox' ).toggleClass( 'closed' ).toggleClass( 'open' ); + var metabox = $( this ).parent( '.wc-metabox' ); + + if ( metabox.hasClass( 'closed' ) ) { + metabox.removeClass( 'closed' ); + } else { + metabox.addClass( 'closed' ); + } + + if ( metabox.hasClass( 'open' ) ) { + metabox.removeClass( 'open' ); + } else { + metabox.addClass( 'open' ); + } }); // Tabbed Panels diff --git a/assets/js/admin/wc-setup.js b/assets/js/admin/wc-setup.js index 99ed685831d..ab29f8c4acd 100644 --- a/assets/js/admin/wc-setup.js +++ b/assets/js/admin/wc-setup.js @@ -139,7 +139,14 @@ jQuery( function( $ ) { } ); $( '.wc-wizard-services-list-toggle' ).on( 'click', function() { - $( this ).closest( '.wc-wizard-services-list-toggle' ).toggleClass( 'closed' ); + var listToggle = $( this ).closest( '.wc-wizard-services-list-toggle' ); + + if ( listToggle.hasClass( 'closed' ) ) { + listToggle.removeClass( 'closed' ); + } else { + listToggle.addClass( 'closed' ); + } + $( this ).closest( '.wc-wizard-services' ).find( '.wc-wizard-service-item' ) .slideToggle() .css( 'display', 'flex' ); From 84533ac38fc033c952f4f0c893f1c78efe0ce2c6 Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 14:06:08 -0800 Subject: [PATCH 253/368] Update deprecated jQuery functions for selectWoo.full.js --- assets/js/selectWoo/selectWoo.full.js | 58 +++++++++++++-------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/assets/js/selectWoo/selectWoo.full.js b/assets/js/selectWoo/selectWoo.full.js index 49cb11ee692..4c4daf83fc9 100644 --- a/assets/js/selectWoo/selectWoo.full.js +++ b/assets/js/selectWoo/selectWoo.full.js @@ -1430,7 +1430,7 @@ S2.define('select2/selection/base',[ // This needs to be delayed as the active element is the body when the // key is pressed. window.setTimeout(function () { - self.$selection.focus(); + self.$selection.trigger( 'focus' ); }, 1); self._detachCloseHandler(container); @@ -1486,8 +1486,8 @@ S2.define('select2/selection/base',[ // Remove any focus when dropdown is closed by clicking outside the select area. // Timeout of 1 required for close to finish wrapping up. setTimeout(function(){ - $this.find('*:focus').blur(); - $target.focus(); + $this.find('*:focus').trigger( 'blur' ); + $target.trigger( 'focus' ); }, 1); }); }); @@ -1591,7 +1591,7 @@ S2.define('select2/selection/single',[ container.on('focus', function (evt) { if (!container.isOpen()) { - self.$selection.focus(); + self.$selection.trigger( 'focus' ); } }); @@ -1737,7 +1737,7 @@ S2.define('select2/selection/multiple',[ // This gets reset automatically when focus is triggered. self._keyUpPrevented = true; - self.$search.focus(); + self.$search.trigger( 'focus' ); }, 1); } } @@ -2109,7 +2109,7 @@ S2.define('select2/selection/search',[ this.resizeSearch(); if (searchHadFocus) { - this.$search.focus(); + this.$search.trigger( 'focus' ); } }; @@ -3547,7 +3547,7 @@ S2.define('select2/data/ajax',[ if (this._request != null) { // JSONP requests cannot always be aborted - if ($.isFunction(this._request.abort)) { + if ('function' === typeof this._request.abort) { this._request.abort(); } @@ -3572,7 +3572,7 @@ S2.define('select2/data/ajax',[ if (self.options.get('debug') && window.console && console.error) { // Check to make sure that the response included a `results` key. - if (!results || !results.results || !$.isArray(results.results)) { + if (!results || !results.results || !Array.isArray(results.results)) { console.error( 'Select2: The AJAX results did not return an array in the ' + '`results` key of the response.' @@ -3631,7 +3631,7 @@ S2.define('select2/data/tags',[ decorated.call(this, $element, options); - if ($.isArray(tags)) { + if (Array.isArray(tags)) { for (var t = 0; t < tags.length; t++) { var tag = tags[t]; var item = this._normalizeItem(tag); @@ -3707,7 +3707,7 @@ S2.define('select2/data/tags',[ }; Tags.prototype.createTag = function (decorated, params) { - var term = $.trim(params.term); + var term = 'string' === typeof params.term ? params.term.trim() : ''; if (term === '') { return null; @@ -3800,7 +3800,7 @@ S2.define('select2/data/tokenizer',[ // Replace the search term if we have the search box if (this.$search.length) { this.$search.val(tokenData.term); - this.$search.focus(); + this.$search.trigger( 'focus' ); } params.term = tokenData.term; @@ -4047,10 +4047,10 @@ S2.define('select2/dropdown/search',[ container.on('open', function () { self.$search.attr('tabindex', 0); self.$search.attr('aria-owns', resultsId); - self.$search.focus(); + self.$search.trigger( 'focus' ); window.setTimeout(function () { - self.$search.focus(); + self.$search.trigger( 'focus' ); }, 0); }); @@ -4063,7 +4063,7 @@ S2.define('select2/dropdown/search',[ container.on('focus', function () { if (!container.isOpen()) { - self.$search.focus(); + self.$search.trigger( 'focus' ); } }); @@ -4878,7 +4878,7 @@ S2.define('select2/defaults',[ } } - if ($.isArray(options.language)) { + if (Array.isArray(options.language)) { var languages = new Translation(); options.language.push('en'); @@ -4941,7 +4941,7 @@ S2.define('select2/defaults',[ function matcher (params, data) { // Always return the object if there is nothing to compare - if ($.trim(params.term) === '') { + if ( 'undefined' === typeof params.term || ( 'string' === typeof params.term && '' === params.term.trim() ) ) { return data; } @@ -5513,7 +5513,7 @@ S2.define('select2/core',[ self.focusOnActiveElement(); } else { // Focus on the search if user starts typing. - $searchField.focus(); + $searchField.trigger( 'focus' ); // Focus back to active selection when finished typing. // Small delay so typed character can be read by screen reader. setTimeout(function(){ @@ -5533,7 +5533,7 @@ S2.define('select2/core',[ Select2.prototype.focusOnActiveElement = function () { // Don't mess with the focus on touchscreens because it causes havoc with on-screen keyboards. if (this.isOpen() && ! Utils.isTouchscreen()) { - this.$results.find('li.select2-results__option--highlighted').focus(); + this.$results.find('li.select2-results__option--highlighted').trigger( 'focus' ); } }; @@ -5724,7 +5724,7 @@ S2.define('select2/core',[ var newVal = args[0]; - if ($.isArray(newVal)) { + if (Array.isArray(newVal)) { newVal = $.map(newVal, function (obj) { return obj.toString(); }); @@ -5801,7 +5801,7 @@ S2.define('select2/compat/utils',[ function syncCssClasses ($dest, $src, adapter) { var classes, replacements = [], adapted; - classes = $.trim($dest.attr('class')); + classes = 'string' === typeof $dest.attr('class') ? $dest.attr('class').trim() : ''; if (classes) { classes = '' + classes; // for IE which returns object @@ -5814,7 +5814,7 @@ S2.define('select2/compat/utils',[ }); } - classes = $.trim($src.attr('class')); + classes = 'string' === typeof $src.attr('class') ? $src.attr('class').trim() : ''; if (classes) { classes = '' + classes; // for IE which returns object @@ -5855,7 +5855,7 @@ S2.define('select2/compat/containerCss',[ var containerCssClass = this.options.get('containerCssClass') || ''; - if ($.isFunction(containerCssClass)) { + if ('function' === typeof containerCssClass) { containerCssClass = containerCssClass(this.$element); } @@ -5881,7 +5881,7 @@ S2.define('select2/compat/containerCss',[ var containerCss = this.options.get('containerCss') || {}; - if ($.isFunction(containerCss)) { + if ('function' === typeof containerCss) { containerCss = containerCss(this.$element); } @@ -5912,7 +5912,7 @@ S2.define('select2/compat/dropdownCss',[ var dropdownCssClass = this.options.get('dropdownCssClass') || ''; - if ($.isFunction(dropdownCssClass)) { + if ('function' === typeof dropdownCssClass) { dropdownCssClass = dropdownCssClass(this.$element); } @@ -5938,7 +5938,7 @@ S2.define('select2/compat/dropdownCss',[ var dropdownCss = this.options.get('dropdownCss') || {}; - if ($.isFunction(dropdownCss)) { + if ('function' === typeof dropdownCss) { dropdownCss = dropdownCss(this.$element); } @@ -5985,7 +5985,7 @@ S2.define('select2/compat/initSelection',[ this.initSelection.call(null, this.$element, function (data) { self._isInitialized = true; - if (!$.isArray(data)) { + if (!Array.isArray(data)) { data = [data]; } @@ -6131,7 +6131,7 @@ S2.define('select2/compat/matcher',[ function wrappedMatcher (params, data) { var match = $.extend(true, {}, data); - if (params.term == null || $.trim(params.term) === '') { + if ( params.term == null || ( 'string' === typeof params.term && '' === params.term.trim() ) ) { return match; } @@ -6374,11 +6374,11 @@ S2.define('select2/selection/stopPropagation',[ $.fn.extend({ mousewheel: function(fn) { - return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel'); + return fn ? this.on('mousewheel', fn) : this.trigger('mousewheel'); }, unmousewheel: function(fn) { - return this.unbind('mousewheel', fn); + return this.off('mousewheel', fn); } }); From a75a3d71769002ebda137af1d821627cca5c76c7 Mon Sep 17 00:00:00 2001 From: roykho Date: Fri, 5 Feb 2021 06:51:57 -0800 Subject: [PATCH 254/368] Update .focus and .toggleClass that were missed --- assets/js/admin/meta-boxes-order.js | 4 ++-- assets/js/frontend/woocommerce.js | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/assets/js/admin/meta-boxes-order.js b/assets/js/admin/meta-boxes-order.js index 692b2d926be..f108dff0ec6 100644 --- a/assets/js/admin/meta-boxes-order.js +++ b/assets/js/admin/meta-boxes-order.js @@ -1470,7 +1470,7 @@ jQuery( function ( $ ) { 'fadeIn': 50, 'fadeOut': 50, 'delay': 0 - }).focus(); + }).trigger( 'focus' ); }, /** @@ -1483,7 +1483,7 @@ jQuery( function ( $ ) { 'fadeIn': 50, 'fadeOut': 50, 'delay': 0 - }).focus(); + }).trigger( 'focus' ); } }; diff --git a/assets/js/frontend/woocommerce.js b/assets/js/frontend/woocommerce.js index 169ac858226..be6a4e160e6 100644 --- a/assets/js/frontend/woocommerce.js +++ b/assets/js/frontend/woocommerce.js @@ -87,7 +87,11 @@ jQuery( function( $ ) { $( '.show-password-input' ).on( 'click', function() { - $( this ).toggleClass( 'display-password' ); + if ( $( this ).hasClass( 'display-password' ) ) { + $( this ).removeClass( 'display-password' ); + } else { + $( this ).addClass( 'display-password' ); + } if ( $( this ).hasClass( 'display-password' ) ) { $( this ).siblings( ['input[type="password"]'] ).prop( 'type', 'text' ); } else { From 6c804e31d7250b3cb372fc7af4dfd0394bc91720 Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 18 Feb 2021 06:35:24 -0800 Subject: [PATCH 255/368] Update deprecated hovers --- assets/js/flexslider/jquery.flexslider.js | 4 ++-- assets/js/jquery-tiptip/jquery.tipTip.js | 10 +++++----- assets/js/prettyPhoto/jquery.prettyPhoto.js | 4 ++-- .../admin/reports/class-wc-report-coupon-usage.php | 4 ++-- includes/admin/reports/class-wc-report-customers.php | 4 ++-- .../reports/class-wc-report-sales-by-category.php | 4 ++-- .../admin/reports/class-wc-report-sales-by-date.php | 4 ++-- .../admin/reports/class-wc-report-sales-by-product.php | 4 ++-- 8 files changed, 19 insertions(+), 19 deletions(-) diff --git a/assets/js/flexslider/jquery.flexslider.js b/assets/js/flexslider/jquery.flexslider.js index 71eb32d5d3f..dbf32efb237 100755 --- a/assets/js/flexslider/jquery.flexslider.js +++ b/assets/js/flexslider/jquery.flexslider.js @@ -137,9 +137,9 @@ // SLIDSESHOW if (slider.vars.slideshow) { if (slider.vars.pauseOnHover) { - slider.hover(function() { + slider.on( 'mouseenter', function() { if (!slider.manualPlay && !slider.manualPause) { slider.pause(); } - }, function() { + } ).on( 'mouseleave', function() { if (!slider.manualPause && !slider.manualPlay && !slider.stopped) { slider.play(); } }); } diff --git a/assets/js/jquery-tiptip/jquery.tipTip.js b/assets/js/jquery-tiptip/jquery.tipTip.js index 3aa2c639e74..810fc3aa76d 100644 --- a/assets/js/jquery-tiptip/jquery.tipTip.js +++ b/assets/js/jquery-tiptip/jquery.tipTip.js @@ -63,15 +63,15 @@ var timeout = false; if(opts.activation == "hover"){ - org_elem.hover(function(){ + org_elem.on( 'mouseenter', function(){ active_tiptip(); - }, function(){ + } ).on( 'mouseleave', function(){ if(!opts.keepAlive || !tiptip_holder.is(':hover')){ deactive_tiptip(); } }); if(opts.keepAlive){ - tiptip_holder.hover(function(){}, function(){ + tiptip_holder.on( 'mouseenter', function(){} ).on( 'mouseleave', function(){ deactive_tiptip(); }); } @@ -85,13 +85,13 @@ org_elem.on( 'click', function(){ active_tiptip(); return false; - }).on( 'hover', function(){},function(){ + }).on( 'mouseenter', function(){} ).on( 'mouseleave' ,function(){ if(!opts.keepAlive){ deactive_tiptip(); } }); if(opts.keepAlive){ - tiptip_holder.hover(function(){}, function(){ + tiptip_holder.on( 'mouseenter', function(){} ).on( 'mouseleave', function(){ deactive_tiptip(); }); } diff --git a/assets/js/prettyPhoto/jquery.prettyPhoto.js b/assets/js/prettyPhoto/jquery.prettyPhoto.js index 59334d51396..ea24b41ed26 100644 --- a/assets/js/prettyPhoto/jquery.prettyPhoto.js +++ b/assets/js/prettyPhoto/jquery.prettyPhoto.js @@ -788,10 +788,10 @@ return false; }); - $pp_pic_holder.find('.pp_content').hover( + $pp_pic_holder.find('.pp_content').on( 'mouseenter', function(){ $pp_pic_holder.find('.pp_gallery:not(.disabled)').fadeIn(); - }, + } ).on( 'mouseleave', function(){ $pp_pic_holder.find('.pp_gallery:not(.disabled)').fadeOut(); }); diff --git a/includes/admin/reports/class-wc-report-coupon-usage.php b/includes/admin/reports/class-wc-report-coupon-usage.php index 7d1a55c3d19..e5e8aade6d6 100644 --- a/includes/admin/reports/class-wc-report-coupon-usage.php +++ b/includes/admin/reports/class-wc-report-coupon-usage.php @@ -556,10 +556,10 @@ class WC_Report_Coupon_Usage extends WC_Admin_Report { drawGraph(); - jQuery('.highlight_series').hover( + jQuery('.highlight_series').on( 'mouseenter', function() { drawGraph( jQuery(this).data('series') ); - }, + } ).on( 'mouseleave', function() { drawGraph(); } diff --git a/includes/admin/reports/class-wc-report-customers.php b/includes/admin/reports/class-wc-report-customers.php index 5cff075d2d3..3366c01ef55 100644 --- a/includes/admin/reports/class-wc-report-customers.php +++ b/includes/admin/reports/class-wc-report-customers.php @@ -417,10 +417,10 @@ class WC_Report_Customers extends WC_Admin_Report { drawGraph(); - jQuery('.highlight_series').hover( + jQuery('.highlight_series').on( 'mouseenter', function() { drawGraph( jQuery(this).data('series') ); - }, + } ).on( 'mouseleave', function() { drawGraph(); } diff --git a/includes/admin/reports/class-wc-report-sales-by-category.php b/includes/admin/reports/class-wc-report-sales-by-category.php index 356fb668d7f..9df5e751c37 100644 --- a/includes/admin/reports/class-wc-report-sales-by-category.php +++ b/includes/admin/reports/class-wc-report-sales-by-category.php @@ -436,10 +436,10 @@ class WC_Report_Sales_By_Category extends WC_Admin_Report { drawGraph(); - jQuery('.highlight_series').hover( + jQuery('.highlight_series').on( 'mouseenter', function() { drawGraph( jQuery(this).data('series') ); - }, + } ).on( 'mouseleave', function() { drawGraph(); } diff --git a/includes/admin/reports/class-wc-report-sales-by-date.php b/includes/admin/reports/class-wc-report-sales-by-date.php index 48c561fd0d1..280aa359595 100644 --- a/includes/admin/reports/class-wc-report-sales-by-date.php +++ b/includes/admin/reports/class-wc-report-sales-by-date.php @@ -854,10 +854,10 @@ class WC_Report_Sales_By_Date extends WC_Admin_Report { drawGraph(); - jQuery('.highlight_series').hover( + jQuery('.highlight_series').on( 'mouseenter', function() { drawGraph( jQuery(this).data('series') ); - }, + } ).on( 'mouseleave', function() { drawGraph(); } diff --git a/includes/admin/reports/class-wc-report-sales-by-product.php b/includes/admin/reports/class-wc-report-sales-by-product.php index 5de38c4bbc5..0b7b8d26cdf 100644 --- a/includes/admin/reports/class-wc-report-sales-by-product.php +++ b/includes/admin/reports/class-wc-report-sales-by-product.php @@ -615,10 +615,10 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report { drawGraph(); - jQuery('.highlight_series').hover( + jQuery('.highlight_series').on( 'mouseenter', function() { drawGraph( jQuery(this).data('series') ); - }, + } ).on( 'mouseleave', function() { drawGraph(); } From 15df81e2d9c0439959c1b373f899500a14e9d5e0 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Mon, 22 Feb 2021 12:32:12 -0600 Subject: [PATCH 256/368] Correct bind usage in product import and export (bind wasn't targeting jQuery object; was native JS bind) --- assets/js/admin/wc-product-export.js | 2 +- assets/js/admin/wc-product-import.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/admin/wc-product-export.js b/assets/js/admin/wc-product-export.js index 84a065214b2..d49928ddb9e 100644 --- a/assets/js/admin/wc-product-export.js +++ b/assets/js/admin/wc-product-export.js @@ -11,7 +11,7 @@ this.$form.find('.woocommerce-exporter-progress').val( 0 ); // Methods. - this.processStep = this.processStep.on( this ); + this.processStep = this.processStep.bind( this ); // Events. $form.on( 'submit', { productExportForm: this }, this.onSubmit ); diff --git a/assets/js/admin/wc-product-import.js b/assets/js/admin/wc-product-import.js index 5222ac4c13f..645f11b5912 100644 --- a/assets/js/admin/wc-product-import.js +++ b/assets/js/admin/wc-product-import.js @@ -23,7 +23,7 @@ // Initial state. this.$form.find('.woocommerce-importer-progress').val( 0 ); - this.run_import = this.run_import.on( this ); + this.run_import = this.run_import.bind( this ); // Start importing. this.run_import(); From f5b3556e14b0b60585b4111bf2872ee69e245ecb Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Mon, 22 Feb 2021 13:10:49 -0600 Subject: [PATCH 257/368] Replace .data() call in checkout.js for jQuery 3 Compatibility --- assets/js/frontend/checkout.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/frontend/checkout.js b/assets/js/frontend/checkout.js index 9607862a5c2..06d2ad9684e 100644 --- a/assets/js/frontend/checkout.js +++ b/assets/js/frontend/checkout.js @@ -452,9 +452,9 @@ jQuery( function( $ ) { $( window ).off('beforeunload', this.handleUnloadEvent); }, blockOnSubmit: function( $form ) { - var form_data = $form.data(); + var isBlocked = $form.data( 'blockUI.isBlocked' ); - if ( 1 !== form_data['blockUI.isBlocked'] ) { + if ( 1 !== isBlocked ) { $form.block({ message: null, overlayCSS: { From 294b257710758b721c7d2f8301eefbe6066d4137 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Wed, 24 Feb 2021 12:25:17 -0600 Subject: [PATCH 258/368] Update cart-fragments.js to remove deprecated jQuery bind function --- assets/js/frontend/cart-fragments.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/frontend/cart-fragments.js b/assets/js/frontend/cart-fragments.js index c5eef7b4c72..e70ad4ad36c 100644 --- a/assets/js/frontend/cart-fragments.js +++ b/assets/js/frontend/cart-fragments.js @@ -180,7 +180,7 @@ jQuery( function( $ ) { wp.customize.widgetsPreview.WidgetPartial ); if ( hasSelectiveRefresh ) { - wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function() { + wp.customize.selectiveRefresh.on( 'partial-content-rendered', function() { refresh_cart_fragment(); } ); } From a61bd3c99d87821b1e1a0b0f00967ea5d151b326 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Wed, 24 Feb 2021 12:28:55 -0600 Subject: [PATCH 259/368] Update price-slider.js to remove deprecated jQuery bind function --- assets/js/frontend/price-slider.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/frontend/price-slider.js b/assets/js/frontend/price-slider.js index 2097dbae270..1c456527d96 100644 --- a/assets/js/frontend/price-slider.js +++ b/assets/js/frontend/price-slider.js @@ -76,7 +76,7 @@ jQuery( function( $ ) { wp.customize.widgetsPreview.WidgetPartial ); if ( hasSelectiveRefresh ) { - wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function() { + wp.customize.selectiveRefresh.on( 'partial-content-rendered', function() { init_price_filter(); } ); } From 7be2388e06c1b6c8a31f2b88aa6563ee4e22bebc Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Wed, 24 Feb 2021 12:44:32 -0600 Subject: [PATCH 260/368] Update jquery-ui-touch=punch.js to remove deprecated jQuery bind and unbind functions --- assets/js/jquery-ui-touch-punch/jquery-ui-touch-punch.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/jquery-ui-touch-punch/jquery-ui-touch-punch.js b/assets/js/jquery-ui-touch-punch/jquery-ui-touch-punch.js index 16ce41d1edf..27363a295c2 100644 --- a/assets/js/jquery-ui-touch-punch/jquery-ui-touch-punch.js +++ b/assets/js/jquery-ui-touch-punch/jquery-ui-touch-punch.js @@ -149,7 +149,7 @@ var self = this; // Delegate the touch handlers to the widget's element - self.element.bind({ + self.element.on({ touchstart: $.proxy(self, '_touchStart'), touchmove: $.proxy(self, '_touchMove'), touchend: $.proxy(self, '_touchEnd') @@ -167,7 +167,7 @@ var self = this; // Delegate the touch handlers to the widget's element - self.element.unbind({ + self.element.off({ touchstart: $.proxy(self, '_touchStart'), touchmove: $.proxy(self, '_touchMove'), touchend: $.proxy(self, '_touchEnd') From 24b787b2dab2b6b255cba8806d408962a6580bcc Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Tue, 2 Mar 2021 09:17:03 -0600 Subject: [PATCH 261/368] Update settings.js to resolve jQuery data change in jQuery 3 --- assets/js/admin/settings.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/js/admin/settings.js b/assets/js/admin/settings.js index d85af6f1951..72306309d24 100644 --- a/assets/js/admin/settings.js +++ b/assets/js/admin/settings.js @@ -48,15 +48,15 @@ event.stopPropagation(); $( '.iris-picker' ).hide(); $( this ).closest( 'td' ).find( '.iris-picker' ).show(); - $( this ).data( 'original-value', $( this ).val() ); + $( this ).data( 'originalValue', $( this ).val() ); }) .on( 'change', function() { if ( $( this ).is( '.iris-error' ) ) { - var original_value = $( this ).data( 'original-value' ); + var original_value = $( this ).data( 'originalValue' ); if ( original_value.match( /^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/ ) ) { - $( this ).val( $( this ).data( 'original-value' ) ).trigger( 'change' ); + $( this ).val( $( this ).data( 'originalValue' ) ).trigger( 'change' ); } else { $( this ).val( '' ).trigger( 'change' ); } From 8f013a9c9a3438415d9e33f8c29e7dc59dc2053d Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Tue, 2 Mar 2021 09:28:22 -0600 Subject: [PATCH 262/368] Update system-status.js to resolve jQuery data change in jQuery 3 --- assets/js/admin/system-status.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/admin/system-status.js b/assets/js/admin/system-status.js index 6cdb54d14cf..a2457530a5a 100644 --- a/assets/js/admin/system-status.js +++ b/assets/js/admin/system-status.js @@ -33,11 +33,11 @@ jQuery( function ( $ ) { $( '.wc_status_table thead, .wc_status_table tbody' ).each( function() { if ( $( this ).is( 'thead' ) ) { - var label = $( this ).find( 'th:eq(0)' ).data( 'export-label' ) || $( this ).text(); + var label = $( this ).find( 'th:eq(0)' ).data( 'exportLabel' ) || $( this ).text(); report = report + '\n### ' + label.trim() + ' ###\n\n'; } else { $( 'tr', $( this ) ).each( function() { - var label = $( this ).find( 'td:eq(0)' ).data( 'export-label' ) || $( this ).find( 'td:eq(0)' ).text(); + var label = $( this ).find( 'td:eq(0)' ).data( 'exportLabel' ) || $( this ).find( 'td:eq(0)' ).text(); var the_name = label.trim().replace( /(<([^>]+)>)/ig, '' ); // Remove HTML. // Find value From f685cda40d8de00df95bd294659675cf682b8e6b Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Tue, 2 Mar 2021 09:34:00 -0600 Subject: [PATCH 263/368] Update wc-orders.js to resolve jQuery data change in jQuery 3 --- assets/js/admin/wc-orders.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/js/admin/wc-orders.js b/assets/js/admin/wc-orders.js index 018e6a23aa3..4fafc95ff81 100644 --- a/assets/js/admin/wc-orders.js +++ b/assets/js/admin/wc-orders.js @@ -45,12 +45,12 @@ jQuery( function( $ ) { */ WCOrdersTable.prototype.onPreview = function() { var $previewButton = $( this ), - $order_id = $previewButton.data( 'order-id' ); + $order_id = $previewButton.data( 'orderId' ); if ( $previewButton.data( 'order-data' ) ) { $( this ).WCBackboneModal({ template: 'wc-modal-view-order', - variable : $previewButton.data( 'order-data' ) + variable : $previewButton.data( 'orderData' ) }); } else { $previewButton.addClass( 'disabled' ); @@ -67,7 +67,7 @@ jQuery( function( $ ) { $( '.order-preview' ).removeClass( 'disabled' ); if ( response.success ) { - $previewButton.data( 'order-data', response.data ); + $previewButton.data( 'orderData', response.data ); $( this ).WCBackboneModal({ template: 'wc-modal-view-order', From a95f084d9ffed13b1f0654fa33a97b617d9fbf11 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Tue, 2 Mar 2021 09:37:59 -0600 Subject: [PATCH 264/368] Update woocommerce.js to resolve jQuery data change in jQuery 3 --- assets/js/frontend/woocommerce.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/frontend/woocommerce.js b/assets/js/frontend/woocommerce.js index be6a4e160e6..b10ad50d951 100644 --- a/assets/js/frontend/woocommerce.js +++ b/assets/js/frontend/woocommerce.js @@ -14,7 +14,7 @@ jQuery( function( $ ) { } }); - var noticeID = $( '.woocommerce-store-notice' ).data( 'notice-id' ) || '', + var noticeID = $( '.woocommerce-store-notice' ).data( 'noticeId' ) || '', cookieName = 'store_notice' + noticeID; // Check the value of that cookie and show/hide the notice accordingly From c9b101209541b288b8c5c3980e0a42898e6ec83d Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Tue, 2 Mar 2021 09:45:28 -0600 Subject: [PATCH 265/368] Update stupidtable.js to resolve jQuery data change in jQuery 3 --- assets/js/stupidtable/stupidtable.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/js/stupidtable/stupidtable.js b/assets/js/stupidtable/stupidtable.js index 017a9fd543b..063f7c8cfb5 100644 --- a/assets/js/stupidtable/stupidtable.js +++ b/assets/js/stupidtable/stupidtable.js @@ -32,9 +32,9 @@ th_index = th_index - 1; // Determine (and/or reverse) sorting direction, default `asc` - var sort_dir = $this.data("sort-default") || dir.ASC; - if ($this.data("sort-dir")) - sort_dir = $this.data("sort-dir") === dir.ASC ? dir.DESC : dir.ASC; + var sort_dir = $this.data("sortDefault") || dir.ASC; + if ($this.data("sortDir")) + sort_dir = $this.data("sortDir") === dir.ASC ? dir.DESC : dir.ASC; // Choose appropriate sorting function. var type = $this.data("sort") || null; @@ -65,7 +65,7 @@ // with the TR itself into a tuple trs.each(function(index,tr) { var $e = $(tr).children().eq(th_index); - var sort_val = $e.data("sort-value"); + var sort_val = $e.data("sortValue"); var order_by = typeof(sort_val) !== "undefined" ? sort_val : $e.text(); column.push([order_by, tr]); }); @@ -83,8 +83,8 @@ }); // Reset siblings - $table.find("th").data("sort-dir", null).removeClass("sorting-desc sorting-asc"); - $this.data("sort-dir", sort_dir).addClass("sorting-"+sort_dir); + $table.find("th").data("sortDir", null).removeClass("sorting-desc sorting-asc"); + $this.data("sortDir", sort_dir).addClass("sorting-"+sort_dir); // Trigger `aftertablesort` event. Similar to `beforetablesort` $table.trigger("aftertablesort", {column: $this.index(), direction: sort_dir}); From a09e82e4b6c52b888501a2e6b3b6486bed0414ca Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Thu, 4 Mar 2021 12:11:36 -0600 Subject: [PATCH 266/368] Update select2.full.js to use trigger('focus') instead of focus() for jQuery 3 compat --- assets/js/select2/select2.full.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/js/select2/select2.full.js b/assets/js/select2/select2.full.js index 49cb11ee692..e9be451ea3b 100644 --- a/assets/js/select2/select2.full.js +++ b/assets/js/select2/select2.full.js @@ -1430,7 +1430,7 @@ S2.define('select2/selection/base',[ // This needs to be delayed as the active element is the body when the // key is pressed. window.setTimeout(function () { - self.$selection.focus(); + self.$selection.trigger( 'focus' ); }, 1); self._detachCloseHandler(container); @@ -1591,7 +1591,7 @@ S2.define('select2/selection/single',[ container.on('focus', function (evt) { if (!container.isOpen()) { - self.$selection.focus(); + self.$selection.trigger( 'focus' ); } }); @@ -2109,7 +2109,7 @@ S2.define('select2/selection/search',[ this.resizeSearch(); if (searchHadFocus) { - this.$search.focus(); + this.$search.trigger( 'focus' ); } }; @@ -3800,7 +3800,7 @@ S2.define('select2/data/tokenizer',[ // Replace the search term if we have the search box if (this.$search.length) { this.$search.val(tokenData.term); - this.$search.focus(); + this.$search.trigger( 'focus' ); } params.term = tokenData.term; @@ -4047,10 +4047,10 @@ S2.define('select2/dropdown/search',[ container.on('open', function () { self.$search.attr('tabindex', 0); self.$search.attr('aria-owns', resultsId); - self.$search.focus(); + self.$search.trigger( 'focus' ); window.setTimeout(function () { - self.$search.focus(); + self.$search.trigger( 'focus' ); }, 0); }); @@ -4063,7 +4063,7 @@ S2.define('select2/dropdown/search',[ container.on('focus', function () { if (!container.isOpen()) { - self.$search.focus(); + self.$search.trigger( 'focus' ); } }); From ce12a2a89582258ec27a154fbcce27180b1daa17 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Thu, 4 Mar 2021 12:17:18 -0600 Subject: [PATCH 267/368] Update select2.full.js to use trigger('focus') instead of focus() for jQuery 3 compat --- assets/js/select2/select2.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assets/js/select2/select2.js b/assets/js/select2/select2.js index 3f27bbd4032..0adb782a691 100644 --- a/assets/js/select2/select2.js +++ b/assets/js/select2/select2.js @@ -1430,7 +1430,7 @@ S2.define('select2/selection/base',[ // This needs to be delayed as the active element is the body when the // key is pressed. window.setTimeout(function () { - self.$selection.focus(); + self.$selection.trigger( 'focus' ); }, 1); self._detachCloseHandler(container); @@ -1591,7 +1591,7 @@ S2.define('select2/selection/single',[ container.on('focus', function (evt) { if (!container.isOpen()) { - self.$selection.focus(); + self.$selection.trigger( 'focus' ); } }); @@ -2109,7 +2109,7 @@ S2.define('select2/selection/search',[ this.resizeSearch(); if (searchHadFocus) { - this.$search.focus(); + this.$search.trigger( 'focus' ); } }; @@ -3800,7 +3800,7 @@ S2.define('select2/data/tokenizer',[ // Replace the search term if we have the search box if (this.$search.length) { this.$search.val(tokenData.term); - this.$search.focus(); + this.$search.trigger( 'focus' ); } params.term = tokenData.term; @@ -4047,10 +4047,10 @@ S2.define('select2/dropdown/search',[ container.on('open', function () { self.$search.attr('tabindex', 0); self.$search.attr('aria-owns', resultsId); - self.$search.focus(); + self.$search.trigger( 'focus' ); window.setTimeout(function () { - self.$search.focus(); + self.$search.trigger( 'focus' ); }, 0); }); @@ -4063,7 +4063,7 @@ S2.define('select2/dropdown/search',[ container.on('focus', function () { if (!container.isOpen()) { - self.$search.focus(); + self.$search.trigger( 'focus' ); } }); From 2e4c7d93c2babcd1e94136da724385bbc2282a1e Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Thu, 4 Mar 2021 12:42:03 -0600 Subject: [PATCH 268/368] Update selectWoo.js to use trigger('focus') instead of focus() for jQuery 3 compat --- assets/js/selectWoo/selectWoo.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/assets/js/selectWoo/selectWoo.js b/assets/js/selectWoo/selectWoo.js index 3f27bbd4032..932a1fe6c7a 100644 --- a/assets/js/selectWoo/selectWoo.js +++ b/assets/js/selectWoo/selectWoo.js @@ -1430,7 +1430,7 @@ S2.define('select2/selection/base',[ // This needs to be delayed as the active element is the body when the // key is pressed. window.setTimeout(function () { - self.$selection.focus(); + self.$selection.trigger( 'focus' ); }, 1); self._detachCloseHandler(container); @@ -1487,7 +1487,7 @@ S2.define('select2/selection/base',[ // Timeout of 1 required for close to finish wrapping up. setTimeout(function(){ $this.find('*:focus').blur(); - $target.focus(); + $target.trigger( 'focus' ); }, 1); }); }); @@ -1591,7 +1591,7 @@ S2.define('select2/selection/single',[ container.on('focus', function (evt) { if (!container.isOpen()) { - self.$selection.focus(); + self.$selection.trigger( 'focus' ); } }); @@ -1737,7 +1737,7 @@ S2.define('select2/selection/multiple',[ // This gets reset automatically when focus is triggered. self._keyUpPrevented = true; - self.$search.focus(); + self.$search.trigger( 'focus' ); }, 1); } } @@ -2109,7 +2109,7 @@ S2.define('select2/selection/search',[ this.resizeSearch(); if (searchHadFocus) { - this.$search.focus(); + this.$search.trigger( 'focus' ); } }; @@ -3800,7 +3800,7 @@ S2.define('select2/data/tokenizer',[ // Replace the search term if we have the search box if (this.$search.length) { this.$search.val(tokenData.term); - this.$search.focus(); + this.$search.trigger( 'focus' ); } params.term = tokenData.term; @@ -4047,10 +4047,10 @@ S2.define('select2/dropdown/search',[ container.on('open', function () { self.$search.attr('tabindex', 0); self.$search.attr('aria-owns', resultsId); - self.$search.focus(); + self.$search.trigger( 'focus' ); window.setTimeout(function () { - self.$search.focus(); + self.$search.trigger( 'focus' ); }, 0); }); @@ -4063,7 +4063,7 @@ S2.define('select2/dropdown/search',[ container.on('focus', function () { if (!container.isOpen()) { - self.$search.focus(); + self.$search.trigger( 'focus' ); } }); @@ -5513,7 +5513,7 @@ S2.define('select2/core',[ self.focusOnActiveElement(); } else { // Focus on the search if user starts typing. - $searchField.focus(); + $searchField.trigger( 'focus' ); // Focus back to active selection when finished typing. // Small delay so typed character can be read by screen reader. setTimeout(function(){ @@ -5533,7 +5533,7 @@ S2.define('select2/core',[ Select2.prototype.focusOnActiveElement = function () { // Don't mess with the focus on touchscreens because it causes havoc with on-screen keyboards. if (this.isOpen() && ! Utils.isTouchscreen()) { - this.$results.find('li.select2-results__option--highlighted').focus(); + this.$results.find('li.select2-results__option--highlighted').trigger( 'focus' ); } }; From 89e9e2932dd9bb42e8422907aa44159a8afa740f Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Thu, 4 Mar 2021 14:16:44 -0600 Subject: [PATCH 269/368] Update select2.full.js to use on() instead of bind() for jQuery 3 compat --- assets/js/select2/select2.full.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/select2/select2.full.js b/assets/js/select2/select2.full.js index e9be451ea3b..06adac0a313 100644 --- a/assets/js/select2/select2.full.js +++ b/assets/js/select2/select2.full.js @@ -6374,7 +6374,7 @@ S2.define('select2/selection/stopPropagation',[ $.fn.extend({ mousewheel: function(fn) { - return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel'); + return fn ? this.on('mousewheel', fn) : this.trigger('mousewheel'); }, unmousewheel: function(fn) { From fc93c2474d4e520c8e4bb7f4bf3e2094ec81b6b8 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Thu, 4 Mar 2021 16:20:02 -0600 Subject: [PATCH 270/368] Update select2.full.js to use off() instead of unbind() for jQuery 3 compat --- assets/js/select2/select2.full.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/select2/select2.full.js b/assets/js/select2/select2.full.js index 06adac0a313..92b37c6b581 100644 --- a/assets/js/select2/select2.full.js +++ b/assets/js/select2/select2.full.js @@ -6378,7 +6378,7 @@ S2.define('select2/selection/stopPropagation',[ }, unmousewheel: function(fn) { - return this.unbind('mousewheel', fn); + return this.off('mousewheel', fn); } }); From e62ea96a3e9a6c8335b9af2c7869a0d8a43d5bc9 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Thu, 4 Mar 2021 16:31:59 -0600 Subject: [PATCH 271/368] Update select2.full.js to use Array.isArray instead of jQuery.isArray for jQuery 3 compat --- assets/js/select2/select2.full.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/js/select2/select2.full.js b/assets/js/select2/select2.full.js index 92b37c6b581..affbec21b14 100644 --- a/assets/js/select2/select2.full.js +++ b/assets/js/select2/select2.full.js @@ -3572,7 +3572,7 @@ S2.define('select2/data/ajax',[ if (self.options.get('debug') && window.console && console.error) { // Check to make sure that the response included a `results` key. - if (!results || !results.results || !$.isArray(results.results)) { + if (!results || !results.results || ! Array.isArray( results.results ) ) { console.error( 'Select2: The AJAX results did not return an array in the ' + '`results` key of the response.' @@ -3631,7 +3631,7 @@ S2.define('select2/data/tags',[ decorated.call(this, $element, options); - if ($.isArray(tags)) { + if ( Array.isArray( tags ) ) { for (var t = 0; t < tags.length; t++) { var tag = tags[t]; var item = this._normalizeItem(tag); @@ -4878,7 +4878,7 @@ S2.define('select2/defaults',[ } } - if ($.isArray(options.language)) { + if ( Array.isArray( options.language ) ) { var languages = new Translation(); options.language.push('en'); @@ -5724,7 +5724,7 @@ S2.define('select2/core',[ var newVal = args[0]; - if ($.isArray(newVal)) { + if ( Array.isArray( newVal ) ) { newVal = $.map(newVal, function (obj) { return obj.toString(); }); @@ -5985,7 +5985,7 @@ S2.define('select2/compat/initSelection',[ this.initSelection.call(null, this.$element, function (data) { self._isInitialized = true; - if (!$.isArray(data)) { + if ( ! Array.isArray( data ) ) { data = [data]; } From 944d5c06c1ed50fdfeded0a1f1d4f11fb57ba905 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Thu, 4 Mar 2021 16:33:47 -0600 Subject: [PATCH 272/368] Update select2.js to use Array.isArray instead of jQuery.isArray for jQuery 3 compat --- assets/js/select2/select2.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/js/select2/select2.js b/assets/js/select2/select2.js index 0adb782a691..e4e214893aa 100644 --- a/assets/js/select2/select2.js +++ b/assets/js/select2/select2.js @@ -3572,7 +3572,7 @@ S2.define('select2/data/ajax',[ if (self.options.get('debug') && window.console && console.error) { // Check to make sure that the response included a `results` key. - if (!results || !results.results || !$.isArray(results.results)) { + if (!results || !results.results || ! Array.isArray( results.results ) ) { console.error( 'Select2: The AJAX results did not return an array in the ' + '`results` key of the response.' @@ -3631,7 +3631,7 @@ S2.define('select2/data/tags',[ decorated.call(this, $element, options); - if ($.isArray(tags)) { + if ( Array.isArray( tags ) ) { for (var t = 0; t < tags.length; t++) { var tag = tags[t]; var item = this._normalizeItem(tag); @@ -4878,7 +4878,7 @@ S2.define('select2/defaults',[ } } - if ($.isArray(options.language)) { + if ( Array.isArray( options.language ) ) { var languages = new Translation(); options.language.push('en'); @@ -5724,7 +5724,7 @@ S2.define('select2/core',[ var newVal = args[0]; - if ($.isArray(newVal)) { + if ( Array.isArray( newVal ) ) { newVal = $.map(newVal, function (obj) { return obj.toString(); }); From 8a2702d0cd88fa896e64a2bdfb9984369ecf3773 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Thu, 4 Mar 2021 16:40:22 -0600 Subject: [PATCH 273/368] Update selectWoo.js to use Array.isArray instead of jQuery.isArray for jQuery 3 compat --- assets/js/selectWoo/selectWoo.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/js/selectWoo/selectWoo.js b/assets/js/selectWoo/selectWoo.js index 932a1fe6c7a..64c1a70d648 100644 --- a/assets/js/selectWoo/selectWoo.js +++ b/assets/js/selectWoo/selectWoo.js @@ -3572,7 +3572,7 @@ S2.define('select2/data/ajax',[ if (self.options.get('debug') && window.console && console.error) { // Check to make sure that the response included a `results` key. - if (!results || !results.results || !$.isArray(results.results)) { + if (!results || !results.results || ! Array.isArray( results.results ) ) { console.error( 'Select2: The AJAX results did not return an array in the ' + '`results` key of the response.' @@ -3631,7 +3631,7 @@ S2.define('select2/data/tags',[ decorated.call(this, $element, options); - if ($.isArray(tags)) { + if ( Array.isArray( tags ) ) { for (var t = 0; t < tags.length; t++) { var tag = tags[t]; var item = this._normalizeItem(tag); @@ -4878,7 +4878,7 @@ S2.define('select2/defaults',[ } } - if ($.isArray(options.language)) { + if ( Array.isArray( options.language ) ) { var languages = new Translation(); options.language.push('en'); @@ -5724,7 +5724,7 @@ S2.define('select2/core',[ var newVal = args[0]; - if ($.isArray(newVal)) { + if ( Array.isArray( newVal ) ) { newVal = $.map(newVal, function (obj) { return obj.toString(); }); From 2e0c538e8f038828010ba7ce3ab9c14fd84d67fd Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Thu, 4 Mar 2021 17:05:09 -0600 Subject: [PATCH 274/368] Update select2.full.js to use typeof check instead of jQuery.isFunction() for jQuery 3 compatibility --- assets/js/select2/select2.full.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/js/select2/select2.full.js b/assets/js/select2/select2.full.js index affbec21b14..84d3be231f0 100644 --- a/assets/js/select2/select2.full.js +++ b/assets/js/select2/select2.full.js @@ -3547,7 +3547,7 @@ S2.define('select2/data/ajax',[ if (this._request != null) { // JSONP requests cannot always be aborted - if ($.isFunction(this._request.abort)) { + if ( typeof this._request.abort === 'function' ) { this._request.abort(); } @@ -5855,7 +5855,7 @@ S2.define('select2/compat/containerCss',[ var containerCssClass = this.options.get('containerCssClass') || ''; - if ($.isFunction(containerCssClass)) { + if ( typeof containerCssClass === 'function' ) { containerCssClass = containerCssClass(this.$element); } @@ -5881,7 +5881,7 @@ S2.define('select2/compat/containerCss',[ var containerCss = this.options.get('containerCss') || {}; - if ($.isFunction(containerCss)) { + if ( typeof containerCss === 'function' ) { containerCss = containerCss(this.$element); } @@ -5912,7 +5912,7 @@ S2.define('select2/compat/dropdownCss',[ var dropdownCssClass = this.options.get('dropdownCssClass') || ''; - if ($.isFunction(dropdownCssClass)) { + if ( typeof dropdownCssClass === 'function' ) { dropdownCssClass = dropdownCssClass(this.$element); } @@ -5938,7 +5938,7 @@ S2.define('select2/compat/dropdownCss',[ var dropdownCss = this.options.get('dropdownCss') || {}; - if ($.isFunction(dropdownCss)) { + if ( typeof dropdownCss === 'function' ) { dropdownCss = dropdownCss(this.$element); } From 56dbdedfb2da1b6e6d6cb80d5d91262b18a7e9c2 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Thu, 4 Mar 2021 17:06:59 -0600 Subject: [PATCH 275/368] Update select2.js to use typeof check instead of jQuery.isFunction() for jQuery 3 compatibility --- assets/js/select2/select2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/select2/select2.js b/assets/js/select2/select2.js index e4e214893aa..b4500ad61a5 100644 --- a/assets/js/select2/select2.js +++ b/assets/js/select2/select2.js @@ -3547,7 +3547,7 @@ S2.define('select2/data/ajax',[ if (this._request != null) { // JSONP requests cannot always be aborted - if ($.isFunction(this._request.abort)) { + if ( typeof this._request.abort === 'function' ) { this._request.abort(); } From a7d6e6033436e5bf4e639c812bb91efbd4acd4c1 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Thu, 4 Mar 2021 17:08:14 -0600 Subject: [PATCH 276/368] Update selectWoo.js to use typeof check instead of jQuery.isFunction() for jQuery 3 compatibility --- assets/js/selectWoo/selectWoo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/selectWoo/selectWoo.js b/assets/js/selectWoo/selectWoo.js index 64c1a70d648..ad7def6b164 100644 --- a/assets/js/selectWoo/selectWoo.js +++ b/assets/js/selectWoo/selectWoo.js @@ -3547,7 +3547,7 @@ S2.define('select2/data/ajax',[ if (this._request != null) { // JSONP requests cannot always be aborted - if ($.isFunction(this._request.abort)) { + if ( typeof this._request.abort === 'function' ) { this._request.abort(); } From 80261317674fcf7971ab985f100b1f626fe53925 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Fri, 5 Mar 2021 11:22:47 -0600 Subject: [PATCH 277/368] Update select2.full.js to use String.prototype.trim instead of jQuery.trim --- assets/js/select2/select2.full.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/js/select2/select2.full.js b/assets/js/select2/select2.full.js index 84d3be231f0..91ed6d34f63 100644 --- a/assets/js/select2/select2.full.js +++ b/assets/js/select2/select2.full.js @@ -3707,7 +3707,7 @@ S2.define('select2/data/tags',[ }; Tags.prototype.createTag = function (decorated, params) { - var term = $.trim(params.term); + var term = params.term.trim(); if (term === '') { return null; @@ -4941,7 +4941,7 @@ S2.define('select2/defaults',[ function matcher (params, data) { // Always return the object if there is nothing to compare - if ($.trim(params.term) === '') { + if ( params.term.trim() === '' ) { return data; } @@ -5801,7 +5801,7 @@ S2.define('select2/compat/utils',[ function syncCssClasses ($dest, $src, adapter) { var classes, replacements = [], adapted; - classes = $.trim($dest.attr('class')); + classes = $dest.attr('class').trim(); if (classes) { classes = '' + classes; // for IE which returns object @@ -5814,7 +5814,7 @@ S2.define('select2/compat/utils',[ }); } - classes = $.trim($src.attr('class')); + classes = $src.attr('class').trim(); if (classes) { classes = '' + classes; // for IE which returns object @@ -6131,7 +6131,7 @@ S2.define('select2/compat/matcher',[ function wrappedMatcher (params, data) { var match = $.extend(true, {}, data); - if (params.term == null || $.trim(params.term) === '') { + if (params.term == null || params.term.trim() === '') { return match; } From 6f1a1b249231f8a7f683ab1acb659e203bd9b466 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Fri, 5 Mar 2021 11:25:13 -0600 Subject: [PATCH 278/368] Update select2.js to use String.prototype.trim instead of jQuery.trim --- assets/js/select2/select2.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/select2/select2.js b/assets/js/select2/select2.js index b4500ad61a5..99431250b9a 100644 --- a/assets/js/select2/select2.js +++ b/assets/js/select2/select2.js @@ -3707,7 +3707,7 @@ S2.define('select2/data/tags',[ }; Tags.prototype.createTag = function (decorated, params) { - var term = $.trim(params.term); + var term = params.term.trim(); if (term === '') { return null; @@ -4941,7 +4941,7 @@ S2.define('select2/defaults',[ function matcher (params, data) { // Always return the object if there is nothing to compare - if ($.trim(params.term) === '') { + if ( params.term.trim() === '' ) { return data; } From 1f7f12c4abf6d7a38cd38f5f7502d666fbaf5c5e Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Fri, 5 Mar 2021 11:34:34 -0600 Subject: [PATCH 279/368] Update selectWoo.js to use String.prototype.trim instead of jQuery.trim --- assets/js/selectWoo/selectWoo.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/selectWoo/selectWoo.js b/assets/js/selectWoo/selectWoo.js index ad7def6b164..4e95b52e75b 100644 --- a/assets/js/selectWoo/selectWoo.js +++ b/assets/js/selectWoo/selectWoo.js @@ -3707,7 +3707,7 @@ S2.define('select2/data/tags',[ }; Tags.prototype.createTag = function (decorated, params) { - var term = $.trim(params.term); + var term = params.term.trim(); if (term === '') { return null; @@ -4941,7 +4941,7 @@ S2.define('select2/defaults',[ function matcher (params, data) { // Always return the object if there is nothing to compare - if ($.trim(params.term) === '') { + if ( params.term.trim() === '' ) { return data; } From 09da77eb18ca7f628e9497702233851df4c2bfdb Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Fri, 5 Mar 2021 12:58:12 -0600 Subject: [PATCH 280/368] Update wc-setup.js to set required prop to false instead of removing attribute for jQuery3 compat --- assets/js/admin/wc-setup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/wc-setup.js b/assets/js/admin/wc-setup.js index ab29f8c4acd..fb24eba10b7 100644 --- a/assets/js/admin/wc-setup.js +++ b/assets/js/admin/wc-setup.js @@ -96,7 +96,7 @@ jQuery( function( $ ) { if ( $.isEmptyObject( country_postcode_obj ) || country_postcode_obj.required ) { $store_postcode_input.attr( 'required', 'true' ); } else { - $store_postcode_input.removeAttr( 'required' ); + $store_postcode_input.prop( 'required', false ); } } ); From 581e402f09245be55ed35dd5c34da328b71025e8 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Fri, 5 Mar 2021 14:40:07 -0600 Subject: [PATCH 281/368] Update selectWoo.js to trigger blur instead of using deprecated blur method for jQuery3 compat --- assets/js/selectWoo/selectWoo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/selectWoo/selectWoo.js b/assets/js/selectWoo/selectWoo.js index 4e95b52e75b..1e894251667 100644 --- a/assets/js/selectWoo/selectWoo.js +++ b/assets/js/selectWoo/selectWoo.js @@ -1486,7 +1486,7 @@ S2.define('select2/selection/base',[ // Remove any focus when dropdown is closed by clicking outside the select area. // Timeout of 1 required for close to finish wrapping up. setTimeout(function(){ - $this.find('*:focus').blur(); + $this.find('*:focus').trigger( 'blur' ); $target.trigger( 'focus' ); }, 1); }); From 38e448a42717b6673b68b0d714853dc8c8ae7e31 Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 07:26:10 -0800 Subject: [PATCH 282/368] Update deprecated jQuery functions for jquery.cookie.js --- assets/js/zeroclipboard/jquery.zeroclipboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/zeroclipboard/jquery.zeroclipboard.js b/assets/js/zeroclipboard/jquery.zeroclipboard.js index 5f64fe299df..dcf333e2856 100644 --- a/assets/js/zeroclipboard/jquery.zeroclipboard.js +++ b/assets/js/zeroclipboard/jquery.zeroclipboard.js @@ -474,7 +474,7 @@ * The underlying implementation of `ZeroClipboard.destroy`. * @private */ - var _destroy = function() { + var _destroy = function() {console.log('zero', ZeroClipboard); ZeroClipboard.clearData(); ZeroClipboard.blur(); ZeroClipboard.emit("destroy"); From e0940ef78d338c7b07e2623a75ae6e0801814d76 Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 07:33:49 -0800 Subject: [PATCH 283/368] Update deprecated jQuery functions for jquery.tiptip.js --- assets/js/zeroclipboard/jquery.zeroclipboard.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/zeroclipboard/jquery.zeroclipboard.js b/assets/js/zeroclipboard/jquery.zeroclipboard.js index dcf333e2856..5f64fe299df 100644 --- a/assets/js/zeroclipboard/jquery.zeroclipboard.js +++ b/assets/js/zeroclipboard/jquery.zeroclipboard.js @@ -474,7 +474,7 @@ * The underlying implementation of `ZeroClipboard.destroy`. * @private */ - var _destroy = function() {console.log('zero', ZeroClipboard); + var _destroy = function() { ZeroClipboard.clearData(); ZeroClipboard.blur(); ZeroClipboard.emit("destroy"); From 796d4f51ac49ddbb5add998f30b97175d2dad266 Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 08:17:41 -0800 Subject: [PATCH 284/368] Update deprecated jQuery functions for meta-boxes-order.js --- assets/js/admin/meta-boxes-order.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/admin/meta-boxes-order.js b/assets/js/admin/meta-boxes-order.js index f108dff0ec6..a77340cd9a6 100644 --- a/assets/js/admin/meta-boxes-order.js +++ b/assets/js/admin/meta-boxes-order.js @@ -117,8 +117,8 @@ jQuery( function ( $ ) { }, init_tiptip: function() { - $( '#tiptip_holder' ).removeAttr( 'style' ); - $( '#tiptip_arrow' ).removeAttr( 'style' ); + $( '#tiptip_holder' )[0].removeAttribute( 'style' ); + $( '#tiptip_arrow' )[0].removeAttribute( 'style' ); $( '.tips' ).tipTip({ 'attribute': 'data-tip', 'fadeIn': 50, From 38cabd27fd5827e1c933b6ed63a2408a1e1ac5bd Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 08:40:24 -0800 Subject: [PATCH 285/368] Update deprecated jQuery functions for meta-boxes-product-variation.js --- assets/js/admin/meta-boxes-product-variation.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/admin/meta-boxes-product-variation.js b/assets/js/admin/meta-boxes-product-variation.js index fbb9701f04d..d55cac3035d 100644 --- a/assets/js/admin/meta-boxes-product-variation.js +++ b/assets/js/admin/meta-boxes-product-variation.js @@ -116,8 +116,8 @@ jQuery( function( $ ) { } // Init TipTip - $( '#tiptip_holder' ).removeAttr( 'style' ); - $( '#tiptip_arrow' ).removeAttr( 'style' ); + $( '#tiptip_holder' )[0].removeAttribute( 'style' ); + $( '#tiptip_arrow' )[0].removeAttribute( 'style' ); $( '.woocommerce_variations .tips, .woocommerce_variations .help_tip, .woocommerce_variations .woocommerce-help-tip', wrapper ) .tipTip({ 'attribute': 'data-tip', From 65228932776de2d6a94b09d8ff89ba0c061e6924 Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 08:47:13 -0800 Subject: [PATCH 286/368] Update deprecated jQuery functions for meta-boxes-product.js --- assets/js/admin/meta-boxes-product.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/js/admin/meta-boxes-product.js b/assets/js/admin/meta-boxes-product.js index e9cad28e4c6..0d60a41ce64 100644 --- a/assets/js/admin/meta-boxes-product.js +++ b/assets/js/admin/meta-boxes-product.js @@ -404,7 +404,7 @@ jQuery( function( $ ) { ui.item.css( 'background-color', '#f6f6f6' ); }, stop: function( event, ui ) { - ui.item.removeAttr( 'style' ); + ui.item[0].removeAttribute( 'style' ); attribute_row_indexes(); } }); @@ -501,7 +501,7 @@ jQuery( function( $ ) { var this_page = window.location.toString(); this_page = this_page.replace( 'post-new.php?', 'post.php?post=' + woocommerce_admin_meta_boxes.post_id + '&action=edit&' ); - $( '#variable_product_options' ).load( this_page + ' #variable_product_options_inner', function() { + $( '#variable_product_options' ).on( 'load', this_page + ' #variable_product_options_inner', function() { $( '#variable_product_options' ).trigger( 'reload' ); } ); } @@ -661,7 +661,7 @@ jQuery( function( $ ) { ui.item.css( 'background-color', '#f6f6f6' ); }, stop: function( event, ui ) { - ui.item.removeAttr( 'style' ); + ui.item[0].removeAttribute( 'style' ); }, update: function() { var attachment_ids = ''; @@ -689,8 +689,8 @@ jQuery( function( $ ) { $image_gallery_ids.val( attachment_ids ); // Remove any lingering tooltips. - $( '#tiptip_holder' ).removeAttr( 'style' ); - $( '#tiptip_arrow' ).removeAttr( 'style' ); + $( '#tiptip_holder' )[0].removeAttribute( 'style' ); + $( '#tiptip_arrow' )[0].removeAttribute( 'style' ); return false; }); From a98b27bd54377a46ec44908d99b05813c4f42cd7 Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 09:04:39 -0800 Subject: [PATCH 287/368] Update deprecated jQuery functions for meta-boxes-product.js --- assets/js/admin/meta-boxes-product.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/js/admin/meta-boxes-product.js b/assets/js/admin/meta-boxes-product.js index 0d60a41ce64..2f4b8c7f643 100644 --- a/assets/js/admin/meta-boxes-product.js +++ b/assets/js/admin/meta-boxes-product.js @@ -404,7 +404,7 @@ jQuery( function( $ ) { ui.item.css( 'background-color', '#f6f6f6' ); }, stop: function( event, ui ) { - ui.item[0].removeAttribute( 'style' ); + ui.item.removeAttr( 'style' ); attribute_row_indexes(); } }); @@ -661,7 +661,7 @@ jQuery( function( $ ) { ui.item.css( 'background-color', '#f6f6f6' ); }, stop: function( event, ui ) { - ui.item[0].removeAttribute( 'style' ); + ui.item.removeAttr( 'style' ); }, update: function() { var attachment_ids = ''; @@ -689,8 +689,8 @@ jQuery( function( $ ) { $image_gallery_ids.val( attachment_ids ); // Remove any lingering tooltips. - $( '#tiptip_holder' )[0].removeAttribute( 'style' ); - $( '#tiptip_arrow' )[0].removeAttribute( 'style' ); + $( '#tiptip_holder' ).removeAttr( 'style' ); + $( '#tiptip_arrow' ).removeAttr( 'style' ); return false; }); From 1710a84948e7fb212e95728edecd62e2911f421b Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 09:07:26 -0800 Subject: [PATCH 288/368] Fixed removeAttribute replacements --- assets/js/admin/meta-boxes-order.js | 4 ++-- assets/js/admin/meta-boxes-product-variation.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/js/admin/meta-boxes-order.js b/assets/js/admin/meta-boxes-order.js index a77340cd9a6..f108dff0ec6 100644 --- a/assets/js/admin/meta-boxes-order.js +++ b/assets/js/admin/meta-boxes-order.js @@ -117,8 +117,8 @@ jQuery( function ( $ ) { }, init_tiptip: function() { - $( '#tiptip_holder' )[0].removeAttribute( 'style' ); - $( '#tiptip_arrow' )[0].removeAttribute( 'style' ); + $( '#tiptip_holder' ).removeAttr( 'style' ); + $( '#tiptip_arrow' ).removeAttr( 'style' ); $( '.tips' ).tipTip({ 'attribute': 'data-tip', 'fadeIn': 50, diff --git a/assets/js/admin/meta-boxes-product-variation.js b/assets/js/admin/meta-boxes-product-variation.js index d55cac3035d..fbb9701f04d 100644 --- a/assets/js/admin/meta-boxes-product-variation.js +++ b/assets/js/admin/meta-boxes-product-variation.js @@ -116,8 +116,8 @@ jQuery( function( $ ) { } // Init TipTip - $( '#tiptip_holder' )[0].removeAttribute( 'style' ); - $( '#tiptip_arrow' )[0].removeAttribute( 'style' ); + $( '#tiptip_holder' ).removeAttr( 'style' ); + $( '#tiptip_arrow' ).removeAttr( 'style' ); $( '.woocommerce_variations .tips, .woocommerce_variations .help_tip, .woocommerce_variations .woocommerce-help-tip', wrapper ) .tipTip({ 'attribute': 'data-tip', From f4745ed022488bc6d6df25f43da60f3b870930db Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 09:18:52 -0800 Subject: [PATCH 289/368] Update deprecated jQuery functions for wc-product-export.js --- assets/js/admin/wc-product-export.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/wc-product-export.js b/assets/js/admin/wc-product-export.js index d49928ddb9e..84a065214b2 100644 --- a/assets/js/admin/wc-product-export.js +++ b/assets/js/admin/wc-product-export.js @@ -11,7 +11,7 @@ this.$form.find('.woocommerce-exporter-progress').val( 0 ); // Methods. - this.processStep = this.processStep.bind( this ); + this.processStep = this.processStep.on( this ); // Events. $form.on( 'submit', { productExportForm: this }, this.onSubmit ); From 1215f1965e7184d6819af4784a8c1c157d1b8ad6 Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 09:19:08 -0800 Subject: [PATCH 290/368] Update deprecated jQuery functions for wc-product-import.js --- assets/js/admin/wc-product-import.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/wc-product-import.js b/assets/js/admin/wc-product-import.js index 645f11b5912..5222ac4c13f 100644 --- a/assets/js/admin/wc-product-import.js +++ b/assets/js/admin/wc-product-import.js @@ -23,7 +23,7 @@ // Initial state. this.$form.find('.woocommerce-importer-progress').val( 0 ); - this.run_import = this.run_import.bind( this ); + this.run_import = this.run_import.on( this ); // Start importing. this.run_import(); From 6a1e3eb85cf7fa33e6b92988a48221b74ec6638e Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 10:57:55 -0800 Subject: [PATCH 291/368] Revert load function --- assets/js/admin/meta-boxes-product.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/meta-boxes-product.js b/assets/js/admin/meta-boxes-product.js index 2f4b8c7f643..e9cad28e4c6 100644 --- a/assets/js/admin/meta-boxes-product.js +++ b/assets/js/admin/meta-boxes-product.js @@ -501,7 +501,7 @@ jQuery( function( $ ) { var this_page = window.location.toString(); this_page = this_page.replace( 'post-new.php?', 'post.php?post=' + woocommerce_admin_meta_boxes.post_id + '&action=edit&' ); - $( '#variable_product_options' ).on( 'load', this_page + ' #variable_product_options_inner', function() { + $( '#variable_product_options' ).load( this_page + ' #variable_product_options_inner', function() { $( '#variable_product_options' ).trigger( 'reload' ); } ); } From 37736799d69dc391cbc8df8b49386b9c04c4b04c Mon Sep 17 00:00:00 2001 From: roykho Date: Thu, 4 Feb 2021 12:31:28 -0800 Subject: [PATCH 292/368] Update deprecated jQuery functions in includes folder --- assets/js/frontend/cart-fragments.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/frontend/cart-fragments.js b/assets/js/frontend/cart-fragments.js index e70ad4ad36c..c5eef7b4c72 100644 --- a/assets/js/frontend/cart-fragments.js +++ b/assets/js/frontend/cart-fragments.js @@ -180,7 +180,7 @@ jQuery( function( $ ) { wp.customize.widgetsPreview.WidgetPartial ); if ( hasSelectiveRefresh ) { - wp.customize.selectiveRefresh.on( 'partial-content-rendered', function() { + wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function() { refresh_cart_fragment(); } ); } From 9e89ac8b952018408ceb9b38e62e42cf9d567c8f Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Mon, 22 Feb 2021 12:32:12 -0600 Subject: [PATCH 293/368] Correct bind usage in product import and export (bind wasn't targeting jQuery object; was native JS bind) --- assets/js/admin/wc-product-export.js | 2 +- assets/js/admin/wc-product-import.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/js/admin/wc-product-export.js b/assets/js/admin/wc-product-export.js index 84a065214b2..d49928ddb9e 100644 --- a/assets/js/admin/wc-product-export.js +++ b/assets/js/admin/wc-product-export.js @@ -11,7 +11,7 @@ this.$form.find('.woocommerce-exporter-progress').val( 0 ); // Methods. - this.processStep = this.processStep.on( this ); + this.processStep = this.processStep.bind( this ); // Events. $form.on( 'submit', { productExportForm: this }, this.onSubmit ); diff --git a/assets/js/admin/wc-product-import.js b/assets/js/admin/wc-product-import.js index 5222ac4c13f..645f11b5912 100644 --- a/assets/js/admin/wc-product-import.js +++ b/assets/js/admin/wc-product-import.js @@ -23,7 +23,7 @@ // Initial state. this.$form.find('.woocommerce-importer-progress').val( 0 ); - this.run_import = this.run_import.on( this ); + this.run_import = this.run_import.bind( this ); // Start importing. this.run_import(); From 4e8629e8c84e78f111f49c9eb7200ae3eb03c6ed Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Wed, 24 Feb 2021 12:25:17 -0600 Subject: [PATCH 294/368] Update cart-fragments.js to remove deprecated jQuery bind function --- assets/js/frontend/cart-fragments.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/frontend/cart-fragments.js b/assets/js/frontend/cart-fragments.js index c5eef7b4c72..e70ad4ad36c 100644 --- a/assets/js/frontend/cart-fragments.js +++ b/assets/js/frontend/cart-fragments.js @@ -180,7 +180,7 @@ jQuery( function( $ ) { wp.customize.widgetsPreview.WidgetPartial ); if ( hasSelectiveRefresh ) { - wp.customize.selectiveRefresh.bind( 'partial-content-rendered', function() { + wp.customize.selectiveRefresh.on( 'partial-content-rendered', function() { refresh_cart_fragment(); } ); } From 98b4968ec2d6d14e1e707c82a7d45d11282a62e4 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Wed, 7 Apr 2021 14:51:48 -0500 Subject: [PATCH 295/368] Address code sniff issues --- includes/admin/class-wc-admin-permalink-settings.php | 2 -- .../reports/class-wc-report-sales-by-category.php | 10 ++++------ includes/admin/settings/views/html-webhooks-edit.php | 9 ++++++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/includes/admin/class-wc-admin-permalink-settings.php b/includes/admin/class-wc-admin-permalink-settings.php index fa86206ab51..04f4ddbd14f 100644 --- a/includes/admin/class-wc-admin-permalink-settings.php +++ b/includes/admin/class-wc-admin-permalink-settings.php @@ -3,8 +3,6 @@ * Adds settings to the permalinks admin settings page * * @class WC_Admin_Permalink_Settings - * @author WooThemes - * @category Admin * @package WooCommerce\Admin * @version 2.3.0 */ diff --git a/includes/admin/reports/class-wc-report-sales-by-category.php b/includes/admin/reports/class-wc-report-sales-by-category.php index 9df5e751c37..dda8c193885 100644 --- a/includes/admin/reports/class-wc-report-sales-by-category.php +++ b/includes/admin/reports/class-wc-report-sales-by-category.php @@ -12,8 +12,6 @@ if ( ! defined( 'ABSPATH' ) ) { /** * WC_Report_Sales_By_Category * - * @author WooThemes - * @category Admin * @package WooCommerce\Admin\Reports * @version 2.1.0 */ @@ -171,11 +169,11 @@ class WC_Report_Sales_By_Category extends WC_Admin_Report { switch ( $this->chart_groupby ) { case 'day': - $time = strtotime( date( 'Ymd', strtotime( $order_item->post_date ) ) ) * 1000; + $time = strtotime( gmdate( 'Ymd', strtotime( $order_item->post_date ) ) ) * 1000; break; case 'month': default: - $time = strtotime( date( 'Ym', strtotime( $order_item->post_date ) ) . '01' ) * 1000; + $time = strtotime( gmdate( 'Ym', strtotime( $order_item->post_date ) ) . '01' ) * 1000; break; } @@ -307,11 +305,11 @@ class WC_Report_Sales_By_Category extends WC_Admin_Report { switch ( $this->chart_groupby ) { case 'day': - $time = strtotime( date( 'Ymd', strtotime( "+{$i} DAY", $this->start_date ) ) ) * 1000; + $time = strtotime( gmdate( 'Ymd', strtotime( "+{$i} DAY", $this->start_date ) ) ) * 1000; break; case 'month': default: - $time = strtotime( date( 'Ym', strtotime( "+{$i} MONTH", $this->start_date ) ) . '01' ) * 1000; + $time = strtotime( gmdate( 'Ym', strtotime( "+{$i} MONTH", $this->start_date ) ) . '01' ) * 1000; break; } diff --git a/includes/admin/settings/views/html-webhooks-edit.php b/includes/admin/settings/views/html-webhooks-edit.php index 760d96fd92d..364867666f5 100644 --- a/includes/admin/settings/views/html-webhooks-edit.php +++ b/includes/admin/settings/views/html-webhooks-edit.php @@ -63,7 +63,8 @@ if ( ! defined( 'ABSPATH' ) ) { $topic_data = WC_Admin_Webhooks::get_topic_data( $webhook ); $topics = apply_filters( - 'woocommerce_webhook_topics', array( + 'woocommerce_webhook_topics', + array( '' => __( 'Select an option…', 'woocommerce' ), 'coupon.created' => __( 'Coupon created', 'woocommerce' ), 'coupon.updated' => __( 'Coupon updated', 'woocommerce' ), @@ -197,8 +198,10 @@ if ( ! defined( 'ABSPATH' ) ) { add_query_arg( array( 'delete' => $webhook->get_id(), - ), admin_url( 'admin.php?page=wc-settings&tab=advanced§ion=webhooks' ) - ), 'delete-webhook' + ), + admin_url( 'admin.php?page=wc-settings&tab=advanced§ion=webhooks' ) + ), + 'delete-webhook' ); ?> From 5db461a21fd138ce023a1d8cbc5c1056d2bd31fd Mon Sep 17 00:00:00 2001 From: Joshua Flowers Date: Wed, 28 Apr 2021 19:01:30 -0400 Subject: [PATCH 296/368] Bump WooCommerce Admin version to 2.2.2-rc.1 --- composer.json | 2 +- composer.lock | 28 +++++++++++++--------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/composer.json b/composer.json index 44863a80836..10c9be56a53 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "pelago/emogrifier": "3.1.0", "psr/container": "1.0.0", "woocommerce/action-scheduler": "3.1.6", - "woocommerce/woocommerce-admin": "2.2.1", + "woocommerce/woocommerce-admin": "2.2.2-rc.1", "woocommerce/woocommerce-blocks": "4.9.1" }, "require-dev": { diff --git a/composer.lock b/composer.lock index e4fe95fe063..e74cb27df92 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "11158f53934e897bd84be190a184ec87", + "content-hash": "be33d948ed1d2ee3a7a23ef657f3148d", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -86,16 +86,16 @@ }, { "name": "composer/installers", - "version": "v1.10.0", + "version": "v1.11.0", "source": { "type": "git", "url": "https://github.com/composer/installers.git", - "reference": "1a0357fccad9d1cc1ea0c9a05b8847fbccccb78d" + "reference": "ae03311f45dfe194412081526be2e003960df74b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/installers/zipball/1a0357fccad9d1cc1ea0c9a05b8847fbccccb78d", - "reference": "1a0357fccad9d1cc1ea0c9a05b8847fbccccb78d", + "url": "https://api.github.com/repos/composer/installers/zipball/ae03311f45dfe194412081526be2e003960df74b", + "reference": "ae03311f45dfe194412081526be2e003960df74b", "shasum": "" }, "require": { @@ -189,6 +189,7 @@ "majima", "mako", "mediawiki", + "miaoxing", "modulework", "modx", "moodle", @@ -206,6 +207,7 @@ "sydes", "sylius", "symfony", + "tastyigniter", "typo3", "wordpress", "yawik", @@ -226,7 +228,7 @@ "type": "tidelift" } ], - "time": "2021-01-14T11:07:16+00:00" + "time": "2021-04-28T06:42:17+00:00" }, { "name": "maxmind-db/reader", @@ -501,16 +503,16 @@ }, { "name": "woocommerce/woocommerce-admin", - "version": "2.2.1", + "version": "2.2.2-rc.1", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-admin.git", - "reference": "78cc9c5ef7de5be5bd0f9208483e5ae97422be9a" + "reference": "0d305d1716481a0cc2010ec7b0a608a2d3c8ebe4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/78cc9c5ef7de5be5bd0f9208483e5ae97422be9a", - "reference": "78cc9c5ef7de5be5bd0f9208483e5ae97422be9a", + "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/0d305d1716481a0cc2010ec7b0a608a2d3c8ebe4", + "reference": "0d305d1716481a0cc2010ec7b0a608a2d3c8ebe4", "shasum": "" }, "require": { @@ -542,7 +544,7 @@ ], "description": "A modern, javascript-driven WooCommerce Admin experience.", "homepage": "https://github.com/woocommerce/woocommerce-admin", - "time": "2021-04-02T19:30:03+00:00" + "time": "2021-04-28T19:39:33+00:00" }, { "name": "woocommerce/woocommerce-blocks", @@ -589,10 +591,6 @@ "gutenberg", "woocommerce" ], - "support": { - "issues": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues", - "source": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/tree/v4.9.1" - }, "time": "2021-04-13T16:11:16+00:00" } ], From eb7fb428884a3ecbc69d5ea4321c3135da60e7dc Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 29 Apr 2021 10:57:31 +0200 Subject: [PATCH 297/368] Add a new debug tools page entry to delete the lookup table. Also, use $wpdb->prefix instead of hardcoded "wp_" for the table name. --- .../DataRegenerator.php | 132 +++++++++++++----- 1 file changed, 98 insertions(+), 34 deletions(-) diff --git a/src/Internal/ProductAttributesLookup/DataRegenerator.php b/src/Internal/ProductAttributesLookup/DataRegenerator.php index a031844ffdb..6848424eea9 100644 --- a/src/Internal/ProductAttributesLookup/DataRegenerator.php +++ b/src/Internal/ProductAttributesLookup/DataRegenerator.php @@ -34,10 +34,21 @@ class DataRegenerator { */ private $data_store; + /** + * The lookup table name. + * + * @var string + */ + private $lookup_table_name; + /** * DataRegenerator constructor. */ public function __construct() { + global $wpdb; + + $this->lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup'; + add_filter( 'woocommerce_debug_tools', function( $tools ) { @@ -103,8 +114,7 @@ class DataRegenerator { /** * Delete all the existing data related to the lookup table, including the table itself. * - * There's no UI to delete the lookup table and the related options, but wp cli can be used - * as follows for that purpose: + * Shortcut to run this method in case the debug tools UI isn't available or for quick debugging: * * wp eval "wc_get_container()->get(Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator::class)->delete_all_attributes_lookup_data();" */ @@ -115,7 +125,8 @@ class DataRegenerator { delete_option( 'woocommerce_attribute_lookup__last_product_id_to_process' ); delete_option( 'woocommerce_attribute_lookup__last_products_page_processed' ); - $wpdb->query( 'DROP TABLE IF EXISTS wp_wc_product_attributes_lookup' ); + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + $wpdb->query( 'DROP TABLE IF EXISTS ' . $this->lookup_table_name ); } /** @@ -127,9 +138,10 @@ class DataRegenerator { private function initialize_table_and_data() { global $wpdb; + // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared $wpdb->query( ' -CREATE TABLE wp_wc_product_attributes_lookup ( +CREATE TABLE ' . $this->lookup_table_name . '( product_id bigint(20) NOT NULL, product_or_parent_id bigint(20) NOT NULL, taxonomy varchar(32) NOT NULL, @@ -139,6 +151,7 @@ CREATE TABLE wp_wc_product_attributes_lookup ( ); ' ); + // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared $last_existing_product_id = current( wc_get_products( @@ -151,7 +164,7 @@ CREATE TABLE wp_wc_product_attributes_lookup ( ) ); if ( false === $last_existing_product_id ) { - // New shop, no products yet, nothing to regenerate. + // No products exist, nothing to (re)generate. return false; } @@ -229,60 +242,111 @@ CREATE TABLE wp_wc_product_attributes_lookup ( update_option( 'woocommerce_attribute_lookup__enabled', 'no' ); } + /** + * Check if the lookup table exists in the database. + * + * @return bool True if the lookup table exists in the database. + */ + private function lookup_table_exists() { + global $wpdb; + $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $this->lookup_table_name ) ); + + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared + return $this->lookup_table_name === $wpdb->get_var( $query ); + } + /** * Add a 'Regenerate product attributes lookup table' entry to the Status - Tools page. * * @param array $tools_array The tool definitions array that is passed ro the woocommerce_debug_tools filter. * @return array The tools array with the entry added. */ - private function add_initiate_regeneration_entry_to_tools_array( $tools_array ) { - // Regenerate table entry. + private function add_initiate_regeneration_entry_to_tools_array( array $tools_array ) { + $lookup_table_exists = $this->lookup_table_exists(); + $generation_is_in_progress = $this->regeneration_is_in_progress(); + + // Regenerate table. + + if ( $lookup_table_exists ) { + $generate_item_name = __( 'Regenerate the product attributes lookup table', 'woocommerce' ); + $generate_item_desc = __( 'This tool will regenerate the product attributes lookup table data from existing products data. This process may take a while.', 'woocommerce' ); + $generate_item_return = __( 'Product attributes lookup table data is regenerating', 'woocommerce' ); + $generate_item_button = __( 'Regenerate', 'woocommerce' ); + } else { + $generate_item_name = __( 'Create and fill product attributes lookup table', 'woocommerce' ); + $generate_item_desc = __( 'This tool will create the product attributes lookup table data and fill it with existing products data. This process may take a while.', 'woocommerce' ); + $generate_item_return = __( 'Product attributes lookup table is being filled', 'woocommerce' ); + $generate_item_button = __( 'Create', 'woocommerce' ); + } $entry = array( - 'name' => __( 'Regenerate product attributes lookup table', 'woocommerce' ), - 'desc' => __( 'This tool will regenerate the product attributes lookup table data. This process may take a while.', 'woocommerce' ), + 'name' => $generate_item_name, + 'desc' => $generate_item_desc, 'requires_refresh' => true, - 'callback' => function() { + 'callback' => function() use ( $generate_item_return ) { $this->initiate_regeneration_from_tools_page(); - return __( 'Product attributes lookup table is regenerating', 'woocommerce' ); + return $generate_item_return; }, ); - if ( $this->regeneration_is_in_progress() ) { - $entry['button'] = __( 'Regeneration in progress', 'woocommerce' ); + if ( $generation_is_in_progress ) { + $entry['button'] = __( 'Filling in progress', 'woocommerce' ); $entry['disabled'] = true; } else { - $entry['button'] = __( 'Regenerate', 'woocommerce' ); + $entry['button'] = $generate_item_button; } $tools_array['regenerate_product_attributes_lookup_table'] = $entry; - // Enable or disable table usage entry. + if ( $lookup_table_exists ) { - if ( 'yes' === get_option( 'woocommerce_attribute_lookup__enabled' ) ) { - $tools_array['disable_product_attributes_lookup_table_usage'] = array( - 'name' => __( 'Disable the product attributes lookup table usage', 'woocommerce' ), - 'desc' => __( 'The product attributes lookup table usage is currently enabled, use this tool to disable it.', 'woocommerce' ), - 'button' => __( 'Disable', 'woocommerce' ), + // Delete the table. + + $tools_array['delete_product_attributes_lookup_table'] = array( + 'name' => __( 'Delete the product attributes lookup table', 'woocommerce' ), + 'desc' => sprintf( + '%1$s %2$s', + __( 'Note:', 'woocommerce' ), + __( 'This will delete the product attributes lookup table. You can create it again with the "Create and fill product attributes lookup table" tool.', 'woocommerce' ) + ), + 'button' => __( 'Delete', 'woocommerce' ), 'requires_refresh' => true, - 'callback' => function() { - $this->enable_or_disable_lookup_table_usage( false ); - return __( 'Product attributes lookup table usage has been disabled.', 'woocommerce' ); - }, - ); - } elseif ( 'no' === get_option( 'woocommerce_attribute_lookup__enabled' ) ) { - $tools_array['enable_product_attributes_lookup_table_usage'] = array( - 'name' => __( 'Enable the product attributes lookup table usage', 'woocommerce' ), - 'desc' => __( 'The product attributes lookup table usage is currently disabled, use this tool to enable it.', 'woocommerce' ), - 'button' => __( 'Enable', 'woocommerce' ), - 'requires_refresh' => true, - 'callback' => function() { - $this->enable_or_disable_lookup_table_usage( true ); - return __( 'Product attributes lookup table usage has been enabled.', 'woocommerce' ); + 'callback' => function () { + $this->delete_all_attributes_lookup_data(); + return __( 'Product attributes lookup table has been deleted.', 'woocommerce' ); }, ); } + if ( $lookup_table_exists && ! $generation_is_in_progress ) { + + // Enable or disable table usage. + + if ( 'yes' === get_option( 'woocommerce_attribute_lookup__enabled' ) ) { + $tools_array['disable_product_attributes_lookup_table_usage'] = array( + 'name' => __( 'Disable the product attributes lookup table usage', 'woocommerce' ), + 'desc' => __( 'The product attributes lookup table usage is currently enabled, use this tool to disable it.', 'woocommerce' ), + 'button' => __( 'Disable', 'woocommerce' ), + 'requires_refresh' => true, + 'callback' => function () { + $this->enable_or_disable_lookup_table_usage( false ); + return __( 'Product attributes lookup table usage has been disabled.', 'woocommerce' ); + }, + ); + } else { + $tools_array['enable_product_attributes_lookup_table_usage'] = array( + 'name' => __( 'Enable the product attributes lookup table usage', 'woocommerce' ), + 'desc' => __( 'The product attributes lookup table usage is currently disabled, use this tool to enable it.', 'woocommerce' ), + 'button' => __( 'Enable', 'woocommerce' ), + 'requires_refresh' => true, + 'callback' => function () { + $this->enable_or_disable_lookup_table_usage( true ); + return __( 'Product attributes lookup table usage has been enabled.', 'woocommerce' ); + }, + ); + } + } + return $tools_array; } From 7f2c2d8b72381fcb918e165b99b4cd6a689368f9 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 29 Apr 2021 11:20:25 +0200 Subject: [PATCH 298/368] Add logging for errors during the execution of a debug tool. --- ...-wc-rest-system-status-tools-v2-controller.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-tools-v2-controller.php b/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-tools-v2-controller.php index bab123382cc..4b8a1db0f4b 100644 --- a/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-tools-v2-controller.php +++ b/includes/rest-api/Controllers/Version2/class-wc-rest-system-status-tools-v2-controller.php @@ -587,6 +587,21 @@ class WC_REST_System_Status_Tools_V2_Controller extends WC_REST_Controller { $ran = false; /* translators: %1$s: callback string, %2$s: error message */ $message = sprintf( __( 'There was an error calling %1$s: %2$s', 'woocommerce' ), $callback_string, $return->getMessage() ); + + $logger = wc_get_logger(); + $logger->error( + sprintf( + 'Error running debug tool %s: %s', + $tool, + $return->getMessage() + ), + array( + 'source' => 'run-debug-tool', + 'tool' => $tool, + 'callback' => $callback, + 'error' => $return, + ) + ); } elseif ( is_string( $return ) ) { $message = $return; } elseif ( false === $return ) { From 44cf1648d5e24bba6794456aece6fefcd8ff10c6 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 29 Apr 2021 11:49:43 +0200 Subject: [PATCH 299/368] DataRegenerator: show lookup table filling process in tools page. The status is displayed in the disabled "Regenerate table" button as follows: "Filling in progress (X)", where X is the number of products processed so far. --- .../ProductAttributesLookup/DataRegenerator.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Internal/ProductAttributesLookup/DataRegenerator.php b/src/Internal/ProductAttributesLookup/DataRegenerator.php index 6848424eea9..8b175dad8d4 100644 --- a/src/Internal/ProductAttributesLookup/DataRegenerator.php +++ b/src/Internal/ProductAttributesLookup/DataRegenerator.php @@ -27,6 +27,8 @@ defined( 'ABSPATH' ) || exit; */ class DataRegenerator { + const PRODUCTS_PER_GENERATION_STEP = 10; + /** * The data store to use. * @@ -215,7 +217,7 @@ CREATE TABLE ' . $this->lookup_table_name . '( $product_ids = wc_get_products( array( - 'limit' => 10, + 'limit' => self::PRODUCTS_PER_GENERATION_STEP, 'page' => $current_products_page, 'orderby' => array( 'ID' => 'ASC', @@ -290,7 +292,11 @@ CREATE TABLE ' . $this->lookup_table_name . '( ); if ( $generation_is_in_progress ) { - $entry['button'] = __( 'Filling in progress', 'woocommerce' ); + $entry['button'] = sprintf( + /* translators: %d: How many products have been processed so far. */ + __( 'Filling in progress (%d)', 'woocommerce' ), + get_option( 'woocommerce_attribute_lookup__last_products_page_processed', 0 ) * self::PRODUCTS_PER_GENERATION_STEP + ); $entry['disabled'] = true; } else { $entry['button'] = $generate_item_button; From a6388d9c34226f7600e4ddcbf11cfb4bdaf05fd0 Mon Sep 17 00:00:00 2001 From: Veljko Date: Thu, 29 Apr 2021 12:27:46 +0200 Subject: [PATCH 300/368] Fix test by adding new shipping zone --- .../specs/shopper/front-end-checkout-create-account.test.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/e2e/core-tests/specs/shopper/front-end-checkout-create-account.test.js b/tests/e2e/core-tests/specs/shopper/front-end-checkout-create-account.test.js index f173b1f8b60..9621ac2f1f3 100644 --- a/tests/e2e/core-tests/specs/shopper/front-end-checkout-create-account.test.js +++ b/tests/e2e/core-tests/specs/shopper/front-end-checkout-create-account.test.js @@ -9,6 +9,7 @@ uiUnblocked, setCheckbox, settingsPageSaveChanges, + addShippingZoneAndMethod, withRestApi, } = require( '@woocommerce/e2e-utils' ); @@ -36,6 +37,10 @@ const runCheckoutCreateAccountTest = () => { await merchant.openSettings('account'); await setCheckbox('#woocommerce_enable_signup_and_login_from_checkout'); await settingsPageSaveChanges(); + + // Set free shipping within California + await addShippingZoneAndMethod('Free Shipping CA', 'state:US:CA', ' ', 'free_shipping'); + await merchant.logout(); // Add simple product to cart and proceed to checkout From ee6acc5fb6f6064ee82da179e78948020a0e5726 Mon Sep 17 00:00:00 2001 From: Joshua Flowers Date: Thu, 29 Apr 2021 10:36:43 -0400 Subject: [PATCH 301/368] Bump WooCommerce Admin version to 2.2.2 --- composer.json | 2 +- composer.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 10c9be56a53..4daa8132829 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "pelago/emogrifier": "3.1.0", "psr/container": "1.0.0", "woocommerce/action-scheduler": "3.1.6", - "woocommerce/woocommerce-admin": "2.2.2-rc.1", + "woocommerce/woocommerce-admin": "2.2.2", "woocommerce/woocommerce-blocks": "4.9.1" }, "require-dev": { diff --git a/composer.lock b/composer.lock index e74cb27df92..57039bbbbce 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "be33d948ed1d2ee3a7a23ef657f3148d", + "content-hash": "a604678b268820c78736d599e1eb6726", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -503,16 +503,16 @@ }, { "name": "woocommerce/woocommerce-admin", - "version": "2.2.2-rc.1", + "version": "2.2.2", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-admin.git", - "reference": "0d305d1716481a0cc2010ec7b0a608a2d3c8ebe4" + "reference": "161e6afa01a3fb69533cfa2b245a71df7512ec3f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/0d305d1716481a0cc2010ec7b0a608a2d3c8ebe4", - "reference": "0d305d1716481a0cc2010ec7b0a608a2d3c8ebe4", + "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/161e6afa01a3fb69533cfa2b245a71df7512ec3f", + "reference": "161e6afa01a3fb69533cfa2b245a71df7512ec3f", "shasum": "" }, "require": { @@ -544,7 +544,7 @@ ], "description": "A modern, javascript-driven WooCommerce Admin experience.", "homepage": "https://github.com/woocommerce/woocommerce-admin", - "time": "2021-04-28T19:39:33+00:00" + "time": "2021-04-29T14:11:48+00:00" }, { "name": "woocommerce/woocommerce-blocks", From e58d26f377a71a4fb880da587fd6a071d834ca43 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Thu, 29 Apr 2021 16:46:41 +0200 Subject: [PATCH 302/368] Fix: using "current" on a possibly "false" value. --- src/Internal/ProductAttributesLookup/DataRegenerator.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Internal/ProductAttributesLookup/DataRegenerator.php b/src/Internal/ProductAttributesLookup/DataRegenerator.php index 8b175dad8d4..1e45d553c84 100644 --- a/src/Internal/ProductAttributesLookup/DataRegenerator.php +++ b/src/Internal/ProductAttributesLookup/DataRegenerator.php @@ -155,7 +155,7 @@ CREATE TABLE ' . $this->lookup_table_name . '( ); // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared - $last_existing_product_id = current( + $last_existing_product_id = wc_get_products( array( 'return' => 'ids', @@ -163,14 +163,14 @@ CREATE TABLE ' . $this->lookup_table_name . '( 'orderby' => 'id', 'order' => 'DESC', ) - ) - ); + ); + if ( false === $last_existing_product_id ) { // No products exist, nothing to (re)generate. return false; } - update_option( 'woocommerce_attribute_lookup__last_product_id_to_process', $last_existing_product_id ); + update_option( 'woocommerce_attribute_lookup__last_product_id_to_process', current( $last_existing_product_id ) ); update_option( 'woocommerce_attribute_lookup__last_products_page_processed', 0 ); return true; From a1be8f996979e2ab0c2db56a6e4ae584fda13813 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Thu, 29 Apr 2021 14:10:50 -0300 Subject: [PATCH 303/368] WIP orders rest repository --- .../api/src/repositories/rest/orders/index.ts | 0 .../api/src/repositories/rest/orders/order.ts | 0 .../repositories/rest/orders/transformer.ts | 24 +++++++++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 tests/e2e/api/src/repositories/rest/orders/index.ts create mode 100644 tests/e2e/api/src/repositories/rest/orders/order.ts create mode 100644 tests/e2e/api/src/repositories/rest/orders/transformer.ts diff --git a/tests/e2e/api/src/repositories/rest/orders/index.ts b/tests/e2e/api/src/repositories/rest/orders/index.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/e2e/api/src/repositories/rest/orders/order.ts b/tests/e2e/api/src/repositories/rest/orders/order.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/e2e/api/src/repositories/rest/orders/transformer.ts b/tests/e2e/api/src/repositories/rest/orders/transformer.ts new file mode 100644 index 00000000000..41452a2ce26 --- /dev/null +++ b/tests/e2e/api/src/repositories/rest/orders/transformer.ts @@ -0,0 +1,24 @@ +import { + AddPropertyTransformation, + CustomTransformation, + IgnorePropertyTransformation, + KeyChangeTransformation, + ModelTransformation, + ModelTransformer, + ModelTransformerTransformation, + PropertyType, + PropertyTypeTransformation, + TransformationOrder, +} from '../../../framework'; +import { + OrderAddress, + OrderCouponLine, + OrderFeeLine, + OrderItemTax, + OrderLineItem, + OrderRefundLine, + OrderShippingLine, + OrderStatus, + OrderTaxRate, +} from '../../../models'; +import { createMetaDataTransformer } from '../shared'; From 467af94b1d20c30837eb3dc40e031cde16a5914d Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 30 Apr 2021 12:10:25 +0200 Subject: [PATCH 304/368] Add unit tests for LookupDataStore::update_data_for_product (simple products) Also: - Add the FakeQueue class - Fix LookupDataStore, it was using a hardcoded "wp_" lookup table name --- .../LookupDataStore.php | 24 ++- tests/Tools/FakeQueue.php | 82 ++++++++ .../LookupDataStoreTest.php | 184 ++++++++++++++++++ 3 files changed, 288 insertions(+), 2 deletions(-) create mode 100644 tests/Tools/FakeQueue.php create mode 100644 tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php diff --git a/src/Internal/ProductAttributesLookup/LookupDataStore.php b/src/Internal/ProductAttributesLookup/LookupDataStore.php index 05d133fcdd5..35486f0a0e8 100644 --- a/src/Internal/ProductAttributesLookup/LookupDataStore.php +++ b/src/Internal/ProductAttributesLookup/LookupDataStore.php @@ -14,6 +14,22 @@ defined( 'ABSPATH' ) || exit; */ class LookupDataStore { + /** + * The lookup table name. + * + * @var string + */ + private $lookup_table_name; + + /** + * LookupDataStore constructor. + */ + public function __construct() { + global $wpdb; + + $this->lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup'; + } + /** * Insert or update the lookup data for a given product or variation. * If a variable product is passed the information is updated for all of its variations. @@ -50,12 +66,14 @@ class LookupDataStore { private function delete_lookup_table_entries_for( int $product_id ) { global $wpdb; + // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared $wpdb->query( $wpdb->prepare( - 'DELETE FROM wp_wc_product_attributes_lookup WHERE product_or_parent_id = %d', + 'DELETE FROM ' . $this->lookup_table_name . ' WHERE product_or_parent_id = %d', $product_id ) ); + // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared } /** @@ -252,9 +270,10 @@ class LookupDataStore { private function insert_lookup_table_data( int $product_id, int $product_or_parent_id, string $taxonomy, int $term_id, bool $is_variation_attribute, bool $has_stock ) { global $wpdb; + // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared $wpdb->query( $wpdb->prepare( - 'INSERT INTO wp_wc_product_attributes_lookup ( + 'INSERT INTO ' . $this->lookup_table_name . ' ( product_id, product_or_parent_id, taxonomy, @@ -271,5 +290,6 @@ class LookupDataStore { $has_stock ? 1 : 0 ) ); + // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared } } diff --git a/tests/Tools/FakeQueue.php b/tests/Tools/FakeQueue.php new file mode 100644 index 00000000000..fe8d8a24f24 --- /dev/null +++ b/tests/Tools/FakeQueue.php @@ -0,0 +1,82 @@ +queue() will return an instance of this class. + */ +class FakeQueue implements \WC_Queue_Interface { + + /** + * Records all the method calls to this instance. + * + * @var array + */ + public $methods_called = array(); + + // phpcs:disable Squiz.Commenting.FunctionComment.Missing + + public function add( $hook, $args = array(), $group = '' ) { + // TODO: Implement add() method. + } + + public function schedule_single( $timestamp, $hook, $args = array(), $group = '' ) { + $this->add_to_methods_called( 'schedule_single', $args, $group, array( 'hook' => $hook ) ); + } + + public function schedule_recurring( $timestamp, $interval_in_seconds, $hook, $args = array(), $group = '' ) { + // TODO: Implement schedule_recurring() method. + } + + public function schedule_cron( $timestamp, $cron_schedule, $hook, $args = array(), $group = '' ) { + // TODO: Implement schedule_cron() method. + } + + public function cancel( $hook, $args = array(), $group = '' ) { + // TODO: Implement cancel() method. + } + + public function cancel_all( $hook, $args = array(), $group = '' ) { + // TODO: Implement cancel_all() method. + } + + public function get_next( $hook, $args = null, $group = '' ) { + // TODO: Implement get_next() method. + } + + public function search( $args = array(), $return_format = OBJECT ) { + // TODO: Implement search() method. + } + + // phpcs:enable Squiz.Commenting.FunctionComment.Missing + + /** + * Registers a method call for this instance. + * + * @param string $method Name of the invoked method. + * @param array $args Arguments passed in '$args' to the method call. + * @param string $group Group name passed in '$group' to the method call. + * @param array $extra_args Any extra information to store about the method call. + */ + private function add_to_methods_called( $method, $args, $group, $extra_args = array() ) { + $value = array( + 'method' => $method, + 'args' => $args, + 'group' => $group, + ); + + $this->methods_called[] = array_merge( $value, $extra_args ); + } +} diff --git a/tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php b/tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php new file mode 100644 index 00000000000..5a9f61c1d20 --- /dev/null +++ b/tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php @@ -0,0 +1,184 @@ +sut = new LookupDataStore(); + + // Initiating regeneration with a fake queue will just create the lookup table in the database. + add_filter( + 'woocommerce_queue_class', + function() { + return FakeQueue::class; + } + ); + $this->get_instance_of( DataRegenerator::class )->initiate_regeneration(); + } + + /** + * @testdox `test_update_data_for_product` throws an exception if a variation is passed. + */ + public function test_update_data_for_product_throws_if_variation_is_passed() { + $product = new \WC_Product_Variation(); + + $this->expectException( \Exception::class ); + $this->expectExceptionMessage( "LookupDataStore::update_data_for_product can't be called for variations." ); + + $this->sut->update_data_for_product( $product ); + } + + /** + * @testdox `test_update_data_for_product` creates the appropriate entries for simple products, skipping custom product attributes. + * + * @testWith [true] + * [false] + * + * @param bool $in_stock 'true' if the product is supposed to be in stock. + */ + public function test_update_data_for_simple_product( $in_stock ) { + $product = new \WC_Product_Simple(); + $product->set_id( 10 ); + $this->set_product_attributes( + $product, + array( + 'pa_attribute_1' => array( + 'id' => 100, + 'options' => array( 51, 52 ), + ), + 'pa_attribute_2' => array( + 'id' => 200, + 'options' => array( 73, 74 ), + ), + 'pa_custom_attribute' => array( + 'id' => 0, + 'options' => array( 'foo', 'bar' ), + ), + ) + ); + + if ( $in_stock ) { + $product->set_stock_status( 'instock' ); + $expected_in_stock = 1; + } else { + $product->set_stock_status( 'outofstock' ); + $expected_in_stock = 0; + } + + $this->sut->update_data_for_product( $product ); + + $expected = array( + array( + 'product_id' => 10, + 'product_or_parent_id' => 10, + 'taxonomy' => 'pa_attribute_1', + 'term_id' => 51, + 'in_stock' => $expected_in_stock, + 'is_variation_attribute' => 0, + ), + array( + 'product_id' => 10, + 'product_or_parent_id' => 10, + 'taxonomy' => 'pa_attribute_1', + 'term_id' => 52, + 'in_stock' => $expected_in_stock, + 'is_variation_attribute' => 0, + ), + array( + 'product_id' => 10, + 'product_or_parent_id' => 10, + 'taxonomy' => 'pa_attribute_2', + 'term_id' => 73, + 'in_stock' => $expected_in_stock, + 'is_variation_attribute' => 0, + ), + array( + 'product_id' => 10, + 'product_or_parent_id' => 10, + 'taxonomy' => 'pa_attribute_2', + 'term_id' => 74, + 'in_stock' => $expected_in_stock, + 'is_variation_attribute' => 0, + ), + ); + + $actual = $this->get_lookup_table_data(); + + $this->assertEquals( $expected, $actual ); + } + + /** + * Set the product attributes from an array with this format: + * + * [ + * 'taxonomy_or_custom_attribute_name' => + * [ + * 'id' => attribute id (0 for custom product attribute), + * 'options' => [term_id, term_id...] (for custom product attributes: ['term', 'term'...] + * 'variation' => 1|0 (optional, default 0) + * ], ... + * ] + * + * @param WC_Product $product The product to set the attributes. + * @param array $attributes_data The attributes to set. + */ + private function set_product_attributes( $product, $attributes_data ) { + $attributes = array(); + foreach ( $attributes_data as $taxonomy => $attribute_data ) { + $attribute = new \WC_Product_Attribute(); + $attribute->set_id( $attribute_data['id'] ); + $attribute->set_name( $taxonomy ); + $attribute->set_options( $attribute_data['options'] ); + $attribute->set_variation( ArrayUtil::get_value_or_default( $attribute_data, 'variation', false ) ); + $attributes[] = $attribute; + } + + $product->set_attributes( $attributes ); + } + + /** + * Get all the data in the lookup table as an array of associative arrays. + * + * @return array All the rows in the lookup table as an array of associative arrays. + */ + private function get_lookup_table_data() { + global $wpdb; + + $result = $wpdb->get_results( 'select * from ' . $wpdb->prefix . 'wc_product_attributes_lookup', ARRAY_A ); + + foreach ( $result as $row ) { + foreach ( $row as $column_name => $value ) { + if ( 'taxonomy' !== $column_name ) { + $row[ $column_name ] = (int) $value; + } + } + } + + return $result; + } +} From 43859058ec3f15808891f3fbdefeec222df65775 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Fri, 30 Apr 2021 09:04:48 -0300 Subject: [PATCH 305/368] run cart/checkout setup tests first --- tests/e2e/specs/front-end/{cart.test.js => cart-begin.test.js} | 0 .../specs/front-end/{checkout.test.js => checkout-begin.test.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename tests/e2e/specs/front-end/{cart.test.js => cart-begin.test.js} (100%) rename tests/e2e/specs/front-end/{checkout.test.js => checkout-begin.test.js} (100%) diff --git a/tests/e2e/specs/front-end/cart.test.js b/tests/e2e/specs/front-end/cart-begin.test.js similarity index 100% rename from tests/e2e/specs/front-end/cart.test.js rename to tests/e2e/specs/front-end/cart-begin.test.js diff --git a/tests/e2e/specs/front-end/checkout.test.js b/tests/e2e/specs/front-end/checkout-begin.test.js similarity index 100% rename from tests/e2e/specs/front-end/checkout.test.js rename to tests/e2e/specs/front-end/checkout-begin.test.js From 7b23b8c8aa1ba5cc2f9b33fb0d3bac87b4cc7df0 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Fri, 30 Apr 2021 16:26:51 -0300 Subject: [PATCH 306/368] two more minor E2E fixes - add shipping zone for first checkout test - increase wait time for product import to complete --- .../specs/merchant/wp-admin-product-import-csv.test.js | 2 +- .../e2e/core-tests/specs/shopper/front-end-checkout.test.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/e2e/core-tests/specs/merchant/wp-admin-product-import-csv.test.js b/tests/e2e/core-tests/specs/merchant/wp-admin-product-import-csv.test.js index d3cb10e1b94..e3705010a93 100644 --- a/tests/e2e/core-tests/specs/merchant/wp-admin-product-import-csv.test.js +++ b/tests/e2e/core-tests/specs/merchant/wp-admin-product-import-csv.test.js @@ -63,7 +63,7 @@ const runImportProductsTest = () => { await expect(page).toClick('button[value="Run the importer"]'); // Waiting for importer to finish - await page.waitForSelector('section.woocommerce-importer-done', {visible:true, timeout: 60000}); + await page.waitForSelector('section.woocommerce-importer-done', {visible:true, timeout: 120000}); await page.waitForSelector('.woocommerce-importer-done'); await expect(page).toMatchElement('.woocommerce-importer-done', {text: 'Import complete!'}); }); diff --git a/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js b/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js index 17e84c339c7..0ec9a92edc5 100644 --- a/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js +++ b/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js @@ -9,7 +9,8 @@ const { setCheckbox, settingsPageSaveChanges, uiUnblocked, - verifyCheckboxIsSet + verifyCheckboxIsSet, + addShippingZoneAndMethod, } = require( '@woocommerce/e2e-utils' ); const config = require( 'config' ); @@ -29,6 +30,8 @@ const runCheckoutPageTest = () => { await merchant.login(); await createSimpleProduct(); + // Set free shipping within California + await addShippingZoneAndMethod('Free Shipping CA', 'state:US:CA', ' ', 'free_shipping'); // Go to general settings page await merchant.openSettings('general'); From 4ae714de56ab39e021037f80a1e4b94c09183967 Mon Sep 17 00:00:00 2001 From: Kapil Paul Date: Sun, 2 May 2021 00:52:38 +0600 Subject: [PATCH 307/368] fix: coding-style-in-class-wc-email.php --- includes/emails/class-wc-email.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/includes/emails/class-wc-email.php b/includes/emails/class-wc-email.php index d5accd8347a..f2e67f8b7ad 100644 --- a/includes/emails/class-wc-email.php +++ b/includes/emails/class-wc-email.php @@ -600,7 +600,8 @@ class WC_Email extends WC_Settings_API { * @return string */ public function get_content_plain() { - return ''; } + return ''; + } /** * Get the email content in HTML format. @@ -608,7 +609,8 @@ class WC_Email extends WC_Settings_API { * @return string */ public function get_content_html() { - return ''; } + return ''; + } /** * Get the from name for outgoing emails. From 42245ed92ad3d4a8bebf299c4d3d87f137412d09 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Mon, 3 May 2021 11:14:33 +0200 Subject: [PATCH 308/368] Add unit tests for LookupDataStore::update_data_for_product (variable products) --- .../LookupDataStore.php | 12 +- .../LookupDataStoreTest.php | 201 +++++++++++++++++- 2 files changed, 209 insertions(+), 4 deletions(-) diff --git a/src/Internal/ProductAttributesLookup/LookupDataStore.php b/src/Internal/ProductAttributesLookup/LookupDataStore.php index 35486f0a0e8..9fceb95f41a 100644 --- a/src/Internal/ProductAttributesLookup/LookupDataStore.php +++ b/src/Internal/ProductAttributesLookup/LookupDataStore.php @@ -41,7 +41,7 @@ class LookupDataStore { // TODO: For now data is always deleted and fully regenerated, existing data should be updated instead. if ( ! is_a( $product, \WC_Product::class ) ) { - $product = wc_get_product( $product ); + $product = WC()->call_function( 'wc_get_product', $product ); } if ( $this->is_variation( $product ) ) { @@ -162,7 +162,8 @@ class LookupDataStore { private function get_term_ids_by_slug_cache( $taxonomies ) { $result = array(); foreach ( $taxonomies as $taxonomy ) { - $terms = get_terms( + $terms = WC()->call_function( + 'get_terms', array( 'taxonomy' => $taxonomy, 'hide_empty' => false, @@ -201,7 +202,12 @@ class LookupDataStore { */ private function get_variations_of( \WC_Product_Variable $product ) { $variation_ids = $product->get_children(); - return array_map( 'wc_get_product', $variation_ids ); + return array_map( + function( $id ) { + return WC()->call_function( 'wc_get_product', $id ); + }, + $variation_ids + ); } /** diff --git a/tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php b/tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php index 5a9f61c1d20..58895eb4746 100644 --- a/tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php +++ b/tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php @@ -129,7 +129,206 @@ class LookupDataStoreTest extends \WC_Unit_Test_Case { $actual = $this->get_lookup_table_data(); - $this->assertEquals( $expected, $actual ); + $this->assertEquals( sort( $expected ), sort( $actual ) ); + } + + /** + * @testdox `test_update_data_for_product` creates the appropriate entries for variable products. + */ + public function test_update_data_for_variable_product() { + $products = array(); + + /** + * Create one normal attribute and two attributes used to define variations, + * with 4 terms each. + */ + + $this->register_legacy_proxy_function_mocks( + array( + 'get_terms' => function( $args ) use ( &$invokations_of_get_terms ) { + switch ( $args['taxonomy'] ) { + case 'non-variation-attribute': + return array( + 10 => 'term_10', + 20 => 'term_20', + 30 => 'term_30', + 40 => 'term_40', + ); + case 'variation-attribute-1': + return array( + 50 => 'term_50', + 60 => 'term_60', + 70 => 'term_70', + 80 => 'term_80', + ); + case 'variation-attribute-2': + return array( + 90 => 'term_90', + 100 => 'term_100', + 110 => 'term_110', + 120 => 'term_120', + ); + default: + throw new \Exception( "Unexpected call to 'get_terms'" ); + } + }, + 'wc_get_product' => function( $id ) use ( &$products ) { + return $products[ $id ]; + }, + ) + ); + + /** + * Create a variable product with: + * - 3 of the 4 values of the regular attribute. + * - A custom product attribute. + * - The two variation attributes, with 3 of the 4 terms for each one. + * - Variation 1 having one value for each of the variation attributes. + * - Variation 2 having one value for variation-attribute-1 + * but none for variation-attribute-2 (so the value for that one is "Any"). + */ + + $product = new \WC_Product_Variable(); + $product->set_id( 1000 ); + $this->set_product_attributes( + $product, + array( + 'non-variation-attribute' => array( + 'id' => 100, + 'options' => array( 10, 20, 30 ), + ), + 'pa_custom_attribute' => array( + 'id' => 0, + 'options' => array( 'foo', 'bar' ), + ), + 'variation-attribute-1' => array( + 'id' => 200, + 'options' => array( 50, 60, 70 ), + 'variation' => true, + ), + 'variation-attribute-2' => array( + 'id' => 300, + 'options' => array( 90, 100, 110 ), + 'variation' => true, + ), + ) + ); + $product->set_stock_status( 'instock' ); + + $variation_1 = new \WC_Product_Variation(); + $variation_1->set_id( 1001 ); + $variation_1->set_attributes( + array( + 'variation-attribute-1' => 'term_50', + 'variation-attribute-2' => 'term_90', + ) + ); + $variation_1->set_stock_status( 'instock' ); + + $variation_2 = new \WC_Product_Variation(); + $variation_2->set_id( 1002 ); + $variation_2->set_attributes( + array( + 'variation-attribute-1' => 'term_60', + ) + ); + $variation_2->set_stock_status( 'outofstock' ); + + $product->set_children( array( 1001, 1002 ) ); + $products[1000] = $product; + $products[1001] = $variation_1; + $products[1002] = $variation_2; + + $this->sut->update_data_for_product( $product ); + + $expected = array( + // Main product: one entry for each of the regular attribute values, + // excluding custom product attributes. + + array( + 'product_id' => '1000', + 'product_or_parent_id' => '1000', + 'taxonomy' => 'non-variation-attribute', + 'term_id' => '10', + 'is_variation_attribute' => '0', + 'in_stock' => '1', + ), + array( + 'product_id' => '1000', + 'product_or_parent_id' => '1000', + 'taxonomy' => 'non-variation-attribute', + 'term_id' => '20', + 'is_variation_attribute' => '0', + 'in_stock' => '1', + ), + array( + 'product_id' => '1000', + 'product_or_parent_id' => '1000', + 'taxonomy' => 'non-variation-attribute', + 'term_id' => '30', + 'is_variation_attribute' => '0', + 'in_stock' => '1', + ), + + // Variation 1: one entry for each of the defined variation attributes. + + array( + 'product_id' => '1001', + 'product_or_parent_id' => '1000', + 'taxonomy' => 'variation-attribute-1', + 'term_id' => '50', + 'is_variation_attribute' => '1', + 'in_stock' => '1', + ), + array( + 'product_id' => '1001', + 'product_or_parent_id' => '1000', + 'taxonomy' => 'variation-attribute-2', + 'term_id' => '90', + 'is_variation_attribute' => '1', + 'in_stock' => '1', + ), + + // Variation 2: one entry for the defined value for variation-attribute-1, + // then one for each of the possible values of variation-attribute-2 + // (the values defined in the parent product). + + array( + 'product_id' => '1002', + 'product_or_parent_id' => '1000', + 'taxonomy' => 'variation-attribute-1', + 'term_id' => '60', + 'is_variation_attribute' => '1', + 'in_stock' => '0', + ), + array( + 'product_id' => '1002', + 'product_or_parent_id' => '1000', + 'taxonomy' => 'variation-attribute-2', + 'term_id' => '90', + 'is_variation_attribute' => '1', + 'in_stock' => '0', + ), + array( + 'product_id' => '1002', + 'product_or_parent_id' => '1000', + 'taxonomy' => 'variation-attribute-2', + 'term_id' => '100', + 'is_variation_attribute' => '1', + 'in_stock' => '0', + ), + array( + 'product_id' => '1002', + 'product_or_parent_id' => '1000', + 'taxonomy' => 'variation-attribute-2', + 'term_id' => '110', + 'is_variation_attribute' => '1', + 'in_stock' => '0', + ), + ); + + $actual = $this->get_lookup_table_data(); + $this->assertEquals( sort( $expected ), sort( $actual ) ); } /** From c354a672923ccc51d4a12ecb11eb86480d12f1a0 Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 3 May 2021 20:21:00 -0600 Subject: [PATCH 309/368] Finish work on order; removed unused variable from test --- tests/e2e/api/src/models/index.ts | 1 + tests/e2e/api/src/models/orders/index.ts | 2 +- tests/e2e/api/src/models/orders/orders.ts | 59 ++-- .../api/src/models/orders/shared/classes.ts | 4 +- tests/e2e/api/src/repositories/rest/index.ts | 5 +- .../api/src/repositories/rest/orders/index.ts | 3 + .../api/src/repositories/rest/orders/order.ts | 47 +++ .../repositories/rest/orders/transformer.ts | 267 +++++++++++++++++- tests/e2e/config/default.json | 11 + tests/e2e/core-tests/specs/api/order.test.js | 82 ++++++ tests/e2e/core-tests/specs/index.js | 3 + .../merchant/wp-admin-order-emails.test.js | 1 - tests/e2e/specs/rest-api/order.js | 6 + 13 files changed, 451 insertions(+), 40 deletions(-) create mode 100644 tests/e2e/core-tests/specs/api/order.test.js create mode 100644 tests/e2e/specs/rest-api/order.js diff --git a/tests/e2e/api/src/models/index.ts b/tests/e2e/api/src/models/index.ts index 13ce569f196..902fdec58e3 100644 --- a/tests/e2e/api/src/models/index.ts +++ b/tests/e2e/api/src/models/index.ts @@ -3,3 +3,4 @@ export * from './model'; export * from './settings'; export * from './shared-types'; export * from './coupons'; +export * from './orders'; diff --git a/tests/e2e/api/src/models/orders/index.ts b/tests/e2e/api/src/models/orders/index.ts index de526a0af64..d4df1e6ca90 100644 --- a/tests/e2e/api/src/models/orders/index.ts +++ b/tests/e2e/api/src/models/orders/index.ts @@ -1,2 +1,2 @@ -export * from './shared'; export * from './orders'; +export * from './shared'; diff --git a/tests/e2e/api/src/models/orders/orders.ts b/tests/e2e/api/src/models/orders/orders.ts index 04fd8a93282..d23c4ca7611 100644 --- a/tests/e2e/api/src/models/orders/orders.ts +++ b/tests/e2e/api/src/models/orders/orders.ts @@ -1,5 +1,5 @@ -//import { HTTPClient } from '../../http'; -//import { orderRESTRepository } from '../../repositories'; +import { HTTPClient } from '../../http'; +import { orderRESTRepository } from '../../repositories'; import { ModelRepositoryParams, CreatesModels, @@ -50,47 +50,47 @@ type OrderUpdateParams = OrderAddressUpdateParams export type OrderRepositoryParams = ModelRepositoryParams< Order, never, never, OrderUpdateParams >; /** - * An interface for creating coupons using the repository. + * An interface for creating orders using the repository. * - * @typedef CreatesCoupons - * @alias CreatesModels. + * @typedef CreatesOrders + * @alias CreatesModels. */ -export type CreatesCoupons = CreatesModels< OrderRepositoryParams >; +export type CreatesOrders = CreatesModels< OrderRepositoryParams >; /** - * An interface for reading coupons using the repository. + * An interface for reading orders using the repository. * - * @typedef ReadsCoupons - * @alias ReadsModels. + * @typedef ReadsOrders + * @alias ReadsModels. */ -export type ReadsCoupons = ReadsModels< OrderRepositoryParams >; +export type ReadsOrders = ReadsModels< OrderRepositoryParams >; /** - * An interface for updating coupons using the repository. + * An interface for updating orders using the repository. * - * @typedef UpdatesCoupons - * @alias UpdatesModels. + * @typedef UpdatesOrders + * @alias UpdatesModels. */ -export type UpdatesCoupons = UpdatesModels< OrderRepositoryParams >; +export type UpdatesOrders = UpdatesModels< OrderRepositoryParams >; /** - * An interface for listing coupons using the repository. + * An interface for listing orders using the repository. * - * @typedef ListsCoupons - * @alias ListsModels. + * @typedef ListsOrders + * @alias ListsModels. */ -export type ListsCoupons = ListsModels< OrderRepositoryParams >; +export type ListsOrders = ListsModels< OrderRepositoryParams >; /** - * An interface for deleting coupons using the repository. + * An interface for deleting orders using the repository. * - * @typedef DeletesCoupons - * @alias DeletesModels. + * @typedef DeletesOrders + * @alias DeletesModels. */ -export type DeletesCoupons = DeletesModels< OrderRepositoryParams >; +export type DeletesOrders = DeletesModels< OrderRepositoryParams >; /** - * A coupon object. + * An order object. */ export class Order extends OrderItemMeta { /** @@ -289,6 +289,13 @@ export class Order extends OrderItemMeta { */ public readonly currencySymbol: string = ''; + /** + * The order's paid state. + * + * @type {boolean} + */ + public readonly setPaid: boolean = false; + /** * The order's line items. * @@ -342,7 +349,7 @@ export class Order extends OrderItemMeta { }; /** - * Creates a new coupon instance with the given properties + * Creates a new order instance with the given properties * * @param {Object} properties The properties to set in the object. */ @@ -350,15 +357,13 @@ export class Order extends OrderItemMeta { super(); Object.assign( this, properties ); } - /* + /** * Returns the repository for interacting with this type of model. * * @param {HTTPClient} httpClient The client for communicating via HTTP. */ - /* public static restRepository( httpClient: HTTPClient ): ReturnType< typeof orderRESTRepository > { return orderRESTRepository( httpClient ); } - */ } diff --git a/tests/e2e/api/src/models/orders/shared/classes.ts b/tests/e2e/api/src/models/orders/shared/classes.ts index f26923edcd5..540c543d4ae 100644 --- a/tests/e2e/api/src/models/orders/shared/classes.ts +++ b/tests/e2e/api/src/models/orders/shared/classes.ts @@ -36,7 +36,7 @@ export class OrderItemTax extends Model { /** * An order address. */ -export class OrderAddress { +export class OrderAddress extends Model { /** * The first name of the person in the address. * @@ -131,7 +131,7 @@ export class OrderLineItem extends OrderItemMeta { * * @type {number} */ - public readonly ProductId: number = -1; + public readonly productId: number = -1; /** * The ID of the product variation. diff --git a/tests/e2e/api/src/repositories/rest/index.ts b/tests/e2e/api/src/repositories/rest/index.ts index 15f18f10ee0..7ae5c9a38a2 100644 --- a/tests/e2e/api/src/repositories/rest/index.ts +++ b/tests/e2e/api/src/repositories/rest/index.ts @@ -1,3 +1,4 @@ -export * from './products'; -export * from './settings'; export * from './coupons'; +export * from './products'; +export * from './orders'; +export * from './settings'; diff --git a/tests/e2e/api/src/repositories/rest/orders/index.ts b/tests/e2e/api/src/repositories/rest/orders/index.ts index e69de29bb2d..fa4dd50d134 100644 --- a/tests/e2e/api/src/repositories/rest/orders/index.ts +++ b/tests/e2e/api/src/repositories/rest/orders/index.ts @@ -0,0 +1,3 @@ +import orderRESTRepository from './order'; + +export { orderRESTRepository }; diff --git a/tests/e2e/api/src/repositories/rest/orders/order.ts b/tests/e2e/api/src/repositories/rest/orders/order.ts index e69de29bb2d..76e29525982 100644 --- a/tests/e2e/api/src/repositories/rest/orders/order.ts +++ b/tests/e2e/api/src/repositories/rest/orders/order.ts @@ -0,0 +1,47 @@ +import { HTTPClient } from '../../../http'; +import { + ModelRepository, +} from '../../../framework'; +import { + ModelID, + Order, + OrderRepositoryParams, + ListsOrders, + ReadsOrders, + UpdatesOrders, + CreatesOrders, + DeletesOrders, +} from '../../../models'; + +import { + restList, + restCreate, + restRead, + restUpdate, + restDelete, +} from '../shared'; + +import { createOrderTransformer } from './transformer'; +/** + * + * @param {HTTPClient} httpClient The HTTP client for the REST requests to be made using. + */ +export default function orderRESTRepository( httpClient: HTTPClient ): CreatesOrders +& ListsOrders +& ReadsOrders +& UpdatesOrders +& DeletesOrders { + const buildURL = ( id: ModelID ) => '/wc/v3/orders/' + id; + // Using `?force=true` permanently deletes the order + const buildDeleteUrl = ( id: ModelID ) => `/wc/v3/orders/${ id }?force=true`; + + const transformer = createOrderTransformer(); + + return new ModelRepository( + restList< OrderRepositoryParams >( () => '/wc/v3/orders', Order, httpClient, transformer ), + restCreate< OrderRepositoryParams >( () => '/wc/v3/orders', Order, httpClient, transformer ), + restRead< OrderRepositoryParams >( buildURL, Order, httpClient, transformer ), + restUpdate< OrderRepositoryParams >( buildURL, Order, httpClient, transformer ), + restDelete< OrderRepositoryParams >( buildDeleteUrl, httpClient ), + ); +} diff --git a/tests/e2e/api/src/repositories/rest/orders/transformer.ts b/tests/e2e/api/src/repositories/rest/orders/transformer.ts index 41452a2ce26..5cd3c0e2b6f 100644 --- a/tests/e2e/api/src/repositories/rest/orders/transformer.ts +++ b/tests/e2e/api/src/repositories/rest/orders/transformer.ts @@ -1,24 +1,277 @@ import { - AddPropertyTransformation, - CustomTransformation, IgnorePropertyTransformation, KeyChangeTransformation, - ModelTransformation, ModelTransformer, ModelTransformerTransformation, PropertyType, PropertyTypeTransformation, - TransformationOrder, } from '../../../framework'; import { + Order, OrderAddress, OrderCouponLine, OrderFeeLine, - OrderItemTax, OrderLineItem, OrderRefundLine, OrderShippingLine, - OrderStatus, OrderTaxRate, } from '../../../models'; -import { createMetaDataTransformer } from '../shared'; + +/** + * Creates a transformer for an order object. + * + * @return {ModelTransformer} The created transformer. + */ +export function createOrderTransformer(): ModelTransformer< Order > { + return new ModelTransformer( + [ + new IgnorePropertyTransformation( [ 'date_created', 'date_modified' ] ), + new ModelTransformerTransformation( 'billing', OrderAddress, createOrderAddressTransformer() ), + new ModelTransformerTransformation( 'tax_lines', OrderTaxRate, createOrderTaxRateTransformer() ), + new ModelTransformerTransformation( 'refunds', OrderRefundLine, createOrderRefundLineTransformer() ), + new ModelTransformerTransformation( 'coupon_lines', OrderCouponLine, createOrdeCouponLineTransformer() ), + new ModelTransformerTransformation( 'fee_lines', OrderFeeLine, createOrderFeeLineTransformer() ), + new ModelTransformerTransformation( 'line_items', OrderLineItem, createOrderLineItemTransformer() ), + new ModelTransformerTransformation( 'shipping_lines', OrderShippingLine, createOrderShippingItemTransformer() ), + + new PropertyTypeTransformation( + { + status: PropertyType.String, + currency: PropertyType.String, + discountTotal: PropertyType.String, + discountTax: PropertyType.String, + shippingTotal: PropertyType.String, + shippingTax: PropertyType.String, + cartTax: PropertyType.String, + total: PropertyType.String, + totalTax: PropertyType.String, + pricesIncludeTax: PropertyType.Boolean, + customerId: PropertyType.Integer, + customerNote: PropertyType.String, + paymentMethod: PropertyType.String, + transactionId: PropertyType.String, + setPaid: PropertyType.Boolean, + }, + ), + new KeyChangeTransformation< Order >( + { + discountTotal: 'discount_total', + discountTax: 'discount_tax', + shippingTotal: 'shipping_total', + shippingTax: 'shipping_tax', + cartTax: 'cart_tax', + totalTax: 'total_tax', + pricesIncludeTax: 'prices_include_tax', + customerId: 'customer_id', + customerNote: 'customer_note', + paymentMethod: 'payment_method', + transactionId: 'transaction_id', + setPaid: 'set_paid', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order address object. + * + * @return {ModelTransformer} The created transformer. + */ +export function createOrderAddressTransformer(): ModelTransformer< OrderAddress > { + return new ModelTransformer( + [ + new PropertyTypeTransformation( + { + firstName: PropertyType.String, + lastName: PropertyType.String, + company: PropertyType.String, + address1: PropertyType.String, + address2: PropertyType.String, + city: PropertyType.String, + state: PropertyType.String, + postCode: PropertyType.String, + country: PropertyType.String, + }, + ), + new KeyChangeTransformation< OrderAddress >( + { + firstName: 'first_name', + lastName: 'last_name', + address1: 'address_1', + address2: 'address_2', + postCode: 'postcode', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order tax rate object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrderTaxRateTransformer(): ModelTransformer< OrderTaxRate > { + return new ModelTransformer( + [ + new PropertyTypeTransformation( + { + rateCode: PropertyType.String, + rateId: PropertyType.Integer, + label: PropertyType.String, + compoundRate: PropertyType.Boolean, + taxTotal: PropertyType.String, + shippingTaxTotal: PropertyType.String, + ratePercent: PropertyType.Integer, + }, + ), + new KeyChangeTransformation< OrderTaxRate >( + { + rateCode: 'rate_code', + rateId: 'rate_id', + compoundRate: 'compound', + taxTotal: 'tax_total', + shippingTaxTotal: 'shipping_tax_total', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order refund line object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrderRefundLineTransformer(): ModelTransformer< OrderRefundLine > { + return new ModelTransformer( + [ + new PropertyTypeTransformation( + { + reason: PropertyType.String, + total: PropertyType.String, + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order coupon line object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrdeCouponLineTransformer(): ModelTransformer< OrderCouponLine > { + return new ModelTransformer( + [ + new PropertyTypeTransformation( + { + code: PropertyType.String, + discount: PropertyType.Integer, + discountTax: PropertyType.String, + }, + ), + new KeyChangeTransformation< OrderCouponLine >( + { + discountTax: 'discount_tax', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order fee line object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrderFeeLineTransformer(): ModelTransformer< OrderFeeLine > { + return new ModelTransformer( + [ + new ModelTransformerTransformation( 'taxes', OrderTaxRate, createOrderTaxRateTransformer() ), + new PropertyTypeTransformation( + { + name: PropertyType.String, + taxClass: PropertyType.String, + taxStatus: PropertyType.String, + total: PropertyType.String, + totalTax: PropertyType.String, + }, + ), + new KeyChangeTransformation< OrderFeeLine >( + { + taxClass: 'tax_class', + taxStatus: 'tax_status', + totalTax: 'total_tax', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order line item object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrderLineItemTransformer(): ModelTransformer< OrderLineItem > { + return new ModelTransformer( + [ + new ModelTransformerTransformation( 'taxes', OrderTaxRate, createOrderTaxRateTransformer() ), + new PropertyTypeTransformation( + { + name: PropertyType.String, + productId: PropertyType.Integer, + variationId: PropertyType.Integer, + quantity: PropertyType.Integer, + taxClass: PropertyType.String, + subtotal: PropertyType.String, + subtotalTax: PropertyType.String, + total: PropertyType.String, + totalTax: PropertyType.String, + sku: PropertyType.String, + price: PropertyType.Integer, + parentName: PropertyType.String, + }, + ), + new KeyChangeTransformation< OrderLineItem >( + { + productId: 'product_id', + variationId: 'variation_id', + taxClass: 'tax_class', + subtotalTax: 'subtotal_tax', + totalTax: 'total_tax', + }, + ), + ], + ); +} + +/** + * Creates a transformer for an order shipping line item object. + * + * @return {ModelTransformer} The created transformer. + */ +function createOrderShippingItemTransformer(): ModelTransformer< OrderShippingLine > { + return new ModelTransformer( + [ + new ModelTransformerTransformation( 'taxes', OrderTaxRate, createOrderTaxRateTransformer() ), + new PropertyTypeTransformation( + { + methodTitle: PropertyType.String, + methodId: PropertyType.String, + total: PropertyType.String, + totalTax: PropertyType.String, + }, + ), + new KeyChangeTransformation< OrderShippingLine >( + { + methodTitle: 'method_title', + methodId: 'method_id', + totalTax: 'total_tax', + }, + ), + ], + ); +} diff --git a/tests/e2e/config/default.json b/tests/e2e/config/default.json index 4d6b397aac2..adb8538915e 100644 --- a/tests/e2e/config/default.json +++ b/tests/e2e/config/default.json @@ -180,6 +180,17 @@ } } }, + "orders": { + "basicPaidOrder": { + "paymentMethod": "cod", + "status": "processing", + "billing": { + "firstName": "John", + "lastName": "Doe", + "email": "john.doe@example.com" + } + } + }, "onboardingwizard": { "industry": "Test industry", "numberofproducts": "1 - 10", diff --git a/tests/e2e/core-tests/specs/api/order.test.js b/tests/e2e/core-tests/specs/api/order.test.js new file mode 100644 index 00000000000..cdfc0b7a5c1 --- /dev/null +++ b/tests/e2e/core-tests/specs/api/order.test.js @@ -0,0 +1,82 @@ +/* eslint-disable jest/no-export, jest/no-disabled-tests */ +/** + * Internal dependencies + */ + const { HTTPClientFactory, Order } = require( '@woocommerce/api' ); + + /** + * External dependencies + */ + const config = require( 'config' ); + const { + it, + describe, + beforeAll, + } = require( '@jest/globals' ); + + /** + * Creates an order and tests interactions with it via the API. + */ +const runOrderApiTest = () => { + describe('REST API > Order', () => { + let client; + let order; + let repository; + + beforeAll(async () => { + order = config.get( 'orders.basicPaidOrder' ); + const admin = config.get( 'users.admin' ); + const url = config.get( 'url' ); + + client = HTTPClientFactory.build( url ) + .withBasicAuth( admin.username, admin.password ) + .withIndexPermalinks() + .create(); + } ); + + it('can create an order', async () => { + repository = Order.restRepository( client ); + + // Check properties of the order in the create order response. + order = await repository.create( order ); + expect( order ).toEqual( expect.objectContaining( order ) ); + }); + + it('can retrieve an order', async () => { + const orderProperties = { + id: order.id, + payment_method: order.paymentMethod, + status: order.status, + }; + + // Read order directly from API to compare. + const response = await client.get( `/wc/v3/orders/${order.id}` ); + expect( response.statusCode ).toBe( 200 ); + expect( response.data ).toEqual( expect.objectContaining( orderProperties ) ); + }); + + it('can update an order', async () => { + const updatedOrderProperties = { + payment_method: 'bacs', + status: 'completed', + }; + + await repository.update( order.id, updatedOrderProperties ); + + // Check the order response for the updated values. + const response = await client.get( `/wc/v3/orders/${order.id}` ); + expect( response.statusCode ).toBe( 200 ); + expect( response.data ).toEqual( expect.objectContaining( updatedOrderProperties ) ); + }); + + it('can delete an order', async () => { + // Delete the order + const status = await repository.delete( order.id ); + + // If the delete is successful, the response comes back truthy + expect( status ).toBeTruthy(); + }); + }); +}; + +module.exports = runOrderApiTest; diff --git a/tests/e2e/core-tests/specs/index.js b/tests/e2e/core-tests/specs/index.js index a0eca5a730f..12ecebb3c24 100644 --- a/tests/e2e/core-tests/specs/index.js +++ b/tests/e2e/core-tests/specs/index.js @@ -51,6 +51,7 @@ const runExternalProductAPITest = require( './api/external-product.test' ); const runCouponApiTest = require( './api/coupon.test' ); const runGroupedProductAPITest = require( './api/grouped-product.test' ); const runVariableProductAPITest = require( './api/variable-product.test' ); +const runOrderApiTest = require( './api/order.test' ); const runSetupOnboardingTests = () => { runActivationTest(); @@ -104,6 +105,7 @@ const runApiTests = () => { runGroupedProductAPITest(); runVariableProductAPITest(); runCouponApiTest(); + runOrderApiTest(); } module.exports = { @@ -133,6 +135,7 @@ module.exports = { runUpdateGeneralSettingsTest, runProductSettingsTest, runTaxSettingsTest, + runOrderApiTest, runOrderStatusFiltersTest, runOrderRefundTest, runOrderApplyCouponTest, diff --git a/tests/e2e/core-tests/specs/merchant/wp-admin-order-emails.test.js b/tests/e2e/core-tests/specs/merchant/wp-admin-order-emails.test.js index ad18a8de6d1..3b69ba28beb 100644 --- a/tests/e2e/core-tests/specs/merchant/wp-admin-order-emails.test.js +++ b/tests/e2e/core-tests/specs/merchant/wp-admin-order-emails.test.js @@ -11,7 +11,6 @@ const { } = require( '@woocommerce/e2e-utils' ); const config = require( 'config' ); -const simpleProductName = config.get( 'products.simple.name' ); const customerEmail = config.get( 'addresses.customer.billing.email' ); const adminEmail = 'admin@woocommercecoree2etestsuite.com'; const storeName = 'WooCommerce Core E2E Test Suite'; diff --git a/tests/e2e/specs/rest-api/order.js b/tests/e2e/specs/rest-api/order.js new file mode 100644 index 00000000000..d73a8be5f28 --- /dev/null +++ b/tests/e2e/specs/rest-api/order.js @@ -0,0 +1,6 @@ +/* + * Internal dependencies + */ +const { runOrderApiTest } = require( '@woocommerce/e2e-core-tests' ); + +runOrderApiTest(); From 6820b6e519794deb375a40dc6ad0a3f1c03fcb70 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 4 May 2021 16:13:48 +0200 Subject: [PATCH 310/368] Add the WC_Queue::reset_instance method --- includes/queue/class-wc-queue.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/includes/queue/class-wc-queue.php b/includes/queue/class-wc-queue.php index 80dd4b67a95..62e8974c3d4 100644 --- a/includes/queue/class-wc-queue.php +++ b/includes/queue/class-wc-queue.php @@ -48,6 +48,14 @@ class WC_Queue { return self::$instance; } + /** + * Reset the singleton instance so that the next time instance() is invoked + * the woocommerce_queue_class hook will be fired again. + */ + final public static function reset_instance() { + self::$instance = null; + } + /** * Get class to instantiate * From 4d13b0ca0724b404b13a3a2aef55b7bc75471cdb Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 4 May 2021 16:14:34 +0200 Subject: [PATCH 311/368] ExtendedContainer::replace now allows registering anonymous classes. --- .../DependencyManagement/ExtendedContainer.php | 12 +++++++++++- .../DependencyManagement/ExtendedContainerTest.php | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/Internal/DependencyManagement/ExtendedContainer.php b/src/Internal/DependencyManagement/ExtendedContainer.php index a4e084cf76a..5058a43c0c6 100644 --- a/src/Internal/DependencyManagement/ExtendedContainer.php +++ b/src/Internal/DependencyManagement/ExtendedContainer.php @@ -81,7 +81,7 @@ class ExtendedContainer extends BaseContainer { } $concrete_class = $this->get_class_from_concrete( $concrete ); - if ( isset( $concrete_class ) && ! $this->is_class_allowed( $concrete_class ) ) { + if ( isset( $concrete_class ) && ! $this->is_class_allowed( $concrete_class ) && ! $this->is_anonymous_class( $concrete_class ) ) { throw new ContainerException( "You cannot use concrete '$concrete_class', only classes in the {$this->woocommerce_namespace} namespace are allowed." ); } @@ -149,4 +149,14 @@ class ExtendedContainer extends BaseContainer { protected function is_class_allowed( string $class_name ): bool { return StringUtil::starts_with( $class_name, $this->woocommerce_namespace, false ) || in_array( $class_name, $this->registration_whitelist, true ); } + + /** + * Check if a class name corresponds to an anonoymous class. + * + * @param string $class_name The class name to check. + * @return bool True if the name correspondos to an anynymous class. + */ + protected function is_anonymous_class( string $class_name ): bool { + return StringUtil::starts_with( $class_name, 'class@anonymous' ); + } } diff --git a/tests/php/src/Internal/DependencyManagement/ExtendedContainerTest.php b/tests/php/src/Internal/DependencyManagement/ExtendedContainerTest.php index 9f7ccc99671..679c45913e9 100644 --- a/tests/php/src/Internal/DependencyManagement/ExtendedContainerTest.php +++ b/tests/php/src/Internal/DependencyManagement/ExtendedContainerTest.php @@ -103,6 +103,20 @@ class ExtendedContainerTest extends \WC_Unit_Test_Case { $this->assertSame( $instance_2, $this->sut->get( DependencyClass::class ) ); } + /** + * @testdox 'replace' should allow to replace existing registrations with anonymous classes. + */ + public function test_replace_allows_replacing_existing_registrations_with_anonymous_classes() { + $instance_1 = new DependencyClass(); + $instance_2 = new class() extends DependencyClass {}; + + $this->sut->add( DependencyClass::class, $instance_1, true ); + $this->assertSame( $instance_1, $this->sut->get( DependencyClass::class ) ); + + $this->sut->replace( DependencyClass::class, $instance_2, true ); + $this->assertSame( $instance_2, $this->sut->get( DependencyClass::class ) ); + } + /** * @testdox 'reset_all_resolved' should discard cached resolutions for classes registered as 'shared'. */ From c4e7074c70f1d2ff743f2bdfd0721f7b1db204b1 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 4 May 2021 16:15:16 +0200 Subject: [PATCH 312/368] Add unit tests for the DataRegenerator class --- .../DataRegenerator.php | 34 ++- tests/Tools/FakeQueue.php | 10 +- .../DataRegeneratorTest.php | 244 ++++++++++++++++++ 3 files changed, 273 insertions(+), 15 deletions(-) create mode 100644 tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php diff --git a/src/Internal/ProductAttributesLookup/DataRegenerator.php b/src/Internal/ProductAttributesLookup/DataRegenerator.php index 1e45d553c84..e1026671836 100644 --- a/src/Internal/ProductAttributesLookup/DataRegenerator.php +++ b/src/Internal/ProductAttributesLookup/DataRegenerator.php @@ -60,14 +60,12 @@ class DataRegenerator { 999 ); - if ( $this->regeneration_is_in_progress() ) { - add_action( - 'woocommerce_run_product_attribute_lookup_update_callback', - function () { - $this->run_regeneration_step_callback(); - } - ); - } + add_action( + 'woocommerce_run_product_attribute_lookup_update_callback', + function () { + $this->run_regeneration_step_callback(); + } + ); } /** @@ -156,16 +154,18 @@ CREATE TABLE ' . $this->lookup_table_name . '( // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared $last_existing_product_id = - wc_get_products( + WC()->call_function( + 'wc_get_products', array( 'return' => 'ids', 'limit' => 1, - 'orderby' => 'id', - 'order' => 'DESC', + 'orderby' => array( + 'ID' => 'DESC', + ), ) ); - if ( false === $last_existing_product_id ) { + if ( ! $last_existing_product_id ) { // No products exist, nothing to (re)generate. return false; } @@ -198,7 +198,7 @@ CREATE TABLE ' . $this->lookup_table_name . '( */ private function enqueue_regeneration_step_run() { WC()->queue()->schedule_single( - time() + 1, + WC()->call_function( 'time' ) + 1, 'woocommerce_run_product_attribute_lookup_update_callback', array(), 'woocommerce-db-updates' @@ -215,7 +215,8 @@ CREATE TABLE ' . $this->lookup_table_name . '( $last_products_page_processed = get_option( 'woocommerce_attribute_lookup__last_products_page_processed' ); $current_products_page = (int) $last_products_page_processed + 1; - $product_ids = wc_get_products( + $product_ids = WC()->call_function( + 'wc_get_products', array( 'limit' => self::PRODUCTS_PER_GENERATION_STEP, 'page' => $current_products_page, @@ -226,11 +227,16 @@ CREATE TABLE ' . $this->lookup_table_name . '( ) ); + if ( ! $product_ids ) { + return false; + } + foreach ( $product_ids as $id ) { $this->data_store->update_data_for_product( $id ); } update_option( 'woocommerce_attribute_lookup__last_products_page_processed', $current_products_page ); + $last_product_id_to_process = get_option( 'woocommerce_attribute_lookup__last_product_id_to_process' ); return end( $product_ids ) < $last_product_id_to_process; } diff --git a/tests/Tools/FakeQueue.php b/tests/Tools/FakeQueue.php index fe8d8a24f24..cfb8b23607c 100644 --- a/tests/Tools/FakeQueue.php +++ b/tests/Tools/FakeQueue.php @@ -33,7 +33,15 @@ class FakeQueue implements \WC_Queue_Interface { } public function schedule_single( $timestamp, $hook, $args = array(), $group = '' ) { - $this->add_to_methods_called( 'schedule_single', $args, $group, array( 'hook' => $hook ) ); + $this->add_to_methods_called( + 'schedule_single', + $args, + $group, + array( + 'timestamp' => $timestamp, + 'hook' => $hook, + ) + ); } public function schedule_recurring( $timestamp, $interval_in_seconds, $hook, $args = array(), $group = '' ) { diff --git a/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php b/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php new file mode 100644 index 00000000000..84ccb5d162b --- /dev/null +++ b/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php @@ -0,0 +1,244 @@ +lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup'; + + add_filter( + 'woocommerce_queue_class', + function() { + return FakeQueue::class; + } + ); + + // phpcs:disable Squiz.Commenting + $this->lookup_data_store = new class() extends LookupDataStore { + public $passed_products = array(); + + public function update_data_for_product( $product ) { + $this->passed_products[] = $product; + } + }; + // phpcs:enable Squiz.Commenting + + // This is needed to prevent the hook to act on the already registered LookupDataStore class. + remove_all_actions( 'woocommerce_run_product_attribute_lookup_update_callback' ); + + $container = wc_get_container(); + $container->reset_all_resolved(); + $container->replace( LookupDataStore::class, $this->lookup_data_store ); + $this->sut = $container->get( DataRegenerator::class ); + + WC()->queue()->methods_called = array(); + } + + /** + * @testdox `initiate_regeneration` creates the lookup table, deleting it first if it already existed. + * + * @testWith [false] + * [true] + * + * @param bool $previously_existing True to create a lookup table beforehand. + */ + public function test_initiate_regeneration_creates_looukp_table( $previously_existing ) { + global $wpdb; + + // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared + + $wpdb->query( 'DROP TABLE IF EXISTS ' . $this->lookup_table_name ); + + if ( $previously_existing ) { + $wpdb->query( 'CREATE TABLE ' . $this->lookup_table_name . ' (foo int);' ); + } + + $this->sut->initiate_regeneration(); + + $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $this->lookup_table_name ) ); + + $this->assertEquals( $this->lookup_table_name, $wpdb->get_var( $query ) ); + + // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared + } + + /** + * @testdox `initiate_regeneration` initializes the transient options, and enqueues the first step for time()+1. + */ + public function test_initiate_regeneration_initializes_temporary_options_and_enqueues_regeneration_step() { + $this->register_legacy_proxy_function_mocks( + array( + 'wc_get_products' => function( $args ) { + return array( 100 ); + }, + 'time' => function() { + return 1000; + }, + ) + ); + + $this->sut->initiate_regeneration(); + + $this->assertEquals( 100, get_option( 'woocommerce_attribute_lookup__last_product_id_to_process' ) ); + $this->assertEquals( 0, get_option( 'woocommerce_attribute_lookup__last_products_page_processed' ) ); + $this->assertFalse( get_option( 'woocommerce_attribute_lookup__enabled' ) ); + + $expected_enqueued = array( + 'method' => 'schedule_single', + 'args' => array(), + 'timestamp' => 1001, + 'hook' => 'woocommerce_run_product_attribute_lookup_update_callback', + 'group' => 'woocommerce-db-updates', + ); + $actual_enqueued = current( WC()->queue()->methods_called ); + + $this->assertEquals( sort( $expected_enqueued ), sort( $actual_enqueued ) ); + } + + /** + * @testdox `initiate_regeneration` finalizes the regeneration process without enqueueing any step if the db is empty. + * + * @testWith [false] + * [[]] + * + * @param mixed $get_products_result Result from wc_get_products. + */ + public function test_initiate_regeneration_does_not_enqueues_regeneration_step_when_no_products( $get_products_result ) { + $this->register_legacy_proxy_function_mocks( + array( + 'wc_get_products' => function( $args ) use ( $get_products_result ) { + return $get_products_result; + }, + ) + ); + + $this->sut->initiate_regeneration(); + + $this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_product_id_to_process' ) ); + $this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_products_page_processed' ) ); + $this->assertEquals( 'no', get_option( 'woocommerce_attribute_lookup__enabled' ) ); + $this->assertEmpty( WC()->queue()->methods_called ); + } + + /** + * @testdox `initiate_regeneration` processes one chunk of products IDs and enqueues next step if there are more products available. + */ + public function test_initiate_regeneration_correctly_processes_ids_and_enqueues_next_step() { + $requested_products_pages = array(); + + $this->register_legacy_proxy_function_mocks( + array( + 'wc_get_products' => function( $args ) use ( &$requested_products_pages ) { + if ( 'DESC' === current( $args['orderby'] ) ) { + return array( 100 ); + } else { + $requested_products_pages[] = $args['page']; + return array( 1, 2, 3 ); + } + }, + 'time' => function() { + return 1000; + }, + ) + ); + + $this->sut->initiate_regeneration(); + WC()->queue()->methods_called = array(); + + update_option( 'woocommerce_attribute_lookup__last_products_page_processed', 7 ); + + do_action( 'woocommerce_run_product_attribute_lookup_update_callback' ); + + $this->assertEquals( array( 1, 2, 3 ), $this->lookup_data_store->passed_products ); + $this->assertEquals( array( 8 ), $requested_products_pages ); + $this->assertEquals( 8, get_option( 'woocommerce_attribute_lookup__last_products_page_processed' ) ); + + $expected_enqueued = array( + 'method' => 'schedule_single', + 'args' => array(), + 'timestamp' => 1001, + 'hook' => 'woocommerce_run_product_attribute_lookup_update_callback', + 'group' => 'woocommerce-db-updates', + ); + $actual_enqueued = current( WC()->queue()->methods_called ); + $this->assertEquals( sort( $expected_enqueued ), sort( $actual_enqueued ) ); + } + + /** + * @testdox `initiate_regeneration` finishes regeneration when the max product id is reached or no more products are returned. + * + * @testWith [[98,99,100]] + * [[99,100,101]] + * [[]] + * + * @param array $product_ids The products ids that wc_get_products will return. + */ + public function test_initiate_regeneration_finishes_when_no_more_products_available( $product_ids ) { + $requested_products_pages = array(); + + $this->register_legacy_proxy_function_mocks( + array( + 'wc_get_products' => function( $args ) use ( &$requested_products_pages, $product_ids ) { + if ( 'DESC' === current( $args['orderby'] ) ) { + return array( 100 ); + } else { + $requested_products_pages[] = $args['page']; + return $product_ids; + } + }, + ) + ); + + $this->sut->initiate_regeneration(); + WC()->queue()->methods_called = array(); + + do_action( 'woocommerce_run_product_attribute_lookup_update_callback' ); + + $this->assertEquals( $product_ids, $this->lookup_data_store->passed_products ); + $this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_product_id_to_process' ) ); + $this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_products_page_processed' ) ); + $this->assertEquals( 'no', get_option( 'woocommerce_attribute_lookup__enabled' ) ); + $this->assertEmpty( WC()->queue()->methods_called ); + } +} From ce1e2f260d0a06e8528c2a66bb681a16d1366a31 Mon Sep 17 00:00:00 2001 From: Veljko Date: Wed, 5 May 2021 09:29:38 +0200 Subject: [PATCH 313/368] Rename the test file --- .../{test-extensions-connect-wccom.js => wccom-connect.test.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/e2e/specs/wp-admin/{test-extensions-connect-wccom.js => wccom-connect.test.js} (100%) diff --git a/tests/e2e/specs/wp-admin/test-extensions-connect-wccom.js b/tests/e2e/specs/wp-admin/wccom-connect.test.js similarity index 100% rename from tests/e2e/specs/wp-admin/test-extensions-connect-wccom.js rename to tests/e2e/specs/wp-admin/wccom-connect.test.js From f53f959d0376b8adf9aacc7052251de40d8727a6 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Wed, 5 May 2021 11:11:36 +0200 Subject: [PATCH 314/368] Fix the usage of FakeQueue in DataRegeneratorTest. Also update the doc comment of FakeQueue itself on how to use it. --- includes/queue/class-wc-queue.php | 8 ----- .../DataRegenerator.php | 3 +- tests/Tools/FakeQueue.php | 13 +++++-- .../DataRegeneratorTest.php | 34 +++++++++---------- 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/includes/queue/class-wc-queue.php b/includes/queue/class-wc-queue.php index 62e8974c3d4..80dd4b67a95 100644 --- a/includes/queue/class-wc-queue.php +++ b/includes/queue/class-wc-queue.php @@ -48,14 +48,6 @@ class WC_Queue { return self::$instance; } - /** - * Reset the singleton instance so that the next time instance() is invoked - * the woocommerce_queue_class hook will be fired again. - */ - final public static function reset_instance() { - self::$instance = null; - } - /** * Get class to instantiate * diff --git a/src/Internal/ProductAttributesLookup/DataRegenerator.php b/src/Internal/ProductAttributesLookup/DataRegenerator.php index e1026671836..ebc1758a0ff 100644 --- a/src/Internal/ProductAttributesLookup/DataRegenerator.php +++ b/src/Internal/ProductAttributesLookup/DataRegenerator.php @@ -197,7 +197,8 @@ CREATE TABLE ' . $this->lookup_table_name . '( * Enqueue one regeneration step in action scheduler. */ private function enqueue_regeneration_step_run() { - WC()->queue()->schedule_single( + $queue = WC()->get_instance_of( \WC_Queue::class ); + $queue->schedule_single( WC()->call_function( 'time' ) + 1, 'woocommerce_run_product_attribute_lookup_update_callback', array(), diff --git a/tests/Tools/FakeQueue.php b/tests/Tools/FakeQueue.php index cfb8b23607c..a8dd9151b55 100644 --- a/tests/Tools/FakeQueue.php +++ b/tests/Tools/FakeQueue.php @@ -11,11 +11,18 @@ namespace Automattic\WooCommerce\Testing\Tools; * Fake scheduled actions queue for unit tests, it just records all the method calls * in a publicly accessible $methods_called property. * - * To use, add this to the setUp method of the unit tests class: + * To use: * - * add_filter( 'woocommerce_queue_class', function() { return FakeQueue::class; } ); + * 1. The production class must get an instance of the queue in this way: * - * then WC->queue() will return an instance of this class. + * WC()->get_instance_of(\WC_Queue::class) + * + * 2. Add the following in the setUp() method of the unit tests class: + * + * $this->register_legacy_proxy_class_mocks([\WC_Queue::class => new FakeQueue()]); + * + * 3. Get the instance of the fake queue with $this->get_legacy_instance_of(\WC_Queue::class) + * and check its methods_called field as appropriate. */ class FakeQueue implements \WC_Queue_Interface { diff --git a/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php b/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php index 84ccb5d162b..bde4569878b 100644 --- a/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php +++ b/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php @@ -33,11 +33,9 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case { private $lookup_table_name; /** - * Runs before all the tests in the class. + * @var FakeQueue */ - public static function setUpBeforeClass() { - \WC_Queue::reset_instance(); - } + private $queue; /** * Runs before each test. @@ -45,14 +43,9 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case { public function setUp() { global $wpdb; - $this->lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup'; + parent::setUp(); - add_filter( - 'woocommerce_queue_class', - function() { - return FakeQueue::class; - } - ); + $this->lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup'; // phpcs:disable Squiz.Commenting $this->lookup_data_store = new class() extends LookupDataStore { @@ -72,7 +65,12 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case { $container->replace( LookupDataStore::class, $this->lookup_data_store ); $this->sut = $container->get( DataRegenerator::class ); - WC()->queue()->methods_called = array(); + $this->register_legacy_proxy_class_mocks( + array( + \WC_Queue::class => new FakeQueue(), + ) + ); + $this->queue = $this->get_legacy_instance_of( \WC_Queue::class ); } /** @@ -131,7 +129,7 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case { 'hook' => 'woocommerce_run_product_attribute_lookup_update_callback', 'group' => 'woocommerce-db-updates', ); - $actual_enqueued = current( WC()->queue()->methods_called ); + $actual_enqueued = current( $this->queue->methods_called ); $this->assertEquals( sort( $expected_enqueued ), sort( $actual_enqueued ) ); } @@ -158,7 +156,7 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case { $this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_product_id_to_process' ) ); $this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_products_page_processed' ) ); $this->assertEquals( 'no', get_option( 'woocommerce_attribute_lookup__enabled' ) ); - $this->assertEmpty( WC()->queue()->methods_called ); + $this->assertEmpty( $this->queue->methods_called ); } /** @@ -184,7 +182,7 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case { ); $this->sut->initiate_regeneration(); - WC()->queue()->methods_called = array(); + $this->queue->methods_called = array(); update_option( 'woocommerce_attribute_lookup__last_products_page_processed', 7 ); @@ -201,7 +199,7 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case { 'hook' => 'woocommerce_run_product_attribute_lookup_update_callback', 'group' => 'woocommerce-db-updates', ); - $actual_enqueued = current( WC()->queue()->methods_called ); + $actual_enqueued = current( $this->queue->methods_called ); $this->assertEquals( sort( $expected_enqueued ), sort( $actual_enqueued ) ); } @@ -231,7 +229,7 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case { ); $this->sut->initiate_regeneration(); - WC()->queue()->methods_called = array(); + $this->queue->methods_called = array(); do_action( 'woocommerce_run_product_attribute_lookup_update_callback' ); @@ -239,6 +237,6 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case { $this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_product_id_to_process' ) ); $this->assertFalse( get_option( 'woocommerce_attribute_lookup__last_products_page_processed' ) ); $this->assertEquals( 'no', get_option( 'woocommerce_attribute_lookup__enabled' ) ); - $this->assertEmpty( WC()->queue()->methods_called ); + $this->assertEmpty( $this->queue->methods_called ); } } From 9dcdfddc15c6b544a7fcfe76248a2a166365c49e Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Wed, 5 May 2021 11:50:43 +0200 Subject: [PATCH 315/368] Fix table creation detection in DataRegeneratorTest --- .../ProductAttributesLookup/DataRegeneratorTest.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php b/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php index bde4569878b..a40f97c42a2 100644 --- a/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php +++ b/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php @@ -94,9 +94,11 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case { $this->sut->initiate_regeneration(); - $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $this->lookup_table_name ) ); - - $this->assertEquals( $this->lookup_table_name, $wpdb->get_var( $query ) ); + // Try to insert a row to verify that the table exists. + // We can't use the regular table existence detection mechanisms because PHPUnit creates all tables as temporary. + $wpdb->query( 'INSERT INTO ' . $this->lookup_table_name . " VALUES (1, 1, 'taxonomy', 1, 1, 1 )" ); + $value = $wpdb->get_var( 'SELECT product_id FROM ' . $this->lookup_table_name . ' LIMIT 1' ); + $this->assertEquals( 1, $value ); // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared } From 3fa233872cb2ab8152e0f8cb4b1bc548ee18a6ba Mon Sep 17 00:00:00 2001 From: And Finally Date: Thu, 6 May 2021 12:55:30 +0100 Subject: [PATCH 316/368] Added `output_ad_block` method to `WC_Admin_Addons` and CSS rules to render a WooCommerce Payments ad banner at the top of the "Featured" section of the WC Core addons page, `wp-admin/admin.php?page=wc-addons§ion=_featured`. This is to fulfil the requirements of WooCommerce.com issue https://github.com/Automattic/woocommerce.com/issues/9860. We output the block if - The user has permissions to install plugins. - Their location is in one of the countries identified in a `geowhitelist`. - WooCommerce Payments is not already active. --- assets/css/admin.scss | 141 +++++++++++++++------ includes/admin/class-wc-admin-addons.php | 152 ++++++++++++++++------- 2 files changed, 212 insertions(+), 81 deletions(-) diff --git a/assets/css/admin.scss b/assets/css/admin.scss index 3dca45bdf8c..3cfc1495fdd 100644 --- a/assets/css/admin.scss +++ b/assets/css/admin.scss @@ -1,4 +1,3 @@ - /** * admin.scss * General WooCommerce admin styles. Settings, product data tabs, reports, etc. @@ -102,6 +101,43 @@ height: 62px; } + .addons-ad-block { + display: flex; + padding: 20px; + + .addons-img { + height: auto; + width: 200px; + } + } + + .addons-ad-block-content { + display: flex; + flex-direction: column; + margin-left: 24px; + } + + .addons-ad-block-description { + margin-bottom: 20px; + } + + .addons-ad-block-title { + margin: 0 0 16px; + padding: 0; + } + + .addons-ad-block-buttons { + margin-top: auto; + + .addons-button { + margin-right: 8px; + + &:last-child { + margin-right: 0; + } + } + } + .addons-banner-block p { margin: 0 0 20px; } @@ -364,6 +400,12 @@ color: #fff; } + .addons-button-expandable { + display: inline-block; + padding: 0 16px; + width: auto !important; + } + .addons-button-solid:hover { color: #fff; opacity: 0.8; @@ -451,9 +493,8 @@ flex: 1; overflow: hidden; background: #f5f5f5; - box-shadow: - inset 0 1px 0 rgba(255, 255, 255, 0.2), - inset 0 -1px 0 rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), + inset 0 -1px 0 rgba(0, 0, 0, 0.1); a { text-decoration: none; @@ -645,7 +686,7 @@ mark.amount { &::after { - @include icon_dashicons( "\f223" ); + @include icon_dashicons("\f223"); cursor: help; } } @@ -830,7 +871,7 @@ table.wc_status_table--tools { } // Adjust log table columns only when table is not collapsed - @media screen and ( min-width: 783px ) { + @media screen and (min-width: 783px) { .column-timestamp { width: 18%; @@ -1021,7 +1062,7 @@ ul.wc_coupon_list { &::before { - @include icon_dashicons( "\f158" ); + @include icon_dashicons("\f158"); } &:hover::before { @@ -1065,7 +1106,7 @@ ul.wc_coupon_list_block { &::after { - @include icon_dashicons( "\f345" ); + @include icon_dashicons("\f345"); line-height: 28px; } } @@ -1589,7 +1630,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons( "\f128" ); + @include icon_dashicons("\f128"); width: 38px; line-height: 38px; display: block; @@ -1837,7 +1878,7 @@ ul.wc_coupon_list_block { &::before { - @include icon( "\e007" ); + @include icon("\e007"); color: #ccc; } } @@ -1852,7 +1893,7 @@ ul.wc_coupon_list_block { &::before { - @include icon( "\e014" ); + @include icon("\e014"); color: #ccc; } } @@ -1869,7 +1910,7 @@ ul.wc_coupon_list_block { &::before { - @include icon( "\e01a" ); + @include icon("\e01a"); color: #ccc; } } @@ -1898,7 +1939,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons( "\f153" ); + @include icon_dashicons("\f153"); color: #999; } @@ -1920,7 +1961,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons( "\f171" ); + @include icon_dashicons("\f171"); position: relative; top: auto; left: auto; @@ -1976,7 +2017,7 @@ ul.wc_coupon_list_block { .edit-order-item::before { - @include icon_dashicons( "\f464" ); + @include icon_dashicons("\f464"); position: relative; } @@ -1985,7 +2026,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons( "\f158" ); + @include icon_dashicons("\f158"); position: relative; } @@ -2353,7 +2394,7 @@ ul.wc_coupon_list_block { &::before { - @include icon( "\e010" ); + @include icon("\e010"); line-height: 16px; font-size: 14px; vertical-align: middle; @@ -2642,6 +2683,29 @@ ul.wc_coupon_list_block { float: right; } } + + .wc_addons_wrap { + .addons-ad-block { + flex-direction: column; + padding: 24px; + + .addons-img { + height: auto; + width: 100%; + max-width: 240px; + margin: 0 auto 20px; + } + } + + .addons-ad-block-content { + display: block; + margin-left: 0; + } + + .addons-ad-block-title { + margin-top: 4px; + } + } } .column-customer_message .note-on { @@ -2652,7 +2716,7 @@ ul.wc_coupon_list_block { &::after { - @include icon( "\e026" ); + @include icon("\e026"); line-height: 16px; } } @@ -2665,7 +2729,7 @@ ul.wc_coupon_list_block { &::after { - @include icon( "\e027" ); + @include icon("\e027"); line-height: 16px; } } @@ -2902,7 +2966,7 @@ table.wp-list-table { &::before { - @include icon_dashicons( "\f128" ); + @include icon_dashicons("\f128"); } } @@ -3867,19 +3931,19 @@ img.help_tip { .status-manual::before { - @include icon( "\e008" ); + @include icon("\e008"); color: #999; } .status-enabled::before { - @include icon( "\e015" ); + @include icon("\e015"); color: $woocommerce; } .status-disabled::before { - @include icon( "\e013" ); + @include icon("\e013"); color: #ccc; } @@ -4298,7 +4362,7 @@ img.help_tip { &::after { - @include icon_dashicons( "\f161" ); + @include icon_dashicons("\f161"); font-size: 2.618em; line-height: 72px; color: #ddd; @@ -4340,7 +4404,7 @@ img.help_tip { &::before { - @include icon_dashicons( "\f153" ); + @include icon_dashicons("\f153"); color: #999; background: #fff; border-radius: 50%; @@ -4527,7 +4591,7 @@ img.help_tip { &::before { - @include iconbeforedashicons( "\f107" ); + @include iconbeforedashicons("\f107"); } } @@ -4611,7 +4675,7 @@ img.help_tip { .add.button::before { - @include iconbefore( "\e007" ); + @include iconbefore("\e007"); } } @@ -4727,7 +4791,7 @@ img.help_tip { &::before { - @include icon_dashicons( "\f153" ); + @include icon_dashicons("\f153"); color: #999; } @@ -5642,7 +5706,7 @@ img.ui-datepicker-trigger { &::before { - @include iconbeforedashicons( "\f346" ); + @include iconbeforedashicons("\f346"); margin-right: 4px; } } @@ -5769,7 +5833,7 @@ img.ui-datepicker-trigger { &::after { - @include iconafter( "\e035" ); + @include iconafter("\e035"); float: right; font-size: 0.9em; line-height: 1.618; @@ -5902,9 +5966,8 @@ img.ui-datepicker-trigger { } &:hover { - box-shadow: - inset 0 -1px 0 0 #dfdfdf, - inset 300px 0 0 rgba(156, 93, 144, 0.1); + box-shadow: inset 0 -1px 0 0 #dfdfdf, + inset 300px 0 0 rgba(156, 93, 144, 0.1); border-right: 5px solid #9c5d90 !important; padding-left: 1.5em; color: #9c5d90; @@ -6104,27 +6167,27 @@ table.bar_chart { .post-type-shop_order .woocommerce-BlankState-message::before { - @include icon( "\e01d" ); + @include icon("\e01d"); } .post-type-shop_coupon .woocommerce-BlankState-message::before { - @include icon( "\e600" ); + @include icon("\e600"); } .post-type-product .woocommerce-BlankState-message::before { - @include icon( "\e006" ); + @include icon("\e006"); } .woocommerce-BlankState--api .woocommerce-BlankState-message::before { - @include icon( "\e01c" ); + @include icon("\e01c"); } .woocommerce-BlankState--webhooks .woocommerce-BlankState-message::before { - @include icon( "\e01b" ); + @include icon("\e01b"); } .woocommerce-BlankState { @@ -7298,7 +7361,7 @@ table.bar_chart { &::before { - @include icon( "\e015" ); + @include icon("\e015"); color: #a16696; position: static; font-size: 100px; diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index ed3a0461368..7c80211290e 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -50,6 +50,7 @@ class WC_Admin_Addons { if ( is_object( $featured ) ) { self::output_featured_sections( $featured->sections ); + return $featured; } } @@ -57,9 +58,9 @@ class WC_Admin_Addons { /** * Build url parameter string * - * @param string $category Addon (sub) category. - * @param string $term Search terms. - * @param string $country Store country. + * @param string $category Addon (sub) category. + * @param string $term Search terms. + * @param string $country Store country. * * @return string url parameter string */ @@ -77,14 +78,14 @@ class WC_Admin_Addons { /** * Call API to get extensions * - * @param string $category Addon (sub) category. - * @param string $term Search terms. - * @param string $country Store country. + * @param string $category Addon (sub) category. + * @param string $term Search terms. + * @param string $country Store country. * * @return array of extensions */ public static function get_extension_data( $category, $term, $country ) { - $parameters = self::build_parameter_string( $category, $term, $country ); + $parameters = self::build_parameter_string( $category, $term, $country ); $headers = array(); $auth = WC_Helper_Options::get( 'auth' ); @@ -101,6 +102,7 @@ class WC_Admin_Addons { if ( ! is_wp_error( $raw_extensions ) ) { $addons = json_decode( wp_remote_retrieve_body( $raw_extensions ) )->products; } + return $addons; } @@ -122,13 +124,14 @@ class WC_Admin_Addons { } } } + return apply_filters( 'woocommerce_addons_sections', $addon_sections ); } /** * Get section for the addons screen. * - * @param string $section_id Required section ID. + * @param string $section_id Required section ID. * * @return object|bool */ @@ -137,13 +140,14 @@ class WC_Admin_Addons { if ( isset( $sections[ $section_id ] ) ) { return $sections[ $section_id ]; } + return false; } /** * Get section content for the addons screen. * - * @param string $section_id Required section ID. + * @param string $section_id Required section ID. * * @return array */ @@ -226,12 +230,12 @@ class WC_Admin_Addons {

title ); ?>

description ); ?>

href, - $item->button, - 'addons-button-solid', - $item->plugin - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-solid', + $item->plugin + ); ?>
@@ -288,12 +292,12 @@ class WC_Admin_Addons {

title ); ?>

href, - $item->button, - 'addons-button-solid', - $item->plugin - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-solid', + $item->plugin + ); ?>

description ); ?>

@@ -320,11 +324,11 @@ class WC_Admin_Addons {
buttons as $button ) : ?> href, - $button->text, - 'addons-button-solid' - ); + self::output_button( + $button->href, + $button->text, + 'addons-button-solid' + ); ?>
@@ -352,11 +356,11 @@ class WC_Admin_Addons { href, - $item->button, - 'addons-button-outline-white' - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-outline-white' + ); ?> @@ -461,11 +465,11 @@ class WC_Admin_Addons { @@ -523,17 +527,75 @@ class WC_Admin_Addons {

geowhitelist ) ) { + $section_object->geowhitelist = explode( ',', $section_object->geowhitelist ); + } + + if ( ! self::show_extension( $section_object ) ) { + return; + } + + ?> +
+ <?php echo esc_attr( $section['image_alt'] ); ?> +
+

+
+ +
+
+ +
+
+
+ site_url(), 'wccom-back' => rawurlencode( $back_admin_path ), @@ -591,7 +657,7 @@ class WC_Admin_Addons { * Adds various url parameters to a url to support a streamlined * flow for obtaining and setting up WooCommerce extensons. * - * @param string $url Destination URL. + * @param string $url Destination URL. */ public static function add_in_app_purchase_url_params( $url ) { return add_query_arg( @@ -632,6 +698,7 @@ class WC_Admin_Addons { if ( isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) { do_action( 'woocommerce_helper_output' ); + return; } @@ -718,6 +785,7 @@ class WC_Admin_Addons { * Should an extension be shown on the featured page. * * @param object $item Item data. + * * @return boolean */ public static function show_extension( $item ) { From f1a69cb4afcd1bad6f1f224f028712603b3df528 Mon Sep 17 00:00:00 2001 From: And Finally Date: Thu, 6 May 2021 15:16:49 +0100 Subject: [PATCH 317/368] Added comment to new `output_ad_block` method. Removed differences introduced by PhpStorm autoformat. --- assets/css/admin.scss | 150 ++++++++++++----------- includes/admin/class-wc-admin-addons.php | 96 +++++++-------- 2 files changed, 124 insertions(+), 122 deletions(-) diff --git a/assets/css/admin.scss b/assets/css/admin.scss index 3cfc1495fdd..cc06dd14e7e 100644 --- a/assets/css/admin.scss +++ b/assets/css/admin.scss @@ -1,3 +1,4 @@ + /** * admin.scss * General WooCommerce admin styles. Settings, product data tabs, reports, etc. @@ -101,43 +102,6 @@ height: 62px; } - .addons-ad-block { - display: flex; - padding: 20px; - - .addons-img { - height: auto; - width: 200px; - } - } - - .addons-ad-block-content { - display: flex; - flex-direction: column; - margin-left: 24px; - } - - .addons-ad-block-description { - margin-bottom: 20px; - } - - .addons-ad-block-title { - margin: 0 0 16px; - padding: 0; - } - - .addons-ad-block-buttons { - margin-top: auto; - - .addons-button { - margin-right: 8px; - - &:last-child { - margin-right: 0; - } - } - } - .addons-banner-block p { margin: 0 0 20px; } @@ -197,6 +161,43 @@ } } + .addons-ad-block { + display: flex; + padding: 20px; + + .addons-img { + height: auto; + width: 200px; + } + } + + .addons-ad-block-content { + display: flex; + flex-direction: column; + margin-left: 24px; + } + + .addons-ad-block-description { + margin-bottom: 20px; + } + + .addons-ad-block-title { + margin: 0 0 16px; + padding: 0; + } + + .addons-ad-block-buttons { + margin-top: auto; + + .addons-button { + margin-right: 8px; + + &:last-child { + margin-right: 0; + } + } + } + .addons-shipping-methods .addons-wcs-banner-block { margin-left: 0; margin-right: 0; @@ -493,8 +494,9 @@ flex: 1; overflow: hidden; background: #f5f5f5; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), - inset 0 -1px 0 rgba(0, 0, 0, 0.1); + box-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.2), + inset 0 -1px 0 rgba(0, 0, 0, 0.1); a { text-decoration: none; @@ -686,7 +688,7 @@ mark.amount { &::after { - @include icon_dashicons("\f223"); + @include icon_dashicons( "\f223" ); cursor: help; } } @@ -871,7 +873,7 @@ table.wc_status_table--tools { } // Adjust log table columns only when table is not collapsed - @media screen and (min-width: 783px) { + @media screen and ( min-width: 783px ) { .column-timestamp { width: 18%; @@ -1062,7 +1064,7 @@ ul.wc_coupon_list { &::before { - @include icon_dashicons("\f158"); + @include icon_dashicons( "\f158" ); } &:hover::before { @@ -1106,7 +1108,7 @@ ul.wc_coupon_list_block { &::after { - @include icon_dashicons("\f345"); + @include icon_dashicons( "\f345" ); line-height: 28px; } } @@ -1630,7 +1632,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons("\f128"); + @include icon_dashicons( "\f128" ); width: 38px; line-height: 38px; display: block; @@ -1878,7 +1880,7 @@ ul.wc_coupon_list_block { &::before { - @include icon("\e007"); + @include icon( "\e007" ); color: #ccc; } } @@ -1893,7 +1895,7 @@ ul.wc_coupon_list_block { &::before { - @include icon("\e014"); + @include icon( "\e014" ); color: #ccc; } } @@ -1910,7 +1912,7 @@ ul.wc_coupon_list_block { &::before { - @include icon("\e01a"); + @include icon( "\e01a" ); color: #ccc; } } @@ -1939,7 +1941,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons("\f153"); + @include icon_dashicons( "\f153" ); color: #999; } @@ -1961,7 +1963,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons("\f171"); + @include icon_dashicons( "\f171" ); position: relative; top: auto; left: auto; @@ -2017,7 +2019,7 @@ ul.wc_coupon_list_block { .edit-order-item::before { - @include icon_dashicons("\f464"); + @include icon_dashicons( "\f464" ); position: relative; } @@ -2026,7 +2028,7 @@ ul.wc_coupon_list_block { &::before { - @include icon_dashicons("\f158"); + @include icon_dashicons( "\f158" ); position: relative; } @@ -2394,7 +2396,7 @@ ul.wc_coupon_list_block { &::before { - @include icon("\e010"); + @include icon( "\e010" ); line-height: 16px; font-size: 14px; vertical-align: middle; @@ -2685,6 +2687,7 @@ ul.wc_coupon_list_block { } .wc_addons_wrap { + .addons-ad-block { flex-direction: column; padding: 24px; @@ -2716,7 +2719,7 @@ ul.wc_coupon_list_block { &::after { - @include icon("\e026"); + @include icon( "\e026" ); line-height: 16px; } } @@ -2729,7 +2732,7 @@ ul.wc_coupon_list_block { &::after { - @include icon("\e027"); + @include icon( "\e027" ); line-height: 16px; } } @@ -2966,7 +2969,7 @@ table.wp-list-table { &::before { - @include icon_dashicons("\f128"); + @include icon_dashicons( "\f128" ); } } @@ -3931,19 +3934,19 @@ img.help_tip { .status-manual::before { - @include icon("\e008"); + @include icon( "\e008" ); color: #999; } .status-enabled::before { - @include icon("\e015"); + @include icon( "\e015" ); color: $woocommerce; } .status-disabled::before { - @include icon("\e013"); + @include icon( "\e013" ); color: #ccc; } @@ -4362,7 +4365,7 @@ img.help_tip { &::after { - @include icon_dashicons("\f161"); + @include icon_dashicons( "\f161" ); font-size: 2.618em; line-height: 72px; color: #ddd; @@ -4404,7 +4407,7 @@ img.help_tip { &::before { - @include icon_dashicons("\f153"); + @include icon_dashicons( "\f153" ); color: #999; background: #fff; border-radius: 50%; @@ -4591,7 +4594,7 @@ img.help_tip { &::before { - @include iconbeforedashicons("\f107"); + @include iconbeforedashicons( "\f107" ); } } @@ -4675,7 +4678,7 @@ img.help_tip { .add.button::before { - @include iconbefore("\e007"); + @include iconbefore( "\e007" ); } } @@ -4791,7 +4794,7 @@ img.help_tip { &::before { - @include icon_dashicons("\f153"); + @include icon_dashicons( "\f153" ); color: #999; } @@ -5706,7 +5709,7 @@ img.ui-datepicker-trigger { &::before { - @include iconbeforedashicons("\f346"); + @include iconbeforedashicons( "\f346" ); margin-right: 4px; } } @@ -5833,7 +5836,7 @@ img.ui-datepicker-trigger { &::after { - @include iconafter("\e035"); + @include iconafter( "\e035" ); float: right; font-size: 0.9em; line-height: 1.618; @@ -5966,8 +5969,9 @@ img.ui-datepicker-trigger { } &:hover { - box-shadow: inset 0 -1px 0 0 #dfdfdf, - inset 300px 0 0 rgba(156, 93, 144, 0.1); + box-shadow: + inset 0 -1px 0 0 #dfdfdf, + inset 300px 0 0 rgba(156, 93, 144, 0.1); border-right: 5px solid #9c5d90 !important; padding-left: 1.5em; color: #9c5d90; @@ -6167,27 +6171,27 @@ table.bar_chart { .post-type-shop_order .woocommerce-BlankState-message::before { - @include icon("\e01d"); + @include icon( "\e01d" ); } .post-type-shop_coupon .woocommerce-BlankState-message::before { - @include icon("\e600"); + @include icon( "\e600" ); } .post-type-product .woocommerce-BlankState-message::before { - @include icon("\e006"); + @include icon( "\e006" ); } .woocommerce-BlankState--api .woocommerce-BlankState-message::before { - @include icon("\e01c"); + @include icon( "\e01c" ); } .woocommerce-BlankState--webhooks .woocommerce-BlankState-message::before { - @include icon("\e01b"); + @include icon( "\e01b" ); } .woocommerce-BlankState { @@ -7361,7 +7365,7 @@ table.bar_chart { &::before { - @include icon("\e015"); + @include icon( "\e015" ); color: #a16696; position: static; font-size: 100px; diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index 7c80211290e..c9aa5a2cd71 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -50,7 +50,6 @@ class WC_Admin_Addons { if ( is_object( $featured ) ) { self::output_featured_sections( $featured->sections ); - return $featured; } } @@ -58,9 +57,9 @@ class WC_Admin_Addons { /** * Build url parameter string * - * @param string $category Addon (sub) category. - * @param string $term Search terms. - * @param string $country Store country. + * @param string $category Addon (sub) category. + * @param string $term Search terms. + * @param string $country Store country. * * @return string url parameter string */ @@ -78,14 +77,14 @@ class WC_Admin_Addons { /** * Call API to get extensions * - * @param string $category Addon (sub) category. - * @param string $term Search terms. - * @param string $country Store country. + * @param string $category Addon (sub) category. + * @param string $term Search terms. + * @param string $country Store country. * * @return array of extensions */ public static function get_extension_data( $category, $term, $country ) { - $parameters = self::build_parameter_string( $category, $term, $country ); + $parameters = self::build_parameter_string( $category, $term, $country ); $headers = array(); $auth = WC_Helper_Options::get( 'auth' ); @@ -102,7 +101,6 @@ class WC_Admin_Addons { if ( ! is_wp_error( $raw_extensions ) ) { $addons = json_decode( wp_remote_retrieve_body( $raw_extensions ) )->products; } - return $addons; } @@ -124,14 +122,13 @@ class WC_Admin_Addons { } } } - return apply_filters( 'woocommerce_addons_sections', $addon_sections ); } /** * Get section for the addons screen. * - * @param string $section_id Required section ID. + * @param string $section_id Required section ID. * * @return object|bool */ @@ -140,14 +137,13 @@ class WC_Admin_Addons { if ( isset( $sections[ $section_id ] ) ) { return $sections[ $section_id ]; } - return false; } /** * Get section content for the addons screen. * - * @param string $section_id Required section ID. + * @param string $section_id Required section ID. * * @return array */ @@ -230,12 +226,12 @@ class WC_Admin_Addons {

title ); ?>

description ); ?>

href, - $item->button, - 'addons-button-solid', - $item->plugin - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-solid', + $item->plugin + ); ?> @@ -292,12 +288,12 @@ class WC_Admin_Addons {

title ); ?>

href, - $item->button, - 'addons-button-solid', - $item->plugin - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-solid', + $item->plugin + ); ?>

description ); ?>

@@ -324,11 +320,11 @@ class WC_Admin_Addons {
buttons as $button ) : ?> href, - $button->text, - 'addons-button-solid' - ); + self::output_button( + $button->href, + $button->text, + 'addons-button-solid' + ); ?>
@@ -356,11 +352,11 @@ class WC_Admin_Addons { href, - $item->button, - 'addons-button-outline-white' - ); + self::output_button( + $item->href, + $item->button, + 'addons-button-outline-white' + ); ?> @@ -465,11 +461,11 @@ class WC_Admin_Addons { @@ -527,17 +523,22 @@ class WC_Admin_Addons {

site_url(), 'wccom-back' => rawurlencode( $back_admin_path ), @@ -657,7 +657,7 @@ class WC_Admin_Addons { * Adds various url parameters to a url to support a streamlined * flow for obtaining and setting up WooCommerce extensons. * - * @param string $url Destination URL. + * @param string $url Destination URL. */ public static function add_in_app_purchase_url_params( $url ) { return add_query_arg( @@ -698,7 +698,6 @@ class WC_Admin_Addons { if ( isset( $_GET['section'] ) && 'helper' === $_GET['section'] ) { do_action( 'woocommerce_helper_output' ); - return; } @@ -785,7 +784,6 @@ class WC_Admin_Addons { * Should an extension be shown on the featured page. * * @param object $item Item data. - * * @return boolean */ public static function show_extension( $item ) { From 2b053d45860a1f6dba8fb3f51853c507dd5e1719 Mon Sep 17 00:00:00 2001 From: And Finally Date: Thu, 6 May 2021 15:22:53 +0100 Subject: [PATCH 318/368] Added docblock comment for `$section` param. --- includes/admin/class-wc-admin-addons.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index c9aa5a2cd71..a168498d4f9 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -537,7 +537,7 @@ class WC_Admin_Addons { /** * Handles the output of a full-width block. * - * @param $section + * array $section Section data for this block, which is a section itself. */ public static function output_ad_block( $section ) { if ( From 21b4801cc1b8186a2d92e424e1b7ed5959633cbc Mon Sep 17 00:00:00 2001 From: And Finally Date: Thu, 6 May 2021 15:40:02 +0100 Subject: [PATCH 319/368] Fixing doc comment for new method. --- includes/admin/class-wc-admin-addons.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index a168498d4f9..0cfb28c1c82 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -537,7 +537,7 @@ class WC_Admin_Addons { /** * Handles the output of a full-width block. * - * array $section Section data for this block, which is a section itself. + * @param array $section Section data. */ public static function output_ad_block( $section ) { if ( From 98af7209da49861ebb44073c180f4d5d07c2b072 Mon Sep 17 00:00:00 2001 From: TimBHowe Date: Wed, 28 Oct 2020 20:31:10 -0400 Subject: [PATCH 320/368] Added the 'after_gmt' and 'before_gm' parameters --- .../Version3/class-wc-rest-crud-controller.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php b/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php index 2767221e7ef..19c77773413 100644 --- a/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php +++ b/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php @@ -300,6 +300,18 @@ abstract class WC_REST_CRUD_Controller extends WC_REST_Posts_Controller { $args['date_query'][0]['after'] = $request['after']; } + // Set before_gmt into date query. Date query must be specified as an array of an array. + if ( isset( $request['before_gmt'] ) ) { + $args['date_query'][0]['before'] = $request['before_gmt']; + $args['date_query']['column'] = 'post_date_gmt'; + } + + // Set after_gmt into date query. Date query must be specified as an array of an array. + if ( isset( $request['after_gmt'] ) ) { + $args['date_query'][0]['after'] = $request['after_gmt']; + $args['date_query']['column'] = 'post_date_gmt'; + } + // Force the post_type argument, since it's not a user input variable. $args['post_type'] = $this->post_type; From f179ff67415dc571290c504ee671e9e775bba19b Mon Sep 17 00:00:00 2001 From: Tim Howe Date: Thu, 6 May 2021 17:06:06 -0400 Subject: [PATCH 321/368] Added dates_are_gmt parameter to allow the uses of post_date_gmt column with the before and after parameters for the order RESTAPI --- .../class-wc-rest-crud-controller.php | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php b/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php index 19c77773413..2ebf47a1eab 100644 --- a/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php +++ b/includes/rest-api/Controllers/Version3/class-wc-rest-crud-controller.php @@ -300,16 +300,11 @@ abstract class WC_REST_CRUD_Controller extends WC_REST_Posts_Controller { $args['date_query'][0]['after'] = $request['after']; } - // Set before_gmt into date query. Date query must be specified as an array of an array. - if ( isset( $request['before_gmt'] ) ) { - $args['date_query'][0]['before'] = $request['before_gmt']; - $args['date_query']['column'] = 'post_date_gmt'; - } - - // Set after_gmt into date query. Date query must be specified as an array of an array. - if ( isset( $request['after_gmt'] ) ) { - $args['date_query'][0]['after'] = $request['after_gmt']; - $args['date_query']['column'] = 'post_date_gmt'; + // Check flag to use post_date vs post_date_gmt. + if ( true === $request['dates_are_gmt'] ) { + if ( isset( $request['before'] ) || isset( $request['after'] ) ) { + $args['date_query']['column'] = 'post_date_gmt'; + } } // Force the post_type argument, since it's not a user input variable. @@ -574,6 +569,12 @@ abstract class WC_REST_CRUD_Controller extends WC_REST_Posts_Controller { 'format' => 'date-time', 'validate_callback' => 'rest_validate_request_arg', ); + $params['dates_are_gmt'] = array( + 'description' => __( 'Whether to use GMT post dates.', 'woocommerce' ), + 'type' => 'boolean', + 'default' => false, + 'validate_callback' => 'rest_validate_request_arg', + ); $params['exclude'] = array( 'description' => __( 'Ensure result set excludes specific IDs.', 'woocommerce' ), 'type' => 'array', From e4d3b157ffa443213be66e82e110e9a27e3bc6c2 Mon Sep 17 00:00:00 2001 From: And Finally Date: Thu, 6 May 2021 22:12:07 +0100 Subject: [PATCH 322/368] Changed block name and CSS classnames to the more generic "promotion block". --- assets/css/admin.scss | 16 ++++++++-------- includes/admin/class-wc-admin-addons.php | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/assets/css/admin.scss b/assets/css/admin.scss index cc06dd14e7e..35bc0dc12e3 100644 --- a/assets/css/admin.scss +++ b/assets/css/admin.scss @@ -161,7 +161,7 @@ } } - .addons-ad-block { + .addons-promotion-block { display: flex; padding: 20px; @@ -171,22 +171,22 @@ } } - .addons-ad-block-content { + .addons-promotion-block-content { display: flex; flex-direction: column; margin-left: 24px; } - .addons-ad-block-description { + .addons-promotion-block-description { margin-bottom: 20px; } - .addons-ad-block-title { + .addons-promotion-block-title { margin: 0 0 16px; padding: 0; } - .addons-ad-block-buttons { + .addons-promotion-block-buttons { margin-top: auto; .addons-button { @@ -2688,7 +2688,7 @@ ul.wc_coupon_list_block { .wc_addons_wrap { - .addons-ad-block { + .addons-promotion-block { flex-direction: column; padding: 24px; @@ -2700,12 +2700,12 @@ ul.wc_coupon_list_block { } } - .addons-ad-block-content { + .addons-promotion-block-content { display: block; margin-left: 0; } - .addons-ad-block-title { + .addons-promotion-block-title { margin-top: 4px; } } diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index 0cfb28c1c82..e90ac2ad9a8 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -539,7 +539,7 @@ class WC_Admin_Addons { * * @param array $section Section data. */ - public static function output_ad_block( $section ) { + public static function output_promotion_block( $section ) { if ( ! current_user_can( 'install_plugins' ) || ! current_user_can( 'activate_plugins' ) @@ -558,18 +558,18 @@ class WC_Admin_Addons { } ?> -
+
<?php echo esc_attr( $section['image_alt'] ); ?> -
-

-
+
+

+
-
+
Date: Fri, 7 May 2021 09:16:45 +0200 Subject: [PATCH 323/368] Fix typos in comments --- src/Internal/DependencyManagement/ExtendedContainer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Internal/DependencyManagement/ExtendedContainer.php b/src/Internal/DependencyManagement/ExtendedContainer.php index 5058a43c0c6..0615ec51713 100644 --- a/src/Internal/DependencyManagement/ExtendedContainer.php +++ b/src/Internal/DependencyManagement/ExtendedContainer.php @@ -151,10 +151,10 @@ class ExtendedContainer extends BaseContainer { } /** - * Check if a class name corresponds to an anonoymous class. + * Check if a class name corresponds to an anonymous class. * * @param string $class_name The class name to check. - * @return bool True if the name correspondos to an anynymous class. + * @return bool True if the name corresponds to an anonymous class. */ protected function is_anonymous_class( string $class_name ): bool { return StringUtil::starts_with( $class_name, 'class@anonymous' ); From 43822b7401917cffafa10b3dbc377043c3e55801 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Mon, 22 Feb 2021 15:18:05 +0530 Subject: [PATCH 324/368] Remove rounding from individual item discount taxes. Rounding here conflicts with round at subtotal settings becase we would round at line item level irrespective of settings. --- includes/class-wc-cart-totals.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-cart-totals.php b/includes/class-wc-cart-totals.php index facee43a729..90efd4246f4 100644 --- a/includes/class-wc-cart-totals.php +++ b/includes/class-wc-cart-totals.php @@ -788,7 +788,7 @@ final class WC_Cart_Totals { if ( $item->product->is_taxable() ) { // Item subtotals were sent, so set 3rd param. - $item_tax = wc_round_tax_total( array_sum( WC_Tax::calc_tax( $coupon_discount, $item->tax_rates, $item->price_includes_tax ) ), 0 ); + $item_tax = array_sum( WC_Tax::calc_tax( $coupon_discount, $item->tax_rates, $item->price_includes_tax ) ); // Sum total tax. $coupon_discount_tax_amounts[ $coupon_code ] += $item_tax; From 973bba347ff264a0aecbe53738f676f2c45302ce Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Mon, 22 Feb 2021 15:21:29 +0530 Subject: [PATCH 325/368] Remove rounding from subtotals as they would already be rounded depending upon settings. --- includes/class-wc-cart-totals.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/class-wc-cart-totals.php b/includes/class-wc-cart-totals.php index 90efd4246f4..2e22789b646 100644 --- a/includes/class-wc-cart-totals.php +++ b/includes/class-wc-cart-totals.php @@ -750,8 +750,8 @@ final class WC_Cart_Totals { $items_subtotal = $this->get_rounded_items_total( $this->get_values_for_total( 'subtotal' ) ); - $this->set_total( 'items_subtotal', NumberUtil::round( $items_subtotal ) ); - $this->set_total( 'items_subtotal_tax', wc_round_tax_total( array_sum( $merged_subtotal_taxes ), 0 ) ); + $this->set_total( 'items_subtotal', $items_subtotal ); + $this->set_total( 'items_subtotal_tax', array_sum( $merged_subtotal_taxes ), 0 ); $this->cart->set_subtotal( $this->get_total( 'items_subtotal' ) ); $this->cart->set_subtotal_tax( $this->get_total( 'items_subtotal_tax' ) ); From b156e329f89f104c505e2899e4fcc4d4e9535e7d Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Mon, 22 Feb 2021 15:22:12 +0530 Subject: [PATCH 326/368] Remove rounding from lines which are not final totals. --- includes/class-wc-cart.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/includes/class-wc-cart.php b/includes/class-wc-cart.php index 594bb904670..cac7a44c107 100644 --- a/includes/class-wc-cart.php +++ b/includes/class-wc-cart.php @@ -430,7 +430,7 @@ class WC_Cart extends WC_Legacy_Cart { * @param string $value Value to set. */ public function set_subtotal( $value ) { - $this->totals['subtotal'] = wc_format_decimal( $value, wc_get_price_decimals() ); + $this->totals['subtotal'] = $value; } /** @@ -470,7 +470,7 @@ class WC_Cart extends WC_Legacy_Cart { * @param string $value Value to set. */ public function set_shipping_total( $value ) { - $this->totals['shipping_total'] = wc_format_decimal( $value, wc_get_price_decimals() ); + $this->totals['shipping_total'] = $value; } /** @@ -490,7 +490,7 @@ class WC_Cart extends WC_Legacy_Cart { * @param string $value Value to set. */ public function set_cart_contents_total( $value ) { - $this->totals['cart_contents_total'] = wc_format_decimal( $value, wc_get_price_decimals() ); + $this->totals['cart_contents_total'] = $value; } /** @@ -531,7 +531,7 @@ class WC_Cart extends WC_Legacy_Cart { * @param string $value Value to set. */ public function set_fee_total( $value ) { - $this->totals['fee_total'] = wc_format_decimal( $value, wc_get_price_decimals() ); + $this->totals['fee_total'] = $value; } /** From a0fbff38793343e07c40a28d3e3e9681f8c50358 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Tue, 23 Feb 2021 14:22:55 +0530 Subject: [PATCH 327/368] Modify unit test to accomodate pre-rounding total. --- tests/legacy/unit-tests/cart/cart.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/legacy/unit-tests/cart/cart.php b/tests/legacy/unit-tests/cart/cart.php index 6895ba49e74..3c8473e76f2 100644 --- a/tests/legacy/unit-tests/cart/cart.php +++ b/tests/legacy/unit-tests/cart/cart.php @@ -73,9 +73,8 @@ class WC_Tests_Cart extends WC_Unit_Test_Case { $this->assertEquals( '13.58', WC()->cart->get_total( 'edit' ) ); $this->assertEquals( 0.66, WC()->cart->get_total_tax() ); - $this->assertEquals( 4.17, WC()->cart->get_discount_total() ); - $this->assertEquals( 0.83, WC()->cart->get_discount_tax() ); - + $this->assertEquals( 0.83, wc_round_tax_total( WC()->cart->get_discount_tax() ) ); + $this->assertEquals( 4.17, \Automattic\WooCommerce\Utilities\NumberUtil::round( WC()->cart->get_discount_total(), 2 ) ); } /** From 2930057847e2a568442ee8a9cb29b6e2d72b2f6a Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Tue, 23 Feb 2021 16:07:12 +0530 Subject: [PATCH 328/368] Add tests to make sure discounts are rounded properly in cart. --- .../includes/class-wc-cart-totals-test.php | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 tests/php/includes/class-wc-cart-totals-test.php diff --git a/tests/php/includes/class-wc-cart-totals-test.php b/tests/php/includes/class-wc-cart-totals-test.php new file mode 100644 index 00000000000..13c7d091e87 --- /dev/null +++ b/tests/php/includes/class-wc-cart-totals-test.php @@ -0,0 +1,80 @@ +cart->empty_cart(); + + $tax_rate = array( + 'tax_rate_country' => '', + 'tax_rate_state' => '', + 'tax_rate' => '27.0000', + 'tax_rate_name' => 'TAX27', + 'tax_rate_priority' => '1', + 'tax_rate_compound' => '0', + 'tax_rate_shipping' => '0', + 'tax_rate_order' => '1', + ); + + WC_Tax::_insert_tax_rate( $tax_rate ); + $product_240 = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 240 ) ); + $product_1250 = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 1250 ) ); + $product_1990 = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 1990 ) ); + $product_3390 = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 3390 ) ); + $product_6200 = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 6200 ) ); + $coupon = WC_Helper_Coupon::create_coupon( 'flat2000', array( 'coupon_amount' => 2000 ) ); + + WC()->cart->add_to_cart( $product_240->get_id(), 1 ); + WC()->cart->add_to_cart( $product_1250->get_id(), 1 ); + WC()->cart->add_to_cart( $product_1990->get_id(), 1 ); + WC()->cart->add_to_cart( $product_3390->get_id(), 1 ); + WC()->cart->add_to_cart( $product_6200->get_id(), 1 ); + WC()->cart->apply_coupon( $coupon->get_code() ); + + $this->assert_discount_tax_rounding_when_rounding_at_subtotal(); + $this->assert_discount_tax_rounding_when_rounding_at_line(); + } + + /** + * Helper method for assertions when prices are rounded at line. + */ + private function assert_discount_tax_rounding_when_rounding_at_line() { + update_option( 'woocommerce_tax_round_at_subtotal', 'no' ); + $decimal_precision = wc_get_price_decimals(); + update_option( 'woocommerce_price_num_decimals', 0 ); + + WC()->cart->calculate_totals(); + update_option( 'woocommerce_price_num_decimals', $decimal_precision ); + + $this->assertEquals( '1575', wc_format_decimal( WC()->cart->get_discount_total(), 0 ) ); + $this->assertEquals( '425', wc_format_decimal( WC()->cart->get_discount_tax(), 0 ) ); + $this->assertEquals( '11070', wc_format_decimal( WC()->cart->get_total(), 0 ) ); + } + + /** + * Helper method for assertions when prices are rounded at line. + */ + private function assert_discount_tax_rounding_when_rounding_at_subtotal() { + update_option( 'woocommerce_tax_round_at_subtotal', 'yes' ); + $decimal_precision = wc_get_price_decimals(); + update_option( 'woocommerce_price_num_decimals', 0 ); + + WC()->cart->calculate_totals(); + + $this->assertEquals( '1575', wc_format_decimal( WC()->cart->get_discount_total(), 0 ) ); + $this->assertEquals( '425', wc_format_decimal( WC()->cart->get_discount_tax(), 0 ) ); + $this->assertEquals( '11070', wc_format_decimal( WC()->cart->get_total(), 0 ) ); + } + +} From c834dfb98bbe0f280ff9de79f69041c671b37537 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Tue, 23 Feb 2021 16:53:16 +0530 Subject: [PATCH 329/368] Add test for when entered price has more precision than displayed price. --- .../includes/class-wc-cart-totals-test.php | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/tests/php/includes/class-wc-cart-totals-test.php b/tests/php/includes/class-wc-cart-totals-test.php index 13c7d091e87..2b8e2e816da 100644 --- a/tests/php/includes/class-wc-cart-totals-test.php +++ b/tests/php/includes/class-wc-cart-totals-test.php @@ -71,10 +71,49 @@ class WC_Cart_Totals_Tests extends WC_Unit_Test_Case { update_option( 'woocommerce_price_num_decimals', 0 ); WC()->cart->calculate_totals(); + update_option( 'woocommerce_price_num_decimals', $decimal_precision ); $this->assertEquals( '1575', wc_format_decimal( WC()->cart->get_discount_total(), 0 ) ); $this->assertEquals( '425', wc_format_decimal( WC()->cart->get_discount_tax(), 0 ) ); $this->assertEquals( '11070', wc_format_decimal( WC()->cart->get_total(), 0 ) ); } + /** + * Tests whether subtotal is properly rounded, when prices entered have higher precision than displayed. + * + * @link https://github.com/woocommerce/woocommerce/issues/28292. + */ + public function test_subtotal_rounding_with_changing_precision() { + update_option( 'woocommerce_prices_include_tax', 'yes' ); + update_option( 'woocommerce_calc_taxes', 'yes' ); + update_option( 'woocommerce_tax_round_at_subtotal', 'yes' ); + $decimal_precision = wc_get_price_decimals(); + update_option( 'woocommerce_price_num_decimals', 0 ); + + WC()->cart->empty_cart(); + + $tax_rate = array( + 'tax_rate_country' => '', + 'tax_rate_state' => '', + 'tax_rate' => '23.0000', + 'tax_rate_name' => 'TAX23', + 'tax_rate_priority' => '1', + 'tax_rate_compound' => '0', + 'tax_rate_shipping' => '0', + 'tax_rate_order' => '1', + ); + + WC_Tax::_insert_tax_rate( $tax_rate ); + $product_301_90909 = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 301.90909 ) ); + + WC()->cart->add_to_cart( $product_301_90909->get_id() ); + WC()->cart->calculate_totals(); + update_option( 'woocommerce_price_num_decimals', $decimal_precision ); + + // Notice how subtotal + tax does not equate to total here. + // This is feature of round at subtotal property, where since we are not rounding, displayed components of price may not add up to displayed total price. + $this->assertEquals( '245', wc_format_decimal( WC()->cart->get_subtotal(), 0 ) ); + $this->assertEquals( '302', wc_format_decimal( WC()->cart->get_total(), 0 ) ); + $this->assertEquals( '56', wc_format_decimal( WC()->cart->get_total_tax(), 0 ) ); + } } From 162588c42dd6d7bae2e4d40a7bcde9a1262bd466 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Mon, 1 Mar 2021 14:18:58 +0530 Subject: [PATCH 330/368] Add test for when product prices has more precision than is displayed. --- .../includes/class-wc-cart-totals-test.php | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/php/includes/class-wc-cart-totals-test.php b/tests/php/includes/class-wc-cart-totals-test.php index 2b8e2e816da..f209505c629 100644 --- a/tests/php/includes/class-wc-cart-totals-test.php +++ b/tests/php/includes/class-wc-cart-totals-test.php @@ -116,4 +116,38 @@ class WC_Cart_Totals_Tests extends WC_Unit_Test_Case { $this->assertEquals( '302', wc_format_decimal( WC()->cart->get_total(), 0 ) ); $this->assertEquals( '56', wc_format_decimal( WC()->cart->get_total_tax(), 0 ) ); } + + /** + * Test subtotal and total are rounded correctly when values are entered with more precision. + * + * @link https://github.com/woocommerce/woocommerce/issues/24184#issue-469311323. + */ + public function test_total_rounding_with_price_entered_has_high_precision() { + update_option( 'woocommerce_prices_include_tax', 'no' ); + update_option( 'woocommerce_calc_taxes', 'yes' ); + update_option( 'woocommerce_tax_round_at_subtotal', 'yes' ); + + WC()->cart->empty_cart(); + + $tax_rate = array( + 'tax_rate_country' => '', + 'tax_rate_state' => '', + 'tax_rate' => '20.0000', + 'tax_rate_name' => 'TAX20', + 'tax_rate_priority' => '1', + 'tax_rate_compound' => '0', + 'tax_rate_shipping' => '0', + 'tax_rate_order' => '1', + ); + WC_Tax::_insert_tax_rate( $tax_rate ); + $product_30_82500 = WC_Helper_Product::create_simple_product( true, array( 'regular_price' => 30.82500 ) ); + + WC()->cart->add_to_cart( $product_30_82500->get_id() ); + + WC()->cart->calculate_totals(); + // Since prices entered have higher precision, subtotal + tax will not equal to total. + $this->assertEquals( '30.83', wc_format_decimal( WC()->cart->get_subtotal(), 2 ) ); + $this->assertEquals( '36.99', WC()->cart->get_total( 'edit' ) ); + $this->assertEquals( '6.17', WC()->cart->get_total_tax() ); + } } From f5056d37e46d9735833240bda3fdc401c03e5e52 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Tue, 9 Mar 2021 18:20:24 +0530 Subject: [PATCH 331/368] Add expected deprecated call so that we can call setUp for this testcase. --- .../unit-tests/util/deprecated-hooks.php | 51 ++++++++++++------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/tests/legacy/unit-tests/util/deprecated-hooks.php b/tests/legacy/unit-tests/util/deprecated-hooks.php index 8867fe90bb3..50530a5080d 100644 --- a/tests/legacy/unit-tests/util/deprecated-hooks.php +++ b/tests/legacy/unit-tests/util/deprecated-hooks.php @@ -1,44 +1,58 @@ handlers = WC()->deprecated_hook_handlers; @@ -49,7 +63,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { * * @since 3.0 */ - function test_deprecated_hook_handlers_exist() { + public function test_deprecated_hook_handlers_exist() { $this->assertArrayHasKey( 'filters', $this->handlers ); $this->assertInstanceOf( 'WC_Deprecated_Filter_Hooks', $this->handlers['filters'] ); @@ -62,7 +76,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { * * @since 3.0 */ - function test_get_old_hooks() { + public function test_get_old_hooks() { $old_filters = $this->handlers['filters']->get_old_hooks( 'woocommerce_structured_data_order' ); $old_actions = $this->handlers['actions']->get_old_hooks( 'woocommerce_new_order_item' ); @@ -75,7 +89,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { * * @since 3.0 */ - function test_hook_in() { + public function test_hook_in() { $this->assertTrue( (bool) has_filter( 'woocommerce_structured_data_order', array( $this->handlers['filters'], 'maybe_handle_deprecated_hook' ) ) ); $this->assertTrue( (bool) has_action( 'woocommerce_new_order_item', array( $this->handlers['actions'], 'maybe_handle_deprecated_hook' ) ) ); } @@ -85,7 +99,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { * * @since 3.0 */ - function test_handle_deprecated_hook_filter() { + public function test_handle_deprecated_hook_filter() { $new_hook = 'wc_new_hook'; $old_hook = 'wc_old_hook'; $args = array( false ); @@ -102,7 +116,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { * * @since 3.0 */ - function test_handle_deprecated_hook_action() { + public function test_handle_deprecated_hook_action() { $new_hook = 'wc_new_hook'; $old_hook = 'wc_old_hook'; $test_value = false; @@ -120,7 +134,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { * * @since 3.0 */ - function test_filter_handler() { + public function test_filter_handler() { $test_width = 1; add_filter( 'woocommerce_product_width', array( $this, 'toggle_value' ) ); @@ -134,7 +148,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { * * @since 3.0 */ - function test_action_handler() { + public function test_action_handler() { $test_product = WC_Helper_Product::create_simple_product(); $test_order = WC_Helper_Order::create_order( 1, $test_product ); $test_order_id = $test_order->get_id(); @@ -142,6 +156,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { $test_item = reset( $test_items ); $test_item_id = $test_item->get_id(); + $this->setExpectedDeprecated( 'woocommerce_order_edit_product' ); add_action( 'woocommerce_order_edit_product', array( $this, 'set_meta' ), 10, 2 ); do_action( 'woocommerce_update_order_item', $test_item_id, $test_item, $test_order_id ); @@ -157,7 +172,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { * * @since 3.0 */ - function test_created_actions_deprecation() { + public function test_created_actions_deprecation() { add_filter( 'woocommerce_payment_token_created', '__return_true' ); add_filter( 'woocommerce_create_product_variation', '__return_true' ); From 30cbf4638d533913e1394f7597721d003572f084 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Tue, 9 Mar 2021 18:22:15 +0530 Subject: [PATCH 332/368] Use constant instead of magic numbers. --- includes/wc-core-functions.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/wc-core-functions.php b/includes/wc-core-functions.php index 63ff71103cc..3ffb94d5d6e 100644 --- a/includes/wc-core-functions.php +++ b/includes/wc-core-functions.php @@ -1821,7 +1821,7 @@ function wc_get_tax_rounding_mode() { $constant = WC_TAX_ROUNDING_MODE; if ( 'auto' === $constant ) { - return 'yes' === get_option( 'woocommerce_prices_include_tax', 'no' ) ? 2 : 1; + return 'yes' === get_option( 'woocommerce_prices_include_tax', 'no' ) ? PHP_ROUND_HALF_DOWN : PHP_ROUND_HALF_UP; } return intval( $constant ); @@ -2413,7 +2413,7 @@ function wc_round_discount( $value, $precision ) { return NumberUtil::round( $value, $precision, WC_DISCOUNT_ROUNDING_MODE ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctionParameters.round_modeFound } - if ( 2 === WC_DISCOUNT_ROUNDING_MODE ) { + if ( PHP_ROUND_HALF_DOWN === WC_DISCOUNT_ROUNDING_MODE ) { return wc_legacy_round_half_down( $value, $precision ); } From 49ed94a1d0ff1ae15a1c820f360723840705a4ca Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Tue, 9 Mar 2021 18:26:15 +0530 Subject: [PATCH 333/368] Add expected deprecate calls to make tests work with parent::setUp. --- tests/legacy/unit-tests/util/deprecated-hooks.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/legacy/unit-tests/util/deprecated-hooks.php b/tests/legacy/unit-tests/util/deprecated-hooks.php index 50530a5080d..6d93a50942d 100644 --- a/tests/legacy/unit-tests/util/deprecated-hooks.php +++ b/tests/legacy/unit-tests/util/deprecated-hooks.php @@ -105,6 +105,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { $args = array( false ); $return = -1; + $this->setExpectedDeprecated( 'wc_old_hook' ); add_filter( $old_hook, array( $this, 'toggle_value' ) ); $result = $this->handlers['filters']->handle_deprecated_hook( $new_hook, $old_hook, $args, $return ); @@ -123,6 +124,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { $args = array( &$test_value ); $return = -1; + $this->setExpectedDeprecated( 'wc_old_hook' ); add_filter( $old_hook, array( $this, 'toggle_value_by_ref' ) ); $this->handlers['actions']->handle_deprecated_hook( $new_hook, $old_hook, $args, $return ); @@ -137,6 +139,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { public function test_filter_handler() { $test_width = 1; + $this->setExpectedDeprecated( 'woocommerce_product_width' ); add_filter( 'woocommerce_product_width', array( $this, 'toggle_value' ) ); $new_width = apply_filters( 'woocommerce_product_get_width', $test_width ); @@ -176,6 +179,9 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { add_filter( 'woocommerce_payment_token_created', '__return_true' ); add_filter( 'woocommerce_create_product_variation', '__return_true' ); + $this->setExpectedDeprecated( 'woocommerce_payment_token_created' ); + $this->setExpectedDeprecated( 'woocommerce_create_product_variation' ); + $token = WC_Helper_Payment_Token::create_stub_token( __FUNCTION__ ); $token->save(); From a0d6cea1393062a305da0e5c27916d8275c162f3 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Tue, 9 Mar 2021 18:29:19 +0530 Subject: [PATCH 334/368] Round shipping and fees tax seperately since they are entered excl taxes. We round up or round down depending upon if prices are entered inclusive or exclusive taxes, however since shipping and fees are always entered exclusive of taxes, they should always be rounded down. --- includes/class-wc-cart-totals.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/includes/class-wc-cart-totals.php b/includes/class-wc-cart-totals.php index 2e22789b646..24bf97d5c5a 100644 --- a/includes/class-wc-cart-totals.php +++ b/includes/class-wc-cart-totals.php @@ -862,7 +862,10 @@ final class WC_Cart_Totals { */ protected function calculate_totals() { $this->set_total( 'total', NumberUtil::round( $this->get_total( 'items_total', true ) + $this->get_total( 'fees_total', true ) + $this->get_total( 'shipping_total', true ) + array_sum( $this->get_merged_taxes( true ) ), 0 ) ); - $this->cart->set_total_tax( array_sum( $this->get_merged_taxes( false ) ) ); + $items_tax = array_sum( $this->get_merged_taxes( false, array( 'items' ) ) ); + // Shipping and fee taxes are rounded because they were entered excluding taxes. + $shipping_and_fee_taxes = NumberUtil::round( array_sum( $this->get_merged_taxes( false, array( 'fees', 'shipping' ) ) ), wc_get_price_decimals() ); + $this->cart->set_total_tax( $items_tax + $shipping_and_fee_taxes ); // Allow plugins to hook and alter totals before final total is calculated. if ( has_action( 'woocommerce_calculate_totals' ) ) { From 833193b7f7e661e4d257054aa09d3724d3301547 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Tue, 9 Mar 2021 18:39:51 +0530 Subject: [PATCH 335/368] Round tax amount appropriately before displaying. We have special method to round taxes which may round up or round down depending upon settings. This method should be used instead of default rounding in formatting funtions. --- includes/admin/meta-boxes/views/html-order-items.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/meta-boxes/views/html-order-items.php b/includes/admin/meta-boxes/views/html-order-items.php index 6a2ff5073ac..386d4f446d0 100644 --- a/includes/admin/meta-boxes/views/html-order-items.php +++ b/includes/admin/meta-boxes/views/html-order-items.php @@ -189,7 +189,7 @@ if ( wc_tax_enabled() ) { label ); ?>: - amount, array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> + amount ), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> From 6c2f30132d84e1015cbe41b5ea41f00a0505bca7 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Wed, 10 Mar 2021 12:48:08 +0530 Subject: [PATCH 336/368] Add clear cart call to prevent side effects from tests. --- tests/php/includes/class-wc-checkout-test.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/php/includes/class-wc-checkout-test.php b/tests/php/includes/class-wc-checkout-test.php index 0a9b87a645f..5b50a877d83 100644 --- a/tests/php/includes/class-wc-checkout-test.php +++ b/tests/php/includes/class-wc-checkout-test.php @@ -32,6 +32,8 @@ class WC_Checkout_Test extends \WC_Unit_Test_Case { } }; // phpcs:enable Generic.CodeAnalysis, Squiz.Commenting + + WC()->cart->empty_cart(); } /** From 18411d2b3bf396e1410290934ecb68900d91be5b Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Wed, 10 Mar 2021 20:44:47 +0530 Subject: [PATCH 337/368] Add code comments for confusing changes. --- includes/admin/meta-boxes/views/html-order-items.php | 5 ++++- includes/class-wc-cart-totals.php | 3 ++- tests/legacy/unit-tests/cart/cart.php | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/includes/admin/meta-boxes/views/html-order-items.php b/includes/admin/meta-boxes/views/html-order-items.php index 386d4f446d0..55d11d01ed0 100644 --- a/includes/admin/meta-boxes/views/html-order-items.php +++ b/includes/admin/meta-boxes/views/html-order-items.php @@ -189,7 +189,10 @@ if ( wc_tax_enabled() ) { label ); ?>: - amount ), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> + amount ), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + ?> diff --git a/includes/class-wc-cart-totals.php b/includes/class-wc-cart-totals.php index 24bf97d5c5a..54afe9827ca 100644 --- a/includes/class-wc-cart-totals.php +++ b/includes/class-wc-cart-totals.php @@ -750,6 +750,7 @@ final class WC_Cart_Totals { $items_subtotal = $this->get_rounded_items_total( $this->get_values_for_total( 'subtotal' ) ); + // Prices are not rounded here because they should already be rounded based on settings in `get_rounded_items_total` and in `round_line_tax` method calls. $this->set_total( 'items_subtotal', $items_subtotal ); $this->set_total( 'items_subtotal_tax', array_sum( $merged_subtotal_taxes ), 0 ); @@ -863,7 +864,7 @@ final class WC_Cart_Totals { protected function calculate_totals() { $this->set_total( 'total', NumberUtil::round( $this->get_total( 'items_total', true ) + $this->get_total( 'fees_total', true ) + $this->get_total( 'shipping_total', true ) + array_sum( $this->get_merged_taxes( true ) ), 0 ) ); $items_tax = array_sum( $this->get_merged_taxes( false, array( 'items' ) ) ); - // Shipping and fee taxes are rounded because they were entered excluding taxes. + // Shipping and fee taxes are rounded seperately because they were entered excluding taxes (as opposed to item prices, which may or may not be including taxes depending upon settings). $shipping_and_fee_taxes = NumberUtil::round( array_sum( $this->get_merged_taxes( false, array( 'fees', 'shipping' ) ) ), wc_get_price_decimals() ); $this->cart->set_total_tax( $items_tax + $shipping_and_fee_taxes ); diff --git a/tests/legacy/unit-tests/cart/cart.php b/tests/legacy/unit-tests/cart/cart.php index 3c8473e76f2..e94d8fd0347 100644 --- a/tests/legacy/unit-tests/cart/cart.php +++ b/tests/legacy/unit-tests/cart/cart.php @@ -73,8 +73,8 @@ class WC_Tests_Cart extends WC_Unit_Test_Case { $this->assertEquals( '13.58', WC()->cart->get_total( 'edit' ) ); $this->assertEquals( 0.66, WC()->cart->get_total_tax() ); - $this->assertEquals( 0.83, wc_round_tax_total( WC()->cart->get_discount_tax() ) ); - $this->assertEquals( 4.17, \Automattic\WooCommerce\Utilities\NumberUtil::round( WC()->cart->get_discount_total(), 2 ) ); + $this->assertEquals( 0.83, wc_format_decimal( WC()->cart->get_discount_tax(), 2 ) ); + $this->assertEquals( 4.17, wc_format_decimal( WC()->cart->get_discount_total(), 2 ) ); } /** From b487e363ce6b2cfc893f3f6b3f9c959635a74067 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Fri, 7 May 2021 14:58:52 +0530 Subject: [PATCH 338/368] Restore formatting but without rounding for backward compat. --- includes/class-wc-cart.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/includes/class-wc-cart.php b/includes/class-wc-cart.php index cac7a44c107..e5cca710813 100644 --- a/includes/class-wc-cart.php +++ b/includes/class-wc-cart.php @@ -430,7 +430,7 @@ class WC_Cart extends WC_Legacy_Cart { * @param string $value Value to set. */ public function set_subtotal( $value ) { - $this->totals['subtotal'] = $value; + $this->totals['subtotal'] = wc_format_decimal( $value ); } /** @@ -470,7 +470,7 @@ class WC_Cart extends WC_Legacy_Cart { * @param string $value Value to set. */ public function set_shipping_total( $value ) { - $this->totals['shipping_total'] = $value; + $this->totals['shipping_total'] = wc_format_decimal( $value ); } /** @@ -490,7 +490,7 @@ class WC_Cart extends WC_Legacy_Cart { * @param string $value Value to set. */ public function set_cart_contents_total( $value ) { - $this->totals['cart_contents_total'] = $value; + $this->totals['cart_contents_total'] = wc_format_decimal( $value ); } /** @@ -531,7 +531,7 @@ class WC_Cart extends WC_Legacy_Cart { * @param string $value Value to set. */ public function set_fee_total( $value ) { - $this->totals['fee_total'] = $value; + $this->totals['fee_total'] = wc_format_decimal( $value ); } /** From f53e9dde44b4a0a4952a0b32799b43223be2b600 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Fri, 7 May 2021 14:59:14 +0530 Subject: [PATCH 339/368] Use edit context to get unformatted price. --- tests/php/includes/class-wc-cart-totals-test.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/php/includes/class-wc-cart-totals-test.php b/tests/php/includes/class-wc-cart-totals-test.php index f209505c629..bb292273ac5 100644 --- a/tests/php/includes/class-wc-cart-totals-test.php +++ b/tests/php/includes/class-wc-cart-totals-test.php @@ -59,7 +59,7 @@ class WC_Cart_Totals_Tests extends WC_Unit_Test_Case { $this->assertEquals( '1575', wc_format_decimal( WC()->cart->get_discount_total(), 0 ) ); $this->assertEquals( '425', wc_format_decimal( WC()->cart->get_discount_tax(), 0 ) ); - $this->assertEquals( '11070', wc_format_decimal( WC()->cart->get_total(), 0 ) ); + $this->assertEquals( '11070', wc_format_decimal( WC()->cart->get_total( 'edit' ), 0 ) ); } /** @@ -75,7 +75,7 @@ class WC_Cart_Totals_Tests extends WC_Unit_Test_Case { $this->assertEquals( '1575', wc_format_decimal( WC()->cart->get_discount_total(), 0 ) ); $this->assertEquals( '425', wc_format_decimal( WC()->cart->get_discount_tax(), 0 ) ); - $this->assertEquals( '11070', wc_format_decimal( WC()->cart->get_total(), 0 ) ); + $this->assertEquals( '11070', wc_format_decimal( WC()->cart->get_total( 'edit' ), 0 ) ); } /** @@ -113,7 +113,7 @@ class WC_Cart_Totals_Tests extends WC_Unit_Test_Case { // Notice how subtotal + tax does not equate to total here. // This is feature of round at subtotal property, where since we are not rounding, displayed components of price may not add up to displayed total price. $this->assertEquals( '245', wc_format_decimal( WC()->cart->get_subtotal(), 0 ) ); - $this->assertEquals( '302', wc_format_decimal( WC()->cart->get_total(), 0 ) ); + $this->assertEquals( '302', wc_format_decimal( WC()->cart->get_total( 'edit' ), 0 ) ); $this->assertEquals( '56', wc_format_decimal( WC()->cart->get_total_tax(), 0 ) ); } From ed7c81127c00ec758197fec5a7e7262459a4cf47 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Fri, 7 May 2021 15:53:52 +0530 Subject: [PATCH 340/368] Add rounding it test since we changed it in code. --- tests/legacy/unit-tests/cart/cart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/legacy/unit-tests/cart/cart.php b/tests/legacy/unit-tests/cart/cart.php index e94d8fd0347..f59fbbb7a05 100644 --- a/tests/legacy/unit-tests/cart/cart.php +++ b/tests/legacy/unit-tests/cart/cart.php @@ -301,7 +301,7 @@ class WC_Tests_Cart extends WC_Unit_Test_Case { WC()->cart->add_to_cart( $product->get_id(), 1 ); WC()->cart->calculate_totals(); - $this->assertEquals( 599, WC()->cart->subtotal ); + $this->assertEquals( 599, wc_format_decimal( WC()->cart->subtotal, wc_get_price_decimals() ) ); $this->assertEquals( 599, WC()->cart->total ); } From 6a6ea2e2921869da7a7c433feb1f6dc0a2aff2e0 Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Fri, 7 May 2021 17:13:30 -0500 Subject: [PATCH 341/368] Update woocommerce-admin to latest version 2.2.6 --- composer.json | 2 +- composer.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 4daa8132829..462458e7920 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "pelago/emogrifier": "3.1.0", "psr/container": "1.0.0", "woocommerce/action-scheduler": "3.1.6", - "woocommerce/woocommerce-admin": "2.2.2", + "woocommerce/woocommerce-admin": "2.2.6", "woocommerce/woocommerce-blocks": "4.9.1" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 57039bbbbce..3f506ced4f6 100644 --- a/composer.lock +++ b/composer.lock @@ -503,7 +503,7 @@ }, { "name": "woocommerce/woocommerce-admin", - "version": "2.2.2", + "version": "2.2.6", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-admin.git", @@ -511,8 +511,8 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/161e6afa01a3fb69533cfa2b245a71df7512ec3f", - "reference": "161e6afa01a3fb69533cfa2b245a71df7512ec3f", + "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/65c5a4d0b0c3a7c7457e250c9ba1f7c15cac6cb8", + "reference": "65c5a4d0b0c3a7c7457e250c9ba1f7c15cac6cb8", "shasum": "" }, "require": { From e25581c29b6442b69bba85ddb8236903bb0f790d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 May 2021 22:44:23 +0000 Subject: [PATCH 342/368] Bump lodash from 4.17.20 to 4.17.21 in /tests/e2e/api Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21) Signed-off-by: dependabot[bot] --- tests/e2e/api/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/api/package-lock.json b/tests/e2e/api/package-lock.json index b33e892c704..0bad8bef45a 100644 --- a/tests/e2e/api/package-lock.json +++ b/tests/e2e/api/package-lock.json @@ -3083,9 +3083,9 @@ } }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "lodash.memoize": { From ce9fce8d0d6c39fef7e6ce1c15c3facfeeab898a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 May 2021 22:44:27 +0000 Subject: [PATCH 343/368] Bump hosted-git-info from 2.8.8 to 2.8.9 in /tests/e2e/api Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9. - [Release notes](https://github.com/npm/hosted-git-info/releases) - [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md) - [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9) Signed-off-by: dependabot[bot] --- tests/e2e/api/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/api/package-lock.json b/tests/e2e/api/package-lock.json index b33e892c704..81f1f5d7ee5 100644 --- a/tests/e2e/api/package-lock.json +++ b/tests/e2e/api/package-lock.json @@ -2101,9 +2101,9 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "html-encoding-sniffer": { From eb2e67d17dd624bb9f1e517d0ba66be93eb6fe4c Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Mon, 10 May 2021 11:32:39 +0200 Subject: [PATCH 344/368] Make the debug tools page entries for attribute filtering hidden by default. To show the entries the following needs to be run: wc_get_container() ->get(\Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore::class) ->show_feature(); --- .../DataRegenerator.php | 4 +++ .../LookupDataStore.php | 35 +++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/Internal/ProductAttributesLookup/DataRegenerator.php b/src/Internal/ProductAttributesLookup/DataRegenerator.php index ebc1758a0ff..e7a60bffd35 100644 --- a/src/Internal/ProductAttributesLookup/DataRegenerator.php +++ b/src/Internal/ProductAttributesLookup/DataRegenerator.php @@ -271,6 +271,10 @@ CREATE TABLE ' . $this->lookup_table_name . '( * @return array The tools array with the entry added. */ private function add_initiate_regeneration_entry_to_tools_array( array $tools_array ) { + if ( ! $this->data_store->is_feature_visible() ) { + return $tools_array; + } + $lookup_table_exists = $this->lookup_table_exists(); $generation_is_in_progress = $this->regeneration_is_in_progress(); diff --git a/src/Internal/ProductAttributesLookup/LookupDataStore.php b/src/Internal/ProductAttributesLookup/LookupDataStore.php index 9fceb95f41a..77cc2845238 100644 --- a/src/Internal/ProductAttributesLookup/LookupDataStore.php +++ b/src/Internal/ProductAttributesLookup/LookupDataStore.php @@ -22,12 +22,43 @@ class LookupDataStore { private $lookup_table_name; /** - * LookupDataStore constructor. + * Is the feature visible? + * + * @var bool + */ + private $is_feature_visible; + + /** + * LookupDataStore constructor. Makes the feature hidden by default. */ public function __construct() { global $wpdb; - $this->lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup'; + $this->lookup_table_name = $wpdb->prefix . 'wc_product_attributes_lookup'; + $this->is_feature_visible = false; + } + + /** + * Checks if the feature is visible (so that dedicated entries will be added to the debug tools page). + * + * @return bool True if the feature is visible. + */ + public function is_feature_visible() { + return $this->is_feature_visible; + } + + /** + * Makes the feature visible, so that dedicated entries will be added to the debug tools page. + */ + public function show_feature() { + $this->is_feature_visible = true; + } + + /** + * Hides the feature, so that no entries will be added to the debug tools page. + */ + public function hide_feature() { + $this->is_feature_visible = false; } /** From bcebdad06def41bbb6a2f46e15a1739e331c1638 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Mon, 10 May 2021 10:08:46 -0300 Subject: [PATCH 345/368] remove the stale label when feedback is provided (#29829) --- .github/workflows/update-feedback-labels.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/update-feedback-labels.yml b/.github/workflows/update-feedback-labels.yml index b353c28032d..d41160cbb1b 100644 --- a/.github/workflows/update-feedback-labels.yml +++ b/.github/workflows/update-feedback-labels.yml @@ -15,8 +15,10 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} labels: 'has feedback' - - name: remove needs feedback + - name: remove needs feedback, stale uses: actions-ecosystem/action-remove-labels@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} - labels: 'needs feedback' + labels: | + 'needs feedback' + 'stale' From afa1ba573d877bb7fd59ebcf2ac01621a558a682 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Mon, 10 May 2021 10:49:32 -0300 Subject: [PATCH 346/368] remove local container from smoke test (#29828) --- .github/workflows/smoke-test-daily.yml | 1 - package-lock.json | 11 +++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/smoke-test-daily.yml b/.github/workflows/smoke-test-daily.yml index d168350f512..e859ad41ed3 100644 --- a/.github/workflows/smoke-test-daily.yml +++ b/.github/workflows/smoke-test-daily.yml @@ -39,5 +39,4 @@ jobs: E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }} E2E_SLACK_CHANNEL: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }} run: | - npx wc-e2e docker:up npx wc-e2e test:e2e diff --git a/package-lock.json b/package-lock.json index 9358ea03b15..0c5d1334562 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8919,7 +8919,8 @@ "dev": true, "requires": { "@jest/globals": "^26.4.2", - "config": "3.3.3" + "config": "3.3.3", + "faker": "^5.1.0" }, "dependencies": { "@jest/environment": { @@ -9307,7 +9308,7 @@ } }, "prettier": { - "version": "npm:prettier@1.19.1", + "version": "npm:wp-prettier@1.19.1", "resolved": "https://registry.npmjs.org/wp-prettier/-/wp-prettier-1.19.1.tgz", "integrity": "sha512-mqAC2r1NDmRjG+z3KCJ/i61tycKlmADIjxnDhQab+KBxSAGbF/W7/zwB2guy/ypIeKrrftNsIYkNZZQKf3vJcg==", "dev": true @@ -25834,6 +25835,12 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, + "faker": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/faker/-/faker-5.5.3.tgz", + "integrity": "sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==", + "dev": true + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", From c7afe437d78e158f7f3b5b150ca6f3c371ed566a Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Mon, 10 May 2021 11:27:01 -0300 Subject: [PATCH 347/368] small E2E coding fixes (#29816) --- tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js | 4 ++-- tests/e2e/utils/src/flows/shopper.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js b/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js index 0ec9a92edc5..8512b52282b 100644 --- a/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js +++ b/tests/e2e/core-tests/specs/shopper/front-end-checkout.test.js @@ -140,7 +140,7 @@ const runCheckoutPageTest = () => { // Get order ID from the order received html element on the page let orderReceivedHtmlElement = await page.$('.woocommerce-order-overview__order.order'); let orderReceivedText = await page.evaluate(element => element.textContent, orderReceivedHtmlElement); - return guestOrderId = orderReceivedText.split(/(\s+)/)[6].toString(); + guestOrderId = orderReceivedText.split(/(\s+)/)[6].toString(); }); it('allows existing customer to place order', async () => { @@ -163,7 +163,7 @@ const runCheckoutPageTest = () => { // Get order ID from the order received html element on the page let orderReceivedHtmlElement = await page.$('.woocommerce-order-overview__order.order'); let orderReceivedText = await page.evaluate(element => element.textContent, orderReceivedHtmlElement); - return customerOrderId = orderReceivedText.split(/(\s+)/)[6].toString(); + customerOrderId = orderReceivedText.split(/(\s+)/)[6].toString(); }); it('store owner can confirm the order was received', async () => { diff --git a/tests/e2e/utils/src/flows/shopper.js b/tests/e2e/utils/src/flows/shopper.js index 1e2b7cd9d13..db347006ec3 100644 --- a/tests/e2e/utils/src/flows/shopper.js +++ b/tests/e2e/utils/src/flows/shopper.js @@ -137,7 +137,7 @@ const shopper = { // Remove products if they exist if ( await page.$( '.remove' ) !== null ) { products = await page.$( '.remove' ); - while ( products.length > 0 ) { + while ( products && products.length > 0 ) { for (let p = 0; p < products.length; p++ ) { await page.click( p ); await uiUnblocked(); From 7237051b67a633d63c757f8251b2ff7df69e7644 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Mon, 10 May 2021 12:16:31 -0300 Subject: [PATCH 348/368] three small e2e fixes found through smoke testing (#29834) - remove merchant login for beforeAll in cart & checkout coupon tests. Test objects created with the rest API. - eliminate error when merchant logout is called when merchant is not logged in - eliminate rest API error when deleting an object that no longer exists --- .../specs/shopper/front-end-cart-coupons.test.js | 2 -- .../specs/shopper/front-end-checkout-coupons.test.js | 2 -- tests/e2e/utils/src/flows/merchant.js | 8 +++++--- tests/e2e/utils/src/flows/with-rest-api.js | 5 ++++- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/e2e/core-tests/specs/shopper/front-end-cart-coupons.test.js b/tests/e2e/core-tests/specs/shopper/front-end-cart-coupons.test.js index c234767f3d6..b9a285811d1 100644 --- a/tests/e2e/core-tests/specs/shopper/front-end-cart-coupons.test.js +++ b/tests/e2e/core-tests/specs/shopper/front-end-cart-coupons.test.js @@ -28,12 +28,10 @@ const runCartApplyCouponsTest = () => { let couponFixedProduct; beforeAll(async () => { - await merchant.login(); await createSimpleProduct(); couponFixedCart = await createCoupon(); couponPercentage = await createCoupon('50', 'Percentage discount'); couponFixedProduct = await createCoupon('5', 'Fixed product discount'); - await merchant.logout(); await shopper.emptyCart(); await shopper.goToShop(); await shopper.addToCartFromShopPage('Simple product'); diff --git a/tests/e2e/core-tests/specs/shopper/front-end-checkout-coupons.test.js b/tests/e2e/core-tests/specs/shopper/front-end-checkout-coupons.test.js index 5722a4f1956..a14ce2279e0 100644 --- a/tests/e2e/core-tests/specs/shopper/front-end-checkout-coupons.test.js +++ b/tests/e2e/core-tests/specs/shopper/front-end-checkout-coupons.test.js @@ -28,12 +28,10 @@ const runCheckoutApplyCouponsTest = () => { let couponFixedProduct; beforeAll(async () => { - await merchant.login(); await createSimpleProduct(); couponFixedCart = await createCoupon(); couponPercentage = await createCoupon('50', 'Percentage discount'); couponFixedProduct = await createCoupon('5', 'Fixed product discount'); - await merchant.logout(); await shopper.emptyCart(); await shopper.goToShop(); await shopper.addToCartFromShopPage('Simple product'); diff --git a/tests/e2e/utils/src/flows/merchant.js b/tests/e2e/utils/src/flows/merchant.js index dad590a4a63..aa78a709f8e 100644 --- a/tests/e2e/utils/src/flows/merchant.js +++ b/tests/e2e/utils/src/flows/merchant.js @@ -57,9 +57,11 @@ const merchant = { ( am ) => am.filter( ( e ) => e.href ).map( ( e ) => e.href ) ); - await page.goto( logoutLinks[ 0 ], { - waitUntil: 'networkidle0', - } ); + if ( logoutLinks && logoutLinks[0] ) { + await page.goto(logoutLinks[0], { + waitUntil: 'networkidle0', + }); + } }, openAllOrdersView: async () => { diff --git a/tests/e2e/utils/src/flows/with-rest-api.js b/tests/e2e/utils/src/flows/with-rest-api.js index 1deefb851bd..442d1d20a8c 100644 --- a/tests/e2e/utils/src/flows/with-rest-api.js +++ b/tests/e2e/utils/src/flows/with-rest-api.js @@ -24,7 +24,10 @@ const deleteAllRepositoryObjects = async ( repository, defaultObjectId = null ) if ( objects[ o ].id == defaultObjectId ) { continue; } - await repository.delete( objects[ o ].id ); + // We may be getting a cached copy of the dataset and the object has already been deleted. + try { + await repository.delete(objects[o].id); + } catch (e) {} } objects = await repository.list(); } From 1ba0e6d382d764fb2026054d98d27faecdf747f5 Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Mon, 10 May 2021 12:19:06 -0300 Subject: [PATCH 349/368] update stale to Stale in feedback label CI (#29871) --- .github/workflows/update-feedback-labels.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/update-feedback-labels.yml b/.github/workflows/update-feedback-labels.yml index d41160cbb1b..2c311f0195a 100644 --- a/.github/workflows/update-feedback-labels.yml +++ b/.github/workflows/update-feedback-labels.yml @@ -21,4 +21,4 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} labels: | 'needs feedback' - 'stale' + 'Stale' From 38a6c9e3e2a913dfd28caffb8db301a0841e1c85 Mon Sep 17 00:00:00 2001 From: Darren Ethier Date: Tue, 11 May 2021 11:37:28 -0400 Subject: [PATCH 350/368] update blocks package to 5.1.0 --- composer.json | 2 +- composer.lock | 61 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/composer.json b/composer.json index 462458e7920..6346176de2a 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "psr/container": "1.0.0", "woocommerce/action-scheduler": "3.1.6", "woocommerce/woocommerce-admin": "2.2.6", - "woocommerce/woocommerce-blocks": "4.9.1" + "woocommerce/woocommerce-blocks": "5.1.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.4" diff --git a/composer.lock b/composer.lock index 3f506ced4f6..16af2df5a8d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a604678b268820c78736d599e1eb6726", + "content-hash": "3f82e5bd9e485ba6bcd94111391f6f11", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -51,6 +51,9 @@ "GPL-2.0-or-later" ], "description": "Creates a custom autoloader for a plugin or theme.", + "support": { + "source": "https://github.com/Automattic/jetpack-autoloader/tree/2.10.1" + }, "time": "2021-03-30T15:15:59+00:00" }, { @@ -82,6 +85,9 @@ "GPL-2.0-or-later" ], "description": "A wrapper for defining constants in a more testable way.", + "support": { + "source": "https://github.com/Automattic/jetpack-constants/tree/v1.5.1" + }, "time": "2020-10-28T19:00:31+00:00" }, { @@ -214,6 +220,10 @@ "zend", "zikula" ], + "support": { + "issues": "https://github.com/composer/installers/issues", + "source": "https://github.com/composer/installers/tree/v1.11.0" + }, "funding": [ { "url": "https://packagist.com", @@ -288,6 +298,10 @@ "geolocation", "maxmind" ], + "support": { + "issues": "https://github.com/maxmind/MaxMind-DB-Reader-php/issues", + "source": "https://github.com/maxmind/MaxMind-DB-Reader-php/tree/v1.6.0" + }, "time": "2019-12-19T22:59:03+00:00" }, { @@ -362,6 +376,10 @@ "email", "pre-processing" ], + "support": { + "issues": "https://github.com/MyIntervals/emogrifier/issues", + "source": "https://github.com/MyIntervals/emogrifier" + }, "time": "2019-12-26T19:37:31+00:00" }, { @@ -411,6 +429,10 @@ "container-interop", "psr" ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/master" + }, "time": "2017-02-14T16:28:37+00:00" }, { @@ -464,6 +486,9 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/css-selector/tree/master" + }, "time": "2017-05-01T15:01:29+00:00" }, { @@ -499,6 +524,10 @@ ], "description": "Action Scheduler for WordPress and WooCommerce", "homepage": "https://actionscheduler.org/", + "support": { + "issues": "https://github.com/woocommerce/action-scheduler/issues", + "source": "https://github.com/woocommerce/action-scheduler/tree/master" + }, "time": "2020-05-12T16:22:33+00:00" }, { @@ -507,7 +536,7 @@ "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-admin.git", - "reference": "161e6afa01a3fb69533cfa2b245a71df7512ec3f" + "reference": "65c5a4d0b0c3a7c7457e250c9ba1f7c15cac6cb8" }, "dist": { "type": "zip", @@ -544,20 +573,24 @@ ], "description": "A modern, javascript-driven WooCommerce Admin experience.", "homepage": "https://github.com/woocommerce/woocommerce-admin", - "time": "2021-04-29T14:11:48+00:00" + "support": { + "issues": "https://github.com/woocommerce/woocommerce-admin/issues", + "source": "https://github.com/woocommerce/woocommerce-admin/tree/v2.2.6" + }, + "time": "2021-05-07T21:29:02+00:00" }, { "name": "woocommerce/woocommerce-blocks", - "version": "v4.9.1", + "version": "v5.1.0", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-gutenberg-products-block.git", - "reference": "62f32bfb45dfcb2ba3ca349a6ed0a8cf48ddefce" + "reference": "a4f168596f3832e161b26dec636b69293039ee51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/62f32bfb45dfcb2ba3ca349a6ed0a8cf48ddefce", - "reference": "62f32bfb45dfcb2ba3ca349a6ed0a8cf48ddefce", + "url": "https://api.github.com/repos/woocommerce/woocommerce-gutenberg-products-block/zipball/a4f168596f3832e161b26dec636b69293039ee51", + "reference": "a4f168596f3832e161b26dec636b69293039ee51", "shasum": "" }, "require": { @@ -565,7 +598,7 @@ "composer/installers": "^1.7.0" }, "require-dev": { - "phpunit/phpunit": "6.5.14", + "phpunit/phpunit": "7.5.20", "woocommerce/woocommerce-sniffs": "0.1.0" }, "type": "wordpress-plugin", @@ -591,7 +624,11 @@ "gutenberg", "woocommerce" ], - "time": "2021-04-13T16:11:16+00:00" + "support": { + "issues": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues", + "source": "https://github.com/woocommerce/woocommerce-gutenberg-products-block/tree/v5.1.0" + }, + "time": "2021-05-10T15:01:42+00:00" } ], "packages-dev": [ @@ -639,6 +676,10 @@ "isolation", "tool" ], + "support": { + "issues": "https://github.com/bamarni/composer-bin-plugin/issues", + "source": "https://github.com/bamarni/composer-bin-plugin/tree/master" + }, "time": "2020-05-03T08:27:20+00:00" } ], @@ -654,5 +695,5 @@ "platform-overrides": { "php": "7.0" }, - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.0.0" } From d73c948c67da01d9653fe72e9e117f5a29d2a940 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 11 May 2021 15:45:21 +0000 Subject: [PATCH 351/368] Bump lodash from 4.17.20 to 4.17.21 in /tests/e2e/utils Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21) Signed-off-by: dependabot[bot] --- tests/e2e/utils/package-lock.json | 171 +++++------------------------- 1 file changed, 24 insertions(+), 147 deletions(-) diff --git a/tests/e2e/utils/package-lock.json b/tests/e2e/utils/package-lock.json index 8bc72f6a287..f7010d03dbb 100644 --- a/tests/e2e/utils/package-lock.json +++ b/tests/e2e/utils/package-lock.json @@ -1,6 +1,6 @@ { "name": "@woocommerce/e2e-utils", - "version": "0.1.1", + "version": "0.1.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -39,16 +39,6 @@ "resolved": "https://registry.npmjs.org/@tannin/postfix/-/postfix-1.1.0.tgz", "integrity": "sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==" }, - "@woocommerce/api": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@woocommerce/api/-/api-0.1.0.tgz", - "integrity": "sha512-OWXL2q6Yh1DBKBPLqqPG+YpCbXw1fW/lf0+v71Pwf+THutya9m02l9BFPnwEX46xONhn1ttDniePU1NtST9m7Q==", - "requires": { - "axios": "0.19.2", - "create-hmac": "1.1.7", - "oauth-1.0a": "2.2.6" - } - }, "@wordpress/deprecated": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-2.10.0.tgz", @@ -112,14 +102,6 @@ "react-native-url-polyfill": "^1.1.2" } }, - "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", - "requires": { - "follow-redirects": "1.5.10" - } - }, "base64-js": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", @@ -134,46 +116,12 @@ "ieee754": "^1.1.4" } }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "config": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/config/-/config-3.3.3.tgz", + "integrity": "sha512-T3RmZQEAji5KYqUQpziWtyGJFli6Khz7h0rpxDwYNjSkr5ynyTWwO7WpfjHzTXclNCDfSWQRcwMb+NwxJesCKw==", "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" + "json5": "^2.1.1" } }, "encoding": { @@ -190,21 +138,13 @@ "integrity": "sha512-RrWKFSSA/aNLP0g3o2WW1Zez7/MnMr7xkiZmoCfAGZmdkDQZ6l2KtuXHN5XjdvpRjDl8+3vf+Rrtl06Z352+Mw==" }, "fishery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fishery/-/fishery-1.0.1.tgz", - "integrity": "sha512-VV8H4ZuCbZ9cCWkrYWLLPoAfpTp0t+hlJVoNWkRRHdXOgQ08wjd8ab9di8/Ed/QhgwxY3h7Y17HgDZ9osaHSSQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fishery/-/fishery-1.2.0.tgz", + "integrity": "sha512-0GG029KHF3p8Q0NiAl/ZOK1fvyAprOiHdtRWUNS46x9QXuQhMwzcGLNDbZ7XIEEBowwBmMsw7StkaU0ek9dSbg==", "requires": { "lodash.mergewith": "^4.6.2" } }, - "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "requires": { - "debug": "=3.1.0" - } - }, "gettext-parser": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.4.0.tgz", @@ -214,16 +154,6 @@ "safe-buffer": "^5.1.1" } }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, "iconv-lite": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", @@ -237,45 +167,38 @@ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "requires": { + "minimist": "^1.2.5" + } + }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "lodash.mergewith": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==" }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, "memize": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/memize/-/memize-1.1.0.tgz", "integrity": "sha512-K4FcPETOMTwe7KL2LK0orMhpOmWD2wRGwWWpbZy0fyArwsyIKR8YJVz8+efBAh3BO4zPqlSICu4vsLTRRqtFAg==" }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "node-fetch": { "version": "1.7.3", @@ -286,11 +209,6 @@ "is-stream": "^1.0.1" } }, - "oauth-1.0a": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/oauth-1.0a/-/oauth-1.0a-2.2.6.tgz", - "integrity": "sha512-6bkxv3N4Gu5lty4viIcIAnq5GbxECviMBeKR3WX/q87SPQ8E8aursPZUtsXDnxCs787af09WPRBLqYrf/lwoYQ==" - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -309,30 +227,11 @@ "whatwg-url-without-unicode": "8.0.0-3" } }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, "regenerator-runtime": { "version": "0.13.7", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -343,28 +242,11 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, "sprintf-js": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, "tannin": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tannin/-/tannin-1.2.0.tgz", @@ -373,11 +255,6 @@ "@tannin/plural-forms": "^1.1.0" } }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" - }, "webidl-conversions": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", From 4e89b08df94dfc4fa8bf12d02e67afd0b86fc733 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 11 May 2021 12:52:24 -0300 Subject: [PATCH 352/368] Remove dependabot from contributors script --- bin/contributors.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/contributors.sh b/bin/contributors.sh index b057ec66d75..e25389fb6e2 100755 --- a/bin/contributors.sh +++ b/bin/contributors.sh @@ -3,7 +3,7 @@ read -p 'What date (YYYY-MM-DD) should we get contributions since? (i.e. date of previous release): ' from_date read -sp 'Provide a personal access token (you must): ' auth_token -ignored_users="renovate-bot,apps/renovate,renovate,renovate[bot],github-actions[bot]" +ignored_users="renovate-bot,apps/renovate,renovate,renovate[bot],github-actions[bot],dependabot,dependabot[bot]" output_file="contributors.html" common_arguments="--owner woocommerce --fromDate $from_date --authToken $auth_token --cols 6 --sortBy contributions --format html --sortOrder desc --showlogin true --filter $ignored_users" From c90681375cddbe25d6a2aaf4504bd4584d281302 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 11 May 2021 13:27:20 -0300 Subject: [PATCH 353/368] Update i18n/states.php --- i18n/states.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/states.php b/i18n/states.php index d77b05248e9..51099857f27 100644 --- a/i18n/states.php +++ b/i18n/states.php @@ -1735,7 +1735,7 @@ return array( 'AE' => __( 'Armed Forces (AE)', 'woocommerce' ), 'AP' => __( 'Armed Forces (AP)', 'woocommerce' ), ), - 'VE' => array( // Venezuela States. Ref: https://en.wikipedia.org/wiki/ISO_3166-2:VE + 'VE' => array( // Venezuela States. Ref: https://github.com/unicode-org/cldr/blob/release-38-1/common/subdivisions/en.xml#L5426-L5451 'A' => __( 'Capital', 'woocommerce' ), 'B' => __( 'Anzoátegui', 'woocommerce' ), From 7c417716df5b536b22a1d67fef3dbb7b04563638 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 11 May 2021 13:27:59 -0300 Subject: [PATCH 354/368] Update i18n/states.php --- i18n/states.php | 1 - 1 file changed, 1 deletion(-) diff --git a/i18n/states.php b/i18n/states.php index 51099857f27..02d850f5039 100644 --- a/i18n/states.php +++ b/i18n/states.php @@ -1736,7 +1736,6 @@ return array( 'AP' => __( 'Armed Forces (AP)', 'woocommerce' ), ), 'VE' => array( // Venezuela States. Ref: https://github.com/unicode-org/cldr/blob/release-38-1/common/subdivisions/en.xml#L5426-L5451 - 'A' => __( 'Capital', 'woocommerce' ), 'B' => __( 'Anzoátegui', 'woocommerce' ), 'C' => __( 'Apure', 'woocommerce' ), From 514530d2e20612a2af093156eaa0ca4cd995bcfe Mon Sep 17 00:00:00 2001 From: Jonathan Sadowski Date: Tue, 11 May 2021 11:39:46 -0500 Subject: [PATCH 355/368] Update changelog and readme for 5.3 release, and bump version in package.json --- changelog.txt | 131 ++++++++++++++++++++++++ package.json | 2 +- readme.txt | 276 ++++++++++++++++++++++---------------------------- 3 files changed, 254 insertions(+), 155 deletions(-) diff --git a/changelog.txt b/changelog.txt index 4b636018665..dc87ea85f2e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,136 @@ == Changelog == += 5.3.0 2021-05-11 = + +**WooCommerce** + +* Dev - Add support for "cities" and "postcodes" fields to the REST API endpoints to create/update tax rates. #29495 +* Dev - The taxes GET endpoint now supports sorting by priority. #29495 +* Enhancement - Add a new `woocommerce_cart_product_not_enough_stock_already_in_cart_message` filter to allow developers to filter an add-to-cart error when there isn't enough in stock taking into account what's already in the cart. #29304 +* Enhancement - Pass `$handler`, and prevent logging from `woocommerce_logger_log_message` filter when the message is null. #29572 +* Fix - Added parameter `$item` (instance of WC_Order_Item) to both the function `wc_downloadable_file_permission` and the filter hook `woocommerce_downloadable_file_permission`. #23188 +* Fix - Add array-typed "cities" and "postcodes" to the response of the "tax" endpoint in the REST API to overcome the limitation of "city" and "postcode" returning always one single value. #27751 +* Fix - Update tax rate for existing taxes when recalculating order totals. #27985 +* Fix - Replace page setup dropdowns with AJAX powered search selects. #29181 +* Fix - Return 0 if order isn't available in `WC_Payment_Gateway::get_order_total()`. #29314 +* Fix - Fix console error on IE11 when opening admin pages. #29322 +* Fix - Prevent crash when log file can't be opened for writing. #29396 +* Fix - Closes the section "Store management insights" in email settings. #29447 +* Fix - Fixed return type of `WC_Shortcode_Products::get_type()`. #29452 +* Fix - Fix syntax error in the admin (products/orders) list table. #29469 +* Fix - Cart duplicate debug shipping notices in certain situations. #29480 +* Fix - Trying to update the cities or postcodes (only) or a tax rate via REST API returned an error. #29495 +* Fix - Unneeded browser popup message of unsaved changes when adding a shipping zone with a shipping method. #29510 +* Fix - Update the persistent cart after it's loaded on customer login. Fixes an issue whereby unavailable products would be validated on every login. #29517 +* Fix - Updated `$customer->get_shipping()` and `$customer->get_billing()` to return the full address after updating individual fields. #29538 +* Fix - Prevent cart to reset all nonce in front-end. #29542 +* Fix - Bump the version of the "Grouped product add to cart" template to 4.8.0 (was still at 4.0.0 by mistake). #29601 +* Fix - If we have a non-empty shipping address then do not overwrite the state or country fields with billing address data. #29605 +* Tweak - Add the support to `optgroups` in single select on Settings API. #29145 +* Tweak - Improves performance by avoiding an unnecessary redirect if custom permalink structure does not contain trailing slashes. #29422 +* Tweak - Update SSR db version tooltip to more accurately state the db version. #29438 +* Tweak - Adjust Twenty Twenty One order items header alignment. #29485 +* Tweak - Lost password form alignment issues. #29496 +* Tweak - Improve accessibility by adding `aria-hidden="true"` on strikethrough prices. #29603 +* Tweak - Default store location to US California. #29654 +* Tweak - Default store currency to USD. #29752 + +** WooCommerce Blocks - 4.8.0 & 4.9.0 & 4.9.1 ** + +* Dev - Removed legacy handling for SSR blocks that rendered shortcodes. #4010 +* Fix - Customer address country saving to orders in certain circumstances. #4013 +* Fix - Prevent error messages returned by the API from displaying raw HTML. #4005 +* Fix - Proceed to checkout button click bug happening when the Coupon error is visible in the Cart block. #3996 +* Fix - Use font color in payment methods border. #4051 +* Fix - Load translation file for JS files that has translatable strings. #4050 +* Fix - Stop shipping package titles line-breaks occurring in the middle of a word. #4049 +* Fix - Fixed styling issues on the cart and checkout page in Twenty(X) themes. #4046 +* Fix - Fix headline alignment in the empty state of the cart block. #4044 +* Fix - Fix button alignment in Featured Product and Featured Category blocks. #4028 +* Fix - Check if Cart and Checkout are registered before removing payment methods. #4056 +* Enhancement - Registered payment methods now have access to the `shouldSavePayment` prop in their components (which indicates whether the shopper has checked the save payment method checkbox. #3990 +* Enhancement - Payment methods implementing the `savedTokenComponent` configuration property will now have the `onPaymentProcessing` event available to the registered component. #3982 + +** WooCommerce Admin - 2.2.0 & 2.2.1 & 2.2.2 & 2.2.3 & 2.2.4 & 2.2.5 & 2.2.6 ** +* Add - Next new novel navigation nudge note #6610 +* Add - Add legacy report items to new navigation #6507 +* Add - Add preview site button on the appearance task #6457 +* Add - Back button to go to home screen from tasks in the task list. #6397 +* Add - Add a "rather not say" option to revenue in the profile wizard. #6475 +* Add - Remove Mollie promo note on install #6510 +* Add - Remote Inbox Notifications rule to trigger when WooCommerce Admin is upgraded. #6040 +* Add - CES survey for search product, order, customer #6420 +* Add - CES survey for importing products #6419 +* Add - CES survey for adding product categories, tags, and attributes #6418 +* Add - Additional analytics tracking for the business details step. #6575 +* Add - Include tracking for mail poet installs in the selective bundle install #6603 +* Add - Paystack payment provider to several african countries. #6579 +* Dev - Close activity panel tabs by default and track #6566 +* Dev - Update undefined task name properties for help panel tracks #6565 +* Dev - Refactor profile wizard benefits step and add tests #6583 +* Dev - Add filter to profile wizard steps #6564 +* Dev - Add nav intro modal tests #6518 +* Dev - Use wc filter to get status tabs for tools category #6525 +* Dev - Add nav header component tests #6509 +* Dev - Add initial tests for navigation Menu class #6492 +* Dev - Remove active item from navigation store #6486 +* Dev - Add navigation container tests #6464 +* Dev - Add nav favorite button tests #6446 +* Dev - Add a changelog lint check to PRs. #6414 +* Dev - Add navigation favorites tests #6409 +* Dev - support use of Array.flat in client and packages. #6411 +* Dev - Deprecate Onboarding::has_woocommerce_support. #6401 +* Dev - Add Dependency Extraction Webpack Plugin #5762 +* Dev - Add client-side filter for Navigation rootBackUrl #6505 +* Dev - Remove `items_purchased` and `account_type` props from onboarding profile API. #6520 +* Dev - Added warning when WC-Admin is active but not being used #6453 +* Dev - Store profiler - Added MailPoet to Business Details step #6503 +* Dev - Store profiler - Added MailPoet to new Business Details step #6515 +* Dev - Add tilde (~) to represent client root directory for imports. #6517 +* Dev - Add script automation for gathering hooks and filters. #6454 +* Dev - Add TypeScript and page objects to the E2E test suite. #6582 +* Dev - Introduce Typescript to Navigation utils #6477 +* Dev - Payments task: include Mercado Pago #6572 +* Dev - Ensure script asset.php files are included in builds #6635 +* Dev - Ensure production script asset names don't include .min suffix #6681 +* Dev - Do a git clean before the core release. #6945 +* Dev - Fix a bug where trying to load an asset registry causes a crash. #6951 +* Fix - Add check for navigating being enabled. #6462 +* Fix - Move the shipping input and text 1px lower. #6408 +* Fix - Correct the Klarna slug #6440 +* Fix - Broken link anchors to online documentation. #6455 +* Fix - Update payment card style on mobile #6413 +* Fix - Missing i18n in Welcome modal. #6456 +* Fix - Restore visual styles back to Analytics tabs. #5913 +* Fix - Update contrast and hover / active colors for analytics dropdown buttons #6504 +* Fix - Associated Order Number for refunds was hidden #6428 +* Fix - Fix issue where Loader::is_admin_page() would error if WooCommerce admin is disabled. #6563 +* Fix - Correct a bug where the JP connection flow would not happen when installing JP in the OBW. #6521 +* Fix - Show management links when the task list is complete (even if its not hidden). #6657 +* Fix - Adding New Zealand and Ireland to selective bundle option, previously missed. #6649 +* Fix - Update the Mercado option used for enabling/disabling. #6677 +* Fix - Improve AddFirstProduct email note contents. #6617 +* Fix - Check if features are currently being enabled #6688 +* Fix - Fix the activity panel toggle not closing on click #6679 +* Fix - Fix use of feature checks and remove deprecated method calls #6687 +* Fix - Allow the manager role to query certain options #6577 +* Fix - Delete customer data on network user deletion #6574 +* Fix - Fix Themes step visibility in IE 11 #6578 +* Fix - Fix hidden menu title on smaller screens #6562 +* Fix - Add gross sales column to CSV export #6567 +* Fix - Disable the continue btn on OBW when requested are being made #6838 +* Fix - Calling of get_script_asset_filename with extra parameter #6955 +* Fix - Address an issue with OBW when installing only WooCommerce payments and Jetpack. #6957 +* Tweak - Add default value for contains op #6622 +* Tweak - Adjust targeting store age for the Add First Product note #6554 +* Tweak - Improve WC Shipping & Tax logic #6547 +* Tweak - Update Insight inbox note content #6555 +* Tweak - Remove mobile activity panel toggle #6539 +* Tweak - Refactor autoloader to remove global variable. #6412 +* Tweak - Revert WCPay international support for bundled package #6901 +* Tweak - Store profiler - Changed MailPoet's title and description #6886 +* Tweak - Update PayU logo #6829 + = 5.2.2 2021-04-15 = **WooCommerce** diff --git a/package.json b/package.json index ecbad3d716b..051360c8dcc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "woocommerce", "title": "WooCommerce", - "version": "5.3.0", + "version": "5.4.0", "homepage": "https://woocommerce.com/", "repository": { "type": "git", diff --git a/readme.txt b/readme.txt index 6c7b73bf3ba..3a622af86bb 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: e-commerce, store, sales, sell, woo, shop, cart, checkout, downloadable, d Requires at least: 5.5 Tested up to: 5.7 Requires PHP: 7.0 -Stable tag: 5.2.2 +Stable tag: 5.3.0 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -160,167 +160,135 @@ WooCommerce comes with some sample data you can use to see how products look; im == Changelog == -= 5.2.2 2021-04-15 = += 5.3.0 2021-05-11 = **WooCommerce** -* Fix - Can't grant permission for download from order details page. #29691 +* Dev - Add support for "cities" and "postcodes" fields to the REST API endpoints to create/update tax rates. #29495 +* Dev - The taxes GET endpoint now supports sorting by priority. #29495 +* Enhancement - Add a new `woocommerce_cart_product_not_enough_stock_already_in_cart_message` filter to allow developers to filter an add-to-cart error when there isn't enough in stock taking into account what's already in the cart. #29304 +* Enhancement - Pass `$handler`, and prevent logging from `woocommerce_logger_log_message` filter when the message is null. #29572 +* Fix - Added parameter `$item` (instance of WC_Order_Item) to both the function `wc_downloadable_file_permission` and the filter hook `woocommerce_downloadable_file_permission`. #23188 +* Fix - Add array-typed "cities" and "postcodes" to the response of the "tax" endpoint in the REST API to overcome the limitation of "city" and "postcode" returning always one single value. #27751 +* Fix - Update tax rate for existing taxes when recalculating order totals. #27985 +* Fix - Replace page setup dropdowns with AJAX powered search selects. #29181 +* Fix - Return 0 if order isn't available in `WC_Payment_Gateway::get_order_total()`. #29314 +* Fix - Fix console error on IE11 when opening admin pages. #29322 +* Fix - Prevent crash when log file can't be opened for writing. #29396 +* Fix - Closes the section "Store management insights" in email settings. #29447 +* Fix - Fixed return type of `WC_Shortcode_Products::get_type()`. #29452 +* Fix - Fix syntax error in the admin (products/orders) list table. #29469 +* Fix - Cart duplicate debug shipping notices in certain situations. #29480 +* Fix - Trying to update the cities or postcodes (only) or a tax rate via REST API returned an error. #29495 +* Fix - Unneeded browser popup message of unsaved changes when adding a shipping zone with a shipping method. #29510 +* Fix - Update the persistent cart after it's loaded on customer login. Fixes an issue whereby unavailable products would be validated on every login. #29517 +* Fix - Updated `$customer->get_shipping()` and `$customer->get_billing()` to return the full address after updating individual fields. #29538 +* Fix - Prevent cart to reset all nonce in front-end. #29542 +* Fix - Bump the version of the "Grouped product add to cart" template to 4.8.0 (was still at 4.0.0 by mistake). #29601 +* Fix - If we have a non-empty shipping address then do not overwrite the state or country fields with billing address data. #29605 +* Tweak - Add the support to `optgroups` in single select on Settings API. #29145 +* Tweak - Improves performance by avoiding an unnecessary redirect if custom permalink structure does not contain trailing slashes. #29422 +* Tweak - Update SSR db version tooltip to more accurately state the db version. #29438 +* Tweak - Adjust Twenty Twenty One order items header alignment. #29485 +* Tweak - Lost password form alignment issues. #29496 +* Tweak - Improve accessibility by adding `aria-hidden="true"` on strikethrough prices. #29603 +* Tweak - Default store location to US California. #29654 +* Tweak - Default store currency to USD. #29752 -= 5.2.1 2021-04-14 = +** WooCommerce Blocks - 4.8.0 & 4.9.0 & 4.9.1 ** -**WooCommerce** +* Dev - Removed legacy handling for SSR blocks that rendered shortcodes. #4010 +* Fix - Customer address country saving to orders in certain circumstances. #4013 +* Fix - Prevent error messages returned by the API from displaying raw HTML. #4005 +* Fix - Proceed to checkout button click bug happening when the Coupon error is visible in the Cart block. #3996 +* Fix - Use font color in payment methods border. #4051 +* Fix - Load translation file for JS files that has translatable strings. #4050 +* Fix - Stop shipping package titles line-breaks occurring in the middle of a word. #4049 +* Fix - Fixed styling issues on the cart and checkout page in Twenty(X) themes. #4046 +* Fix - Fix headline alignment in the empty state of the cart block. #4044 +* Fix - Fix button alignment in Featured Product and Featured Category blocks. #4028 +* Fix - Check if Cart and Checkout are registered before removing payment methods. #4056 +* Enhancement - Registered payment methods now have access to the `shouldSavePayment` prop in their components (which indicates whether the shopper has checked the save payment method checkbox. #3990 +* Enhancement - Payment methods implementing the `savedTokenComponent` configuration property will now have the `onPaymentProcessing` event available to the registered component. #3982 -* Update - WooCommerce Blocks package 4.7.2. #29660 - -**WooCommerce Blocks - 4.7.2** - -* Fix - Check if Cart and Checkout are registered before removing payment methods. ([4056](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/4056)) - -= 5.2.0 2021-04-13 = - -**WooCommerce** - -* Add - Filter woocommerce_product_recount_terms to allow/prevent recounting of product terms. #29281 -* Add - Result return array to the checkout_place_order_success callback to allow 3rd party to manipulate results. #29232 -* Dev - Fix miscellaneous typos in docblocks. #29285 -* Dev - Added woocommerce_ajax_order_items_removed hook. #29241 -* Dev - Fix usage of docker-compose (wc-e2e) commands in e2e tests when running them within WSL2. #29207 -* Dev - Fixes to documentation of WC_Shipping_Rate. #29117 -* Dev - Add tracks event when a user clicks on the links of the WooCommerce Status widget. #29109 -* Dev - Track the number of installations of WooCommerce Payments via that extensions banner for stores that have opted in to tracking. #29052 -* Dev - Added woocommerce_ajax_order_items_removed hook. #28936 -* Dev - Add tracking of woocommerce_admin_disabled usage. #28535 -* Enhancement - Add support for the low stock threshold for variations. #29345 -* Enhancement - Clean up of major version update compatibility warnings. #29200 -* Enhancement - Add a new dashboard widget to promote users to finish onboarding tasks. #29174 -* Enhancement - Update the Woo widget net sales link and logic to use the new analytics page and data. #29149 -* Enhancement - Added the body class woocommerce-shop to the shop page, so that it can be targeted via CSS. (#28724). #29051 -* Enhancement - Make sure downloadable file paths are properly recognized for strengthened security. #28699 -* Enhancement - Delay the registration of data exporters and erasers to avoid multiple language files from being loaded. #28078 -* Fix - Offsets not calculated correctly sometimes on select2 dropdowns causing usability issues. #29397 -* Fix - Handle errors in fault installations of PHP Intl. #29391 -* Fix - Cart page calculate shipping fields not showing correct fields based on location. #29282 -* Fix - Product categories widget item count not always showing the correct number. #29281 -* Fix - Updated include/rest-api/Controllers/Version3/class-wc-rest-shipping-zone-methods-controller.php to include a item schema function which appends support for order and class type values. #29218 -* Fix - Check if variation_id if belongs to the parent product while adding products to the cart. #29208 -* Fix - Reduce the number of ajax calls used when Geolocation (with Page Caching Enabled) mode is enabled. #29182 -* Fix - Don't display the coupon form on checkouts requiring the customer to be logged in to checkout. #29151 -* Fix - If coupon_lines are specified within a REST API order update, return an error if coupon item IDs are also specified. #29146 -* Fix - Avoids duplicating the word '(optional)' in the context of the Billing Address 2 field. #29136 -* Fix - PHP notice when checking out. #29133 -* Fix - Remove duplicate containers from the single and archive product pages. #29121 -* Fix - Wrong taxonomy caching in term and product attributes controllers. #29115 -* Fix - Make the parameters of the refund creation REST API behave as documented. #29099 -* Fix - Shipping methods with similar names could cause shipping method not selectable in order page. #29049 -* Fix - WC_Countries::get_formatted_address() not returning full name in correct order in some languages. #29008 -* Fix - add validation of the posted country codes on checkout. #28849 -* Fix - Correctly display pagination arrows on RTL languages. #28523 -* Fix - Invalid refund amount error on $0 refund when number of decimals is equal to 0. #27277 -* Fix - "Sale" badge misaligned on products when displaying 1 item per row. #29425 -* Fix - Revert a replacement of wp_redirect to wp_safe_redirect in WC_Checkout::process_order_payment that caused issues in the default PayPal interface. #29459 -* Fix - Don't remove existing coupons from order when an invalid REST API request for updating coupons is submitted. #29474 -* Fix - Wrong logic for including or excluding the payments step in the list of completed tasks in the onboarding wizard. #29518 -* Fix - Error when loading the admin dashboard while the admin package was disabled. #29613 -* Fix - "'' is not a valid country code" error when no billing/shipping country specified (e.g. when using PayPal checkout). #29606 -* Fix - Sanitize tax class and display errors in admin while creating tax classes. -* Fix - Check if a verified product owner is required before placing a review. -* Fix - Make product name escaping consistent in the front-end. -* Tweak - Added the Mercado Pago logo into the assets/images folder in order to use it in the payments setup task. #29365 -* Tweak - Update the contributor guidelines. #29150 -* Tweak - Introduced phone number input validation. #27242 -* Tweak - Escape short description. -* Update - WooCommerce Admin package 2.1.5. #29577 -* Update - WooCommerce Blocks package 4.7.0. #29406 - -**WooCommerce Admin - 2.1.0 & 2.1.1 & 2.1.2 & 2.1.3 & 2.1.4 & 2.1.5** - -* Add - Add navigation intro modal. #6367 -* Add - CES track settings tab on updating settings #6368 -* Add - Core settings redirection to new settings pages #6091 -* Add - Favorites tooltip to the navigation #6312 -* Add - Favoriting extensions client UI #6287 -* Add - Remove CES actions for adding and editing a product and editing an order #6355 -* Add - Settings client pages #6092 -* Add - Settings feature and pages #6089 -* Dev - Add filter to allow enabling the WP toolbar within the new navigation. #6371 -* Dev - Add navigation favorites data store #6275 -* Dev - Add unit tests to Navigation's Container component. #6344 -* Dev - Allow highlight tooltip to use body tag as parent. #6309 -* Dev - Change `siteUrl` to `homeUrl` on navigation site title #6240 -* Dev - Fix the react state update error on homescreen. #6320 -* Dev - Refactor head and body heights #6247 -* Dev - Remove Google fonts and material icons. #6343 -* Dev - Use box sizing and padding to fix nav and admin menu styling #6335 -* Enhancement - Move capability checks to client #6365 -* Enhancement - Move favorited menu items to primary menu #6290 -* Enhancement - Navigation: Add test to container component #6344 -* Enhancement - override wpbody styles when nav present #6354 -* Feature - Increase target audience for business feature step. #6508 +** WooCommerce Admin - 2.2.0 & 2.2.1 & 2.2.2 & 2.2.3 & 2.2.4 & 2.2.5 & 2.2.6 ** +* Add - Next new novel navigation nudge note #6610 +* Add - Add legacy report items to new navigation #6507 +* Add - Add preview site button on the appearance task #6457 +* Add - Back button to go to home screen from tasks in the task list. #6397 +* Add - Add a "rather not say" option to revenue in the profile wizard. #6475 +* Add - Remove Mollie promo note on install #6510 +* Add - Remote Inbox Notifications rule to trigger when WooCommerce Admin is upgraded. #6040 +* Add - CES survey for search product, order, customer #6420 +* Add - CES survey for importing products #6419 +* Add - CES survey for adding product categories, tags, and attributes #6418 +* Add - Additional analytics tracking for the business details step. #6575 +* Add - Include tracking for mail poet installs in the selective bundle install #6603 +* Add - Paystack payment provider to several african countries. #6579 +* Dev - Close activity panel tabs by default and track #6566 +* Dev - Update undefined task name properties for help panel tracks #6565 +* Dev - Refactor profile wizard benefits step and add tests #6583 +* Dev - Add filter to profile wizard steps #6564 +* Dev - Add nav intro modal tests #6518 +* Dev - Use wc filter to get status tabs for tools category #6525 +* Dev - Add nav header component tests #6509 +* Dev - Add initial tests for navigation Menu class #6492 +* Dev - Remove active item from navigation store #6486 +* Dev - Add navigation container tests #6464 +* Dev - Add nav favorite button tests #6446 +* Dev - Add a changelog lint check to PRs. #6414 +* Dev - Add navigation favorites tests #6409 +* Dev - support use of Array.flat in client and packages. #6411 +* Dev - Deprecate Onboarding::has_woocommerce_support. #6401 +* Dev - Add Dependency Extraction Webpack Plugin #5762 +* Dev - Add client-side filter for Navigation rootBackUrl #6505 +* Dev - Remove `items_purchased` and `account_type` props from onboarding profile API. #6520 +* Dev - Added warning when WC-Admin is active but not being used #6453 +* Dev - Store profiler - Added MailPoet to Business Details step #6503 +* Dev - Store profiler - Added MailPoet to new Business Details step #6515 +* Dev - Add tilde (~) to represent client root directory for imports. #6517 +* Dev - Add script automation for gathering hooks and filters. #6454 +* Dev - Add TypeScript and page objects to the E2E test suite. #6582 +* Dev - Introduce Typescript to Navigation utils #6477 +* Dev - Payments task: include Mercado Pago #6572 +* Dev - Ensure script asset.php files are included in builds #6635 +* Dev - Ensure production script asset names don't include .min suffix #6681 +* Dev - Do a git clean before the core release. #6945 +* Dev - Fix a bug where trying to load an asset registry causes a crash. #6951 * Fix - Add check for navigating being enabled. #6462 -* Fix - Add customer name column to CSV export #6556 -* Fix - Add guard to "Deactivate Plugin" note handlers to prevent fatal error. #6532 -* Fix - Adding New Zealand and Ireland to selective bundle option, previously missed. #6649 +* Fix - Move the shipping input and text 1px lower. #6408 +* Fix - Correct the Klarna slug #6440 * Fix - Broken link anchors to online documentation. #6455 -* Fix - Check if tax was successfully added before displaying notice #6229 +* Fix - Update payment card style on mobile #6413 +* Fix - Missing i18n in Welcome modal. #6456 +* Fix - Restore visual styles back to Analytics tabs. #5913 +* Fix - Update contrast and hover / active colors for analytics dropdown buttons #6504 +* Fix - Associated Order Number for refunds was hidden #6428 +* Fix - Fix issue where Loader::is_admin_page() would error if WooCommerce admin is disabled. #6563 * Fix - Correct a bug where the JP connection flow would not happen when installing JP in the OBW. #6521 -* Fix - Crash of Analytics > Settings page when Gutenberg is installed. #6540 -* Fix - Display" option fails to collapse upon invoking "Help" option #6233 -* Fix - Email notes now are turned off by default #6324 -* Fix - Empty nav menu #6366 -* Fix - Enqueue scripts called incorrectly in php unit tests #6358 -* Fix - Hide tooltip in welcome modal #6142 -* Fix - Recommended Payment Banner missing in Safari #6375 -* Fix - Removal of core settings pages #6328 -* Fix - Removed @woocommerce/components/card from OBW #6374 -* Fix - Reset Navigation submenu before making Flyout #6396 -* Fix - Restore missing Correct the Klarna slug #6440 -* Fix - Top bar slightly overlaps wp-admin navigation on mobile #6292 -* Fix - update single column home screen width to 680px #6297 -* Fix - Update timing of InboxPanel state changes for the unread indicator #6246 -* Tweak - Enqueue beta features scripts on enqueue_scripts action instead of filter #6358 -* Tweak - Move admin menu manipulation from admin_head to admin_menu #6310 -* Tweak - Navigation: Migrate methods to `admin_menu` hook #6319 -* Tweak - New Settings: Turn off in dev mode #6348 -* Tweak - Order and styles updates to nav footer #6373 -* Tweak - Remove categories without menu items #6329 -* Tweak - Set international country feature flag off -* Tweak - Set `is_deleted` from the database when instantiating a `Note` #6322 -* Tweak - Update inline documentation for navigation Screen class #6173 -* Tweak - Updates to copy and punctuation to be more conversational and consistent. #6298 - -**WooCommerce Blocks - 4.5.0 & 4.6.0 & 4.7.0 & 4.7.1** - -* Enhancement - Login links on the checkout should use the account page. ([3844](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3844)) -* Enhancement - Prevent checkout linking to trashed terms and policy pages. ([3843](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3843)) -* Enhancement - Improved nonce logic by moving nonces to cart routes only. ([3812](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3812)) -* Enhancement - If coupons become invalid between applying to a cart and checking out, show the user a notice when the order is placed. ([3810](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3810)) -* Enhancement - Improve design of cart and checkout sidebars. ([3797](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3797)) -* Enhancement - Improve error displayed to customers when an item's stock status changes during checkout. ([3703](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3703)) -* Enhancement - Dev - Block Checkout will now respect custom address locales and custom country states via core filter hooks. ([3662](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3662)) -* Enhancement - Update checkout block payment methods UI. ([3439](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3439)) -* Enhancement - StoreAPI: Inject Order and Cart Controllers into Routes. ([3871](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3871)) -* Enhancement - Update Panel component class names to follow guidelines. More info can be found in our theming docs: https://github.com/woocommerce/woocommerce-gutenberg-products-block/blob/18dd54f07262b4d1dcf15561624617f824fcdc22/docs/theming/class-names-update-460.md. ([3860](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3860)) -* Enhancement - Refactor block type registration to support 3rd party integrations. -* Enhancement - A new configuration property is available to registered payment methods for additional logic handling of saved payment method tokens. ([3961](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3961)) -* Enhancement - Provided billing data to payment method extensions so they can decide if payment is possible. ([3922](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3922)) -* Enhancement - Prevent errant payment methods from keeping Cart and Checkout blocks from loading. ([3920](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3920)) -* Fix block elements that don't play well with dark backgrounds. ([3887](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3887)) -* Fix - JS warning if two cart products share the same name. ([3814](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3814)) -* Fix - Align place order button to the right of the block. ([3803](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3803)) -* Fix - Ensure special characters are displayed properly in the Cart sidebar. ([3721](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3721)) -* Fix - Bug where the total price of items did not include tax in the cart and checkout blocks. ([3851](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3851)) -* Fix - Handle out-of-stock product visibility setting in All Products block. ([3859](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3859)) -* Fix - Show cart item subtotal instead of total in Cart and Checkout blocks ([#3905](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3905)) -* Fix - Fix button styles in Twenty Nineteen theme. ([3862](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3862)) -* Fix - Return correct sale/regular prices for variable products in the Store API. ([3854](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3854)) -* Fix - Remove shadows from text buttons and gradient background from selects in some themes. ([3846](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3846)) -* Fix - Hide Browse Shop link in cart block empty state when there is no shop page. ([3845](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3845)) -* Fix - Remove extra padding from payment methods with no description. ([3952](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3952)) -* Fix - "save payment" checkbox not showing for payment methods. ([3950](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3950)) -* Fix - Cart preview when shipping rates are set to be hidden until an address is entered. ([3946](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3946)) -* Fix - Sync cart item quantity if its Implicitly changed. ([3907](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3907)) -* Fix - FSE not being visible when WC Blocks was enabled. ([3898](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3898)) -* Fix - Ensure sale badges have a uniform height in the Cart block. ([3897](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3897)) -* Note - Internally, this release has modified how `AbstractBlock` (the base class for all of our blocks) functions, and how it loads assets. `AbstractBlock` is internal to this project and does not seem like something that would ever need to be extended by 3rd parties, but note if you are doing so for whatever reason, your implementation would need to be updated to match. ([3829](https://github.com/woocommerce/woocommerce-gutenberg-products-block/pull/3829)) +* Fix - Show management links when the task list is complete (even if its not hidden). #6657 +* Fix - Adding New Zealand and Ireland to selective bundle option, previously missed. #6649 +* Fix - Update the Mercado option used for enabling/disabling. #6677 +* Fix - Improve AddFirstProduct email note contents. #6617 +* Fix - Check if features are currently being enabled #6688 +* Fix - Fix the activity panel toggle not closing on click #6679 +* Fix - Fix use of feature checks and remove deprecated method calls #6687 +* Fix - Allow the manager role to query certain options #6577 +* Fix - Delete customer data on network user deletion #6574 +* Fix - Fix Themes step visibility in IE 11 #6578 +* Fix - Fix hidden menu title on smaller screens #6562 +* Fix - Add gross sales column to CSV export #6567 +* Fix - Disable the continue btn on OBW when requested are being made #6838 +* Fix - Calling of get_script_asset_filename with extra parameter #6955 +* Fix - Address an issue with OBW when installing only WooCommerce payments and Jetpack. #6957 +* Tweak - Add default value for contains op #6622 +* Tweak - Adjust targeting store age for the Add First Product note #6554 +* Tweak - Improve WC Shipping & Tax logic #6547 +* Tweak - Update Insight inbox note content #6555 +* Tweak - Remove mobile activity panel toggle #6539 +* Tweak - Refactor autoloader to remove global variable. #6412 +* Tweak - Revert WCPay international support for bundled package #6901 +* Tweak - Store profiler - Changed MailPoet's title and description #6886 +* Tweak - Update PayU logo #6829 [See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce/trunk/changelog.txt). From 20b39bedac1cb5c7935cf056e904c79b8f214656 Mon Sep 17 00:00:00 2001 From: Menaka S Date: Tue, 11 May 2021 12:33:23 +0530 Subject: [PATCH 356/368] Restore direct SQL queries and functions from WC 5.0 --- includes/class-wc-tracker.php | 216 ++++++++++++++++------------------ 1 file changed, 103 insertions(+), 113 deletions(-) diff --git a/includes/class-wc-tracker.php b/includes/class-wc-tracker.php index 9b009e035ea..fcf9909e31c 100644 --- a/includes/class-wc-tracker.php +++ b/includes/class-wc-tracker.php @@ -355,122 +355,123 @@ class WC_Tracker { } /** - * Get all order data. + * Get order counts + * + * @return array + */ + private static function get_order_counts() { + $order_count = array(); + $order_count_data = wp_count_posts( 'shop_order' ); + foreach ( wc_get_order_statuses() as $status_slug => $status_name ) { + $order_count[ $status_slug ] = $order_count_data->{ $status_slug }; + } + return $order_count; + } + + /** + * Combine all order data. * * @return array */ private static function get_orders() { - $args = array( - 'type' => array( 'shop_order', 'shop_order_refund' ), - 'limit' => get_option( 'posts_per_page' ), - 'paged' => 1, + $order_dates = self::get_order_dates(); + $order_counts = self::get_order_counts(); + $order_totals = self::get_order_totals(); + + return array_merge( $order_dates, $order_counts, $order_totals ); + } + + /** + * Get order totals + * + * @return array + */ + public static function get_order_totals() { + global $wpdb; + + $gross_total = $wpdb->get_var( + " + SELECT + SUM( order_meta.meta_value ) AS 'gross_total' + FROM {$wpdb->prefix}posts AS orders + LEFT JOIN {$wpdb->prefix}postmeta AS order_meta ON order_meta.post_id = orders.ID + WHERE order_meta.meta_key = '_order_total' + AND orders.post_status in ( 'wc-completed', 'wc-refunded' ) + GROUP BY order_meta.meta_key + " ); - $first = time(); - $processing_first = $first; - $first_time = $first; - $last = 0; - $processing_last = 0; - $order_data = array(); - - $orders = wc_get_orders( $args ); - $orders_count = count( $orders ); - - while ( $orders_count ) { - - foreach ( $orders as $order ) { - - $date_created = (int) $order->get_date_created()->getTimestamp(); - $type = $order->get_type(); - $status = $order->get_status(); - - if ( 'shop_order' == $type ) { - - // Find the first and last order dates for completed and processing statuses. - if ( 'completed' == $status && $date_created < $first ) { - $first = $date_created; - } - if ( 'completed' == $status && $date_created > $last ) { - $last = $date_created; - } - if ( 'processing' == $status && $date_created < $processing_first ) { - $processing_first = $date_created; - } - if ( 'processing' == $status && $date_created > $processing_last ) { - $processing_last = $date_created; - } - - // Get order counts by status. - $status = 'wc-' . $status; - - if ( ! isset( $order_data[ $status ] ) ) { - $order_data[ $status ] = 1; - } else { - $order_data[ $status ] += 1; - } - - // Count number of orders by gateway used. - $gateway = $order->get_payment_method(); - - if ( ! empty( $gateway ) && in_array( $status, array( 'wc-completed', 'wc-refunded', 'wc-processing' ) ) ) { - $gateway = 'gateway_' . $gateway; - - if ( ! isset( $order_data[ $gateway ] ) ) { - $order_data[ $gateway ] = 1; - } else { - $order_data[ $gateway ] += 1; - } - } - } else { - // If it is a refunded order (shop_order_refunnd type), add the prefix as this prefix gets - // added midway in the if clause. - $status = 'wc-' . $status; - } - - // Calculate the gross total for 'completed' and 'processing' orders. - $total = $order->get_total(); - - if ( in_array( $status, array( 'wc-completed', 'wc-refunded' ) ) ) { - if ( ! isset( $order_data['gross'] ) ) { - $order_data['gross'] = $total; - } else { - $order_data['gross'] += $total; - } - } elseif ( 'wc-processing' == $status ) { - if ( ! isset( $order_data['processing_gross'] ) ) { - $order_data['processing_gross'] = $total; - } else { - $order_data['processing_gross'] += $total; - } - } - } - $args['paged']++; - - $orders = wc_get_orders( $args ); - $orders_count = count( $orders ); + if ( is_null( $gross_total ) ) { + $gross_total = 0; } - if ( $first !== $first_time ) { - $order_data['first'] = gmdate( 'Y-m-d H:i:s', $first ); + $processing_gross_total = $wpdb->get_var( + " + SELECT + SUM( order_meta.meta_value ) AS 'gross_total' + FROM {$wpdb->prefix}posts AS orders + LEFT JOIN {$wpdb->prefix}postmeta AS order_meta ON order_meta.post_id = orders.ID + WHERE order_meta.meta_key = '_order_total' + AND orders.post_status = 'wc-processing' + GROUP BY order_meta.meta_key + " + ); + + if ( is_null( $processing_gross_total ) ) { + $processing_gross_total = 0; } - if ( $processing_first !== $first_time ) { - $order_data['processing_first'] = gmdate( 'Y-m-d H:i:s', $processing_first ); + return array( + 'gross' => $gross_total, + 'processing_gross' => $processing_gross_total, + ); + } + + /** + * Get last order date + * + * @return string + */ + private static function get_order_dates() { + global $wpdb; + + $min_max = $wpdb->get_row( + " + SELECT + MIN( post_date_gmt ) as 'first', MAX( post_date_gmt ) as 'last' + FROM {$wpdb->prefix}posts + WHERE post_type = 'shop_order' + AND post_status = 'wc-completed' + ", + ARRAY_A + ); + + if ( is_null( $min_max ) ) { + $min_max = array( + 'first' => '-', + 'last' => '-', + ); } - if ( $last ) { - $order_data['last'] = gmdate( 'Y-m-d H:i:s', $last ); + $processing_min_max = $wpdb->get_row( + " + SELECT + MIN( post_date_gmt ) as 'processing_first', MAX( post_date_gmt ) as 'processing_last' + FROM {$wpdb->prefix}posts + WHERE post_type = 'shop_order' + AND post_status = 'wc-processing' + ", + ARRAY_A + ); + + if ( is_null( $processing_min_max ) ) { + $processing_min_max = array( + 'processing_first' => '-', + 'processing_last' => '-', + ); } - if ( $processing_last ) { - $order_data['processing_last'] = gmdate( 'Y-m-d H:i:s', $processing_last ); - } - - foreach ( $order_data as $key => $value ) { - $order_data[ $key ] = (string) $value; - } - - return $order_data; + return array_merge( $min_max, $processing_min_max ); } /** @@ -635,17 +636,6 @@ class WC_Tracker { return array_filter( (array) get_option( 'woocommerce_tracker_ua', array() ) ); } - /** - * Get order totals - * - * @deprecated 5.1.0 Logic moved to get_orders. - * @return array - */ - public static function get_order_totals() { - wc_deprecated_function( 'WC_Tracker::get_order_totals', '5.1.0', '' ); - return self::get_orders(); - } - /** * Search a specific post for text content. * From 5dfac89d80418ad30cf33734ff64e9cb090c9a1d Mon Sep 17 00:00:00 2001 From: Menaka S Date: Tue, 11 May 2021 17:51:42 +0530 Subject: [PATCH 357/368] Add function to get order details by gateway --- includes/class-wc-tracker.php | 53 ++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/includes/class-wc-tracker.php b/includes/class-wc-tracker.php index fcf9909e31c..4a958eeb9e9 100644 --- a/includes/class-wc-tracker.php +++ b/includes/class-wc-tracker.php @@ -374,11 +374,12 @@ class WC_Tracker { * @return array */ private static function get_orders() { - $order_dates = self::get_order_dates(); - $order_counts = self::get_order_counts(); - $order_totals = self::get_order_totals(); + $order_dates = self::get_order_dates(); + $order_counts = self::get_order_counts(); + $order_totals = self::get_order_totals(); + $order_gateways = self::get_orders_by_gateway(); - return array_merge( $order_dates, $order_counts, $order_totals ); + return array_merge( $order_dates, $order_counts, $order_totals, $order_gateways ); } /** @@ -474,6 +475,50 @@ class WC_Tracker { return array_merge( $min_max, $processing_min_max ); } + /** + * Get order details by gateway + * + * @return array + */ + public static function get_orders_by_gateway() { + global $wpdb; + + $orders_by_gateway = $wpdb->get_results( + " + SELECT + gateway, currency, SUM(total) AS totals, COUNT(order_id) AS counts + FROM ( + SELECT + orders.id AS order_id, + MAX(CASE WHEN meta_key = '_payment_method' THEN meta_value END) gateway, + MAX(CASE WHEN meta_key = '_order_total' THEN meta_value END) total, + MAX(CASE WHEN meta_key = '_order_currency' THEN meta_value END) currency + FROM + {$wpdb->prefix}posts orders + LEFT JOIN + {$wpdb->prefix}postmeta order_meta ON order_meta.post_id = orders.id + WHERE orders.post_type = 'shop_order' + AND orders.post_status in ( 'wc-completed', 'wc-processing', 'wc-refunded' ) + AND meta_key in( '_payment_method','_order_total','_order_currency') + GROUP BY orders.id + ) order_gateways + GROUP BY gateway, currency + " + ); + + foreach ( $orders_by_gateway as $orders_details ) { + $gateway = 'gateway_' . $orders_details->gateway; + $currency = $orders_details->currency; + $count = $gateway . '_' . $currency . '_count'; + $total = $gateway . '_' . $currency . '_total'; + + $orders_by_gateway_currency[ $count ] = $orders_details->counts; + $orders_by_gateway_currency[ $total ] = $orders_details->totals; + } + + return $orders_by_gateway_currency; + } + /** * Get review counts for different statuses. * From d13ce85b6641630443202f5737eda9c719b436ce Mon Sep 17 00:00:00 2001 From: Dan Wyman Date: Tue, 11 May 2021 12:33:18 -0700 Subject: [PATCH 358/368] Set default value for variable --- includes/class-wc-tracker.php | 1 + 1 file changed, 1 insertion(+) diff --git a/includes/class-wc-tracker.php b/includes/class-wc-tracker.php index 4a958eeb9e9..71ecf606ac0 100644 --- a/includes/class-wc-tracker.php +++ b/includes/class-wc-tracker.php @@ -506,6 +506,7 @@ class WC_Tracker { " ); + $orders_by_gateway_currency = array(); foreach ( $orders_by_gateway as $orders_details ) { $gateway = 'gateway_' . $orders_details->gateway; $currency = $orders_details->currency; From ffd6bd416304150aa7a418183e5d6b2c692639ea Mon Sep 17 00:00:00 2001 From: Menaka S Date: Wed, 12 May 2021 06:43:36 +0530 Subject: [PATCH 359/368] Make the new function private --- includes/class-wc-tracker.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-tracker.php b/includes/class-wc-tracker.php index 71ecf606ac0..775db09022f 100644 --- a/includes/class-wc-tracker.php +++ b/includes/class-wc-tracker.php @@ -480,7 +480,7 @@ class WC_Tracker { * * @return array */ - public static function get_orders_by_gateway() { + private static function get_orders_by_gateway() { global $wpdb; $orders_by_gateway = $wpdb->get_results( From e20223f63e32cc6c01fdeddddd12fe0989f66dae Mon Sep 17 00:00:00 2001 From: Menaka S Date: Wed, 12 May 2021 06:45:43 +0530 Subject: [PATCH 360/368] Make the restored function private --- includes/class-wc-tracker.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/includes/class-wc-tracker.php b/includes/class-wc-tracker.php index 775db09022f..179686c9abd 100644 --- a/includes/class-wc-tracker.php +++ b/includes/class-wc-tracker.php @@ -385,9 +385,10 @@ class WC_Tracker { /** * Get order totals * + * @since 5.4.0 * @return array */ - public static function get_order_totals() { + private static function get_order_totals() { global $wpdb; $gross_total = $wpdb->get_var( From de331ad8935d01eafc910d84fc4464469cfd1dac Mon Sep 17 00:00:00 2001 From: And Finally Date: Wed, 12 May 2021 09:41:31 +0100 Subject: [PATCH 361/368] Addressing feedback. Removed `!important` from `.addons-button-expandable` rule. Renamed `geowhitelist` and `geoblacklist` to `geo_allow_list` and `geo_block_list`. --- assets/css/admin.scss | 2 +- includes/admin/class-wc-admin-addons.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/css/admin.scss b/assets/css/admin.scss index 35bc0dc12e3..6ea357b8e2a 100644 --- a/assets/css/admin.scss +++ b/assets/css/admin.scss @@ -404,7 +404,7 @@ .addons-button-expandable { display: inline-block; padding: 0 16px; - width: auto !important; + width: auto; } .addons-button-solid:hover { diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index e90ac2ad9a8..fafe07d5ce7 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -549,8 +549,8 @@ class WC_Admin_Addons { $section_object = (object) $section; - if ( ! empty( $section_object->geowhitelist ) ) { - $section_object->geowhitelist = explode( ',', $section_object->geowhitelist ); + if ( ! empty( $section_object->geo_allow_list ) ) { + $section_object->geo_allow_list = explode( ',', $section_object->geo_allow_list ); } if ( ! self::show_extension( $section_object ) ) { @@ -788,11 +788,11 @@ class WC_Admin_Addons { */ public static function show_extension( $item ) { $location = WC()->countries->get_base_country(); - if ( isset( $item->geowhitelist ) && ! in_array( $location, $item->geowhitelist, true ) ) { + if ( isset( $item->geo_allow_list ) && ! in_array( $location, $item->geo_allow_list, true ) ) { return false; } - if ( isset( $item->geoblacklist ) && in_array( $location, $item->geoblacklist, true ) ) { + if ( isset( $item->geo_block_list ) && in_array( $location, $item->geo_block_list, true ) ) { return false; } From e086c82b68bdf580e2525bc67b4610ee374dfb40 Mon Sep 17 00:00:00 2001 From: Leif Singer Date: Wed, 12 May 2021 11:06:13 +0200 Subject: [PATCH 362/368] Bump node version to align with v12 used in .nvmrc --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 051360c8dcc..00559ae31f1 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "wp-textdomain": "1.0.1" }, "engines": { - "node": "^10.22.0", + "node": "^12.20.1", "npm": "^6.14.6" }, "husky": { From 6bb1ec73a4757cf38ddb1893a06515ccb6263b57 Mon Sep 17 00:00:00 2001 From: And Finally Date: Wed, 12 May 2021 17:48:37 +0100 Subject: [PATCH 363/368] Reverted renaming of `geowhitelist` and `geoblacklist`, in case they are still present in other endpoints. --- includes/admin/class-wc-admin-addons.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index fafe07d5ce7..e90ac2ad9a8 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -549,8 +549,8 @@ class WC_Admin_Addons { $section_object = (object) $section; - if ( ! empty( $section_object->geo_allow_list ) ) { - $section_object->geo_allow_list = explode( ',', $section_object->geo_allow_list ); + if ( ! empty( $section_object->geowhitelist ) ) { + $section_object->geowhitelist = explode( ',', $section_object->geowhitelist ); } if ( ! self::show_extension( $section_object ) ) { @@ -788,11 +788,11 @@ class WC_Admin_Addons { */ public static function show_extension( $item ) { $location = WC()->countries->get_base_country(); - if ( isset( $item->geo_allow_list ) && ! in_array( $location, $item->geo_allow_list, true ) ) { + if ( isset( $item->geowhitelist ) && ! in_array( $location, $item->geowhitelist, true ) ) { return false; } - if ( isset( $item->geo_block_list ) && in_array( $location, $item->geo_block_list, true ) ) { + if ( isset( $item->geoblacklist ) && in_array( $location, $item->geoblacklist, true ) ) { return false; } From 7202f19631e474d1adc93d83acc1499bab0b6b3d Mon Sep 17 00:00:00 2001 From: And Finally Date: Wed, 12 May 2021 17:54:20 +0100 Subject: [PATCH 364/368] Added support for `geoblacklist` in `output_promotion_block`. --- includes/admin/class-wc-admin-addons.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index e90ac2ad9a8..ff33de129e0 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -553,6 +553,10 @@ class WC_Admin_Addons { $section_object->geowhitelist = explode( ',', $section_object->geowhitelist ); } + if ( ! empty( $section_object->geoblacklist ) ) { + $section_object->geoblacklist = explode( ',', $section_object->geoblacklist ); + } + if ( ! self::show_extension( $section_object ) ) { return; } From 721fee7064be9cb7f478e43ce1863682045457fc Mon Sep 17 00:00:00 2001 From: Dan Wyman Date: Wed, 12 May 2021 14:23:07 -0700 Subject: [PATCH 365/368] Add periods to comments. --- includes/class-wc-tracker.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/includes/class-wc-tracker.php b/includes/class-wc-tracker.php index 179686c9abd..582a2210d19 100644 --- a/includes/class-wc-tracker.php +++ b/includes/class-wc-tracker.php @@ -355,7 +355,7 @@ class WC_Tracker { } /** - * Get order counts + * Get order counts. * * @return array */ @@ -383,7 +383,7 @@ class WC_Tracker { } /** - * Get order totals + * Get order totals. * * @since 5.4.0 * @return array @@ -430,7 +430,7 @@ class WC_Tracker { } /** - * Get last order date + * Get last order date. * * @return string */ @@ -477,7 +477,7 @@ class WC_Tracker { } /** - * Get order details by gateway + * Get order details by gateway. * * @return array */ From 7806ea2b5d25c9ce02511d1db143aadea79ea54d Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Thu, 13 May 2021 09:25:14 -0300 Subject: [PATCH 366/368] update remove stale on comment (#29882) * remove the stale label when feedback is provided * remove labels in separate steps --- .github/workflows/update-feedback-labels.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/update-feedback-labels.yml b/.github/workflows/update-feedback-labels.yml index 2c311f0195a..bb0af46f64b 100644 --- a/.github/workflows/update-feedback-labels.yml +++ b/.github/workflows/update-feedback-labels.yml @@ -15,10 +15,13 @@ jobs: with: github_token: ${{ secrets.GITHUB_TOKEN }} labels: 'has feedback' - - name: remove needs feedback, stale + - name: remove needs feedback uses: actions-ecosystem/action-remove-labels@v1 with: github_token: ${{ secrets.GITHUB_TOKEN }} - labels: | - 'needs feedback' - 'Stale' + labels: 'needs feedback' + - name: remove stale + uses: actions-ecosystem/action-remove-labels@v1 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + labels: Stale From 2a86d2b2ab572bc0d3caad4056ba5f81a33589ab Mon Sep 17 00:00:00 2001 From: Ron Rennick Date: Thu, 13 May 2021 16:06:28 -0300 Subject: [PATCH 367/368] update api package readme & changelog to prep for release --- tests/e2e/api/CHANGELOG.md | 9 ++++++++- tests/e2e/api/README.md | 18 +++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/tests/e2e/api/CHANGELOG.md b/tests/e2e/api/CHANGELOG.md index a2c57debaf4..605741512f5 100644 --- a/tests/e2e/api/CHANGELOG.md +++ b/tests/e2e/api/CHANGELOG.md @@ -1,5 +1,12 @@ # Unreleased +## Added + +- Support for orders. + +## Changed + +- `delete()` now deletes products and coupons instead of moving to `trash`. # 0.1.2 @@ -14,7 +21,7 @@ ## Breaking Changes -- The `HTTPClientFactory` API was changed to make it easier to configure instances with +- The `HTTPClientFactory` API was changed to make it easier to configure instances ## Added diff --git a/tests/e2e/api/README.md b/tests/e2e/api/README.md index 7eadd2d5de1..21398557049 100644 --- a/tests/e2e/api/README.md +++ b/tests/e2e/api/README.md @@ -6,7 +6,7 @@ features: - [x] TypeScript Definitions - [x] Axios API Client with support for OAuth & basic auth - [x] Repositories to simplify interaction with basic data types -- [ ] Service classes for common activities such as changing settings +- [x] Service classes for common activities such as changing settings ## Usage @@ -51,12 +51,20 @@ httpClient.get( '/wc/v3/products' ).then( ( response ) => { As a convenience utility we've created repositories for core data types that can simplify interacting with the API: +#### Parent/Base Repositories + - `SimpleProduct` - `ExternalProduct` - `GroupedProduct` - `VariableProduct` -- `ProductVariation` - `Coupon` +- `Order` +- `SettingsGroup` + +#### Child Repositories + +- `ProductVariation` +- `Setting` These repositories provide CRUD methods for ease-of-use: @@ -80,7 +88,7 @@ product.id; #### Repository Methods -The following methods are available on all repositories: +The following methods are available on all repositories if the corresponding method is available on the API endpoint: - `create( {...properties} )` - Create a single object of the model type - `delete( objectId )` - Delete a single object of the model type @@ -90,14 +98,14 @@ The following methods are available on all repositories: #### Child Repositories -`ProductVariation` is a child model repository. In child model repositories, each method requires the `parentId` as the first parameter: +In child model repositories, each method requires the `parentId` as the first parameter: ```javascript import { HTTPClientFactory, VariableProduct, ProductVariation } from '@woocommerce/api'; const httpClient = HTTPClientFactory.build( 'https://example.com' ) .withBasicAuth( 'username', 'password' ) - .withIndexPermalinks() + .withIndexPermalinks() .create(); const productRepository = VariableProduct.restRepository( httpClient ); From 771548f852e606cd48defdd3c0b0b8bca8cf4fa3 Mon Sep 17 00:00:00 2001 From: Timmy Crawford Date: Wed, 12 May 2021 08:47:08 -0700 Subject: [PATCH 368/368] Update woocommerce-admin package to 2.3.0 --- bin/composer/mozart/composer.lock | 52 +++++++++++------------ bin/composer/phpcs/composer.lock | 10 ++--- bin/composer/wp/composer.lock | 70 ++++++++++++++++++------------- composer.json | 2 +- composer.lock | 19 +++++---- 5 files changed, 84 insertions(+), 69 deletions(-) diff --git a/bin/composer/mozart/composer.lock b/bin/composer/mozart/composer.lock index 6e9a52a1179..81ac1cea0fc 100644 --- a/bin/composer/mozart/composer.lock +++ b/bin/composer/mozart/composer.lock @@ -267,16 +267,16 @@ }, { "name": "symfony/console", - "version": "v5.2.6", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d" + "reference": "864568fdc0208b3eba3638b6000b69d2386e6768" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/35f039df40a3b335ebf310f244cb242b3a83ac8d", - "reference": "35f039df40a3b335ebf310f244cb242b3a83ac8d", + "url": "https://api.github.com/repos/symfony/console/zipball/864568fdc0208b3eba3638b6000b69d2386e6768", + "reference": "864568fdc0208b3eba3638b6000b69d2386e6768", "shasum": "" }, "require": { @@ -344,7 +344,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.2.6" + "source": "https://github.com/symfony/console/tree/v5.2.8" }, "funding": [ { @@ -360,20 +360,20 @@ "type": "tidelift" } ], - "time": "2021-03-28T09:42:18+00:00" + "time": "2021-05-11T15:45:21+00:00" }, { "name": "symfony/finder", - "version": "v5.2.4", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "0d639a0943822626290d169965804f79400e6a04" + "reference": "eccb8be70d7a6a2230d05f6ecede40f3fdd9e252" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/0d639a0943822626290d169965804f79400e6a04", - "reference": "0d639a0943822626290d169965804f79400e6a04", + "url": "https://api.github.com/repos/symfony/finder/zipball/eccb8be70d7a6a2230d05f6ecede40f3fdd9e252", + "reference": "eccb8be70d7a6a2230d05f6ecede40f3fdd9e252", "shasum": "" }, "require": { @@ -405,7 +405,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.2.4" + "source": "https://github.com/symfony/finder/tree/v5.2.8" }, "funding": [ { @@ -421,7 +421,7 @@ "type": "tidelift" } ], - "time": "2021-02-15T18:55:04+00:00" + "time": "2021-05-10T14:39:23+00:00" }, { "name": "symfony/polyfill-ctype", @@ -911,21 +911,21 @@ }, { "name": "symfony/service-contracts", - "version": "v2.2.0", + "version": "v2.4.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1" + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d15da7ba4957ffb8f1747218be9e1a121fd298a1", - "reference": "d15da7ba4957ffb8f1747218be9e1a121fd298a1", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", + "reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb", "shasum": "" }, "require": { "php": ">=7.2.5", - "psr/container": "^1.0" + "psr/container": "^1.1" }, "suggest": { "symfony/service-implementation": "" @@ -933,7 +933,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-main": "2.4-dev" }, "thanks": { "name": "symfony/contracts", @@ -970,7 +970,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/master" + "source": "https://github.com/symfony/service-contracts/tree/v2.4.0" }, "funding": [ { @@ -986,20 +986,20 @@ "type": "tidelift" } ], - "time": "2020-09-07T11:33:47+00:00" + "time": "2021-04-01T10:43:52+00:00" }, { "name": "symfony/string", - "version": "v5.2.6", + "version": "v5.2.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572" + "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", - "reference": "ad0bd91bce2054103f5eaa18ebeba8d3bc2a0572", + "url": "https://api.github.com/repos/symfony/string/zipball/01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", + "reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db", "shasum": "" }, "require": { @@ -1053,7 +1053,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.2.6" + "source": "https://github.com/symfony/string/tree/v5.2.8" }, "funding": [ { @@ -1069,7 +1069,7 @@ "type": "tidelift" } ], - "time": "2021-03-17T17:12:15+00:00" + "time": "2021-05-10T14:56:10+00:00" } ], "aliases": [], diff --git a/bin/composer/phpcs/composer.lock b/bin/composer/phpcs/composer.lock index d784a60a0a0..e0653d55467 100644 --- a/bin/composer/phpcs/composer.lock +++ b/bin/composer/phpcs/composer.lock @@ -251,16 +251,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.5.8", + "version": "3.6.0", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4" + "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/9d583721a7157ee997f235f327de038e7ea6dac4", - "reference": "9d583721a7157ee997f235f327de038e7ea6dac4", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ffced0d2c8fa8e6cdc4d695a743271fab6c38625", + "reference": "ffced0d2c8fa8e6cdc4d695a743271fab6c38625", "shasum": "" }, "require": { @@ -303,7 +303,7 @@ "source": "https://github.com/squizlabs/PHP_CodeSniffer", "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" }, - "time": "2020-10-23T02:01:07+00:00" + "time": "2021-04-09T00:54:41+00:00" }, { "name": "woocommerce/woocommerce-sniffs", diff --git a/bin/composer/wp/composer.lock b/bin/composer/wp/composer.lock index 8fb33475e13..3532eb3520e 100644 --- a/bin/composer/wp/composer.lock +++ b/bin/composer/wp/composer.lock @@ -254,23 +254,30 @@ }, { "name": "rmccue/requests", - "version": "v1.7.0", + "version": "v1.8.0", "source": { "type": "git", - "url": "https://github.com/rmccue/Requests.git", - "reference": "87932f52ffad70504d93f04f15690cf16a089546" + "url": "https://github.com/WordPress/Requests.git", + "reference": "afbe4790e4def03581c4a0963a1e8aa01f6030f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rmccue/Requests/zipball/87932f52ffad70504d93f04f15690cf16a089546", - "reference": "87932f52ffad70504d93f04f15690cf16a089546", + "url": "https://api.github.com/repos/WordPress/Requests/zipball/afbe4790e4def03581c4a0963a1e8aa01f6030f1", + "reference": "afbe4790e4def03581c4a0963a1e8aa01f6030f1", "shasum": "" }, "require": { "php": ">=5.2" }, "require-dev": { - "requests/test-server": "dev-master" + "dealerdirect/phpcodesniffer-composer-installer": "^0.7", + "php-parallel-lint/php-console-highlighter": "^0.5.0", + "php-parallel-lint/php-parallel-lint": "^1.3", + "phpcompatibility/php-compatibility": "^9.0", + "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5", + "requests/test-server": "dev-master", + "squizlabs/php_codesniffer": "^3.5", + "wp-coding-standards/wpcs": "^2.0" }, "type": "library", "autoload": { @@ -289,7 +296,7 @@ } ], "description": "A HTTP library written in PHP, for human beings.", - "homepage": "http://github.com/rmccue/Requests", + "homepage": "http://github.com/WordPress/Requests", "keywords": [ "curl", "fsockopen", @@ -300,10 +307,10 @@ "sockets" ], "support": { - "issues": "https://github.com/rmccue/Requests/issues", - "source": "https://github.com/rmccue/Requests/tree/master" + "issues": "https://github.com/WordPress/Requests/issues", + "source": "https://github.com/WordPress/Requests/tree/v1.8.0" }, - "time": "2016-10-13T00:11:37+00:00" + "time": "2021-04-27T11:05:25+00:00" }, { "name": "symfony/finder", @@ -359,26 +366,26 @@ }, { "name": "wp-cli/i18n-command", - "version": "v2.2.6", + "version": "v2.2.8", "source": { "type": "git", "url": "https://github.com/wp-cli/i18n-command.git", - "reference": "a66da3f09f6a728832381012848c3074bf1635c8" + "reference": "8bc234617edc533590ac0f41080164a8d85ec9ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/a66da3f09f6a728832381012848c3074bf1635c8", - "reference": "a66da3f09f6a728832381012848c3074bf1635c8", + "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/8bc234617edc533590ac0f41080164a8d85ec9ce", + "reference": "8bc234617edc533590ac0f41080164a8d85ec9ce", "shasum": "" }, "require": { "gettext/gettext": "^4.8", "mck89/peast": "^1.8", - "wp-cli/wp-cli": "^2" + "wp-cli/wp-cli": "^2.5" }, "require-dev": { "wp-cli/scaffold-command": "^1.2 || ^2", - "wp-cli/wp-cli-tests": "^2.1.3" + "wp-cli/wp-cli-tests": "^3.0.11" }, "type": "wp-cli-package", "extra": { @@ -414,9 +421,9 @@ "homepage": "https://github.com/wp-cli/i18n-command", "support": { "issues": "https://github.com/wp-cli/i18n-command/issues", - "source": "https://github.com/wp-cli/i18n-command/tree/v2.2.6" + "source": "https://github.com/wp-cli/i18n-command/tree/v2.2.8" }, - "time": "2020-12-07T19:28:27+00:00" + "time": "2021-05-10T10:24:16+00:00" }, { "name": "wp-cli/mustangostang-spyc", @@ -525,23 +532,23 @@ }, { "name": "wp-cli/wp-cli", - "version": "v2.4.1", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/wp-cli/wp-cli.git", - "reference": "ceb18598e79befa9b2a37a51efbb34910628988b" + "reference": "4c4746d06640af7698f3792cc4c327a8482dc40f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/ceb18598e79befa9b2a37a51efbb34910628988b", - "reference": "ceb18598e79befa9b2a37a51efbb34910628988b", + "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/4c4746d06640af7698f3792cc4c327a8482dc40f", + "reference": "4c4746d06640af7698f3792cc4c327a8482dc40f", "shasum": "" }, "require": { "ext-curl": "*", "mustache/mustache": "~2.13", - "php": "^5.4 || ^7.0", - "rmccue/requests": "~1.6", + "php": "^5.6 || ^7.0 || ^8.0", + "rmccue/requests": "^1.8", "symfony/finder": ">2.7", "wp-cli/mustangostang-spyc": "^0.6.3", "wp-cli/php-cli-tools": "~0.11.2" @@ -552,12 +559,13 @@ "wp-cli/entity-command": "^1.2 || ^2", "wp-cli/extension-command": "^1.1 || ^2", "wp-cli/package-command": "^1 || ^2", - "wp-cli/wp-cli-tests": "^2.1" + "wp-cli/wp-cli-tests": "^3.0.7" }, "suggest": { "ext-readline": "Include for a better --prompt implementation", "ext-zip": "Needed to support extraction of ZIP archives when doing downloads or updates" }, + "default-branch": true, "bin": [ "bin/wp", "bin/wp.bat" @@ -565,13 +573,17 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4.x-dev" + "dev-master": "2.5.x-dev" } }, "autoload": { "psr-0": { - "WP_CLI": "php" - } + "WP_CLI\\": "php/" + }, + "classmap": [ + "php/class-wp-cli.php", + "php/class-wp-cli-command.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -588,7 +600,7 @@ "issues": "https://github.com/wp-cli/wp-cli/issues", "source": "https://github.com/wp-cli/wp-cli" }, - "time": "2020-02-18T08:15:37+00:00" + "time": "2021-05-13T09:36:33+00:00" } ], "aliases": [], diff --git a/composer.json b/composer.json index 6346176de2a..34a1dc6a246 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "pelago/emogrifier": "3.1.0", "psr/container": "1.0.0", "woocommerce/action-scheduler": "3.1.6", - "woocommerce/woocommerce-admin": "2.2.6", + "woocommerce/woocommerce-admin": "2.3.0", "woocommerce/woocommerce-blocks": "5.1.0" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 16af2df5a8d..966a06ec993 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3f82e5bd9e485ba6bcd94111391f6f11", + "content-hash": "ac338dadb8929c73ad9606426621f9ba", "packages": [ { "name": "automattic/jetpack-autoloader", @@ -532,16 +532,16 @@ }, { "name": "woocommerce/woocommerce-admin", - "version": "2.2.6", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/woocommerce/woocommerce-admin.git", - "reference": "65c5a4d0b0c3a7c7457e250c9ba1f7c15cac6cb8" + "reference": "c690969d301ddb7145b43e72e4dd99c84cc8ba66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/65c5a4d0b0c3a7c7457e250c9ba1f7c15cac6cb8", - "reference": "65c5a4d0b0c3a7c7457e250c9ba1f7c15cac6cb8", + "url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/c690969d301ddb7145b43e72e4dd99c84cc8ba66", + "reference": "c690969d301ddb7145b43e72e4dd99c84cc8ba66", "shasum": "" }, "require": { @@ -550,7 +550,7 @@ "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "7.5.20", + "bamarni/composer-bin-plugin": "^1.4", "suin/phpcs-psr4-sniff": "^2.2", "woocommerce/woocommerce-sniffs": "0.1.0" }, @@ -560,6 +560,9 @@ "test": "Run unit tests", "phpcs": "Analyze code against the WordPress coding standards with PHP_CodeSniffer", "phpcbf": "Fix coding standards warnings/errors automatically with PHP Code Beautifier" + }, + "bamarni-bin": { + "target-directory": "bin/composer" } }, "autoload": { @@ -575,9 +578,9 @@ "homepage": "https://github.com/woocommerce/woocommerce-admin", "support": { "issues": "https://github.com/woocommerce/woocommerce-admin/issues", - "source": "https://github.com/woocommerce/woocommerce-admin/tree/v2.2.6" + "source": "https://github.com/woocommerce/woocommerce-admin/tree/v2.3.0" }, - "time": "2021-05-07T21:29:02+00:00" + "time": "2021-05-12T15:20:07+00:00" }, { "name": "woocommerce/woocommerce-blocks",