From 5c110acd4a20f1da0aa3c7d49a07dea9c8e911b4 Mon Sep 17 00:00:00 2001 From: Veljko Date: Thu, 28 Oct 2021 13:52:12 +0200 Subject: [PATCH 01/91] Add performance orders search --- .../requests/merchant/orders-search.js | 48 +++++++++++++++++++ .../example-all-requests-arrival-rate.js | 2 + .../tests/example-all-requests-ramping-vus.js | 2 + .../tests/simple-all-merchant-requests.js | 2 + 4 files changed, 54 insertions(+) create mode 100644 plugins/woocommerce/tests/performance/requests/merchant/orders-search.js diff --git a/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js b/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js new file mode 100644 index 00000000000..b5a75d1da6b --- /dev/null +++ b/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js @@ -0,0 +1,48 @@ +import { sleep, check, group } from "k6"; +import http from "k6/http"; +import { Trend } from "k6/metrics"; +import { randomIntBetween } from "https://jslib.k6.io/k6-utils/1.1.0/index.js"; +import { base_url, think_time_min, think_time_max } from "../../config.js"; +import { + htmlRequestHeader, + commonRequestHeaders, + commonGetRequestHeaders, + commonNonStandardHeaders, +} from "../../headers.js"; + +// Custom metrics to add to standard results output. +let postTypeOrderSearchTrend = new Trend("wc_get_post_type_order_search"); + +export function ordersSearch() { + let response; + + group("Orders Search", function () { + var requestHeaders = Object.assign({}, + htmlRequestHeader, + commonRequestHeaders, + commonGetRequestHeaders, + commonNonStandardHeaders + ); + + response = http.get( + `${base_url}/wp-admin/edit.php?s&` + + `post_status=all&post_type=shop_order&action=-1&m=0&_customer_user&` + + `paged=1&action2=-1`, + { + headers: requestHeaders, + } + ); + postTypeOrderSearchTrend.add(response.timings.duration); + check(response, { + "is status 200": (r) => r.status === 200, + "body contains: 'Orders' header": (response) => + response.body.includes("Orders"), + }); + }); + + sleep(randomIntBetween(`${think_time_min}`, `${think_time_max}`)); +} + +export default function () { + ordersSearch(); +} diff --git a/plugins/woocommerce/tests/performance/tests/example-all-requests-arrival-rate.js b/plugins/woocommerce/tests/performance/tests/example-all-requests-arrival-rate.js index 1fd9716c9bc..b1c4318f54a 100644 --- a/plugins/woocommerce/tests/performance/tests/example-all-requests-arrival-rate.js +++ b/plugins/woocommerce/tests/performance/tests/example-all-requests-arrival-rate.js @@ -13,6 +13,7 @@ import { products } from '../requests/merchant/products.js'; import { addProduct } from '../requests/merchant/add-product.js'; import { orders } from '../requests/merchant/orders.js'; import { ordersHeartbeat } from '../requests/merchant/orders-heartbeat.js'; +import { ordersSearch } from '../requests/merchant/orders-search.js'; import { homeWCAdmin } from '../requests/merchant/home-wc-admin.js'; import { myAccountMerchantLogin } from '../requests/merchant/my-account-merchant.js'; @@ -106,6 +107,7 @@ export function merchantAllFlows() { myAccountMerchantLogin(); homeWCAdmin(); orders(); + ordersSearch(); products(); addProduct(); } diff --git a/plugins/woocommerce/tests/performance/tests/example-all-requests-ramping-vus.js b/plugins/woocommerce/tests/performance/tests/example-all-requests-ramping-vus.js index 470458b809e..3300a468b36 100644 --- a/plugins/woocommerce/tests/performance/tests/example-all-requests-ramping-vus.js +++ b/plugins/woocommerce/tests/performance/tests/example-all-requests-ramping-vus.js @@ -13,6 +13,7 @@ import { products } from '../requests/merchant/products.js'; import { addProduct } from '../requests/merchant/add-product.js'; import { orders } from '../requests/merchant/orders.js'; import { ordersHeartbeat } from '../requests/merchant/orders-heartbeat.js'; +import { ordersSearch } from '../requests/merchant/orders-search.js'; import { homeWCAdmin } from '../requests/merchant/home-wc-admin.js'; import { myAccountMerchantLogin } from '../requests/merchant/my-account-merchant.js'; @@ -96,6 +97,7 @@ export function merchantAllFlows() { myAccountMerchantLogin(); homeWCAdmin(); orders(); + ordersSearch(); products(); addProduct(); } diff --git a/plugins/woocommerce/tests/performance/tests/simple-all-merchant-requests.js b/plugins/woocommerce/tests/performance/tests/simple-all-merchant-requests.js index dd277cc8d57..473387ab0fe 100644 --- a/plugins/woocommerce/tests/performance/tests/simple-all-merchant-requests.js +++ b/plugins/woocommerce/tests/performance/tests/simple-all-merchant-requests.js @@ -2,6 +2,7 @@ import { wpLogin } from '../requests/merchant/wp-login.js'; import { products } from '../requests/merchant/products.js'; import { addProduct } from '../requests/merchant/add-product.js'; import { orders } from '../requests/merchant/orders.js'; +import { ordersSearch } from '../requests/merchant/orders-search.js'; import { homeWCAdmin } from '../requests/merchant/home-wc-admin.js'; import { myAccountMerchantLogin } from '../requests/merchant/my-account-merchant.js'; @@ -22,6 +23,7 @@ export function allMerchantFlow() { wpLogin(); homeWCAdmin(); orders(); + ordersSearch(); products(); addProduct(); } From 55e1fadd3d5cdea3bb56df4c8b7a27c56a7ee394 Mon Sep 17 00:00:00 2001 From: Carl Alexander Date: Sun, 21 Nov 2021 14:35:58 -0500 Subject: [PATCH 02/91] Add `file` to check import file path hooks --- .../importers/class-wc-product-csv-importer-controller.php | 2 +- plugins/woocommerce/includes/wc-conditional-functions.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/woocommerce/includes/admin/importers/class-wc-product-csv-importer-controller.php b/plugins/woocommerce/includes/admin/importers/class-wc-product-csv-importer-controller.php index b14ad20f453..d22dd430441 100644 --- a/plugins/woocommerce/includes/admin/importers/class-wc-product-csv-importer-controller.php +++ b/plugins/woocommerce/includes/admin/importers/class-wc-product-csv-importer-controller.php @@ -92,7 +92,7 @@ class WC_Product_CSV_Importer_Controller { * @return bool */ public static function is_file_valid_csv( $file, $check_path = true ) { - if ( $check_path && apply_filters( 'woocommerce_product_csv_importer_check_import_file_path', true ) && false !== stripos( $file, '://' ) ) { + if ( $check_path && apply_filters( 'woocommerce_product_csv_importer_check_import_file_path', true, $file ) && false !== stripos( $file, '://' ) ) { return false; } diff --git a/plugins/woocommerce/includes/wc-conditional-functions.php b/plugins/woocommerce/includes/wc-conditional-functions.php index bdebe59dc48..f44ee86eac9 100644 --- a/plugins/woocommerce/includes/wc-conditional-functions.php +++ b/plugins/woocommerce/includes/wc-conditional-functions.php @@ -466,7 +466,7 @@ function wc_is_file_valid_csv( $file, $check_path = true ) { * @since 3.6.4 * @param bool $check_import_file_path If requires file path check. Defaults to true. */ - $check_import_file_path = apply_filters( 'woocommerce_csv_importer_check_import_file_path', true ); + $check_import_file_path = apply_filters( 'woocommerce_csv_importer_check_import_file_path', true, $file ); if ( $check_path && $check_import_file_path && false !== stripos( $file, '://' ) ) { return false; From b068ade7c61562e1d1ecba544aa7038e803a0dbc Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 19 Nov 2021 11:36:19 +0100 Subject: [PATCH 03/91] Create and activate product attributes lookup table in data migration Until now the product attributes lookup table had to be created and its usage had to be activated manually, via the tools page. This commit does the following: 1. Remove the tools to create and delete the table (but keeps the tool to regenerate the table data for one or for all the products) 2. Creates a data migration that triggers the table creation and filling (unless the table already existed) for Woo 6.1 3. After the migration finishes, activates the table usage for product filtering (site admin can still disable it via Settings - Products - Advanced) --- .../woocommerce/includes/class-wc-install.php | 12 ++- .../includes/wc-update-functions.php | 29 ++++++- .../DataRegenerator.php | 86 +++++-------------- .../DataRegeneratorTest.php | 4 +- .../LookupDataStoreTest.php | 2 - 5 files changed, 60 insertions(+), 73 deletions(-) diff --git a/plugins/woocommerce/includes/class-wc-install.php b/plugins/woocommerce/includes/class-wc-install.php index da64bb85fdd..62811c42081 100644 --- a/plugins/woocommerce/includes/class-wc-install.php +++ b/plugins/woocommerce/includes/class-wc-install.php @@ -169,6 +169,10 @@ class WC_Install { 'wc_update_600_migrate_rate_limit_options', 'wc_update_600_db_version', ), + '6.1.0' => array( + 'wc_create_product_attributes_lookup_table', + 'wc_update_610_db_version', + ), ); /** @@ -571,22 +575,22 @@ class WC_Install { $pages = apply_filters( 'woocommerce_create_pages', array( - 'shop' => array( + 'shop' => array( 'name' => _x( 'shop', 'Page slug', 'woocommerce' ), 'title' => _x( 'Shop', 'Page title', 'woocommerce' ), 'content' => '', ), - 'cart' => array( + 'cart' => array( 'name' => _x( 'cart', 'Page slug', 'woocommerce' ), 'title' => _x( 'Cart', 'Page title', 'woocommerce' ), 'content' => '[' . apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) . ']', ), - 'checkout' => array( + 'checkout' => array( 'name' => _x( 'checkout', 'Page slug', 'woocommerce' ), 'title' => _x( 'Checkout', 'Page title', 'woocommerce' ), 'content' => '[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']', ), - 'myaccount' => array( + 'myaccount' => array( 'name' => _x( 'my-account', 'Page slug', 'woocommerce' ), 'title' => _x( 'My account', 'Page title', 'woocommerce' ), 'content' => '[' . apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) . ']', diff --git a/plugins/woocommerce/includes/wc-update-functions.php b/plugins/woocommerce/includes/wc-update-functions.php index a845efd3a23..1a27c786f37 100644 --- a/plugins/woocommerce/includes/wc-update-functions.php +++ b/plugins/woocommerce/includes/wc-update-functions.php @@ -11,6 +11,8 @@ defined( 'ABSPATH' ) || exit; use Automattic\WooCommerce\Internal\AssignDefaultCategory; +use Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator; +use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore; /** * Update file paths for 2.0 @@ -2306,7 +2308,7 @@ function wc_update_560_db_version() { function wc_update_600_migrate_rate_limit_options() { global $wpdb; - $rate_limits = $wpdb->get_results( + $rate_limits = $wpdb->get_results( " SELECT option_name, option_value FROM $wpdb->options @@ -2335,3 +2337,28 @@ function wc_update_600_migrate_rate_limit_options() { function wc_update_600_db_version() { WC_Install::update_db_version( '6.0.0' ); } + +/** + * Create the product attributes lookup table and initiate its filling, + * unless the table had been already created manually (via the tools page). + * + * @return false Always false, since the LookupDataStore class handles all the data filling process. + */ +function wc_create_product_attributes_lookup_table() { + $data_store = wc_get_container()->get( LookupDataStore::class ); + if ( $data_store->check_lookup_table_exists() ) { + return false; + } + + $data_regenerator = wc_get_container()->get( DataRegenerator::class ); + $data_regenerator->initiate_regeneration(); + return false; +} + +/** + * + * Update DB version to 6.1.0. + */ +function wc_update_610_db_version() { + WC_Install::update_db_version( '6.1.0' ); +} diff --git a/plugins/woocommerce/src/Internal/ProductAttributesLookup/DataRegenerator.php b/plugins/woocommerce/src/Internal/ProductAttributesLookup/DataRegenerator.php index 5f06e5298fb..fca68226c66 100644 --- a/plugins/woocommerce/src/Internal/ProductAttributesLookup/DataRegenerator.php +++ b/plugins/woocommerce/src/Internal/ProductAttributesLookup/DataRegenerator.php @@ -21,7 +21,7 @@ defined( 'ABSPATH' ) || exit; * the data store classes) whenever a product is created/updated. * * Additionally, after the regeneration is completed a 'woocommerce_attribute_lookup_enabled' option - * with a value of 'no' will have been created. + * with a value of 'yes' will have been created, thus effectively enabling the table usage. * * This class also adds two entries to the Status - Tools menu: one for manually regenerating the table contents, * and another one for enabling or disabling the actual lookup table usage. @@ -84,14 +84,8 @@ class DataRegenerator { * deletes the lookup table and related options if they exist, * then it creates the table and runs the first step of the regeneration process. * - * This is the method that should be used as a callback for a data regeneration in wc-update-functions, e.g.: - * - * function wc_update_XX_regenerate_product_attributes_lookup_table() { - * wc_get_container()->get(DataRegenerator::class)->initiate_regeneration(); - * return false; - * } - * - * (Note how we are returning "false" since the class handles the step scheduling by itself). + * This method is intended ONLY to be used as a callback for a db update in wc-update-functions, + * regeneration triggered from the tools page will use initiate_regeneration_from_tools_page instead. */ public function initiate_regeneration() { $this->enable_or_disable_lookup_table_usage( false ); @@ -107,12 +101,8 @@ class DataRegenerator { /** * Delete all the existing data related to the lookup table, including the table itself. - * - * 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();" */ - public function delete_all_attributes_lookup_data() { + private function delete_all_attributes_lookup_data() { global $wpdb; delete_option( 'woocommerce_attribute_lookup_enabled' ); @@ -244,7 +234,7 @@ CREATE TABLE ' . $this->lookup_table_name . '( private function finalize_regeneration() { delete_option( 'woocommerce_attribute_lookup_last_product_id_to_process' ); delete_option( 'woocommerce_attribute_lookup_last_products_page_processed' ); - update_option( 'woocommerce_attribute_lookup_enabled', 'no' ); + update_option( 'woocommerce_attribute_lookup_enabled', 'yes' ); $this->data_store->unset_regeneration_in_progress_flag(); } @@ -255,42 +245,29 @@ 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 ) { - $lookup_table_exists = $this->data_store->check_lookup_table_exists(); - $generation_is_in_progress = $this->data_store->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 product(s) 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' ); + if ( ! $this->data_store->check_lookup_table_exists() ) { + return $tools_array; } - $entry = array( - 'name' => $generate_item_name, - 'desc' => $generate_item_desc, - 'requires_refresh' => true, - 'callback' => function() use ( $generate_item_return ) { - $this->initiate_regeneration_from_tools_page(); - return $generate_item_return; - }, - ); + $generation_is_in_progress = $this->data_store->regeneration_is_in_progress(); - if ( $lookup_table_exists ) { - $entry['selector'] = array( + $entry = array( + 'name' => __( 'Regenerate the product attributes lookup table', 'woocommerce' ), + 'desc' => __( 'This tool will regenerate the product attributes lookup table data from existing product(s) data. This process may take a while.', 'woocommerce' ), + 'requires_refresh' => true, + 'callback' => function() { + $this->initiate_regeneration_from_tools_page(); + return __( 'Product attributes lookup table data is regenerating', 'woocommerce' ); + + }, + 'selector' => array( 'description' => __( 'Select a product to regenerate the data for, or leave empty for a full table regeneration:', 'woocommerce' ), 'class' => 'wc-product-search', 'search_action' => 'woocommerce_json_search_products', 'name' => 'regenerate_product_attribute_lookup_data_product_id', 'placeholder' => esc_attr__( 'Search for a product…', 'woocommerce' ), - ); - } + ), + ); if ( $generation_is_in_progress ) { $entry['button'] = sprintf( @@ -300,31 +277,12 @@ CREATE TABLE ' . $this->lookup_table_name . '( ); $entry['disabled'] = true; } else { - $entry['button'] = $generate_item_button; + $entry['button'] = __( 'Regenerate', 'woocommerce' ); + } $tools_array['regenerate_product_attributes_lookup_table'] = $entry; - if ( $lookup_table_exists ) { - - // 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->delete_all_attributes_lookup_data(); - return __( 'Product attributes lookup table has been deleted.', 'woocommerce' ); - }, - ); - } - return $tools_array; } diff --git a/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php b/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php index 2a4ccfce1f3..ee9ff63ce8d 100644 --- a/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php +++ b/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/DataRegeneratorTest.php @@ -157,7 +157,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->assertEquals( 'yes', get_option( 'woocommerce_attribute_lookup_enabled' ) ); $this->assertEmpty( $this->queue->get_methods_called() ); } @@ -238,7 +238,7 @@ class DataRegeneratorTest extends \WC_Unit_Test_Case { $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->assertEquals( 'yes', get_option( 'woocommerce_attribute_lookup_enabled' ) ); $this->assertEmpty( $this->queue->get_methods_called() ); } } diff --git a/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php b/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php index daf91d68c61..3b124f31645 100644 --- a/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php +++ b/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/LookupDataStoreTest.php @@ -9,7 +9,6 @@ use Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator; use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore; use Automattic\WooCommerce\Testing\Tools\FakeQueue; use Automattic\WooCommerce\Utilities\ArrayUtil; -use Automattic\WooCommerce\Testing\Tools\CodeHacking\Hacks\FunctionsMockerHack; /** * Tests for the LookupDataStore class. @@ -36,7 +35,6 @@ class LookupDataStoreTest extends \WC_Unit_Test_Case { */ public static function tearDownAfterClass() { parent::tearDownAfterClass(); - wc_get_container()->get( DataRegenerator::class )->delete_all_attributes_lookup_data(); } /** From 5253a1adae6d1984c8d170db3d26f94556c38c50 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Tue, 23 Nov 2021 10:09:30 +0100 Subject: [PATCH 04/91] Sort arrays before comparison in unit test Without this a test fails in GitHub ("Run unit tests with code coverage" task). --- .../src/Internal/ProductAttributesLookup/FiltererTest.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/FiltererTest.php b/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/FiltererTest.php index 0ac8094b112..a5ae813f5a2 100644 --- a/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/FiltererTest.php +++ b/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/FiltererTest.php @@ -1356,9 +1356,12 @@ class FiltererTest extends \WC_Unit_Test_Case { wp_set_object_terms( $product_simple_1->get_id(), $terms, 'product_visibility' ); wp_set_object_terms( $product_variable_1['id'], $terms, 'product_visibility' ); - $filtered_product_ids = $this->do_product_request( array() ); + $actual_filtered_product_ids = $this->do_product_request( array() ); + $expected_filtered_product_ids = array( $product_simple_2->get_id(), $product_variable_2['id'] ); + sort( $actual_filtered_product_ids ); + sort( $expected_filtered_product_ids ); - $this->assertEquals( array( $product_simple_2->get_id(), $product_variable_2['id'] ), $filtered_product_ids ); + $this->assertEquals( $expected_filtered_product_ids, $actual_filtered_product_ids ); $this->assert_counters( 'Color', $expected_colors_included_in_counters ); $this->assert_counters( 'Features', array( 'Ironable' ) ); From 870d706d1a6d96889a8d2df47c72f1a828e2347c Mon Sep 17 00:00:00 2001 From: Paulo Chang Date: Thu, 25 Nov 2021 17:38:13 +0100 Subject: [PATCH 05/91] Unhide GT Postcode It seems that some private courier services use the post code internally to price services. --- plugins/woocommerce/includes/class-wc-countries.php | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/woocommerce/includes/class-wc-countries.php b/plugins/woocommerce/includes/class-wc-countries.php index 3ad821411c4..fd2a1b96a2b 100644 --- a/plugins/woocommerce/includes/class-wc-countries.php +++ b/plugins/woocommerce/includes/class-wc-countries.php @@ -1056,7 +1056,6 @@ class WC_Countries { 'GT' => array( 'postcode' => array( 'required' => false, - 'hidden' => true, ), 'state' => array( 'label' => __( 'Department', 'woocommerce' ), From fd81e477d22f849d232444185e0417723a9cc048 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 3 Dec 2021 12:22:52 +0100 Subject: [PATCH 06/91] Fix: bad counters in the filter by attribute widget for OR. When a filter by attribute widget was configured as OR, the query to return the product counts was overfiltering and returning less results than it should. It now works as in the case of not using the lookup table. --- .../ProductAttributesLookup/Filterer.php | 21 ++------- .../ProductAttributesLookup/FiltererTest.php | 44 ++----------------- 2 files changed, 8 insertions(+), 57 deletions(-) diff --git a/plugins/woocommerce/src/Internal/ProductAttributesLookup/Filterer.php b/plugins/woocommerce/src/Internal/ProductAttributesLookup/Filterer.php index a4d6f97850b..6d16d9061fe 100644 --- a/plugins/woocommerce/src/Internal/ProductAttributesLookup/Filterer.php +++ b/plugins/woocommerce/src/Internal/ProductAttributesLookup/Filterer.php @@ -226,17 +226,15 @@ class Filterer { if ( ! empty( $attributes_to_filter_by ) ) { $and_term_ids = array(); - $or_term_ids = array(); foreach ( $attributes_to_filter_by as $taxonomy => $data ) { + if ( 'and' !== $data['query_type'] ) { + continue; + } $all_terms = get_terms( $taxonomy, array( 'hide_empty' => false ) ); $term_ids_by_slug = wp_list_pluck( $all_terms, 'term_id', 'slug' ); $term_ids_to_filter_by = array_values( array_intersect_key( $term_ids_by_slug, array_flip( $data['terms'] ) ) ); - if ( 'and' === $data['query_type'] ) { - $and_term_ids = array_merge( $and_term_ids, $term_ids_to_filter_by ); - } else { - $or_term_ids = array_merge( $or_term_ids, $term_ids_to_filter_by ); - } + $and_term_ids = array_merge( $and_term_ids, $term_ids_to_filter_by ); } if ( ! empty( $and_term_ids ) ) { @@ -261,17 +259,6 @@ class Filterer { AND term_id in {$term_ids_list} ) temp )"; } - - if ( ! empty( $or_term_ids ) ) { - $term_ids_list = '(' . join( ',', $or_term_ids ) . ')'; - $query['where'] .= " - AND product_or_parent_id IN ( SELECT product_or_parent_id FROM ( - SELECT product_or_parent_id FROM {$this->lookup_table_name} - WHERE term_id in {$term_ids_list} - {$in_stock_clause} - ) temp )"; - - } } else { $query['where'] .= $in_stock_clause; } diff --git a/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/FiltererTest.php b/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/FiltererTest.php index a5ae813f5a2..655b0afe4bd 100644 --- a/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/FiltererTest.php +++ b/plugins/woocommerce/tests/php/src/Internal/ProductAttributesLookup/FiltererTest.php @@ -545,16 +545,7 @@ class FiltererTest extends \WC_Unit_Test_Case { $this->assertEmpty( $filtered_product_ids ); } - /* - * If a variable product defines an attribute value that isn't used by any variation: - * When using the lookup table: that value is not included in the count. - * When not using the lookup table: the value is included in the count since it is part of the parent product. - */ - if ( $using_lookup_table && 'or' === $filter_type && array( 'Green' ) === $attributes ) { - $expected_to_be_included_in_count = false; - } else { - $expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible; - } + $expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible; $this->assert_counters( 'Color', $expected_to_be_included_in_count ? array( 'Blue', 'Red' ) : array(), $filter_type ); } @@ -822,16 +813,7 @@ class FiltererTest extends \WC_Unit_Test_Case { $this->assertEmpty( $filtered_product_ids ); } - /* - * If a variable product defines an attribute value that isn't used by any variation: - * When using the lookup table: that value is not included in the count. - * When not using the lookup table: the value is included in the count since it is part of the parent product. - */ - if ( $using_lookup_table && 'or' === $filter_type && array( 'Elastic' ) === $attributes ) { - $expected_to_be_included_in_count = false; - } else { - $expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible; - } + $expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible; $this->assert_counters( 'Features', $expected_to_be_included_in_count ? array( 'Washable', 'Ironable' ) : array(), $filter_type ); } @@ -1075,16 +1057,7 @@ class FiltererTest extends \WC_Unit_Test_Case { $this->assertEmpty( $filtered_product_ids ); } - /* - * If a variable product defines an attribute value that isn't used by any variation: - * When using the lookup table: that value is not included in the count. - * When not using the lookup table: the value is included in the count since it is part of the parent product. - */ - if ( $using_lookup_table && 'or' === $filter_type && array( 'Green' ) === $attributes ) { - $expected_counted_attributes = array(); - } else { - $expected_counted_attributes = 'or' === $filter_type || $expected_to_be_visible ? array( 'Blue', 'Red' ) : array(); - } + $expected_counted_attributes = 'or' === $filter_type || $expected_to_be_visible ? array( 'Blue', 'Red' ) : array(); $this->assert_counters( 'Color', $expected_counted_attributes, $filter_type ); } @@ -1208,16 +1181,7 @@ class FiltererTest extends \WC_Unit_Test_Case { $this->assertEmpty( $filtered_product_ids ); } - /* - * If a variable product defines an attribute value that isn't used by any variation: - * When using the lookup table: that value is not included in the count. - * When not using the lookup table: the value is included in the count since it is part of the parent product. - */ - if ( $using_lookup_table && 'or' === $filter_type && array( 'White' ) === $attributes ) { - $expected_to_be_included_in_count = false; - } else { - $expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible; - } + $expected_to_be_included_in_count = 'or' === $filter_type || $expected_to_be_visible; $this->assert_counters( 'Color', $expected_to_be_included_in_count ? array( 'Blue', 'Red', 'Green' ) : array(), $filter_type ); } From 79f2936ae95ceaa68c3b4cdad8325d5ed217758f Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 3 Dec 2021 12:25:20 +0100 Subject: [PATCH 07/91] Temporary fix for a unit test. The "Advanced" section in the product settings page exists only if the product attributes lookup table exists. The table will eventually exist for everybody, so a temporary check has been added. --- .../class-wc-settings-products-test.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/plugins/woocommerce/tests/php/includes/settings/class-wc-settings-products-test.php b/plugins/woocommerce/tests/php/includes/settings/class-wc-settings-products-test.php index 5f7941e6af6..815d7207f08 100644 --- a/plugins/woocommerce/tests/php/includes/settings/class-wc-settings-products-test.php +++ b/plugins/woocommerce/tests/php/includes/settings/class-wc-settings-products-test.php @@ -7,6 +7,8 @@ // phpcs:ignore Squiz.Commenting.FileComment.Missing +use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore; + require_once __DIR__ . '/class-wc-settings-unit-test-case.php'; /** @@ -28,6 +30,11 @@ class WC_Settings_Products_Test extends WC_Settings_Unit_Test_Case { 'downloadable', ); + // TODO: Once the lookup table is created in a migration, remove the check and just include 'advanced' in $expected. + if ( wc_get_container()->get( LookupDataStore::class )->check_lookup_table_exists() ) { + array_push( $expected, 'advanced' ); + } + $this->assertEquals( $expected, $section_names ); } @@ -134,12 +141,12 @@ class WC_Settings_Products_Test extends WC_Settings_Unit_Test_Case { $settings_ids_and_types = $this->get_ids_and_types( $settings ); $expected = array( - 'digital_download_options' => array( 'title', 'sectionend' ), - 'woocommerce_file_download_method' => 'select', - 'woocommerce_downloads_redirect_fallback_allowed' => 'checkbox', - 'woocommerce_downloads_require_login' => 'checkbox', + 'digital_download_options' => array( 'title', 'sectionend' ), + 'woocommerce_file_download_method' => 'select', + 'woocommerce_downloads_redirect_fallback_allowed' => 'checkbox', + 'woocommerce_downloads_require_login' => 'checkbox', 'woocommerce_downloads_grant_access_after_payment' => 'checkbox', - 'woocommerce_downloads_add_hash_to_filename' => 'checkbox', + 'woocommerce_downloads_add_hash_to_filename' => 'checkbox', ); $this->assertEquals( $expected, $settings_ids_and_types ); From 95dde6c082ca8dced1e9c8dcdeea3ebfd548c353 Mon Sep 17 00:00:00 2001 From: Nestor Soriano Date: Fri, 3 Dec 2021 12:49:07 +0100 Subject: [PATCH 08/91] Change db update version from 6.1 to 6.2. --- plugins/woocommerce/includes/class-wc-install.php | 4 ++-- plugins/woocommerce/includes/wc-update-functions.php | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/woocommerce/includes/class-wc-install.php b/plugins/woocommerce/includes/class-wc-install.php index 62811c42081..eb8faddbe46 100644 --- a/plugins/woocommerce/includes/class-wc-install.php +++ b/plugins/woocommerce/includes/class-wc-install.php @@ -169,9 +169,9 @@ class WC_Install { 'wc_update_600_migrate_rate_limit_options', 'wc_update_600_db_version', ), - '6.1.0' => array( + '6.2.0' => array( 'wc_create_product_attributes_lookup_table', - 'wc_update_610_db_version', + 'wc_update_620_db_version', ), ); diff --git a/plugins/woocommerce/includes/wc-update-functions.php b/plugins/woocommerce/includes/wc-update-functions.php index 1a27c786f37..81df68a942f 100644 --- a/plugins/woocommerce/includes/wc-update-functions.php +++ b/plugins/woocommerce/includes/wc-update-functions.php @@ -2357,8 +2357,8 @@ function wc_create_product_attributes_lookup_table() { /** * - * Update DB version to 6.1.0. + * Update DB version to 6.2.0. */ -function wc_update_610_db_version() { - WC_Install::update_db_version( '6.1.0' ); +function wc_update_620_db_version() { + WC_Install::update_db_version( '6.2.0' ); } From 829d9b3035978e75713c6424c4c4b0fbb21c3179 Mon Sep 17 00:00:00 2001 From: Veljko V Date: Tue, 21 Dec 2021 13:54:12 +0100 Subject: [PATCH 09/91] Update plugins/woocommerce/tests/performance/requests/merchant/orders-search.js Co-authored-by: Tam Mullen --- .../tests/performance/requests/merchant/orders-search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js b/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js index b5a75d1da6b..f2f0c716274 100644 --- a/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js +++ b/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js @@ -25,7 +25,7 @@ export function ordersSearch() { ); response = http.get( - `${base_url}/wp-admin/edit.php?s&` + + `${base_url}/wp-admin/edit.php?s=${product_search_term}&` + `post_status=all&post_type=shop_order&action=-1&m=0&_customer_user&` + `paged=1&action2=-1`, { From 0fb8047bcc6d9ada86de68903293366c29909f89 Mon Sep 17 00:00:00 2001 From: Veljko V Date: Tue, 21 Dec 2021 13:54:23 +0100 Subject: [PATCH 10/91] Update plugins/woocommerce/tests/performance/requests/merchant/orders-search.js Co-authored-by: Tam Mullen --- .../tests/performance/requests/merchant/orders-search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js b/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js index f2f0c716274..87ed0881a7d 100644 --- a/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js +++ b/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js @@ -36,7 +36,7 @@ export function ordersSearch() { check(response, { "is status 200": (r) => r.status === 200, "body contains: 'Orders' header": (response) => - response.body.includes("Orders"), + response.body.includes("Search results for:"), }); }); From 03a4ed7ed9a1841b7c7d62a6a88b9044b3c009a0 Mon Sep 17 00:00:00 2001 From: Veljko V Date: Tue, 21 Dec 2021 13:56:11 +0100 Subject: [PATCH 11/91] Update plugins/woocommerce/tests/performance/requests/merchant/orders-search.js Co-authored-by: Tam Mullen --- .../tests/performance/requests/merchant/orders-search.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js b/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js index 87ed0881a7d..52e0398a8b3 100644 --- a/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js +++ b/plugins/woocommerce/tests/performance/requests/merchant/orders-search.js @@ -35,7 +35,7 @@ export function ordersSearch() { postTypeOrderSearchTrend.add(response.timings.duration); check(response, { "is status 200": (r) => r.status === 200, - "body contains: 'Orders' header": (response) => + "body contains: 'Search results' subtitle": (response) => response.body.includes("Search results for:"), }); }); From 56820e943137a0b410d93c556166371e88d613b7 Mon Sep 17 00:00:00 2001 From: Tam Mullen Date: Wed, 22 Dec 2021 13:41:31 +0000 Subject: [PATCH 12/91] Added workflow for issue triage replies --- .github/workflows/triage-replies.yml | 120 +++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 .github/workflows/triage-replies.yml diff --git a/.github/workflows/triage-replies.yml b/.github/workflows/triage-replies.yml new file mode 100644 index 00000000000..11e77830e2f --- /dev/null +++ b/.github/workflows/triage-replies.yml @@ -0,0 +1,120 @@ +name: Add issue triage comments. +on: + issues: + types: + - labeled +jobs: + add-dev-comment: + if: "github.event.label.name == 'needs developer feedback'" + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: Add developer feedback comment + uses: actions/github-script@v5 + with: + github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }} + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Hi @${{ github.event.issue.user.login }},\n\n\ + Thank you for opening the issue! It requires further feedback from the WooCommerce Core team.\n\n\ + We are adding the `needs developer feedback` label to this issue so that the Core team could take a look.\n\n\ + Please note it may take a few days for them to get to this issue. Thank you for your patience.' + }) + add-reproduction-comment: + if: "github.event.label.name == 'status: needs reproduction'" + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: Add needs reproduction comment + uses: actions/github-script@v5 + with: + github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }} + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'We are adding the `status: needs reproduction` label to this issue to try reproduce it on the \ + current released version of WooCommerce.\n\n\ + Thank you for your patience.' + }) + add-support-comment: + if: "github.event.label.name == 'type: support request'" + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: Add support request comment + uses: actions/github-script@v5 + with: + github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }} + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Hi @${{ github.event.issue.user.login }},\n\n\ + While our goal is to address all the issues reported in this repository, \ + GitHub should be treated as a place to report confirmed bugs only.\n\n\ + The type of issue you submitted looks like a support request which may or may not reveal a bug once proper \ + troubleshooting is done. In order to confirm the bug, please follow one of the steps below:\n\n\ + - Review [WooCommerce Self-Service Guide](https://docs.woocommerce.com/document/woocommerce-self-service-guide/) \ + to see if the solutions listed there apply to your case;\n\ + - If you are a paying customer of WooCommerce, contact WooCommerce support by \ + [opening a ticket or starting a live chat](https://woocommerce.com/contact-us/);\n\ + - Make a post on [WooCommerce community forum](https://wordpress.org/support/plugin/woocommerce/)\n\n\ + If you confirm the bug, please provide us with clear steps to reproduce it.\n\n\ + We are closing this issue for now as it seems to be a support request and not a bug. \ + If we missed something, please leave a comment and we will take a second look.' + }) + - name: Close support request issue + uses: actions/github-script@v5 + with: + github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }} + script: | + github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + state: 'closed' + }) + add-votes-comment: + if: "github.event.label.name == 'votes needed'" + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: Add votes needed comment + uses: actions/github-script@v5 + with: + github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }} + script: | + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'Thanks for the suggestion @${{ github.event.issue.user.login }},\n\n\ + While we appreciate you sharing your ideas with us, it doesn’t fit in with our current priorities for the project.\n\ + At some point, we may revisit our priorities and look through the list of suggestions like this one to see if it \ + warrants a second look.\n\n\ + In the meantime, we are going to close this issue with the `votes needed` label and evaluate over time if this \ + issue collects more feedback.\n\n\ + Don’t be alarmed if you don’t see any activity on this issue for a while. \ + We'll keep an eye on the popularity of this request.' + }) + - name: Close votes needed issue + uses: actions/github-script@v5 + with: + github-token: ${{ secrets.WC_BOT_TRIAGE_TOKEN }} + script: | + github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + state: 'closed' + }) From 757094ea436c5de020a0ec34f966129b073be342 Mon Sep 17 00:00:00 2001 From: John Regan Date: Wed, 5 Jan 2022 08:56:01 -0600 Subject: [PATCH 13/91] Add var to woocommerce_variation_header hook --- .../includes/admin/meta-boxes/views/html-variation-admin.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/woocommerce/includes/admin/meta-boxes/views/html-variation-admin.php b/plugins/woocommerce/includes/admin/meta-boxes/views/html-variation-admin.php index fb282200335..2bfdc85b8f3 100644 --- a/plugins/woocommerce/includes/admin/meta-boxes/views/html-variation-admin.php +++ b/plugins/woocommerce/includes/admin/meta-boxes/views/html-variation-admin.php @@ -57,8 +57,9 @@ defined( 'ABSPATH' ) || exit; * @since 3.6.0 * * @param WP_Post $variation Post data. + * @param int $loop Position in the loop. */ - do_action( 'woocommerce_variation_header', $variation ); + do_action( 'woocommerce_variation_header', $variation, $loop ); ?>