From 95b669280a7d28d61d2ec57eb783803cd528d1f3 Mon Sep 17 00:00:00 2001 From: Gerhard Potgieter Date: Mon, 20 Nov 2017 08:44:42 +0200 Subject: [PATCH 01/76] Refactor wc_update_new_customer_past_orders to not call update_post_meta directly but use the datastore. Check if order has downloadable items and then regenerate permissions. --- includes/wc-user-functions.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/includes/wc-user-functions.php b/includes/wc-user-functions.php index 9855f95cf3f..96d0d0d2daf 100644 --- a/includes/wc-user-functions.php +++ b/includes/wc-user-functions.php @@ -148,7 +148,19 @@ function wc_update_new_customer_past_orders( $customer_id ) { if ( ! empty( $customer_orders ) ) { foreach ( $customer_orders as $order_id ) { - update_post_meta( $order_id, '_customer_user', $customer->ID ); + $order = wc_get_order( $order_id ); + if ( ! $order ) { + continue; + } + + $order->set_customer_id( $customer->ID ); + $order->save(); + + if ( $order->has_downloadable_item() ) { + $data_store = WC_Data_Store::load( 'customer-download' ); + $data_store->delete_by_order_id( $order->get_id() ); + wc_downloadable_product_permissions( $order->get_id(), true ); + } do_action( 'woocommerce_update_new_customer_past_order', $order_id, $customer ); From 32c568209d8dc20ada60269d60b66e2ab9ee2598 Mon Sep 17 00:00:00 2001 From: Gerhard Potgieter Date: Mon, 20 Nov 2017 10:12:59 +0200 Subject: [PATCH 02/76] Add unit test to cover download permissions when running wc_update_new_customer_past_orders --- tests/unit-tests/customer/functions.php | 32 ++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/tests/unit-tests/customer/functions.php b/tests/unit-tests/customer/functions.php index 013e6dd29fa..c4a0b32ed33 100644 --- a/tests/unit-tests/customer/functions.php +++ b/tests/unit-tests/customer/functions.php @@ -69,11 +69,41 @@ class WC_Tests_Customer_Functions extends WC_Unit_Test_Case { $order2 = new WC_Order; $order2->save(); + // Test download permissions + $prod_download = new WC_Product_Download; + $prod_download->set_file( plugin_dir_url( __FILE__ ) . '/assets/images/help.png' ); + $prod_download->set_id( 'download' ); + + $product = new WC_Product_Simple; + $product->set_downloadable( 'yes' ); + $product->set_downloads( array( $prod_download ) ); + $product->save(); + + $order3 = new WC_Order; + $item = new WC_Order_Item_Product(); + $item->set_props( array( + 'product' => $product, + 'quantity' => 1, + ) ); + $order3->set_billing_email( 'test@example.com' ); + $order3->set_status( 'completed' ); + $order3->add_item( $item ); + $order3->save(); + + $downloads = wc_get_customer_available_downloads( $customer_id ); + $this->assertEquals( 0, count( $downloads ) ); + // Link orders that haven't been linked. $linked = wc_update_new_customer_past_orders( $customer_id ); - $this->assertEquals( 1, $linked ); + $this->assertEquals( 2, $linked ); $order1 = wc_get_order( $order1->get_id() ); $this->assertEquals( $customer_id, $order1->get_customer_id() ); + $order3 = wc_get_order( $order3->get_id() ); + $this->assertEquals( $customer_id, $order3->get_customer_id() ); + + // Test download permissions. + $downloads = wc_get_customer_available_downloads( $customer_id ); + $this->assertEquals( 1, count( $downloads ) ); // Don't link linked orders again. $linked = wc_update_new_customer_past_orders( $customer_id ); From c380c06aff0cea98d0275763813621ad7870e862 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Mon, 20 Nov 2017 10:23:26 -0200 Subject: [PATCH 03/76] Update wc-e2e-page-objects to version 0.5.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ba6a4afaf71..1267266e7d6 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "istanbul": "^1.0.0-alpha", "mocha": "^3.0.2", "stylelint": "~8.2.0", - "wc-e2e-page-objects": "0.4.0" + "wc-e2e-page-objects": "0.5.0" }, "engines": { "node": ">=6.9.4", From b28280f9ab9c341055c9d0a25c8c041f78583a54 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Mon, 20 Nov 2017 10:36:49 -0200 Subject: [PATCH 04/76] Typo --- tests/e2e-tests/cart-page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e-tests/cart-page.js b/tests/e2e-tests/cart-page.js index 6cb54e3821d..1ddff905055 100644 --- a/tests/e2e-tests/cart-page.js +++ b/tests/e2e-tests/cart-page.js @@ -93,7 +93,7 @@ test.describe( 'Cart page', function() { ); } ); - test.it( 'should go to the checkout page when "Proceed to Chcekout" is clicked', () => { + test.it( 'should go to the checkout page when "Proceed to Checkout" is clicked', () => { const cartPage = new CartPage( driver, { url: manager.getPageUrl( '/cart' ) } ); const checkoutPage = cartPage.checkout(); From 9793bd69859b5b02a279a6a0d9b09a2c87de0a5e Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Mon, 20 Nov 2017 10:42:28 -0200 Subject: [PATCH 05/76] Update e2e tests to work with the latest version of selenium-webdriver The new version of selenium-webdriver no longer supports passing a description to before() and after(). --- tests/e2e-tests/cart-page.js | 6 ++++-- tests/e2e-tests/checkout-page.js | 6 ++++-- tests/e2e-tests/single-product.js | 6 ++++-- tests/e2e-tests/wp-admin/wp-admin-coupon-new.js | 6 ++++-- tests/e2e-tests/wp-admin/wp-admin-order-new.js | 6 ++++-- tests/e2e-tests/wp-admin/wp-admin-product-new.js | 9 ++++++--- tests/e2e-tests/wp-admin/wp-admin-wc-settings-general.js | 9 ++++++--- .../wp-admin-wc-settings-products-downloadable.js | 9 ++++++--- tests/e2e-tests/wp-admin/wp-admin-wc-settings-tax.js | 9 ++++++--- 9 files changed, 44 insertions(+), 22 deletions(-) diff --git a/tests/e2e-tests/cart-page.js b/tests/e2e-tests/cart-page.js index 1ddff905055..4ba9014611c 100644 --- a/tests/e2e-tests/cart-page.js +++ b/tests/e2e-tests/cart-page.js @@ -12,7 +12,8 @@ let manager; let driver; test.describe( 'Cart page', function() { - test.before( 'open browser', function() { + // open browser + test.before( function() { this.timeout( config.get( 'startBrowserTimeoutMs' ) ); manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } ); @@ -104,7 +105,8 @@ test.describe( 'Cart page', function() { ); } ); - test.after( 'quit browser', () => { + // quit browser + test.after( () => { manager.quitBrowser(); } ); } ); diff --git a/tests/e2e-tests/checkout-page.js b/tests/e2e-tests/checkout-page.js index 44a47ccb029..c17fabe718e 100644 --- a/tests/e2e-tests/checkout-page.js +++ b/tests/e2e-tests/checkout-page.js @@ -26,7 +26,8 @@ let manager; let driver; test.describe( 'Checkout Page', function() { - test.before( 'open browser', function() { + // open browser + test.before( function() { this.timeout( config.get( 'startBrowserTimeoutMs' ) ); manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } ); @@ -148,7 +149,8 @@ test.describe( 'Checkout Page', function() { ); } ); - test.after( 'quit browser', () => { + // quit browser + test.after( () => { manager.quitBrowser(); } ); } ); diff --git a/tests/e2e-tests/single-product.js b/tests/e2e-tests/single-product.js index 54eff013a20..8febfad25fd 100644 --- a/tests/e2e-tests/single-product.js +++ b/tests/e2e-tests/single-product.js @@ -16,7 +16,8 @@ let manager; let driver; test.describe( 'Single Product Page', function() { - test.before( 'open browser', function() { + // open browser + test.before( function() { this.timeout( config.get( 'startBrowserTimeoutMs' ) ); manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } ); @@ -52,7 +53,8 @@ test.describe( 'Single Product Page', function() { assert.eventually.equal( cartPage.hasItem( 'Hoodie - Green' ), true ); } ); - test.after( 'quit browser', () => { + // quit browser + test.after( () => { manager.quitBrowser(); } ); } ); diff --git a/tests/e2e-tests/wp-admin/wp-admin-coupon-new.js b/tests/e2e-tests/wp-admin/wp-admin-coupon-new.js index 672ea64d8ea..3d0165c7c8d 100644 --- a/tests/e2e-tests/wp-admin/wp-admin-coupon-new.js +++ b/tests/e2e-tests/wp-admin/wp-admin-coupon-new.js @@ -12,7 +12,8 @@ let manager; let driver; test.describe( 'Add New Coupon Page', function() { - test.before( 'open browser', function() { + // open browser + test.before( function() { this.timeout( config.get( 'startBrowserTimeoutMs' ) ); manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } ); @@ -45,7 +46,8 @@ test.describe( 'Add New Coupon Page', function() { assert.eventually.ok( couponPage.hasNotice( 'Coupon updated.' ) ); } ); - test.after( 'quit browser', () => { + // quit browser + test.after( () => { manager.quitBrowser(); } ); } ); diff --git a/tests/e2e-tests/wp-admin/wp-admin-order-new.js b/tests/e2e-tests/wp-admin/wp-admin-order-new.js index 462eaa870b2..018ab113166 100644 --- a/tests/e2e-tests/wp-admin/wp-admin-order-new.js +++ b/tests/e2e-tests/wp-admin/wp-admin-order-new.js @@ -12,7 +12,8 @@ let manager; let driver; test.describe( 'Add New Order Page', function() { - test.before( 'open browser', function() { + // open browser + test.before( function() { this.timeout( config.get( 'startBrowserTimeoutMs' ) ); manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } ); @@ -46,7 +47,8 @@ test.describe( 'Add New Order Page', function() { assert.eventually.ok( orderNotes.hasNote( 'Order status changed from Pending payment to Processing.' ) ); } ); - test.after( 'quit browser', () => { + // quit browser + test.after( () => { manager.quitBrowser(); } ); } ); diff --git a/tests/e2e-tests/wp-admin/wp-admin-product-new.js b/tests/e2e-tests/wp-admin/wp-admin-product-new.js index 89d38616e32..c4dc519732f 100644 --- a/tests/e2e-tests/wp-admin/wp-admin-product-new.js +++ b/tests/e2e-tests/wp-admin/wp-admin-product-new.js @@ -13,7 +13,8 @@ let manager; let driver; test.describe( 'Add New Product Page', function() { - test.before( 'open browser', function() { + // open browser + test.before( function() { this.timeout( config.get( 'startBrowserTimeoutMs' ) ); manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } ); @@ -24,7 +25,8 @@ test.describe( 'Add New Product Page', function() { this.timeout( config.get( 'mochaTimeoutMs' ) ); - test.before( 'login', () => { + // login + test.before( () => { const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } ); wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) ); } ); @@ -121,7 +123,8 @@ test.describe( 'Add New Product Page', function() { assert.eventually.ok( product.hasNotice( '1 product moved to the Trash.' ) ); } ); - test.after( 'quit browser', () => { + // quit browser + test.after( () => { manager.quitBrowser(); } ); } ); diff --git a/tests/e2e-tests/wp-admin/wp-admin-wc-settings-general.js b/tests/e2e-tests/wp-admin/wp-admin-wc-settings-general.js index 15b9821ef79..c8f75bf0b38 100644 --- a/tests/e2e-tests/wp-admin/wp-admin-wc-settings-general.js +++ b/tests/e2e-tests/wp-admin/wp-admin-wc-settings-general.js @@ -13,7 +13,8 @@ let manager; let driver; test.describe( 'WooCommerce General Settings', function() { - test.before( 'open browser', function() { + // open browser + test.before( function() { this.timeout( config.get( 'startBrowserTimeoutMs' ) ); manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } ); @@ -24,7 +25,8 @@ test.describe( 'WooCommerce General Settings', function() { this.timeout( config.get( 'mochaTimeoutMs' ) ); - test.before( 'login', () => { + // login + test.before( () => { const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } ); wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) ); } ); @@ -64,7 +66,8 @@ test.describe( 'WooCommerce General Settings', function() { assert.eventually.ok( settings.hasNotice( 'Your settings have been saved.' ) ); } ); - test.after( 'quit browser', () => { + // quit browser + test.after( () => { manager.quitBrowser(); } ); } ); diff --git a/tests/e2e-tests/wp-admin/wp-admin-wc-settings-products-downloadable.js b/tests/e2e-tests/wp-admin/wp-admin-wc-settings-products-downloadable.js index bb710b489ff..8fdb2262631 100644 --- a/tests/e2e-tests/wp-admin/wp-admin-wc-settings-products-downloadable.js +++ b/tests/e2e-tests/wp-admin/wp-admin-wc-settings-products-downloadable.js @@ -13,7 +13,8 @@ let manager; let driver; test.describe( 'WooCommerce Products > Downloadable Products Settings', function() { - test.before( 'open browser', function() { + // open browser + test.before( function() { this.timeout( config.get( 'startBrowserTimeoutMs' ) ); manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } ); @@ -24,7 +25,8 @@ test.describe( 'WooCommerce Products > Downloadable Products Settings', function this.timeout( config.get( 'mochaTimeoutMs' ) ); - test.before( 'login', () => { + // login + test.before( () => { const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } ); wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) ); } ); @@ -49,7 +51,8 @@ test.describe( 'WooCommerce Products > Downloadable Products Settings', function assert.eventually.ok( settings.hasNotice( 'Your settings have been saved.' ) ); } ); - test.after( 'quit browser', () => { + // quit browser + test.after( () => { manager.quitBrowser(); } ); } ); diff --git a/tests/e2e-tests/wp-admin/wp-admin-wc-settings-tax.js b/tests/e2e-tests/wp-admin/wp-admin-wc-settings-tax.js index f0b629fc6c7..a3f4bbf8e2d 100644 --- a/tests/e2e-tests/wp-admin/wp-admin-wc-settings-tax.js +++ b/tests/e2e-tests/wp-admin/wp-admin-wc-settings-tax.js @@ -13,7 +13,8 @@ let manager; let driver; test.describe( 'WooCommerce Tax Settings', function() { - test.before( 'open browser', function() { + // open browser + test.before( function() { this.timeout( config.get( 'startBrowserTimeoutMs' ) ); manager = new WebDriverManager( 'chrome', { baseUrl: config.get( 'url' ) } ); @@ -24,7 +25,8 @@ test.describe( 'WooCommerce Tax Settings', function() { this.timeout( config.get( 'mochaTimeoutMs' ) ); - test.before( 'login', () => { + // login + test.before( () => { const wpLogin = new WPLogin( driver, { url: manager.getPageUrl( '/wp-login.php' ) } ); wpLogin.login( config.get( 'users.admin.username' ), config.get( 'users.admin.password' ) ); } ); @@ -93,7 +95,8 @@ test.describe( 'WooCommerce Tax Settings', function() { assert.eventually.ifError( settings.hasSubTab( 'Fancy rates' ) ); } ); - test.after( 'quit browser', () => { + // quit browser + test.after( () => { manager.quitBrowser(); } ); } ); From 80ffcfb45df0873b26f738d31cefa2f198e48b54 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Mon, 20 Nov 2017 16:30:04 +0000 Subject: [PATCH 06/76] Add round param for `wc_add_number_precision` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let’s us return the cent value without rounding to an integer. --- includes/wc-core-functions.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/includes/wc-core-functions.php b/includes/wc-core-functions.php index 872dd218131..3c03189e2b7 100644 --- a/includes/wc-core-functions.php +++ b/includes/wc-core-functions.php @@ -1495,11 +1495,13 @@ function wc_get_rounding_precision() { * * @since 3.2.0 * @param float $value Number to add precision to. - * @return int + * @param bool $round Should we round after adding precision? + * @return int|float */ -function wc_add_number_precision( $value ) { +function wc_add_number_precision( $value, $round = false ) { $precision = pow( 10, wc_get_price_decimals() ); - return intval( round( $value * $precision ) ); + $value = $value * $precision; + return $round ? intval( round( $value ) ) : $value; } /** @@ -1519,15 +1521,16 @@ function wc_remove_number_precision( $value ) { * * @since 3.2.0 * @param array $value Number to add precision to. + * @param bool $round Should we round after adding precision? * @return int */ -function wc_add_number_precision_deep( $value ) { +function wc_add_number_precision_deep( $value, $round = false ) { if ( is_array( $value ) ) { foreach ( $value as $key => $subvalue ) { - $value[ $key ] = wc_add_number_precision_deep( $subvalue ); + $value[ $key ] = wc_add_number_precision_deep( $subvalue, $round ); } } else { - $value = wc_add_number_precision( $value ); + $value = wc_add_number_precision( $value, $round ); } return $value; } From ec5db3b123fdab3d4ac85bc8ef41219dcf523fc9 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Mon, 20 Nov 2017 16:30:23 +0000 Subject: [PATCH 07/76] When adding precision to taxes, don't round when adding precision. --- 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 fec8bda64a5..8a0c128701f 100644 --- a/includes/class-wc-cart-totals.php +++ b/includes/class-wc-cart-totals.php @@ -349,8 +349,8 @@ final class WC_Cart_Totals { $shipping_line->tax_class = get_option( 'woocommerce_shipping_tax_class' ); $shipping_line->taxable = true; $shipping_line->total = wc_add_number_precision_deep( $shipping_object->cost ); - $shipping_line->taxes = wc_add_number_precision_deep( $shipping_object->taxes ); - $shipping_line->total_tax = wc_add_number_precision_deep( array_sum( $shipping_object->taxes ) ); + $shipping_line->taxes = wc_add_number_precision_deep( $shipping_object->taxes, false ); + $shipping_line->total_tax = wc_add_number_precision_deep( array_sum( $shipping_object->taxes ), false ); if ( ! $this->round_at_subtotal() ) { $shipping_line->total_tax = wc_round_tax_total( $shipping_line->total_tax, wc_get_rounding_precision() ); From c8d1a46315f0b3e187d142d09263e1f58d2ca53e Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Mon, 20 Nov 2017 16:37:44 +0000 Subject: [PATCH 08/76] Default rounding to true. --- 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 3c03189e2b7..ce71b51384b 100644 --- a/includes/wc-core-functions.php +++ b/includes/wc-core-functions.php @@ -1498,7 +1498,7 @@ function wc_get_rounding_precision() { * @param bool $round Should we round after adding precision? * @return int|float */ -function wc_add_number_precision( $value, $round = false ) { +function wc_add_number_precision( $value, $round = true ) { $precision = pow( 10, wc_get_price_decimals() ); $value = $value * $precision; return $round ? intval( round( $value ) ) : $value; @@ -1524,7 +1524,7 @@ function wc_remove_number_precision( $value ) { * @param bool $round Should we round after adding precision? * @return int */ -function wc_add_number_precision_deep( $value, $round = false ) { +function wc_add_number_precision_deep( $value, $round = true ) { if ( is_array( $value ) ) { foreach ( $value as $key => $subvalue ) { $value[ $key ] = wc_add_number_precision_deep( $subvalue, $round ); From 5a858eb2b1537c901657d7e3fd5be83c64cece41 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Mon, 20 Nov 2017 14:40:56 -0200 Subject: [PATCH 09/76] Use WC_Query->get_query_vars() instead of WC_Query->query_vars Closes #17733 --- includes/class-wc-query.php | 6 +++--- includes/wc-page-functions.php | 7 ++++--- includes/wc-template-functions.php | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/includes/class-wc-query.php b/includes/class-wc-query.php index df8d29d1c0e..762fdef6807 100644 --- a/includes/class-wc-query.php +++ b/includes/class-wc-query.php @@ -159,7 +159,7 @@ class WC_Query { public function add_endpoints() { $mask = $this->get_endpoints_mask(); - foreach ( $this->query_vars as $key => $var ) { + foreach ( $this->get_query_vars() as $key => $var ) { if ( ! empty( $var ) ) { add_rewrite_endpoint( $var, $mask ); } @@ -248,7 +248,7 @@ class WC_Query { * @param object $q query object */ public function pre_get_posts( $q ) { - // We only want to affect the main query + // We only want to affect the main query. if ( ! $q->is_main_query() ) { return; } @@ -256,7 +256,7 @@ class WC_Query { // Fix for endpoints on the homepage if ( $this->is_showing_page_on_front( $q ) && ! $this->page_on_front_is( $q->get( 'page_id' ) ) ) { $_query = wp_parse_args( $q->query ); - if ( ! empty( $_query ) && array_intersect( array_keys( $_query ), array_keys( $this->query_vars ) ) ) { + if ( ! empty( $_query ) && array_intersect( array_keys( $_query ), array_keys( $this->get_query_vars() ) ) ) { $q->is_page = true; $q->is_home = false; $q->is_singular = true; diff --git a/includes/wc-page-functions.php b/includes/wc-page-functions.php index 206af096128..2b28b31087d 100644 --- a/includes/wc-page-functions.php +++ b/includes/wc-page-functions.php @@ -89,9 +89,10 @@ function wc_get_endpoint_url( $endpoint, $value = '', $permalink = '' ) { $permalink = get_permalink(); } - // Map endpoint to options - $endpoint = ! empty( WC()->query->query_vars[ $endpoint ] ) ? WC()->query->query_vars[ $endpoint ] : $endpoint; - $value = ( get_option( 'woocommerce_myaccount_edit_address_endpoint', 'edit-address' ) === $endpoint ) ? wc_edit_address_i18n( $value ) : $value; + // Map endpoint to options. + $query_vars = WC()->query->get_query_vars(); + $endpoint = ! empty( $query_vars[ $endpoint ] ) ? $query_vars[ $endpoint ]: $endpoint; + $value = ( get_option( 'woocommerce_myaccount_edit_address_endpoint', 'edit-address' ) === $endpoint ) ? wc_edit_address_i18n( $value ) : $value; if ( get_option( 'permalink_structure' ) ) { if ( strstr( $permalink, '?' ) ) { diff --git a/includes/wc-template-functions.php b/includes/wc-template-functions.php index 58f572369cf..b728216df5c 100644 --- a/includes/wc-template-functions.php +++ b/includes/wc-template-functions.php @@ -259,7 +259,7 @@ function wc_body_class( $classes ) { $classes[] = 'woocommerce-demo-store'; } - foreach ( WC()->query->query_vars as $key => $value ) { + foreach ( WC()->query->get_query_vars() as $key => $value ) { if ( is_wc_endpoint_url( $key ) ) { $classes[] = 'woocommerce-' . sanitize_html_class( $key ); } From 14e5bcd51d458e6c9ae2ce57ec118973374f604c Mon Sep 17 00:00:00 2001 From: JeroenSormani Date: Mon, 20 Nov 2017 20:14:23 +0100 Subject: [PATCH 10/76] Exclude virtual tax classes from calcluation for shipping taxes --- includes/abstracts/abstract-wc-product.php | 2 +- includes/class-wc-cart.php | 17 +++++++++++++++++ includes/class-wc-tax.php | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/includes/abstracts/abstract-wc-product.php b/includes/abstracts/abstract-wc-product.php index 76001c6f88f..366470e093f 100644 --- a/includes/abstracts/abstract-wc-product.php +++ b/includes/abstracts/abstract-wc-product.php @@ -1518,7 +1518,7 @@ class WC_Product extends WC_Abstract_Legacy_Product { * @return bool */ public function is_shipping_taxable() { - return $this->get_tax_status() === 'taxable' || $this->get_tax_status() === 'shipping'; + return $this->needs_shipping() && ( $this->get_tax_status() === 'taxable' || $this->get_tax_status() === 'shipping' ); } /** diff --git a/includes/class-wc-cart.php b/includes/class-wc-cart.php index a9170be2b97..9e6dba6a43e 100644 --- a/includes/class-wc-cart.php +++ b/includes/class-wc-cart.php @@ -967,6 +967,23 @@ class WC_Cart extends WC_Legacy_Cart { return array_unique( $found_tax_classes ); } + /** + * Get all tax classes for shipping based on the items in the cart. + * + * @return array + */ + public function get_cart_item_tax_classes_for_shipping() { + $found_tax_classes = array(); + + foreach ( WC()->cart->get_cart() as $item ) { + if ( $item['data'] && ( $item['data']->is_shipping_taxable() ) ) { + $found_tax_classes[] = $item['data']->get_tax_class(); + } + } + + return array_unique( $found_tax_classes ); + } + /** * Determines the value that the customer spent and the subtotal * displayed, used for things like coupon validation. diff --git a/includes/class-wc-tax.php b/includes/class-wc-tax.php index a2a4caafaf3..8ba7940b088 100644 --- a/includes/class-wc-tax.php +++ b/includes/class-wc-tax.php @@ -579,7 +579,7 @@ class WC_Tax { } elseif ( WC()->cart->get_cart() ) { // This will be per order shipping - loop through the order and find the highest tax class rate - $cart_tax_classes = WC()->cart->get_cart_item_tax_classes(); + $cart_tax_classes = WC()->cart->get_cart_item_tax_classes_for_shipping(); // No tax classes = no taxable items. if ( empty( $cart_tax_classes ) ) { From 698db6c1315bcc9b05cde1d403619a940c2fcd79 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Mon, 20 Nov 2017 20:51:32 +0000 Subject: [PATCH 11/76] When custom attributes are created, they are decoded. Make the values match. When we create/link variations, the entities are decoded. When the variation form is posted, the entities are encoded (esc_attr). This decodes them so they match correctly. Fixes #17820 --- .../meta-boxes/class-wc-meta-box-product-data.php | 12 +++++++++--- includes/class-wc-form-handler.php | 2 +- includes/wc-attribute-functions.php | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/includes/admin/meta-boxes/class-wc-meta-box-product-data.php b/includes/admin/meta-boxes/class-wc-meta-box-product-data.php index c15ab9c8133..a4c57c545ba 100644 --- a/includes/admin/meta-boxes/class-wc-meta-box-product-data.php +++ b/includes/admin/meta-boxes/class-wc-meta-box-product-data.php @@ -284,12 +284,18 @@ class WC_Meta_Box_Product_Data { $attribute_key = sanitize_title( $attribute->get_name() ); if ( ! is_null( $index ) ) { - $value = isset( $_POST[ $key_prefix . $attribute_key ][ $index ] ) ? stripslashes( $_POST[ $key_prefix . $attribute_key ][ $index ] ) : ''; + $value = isset( $_POST[ $key_prefix . $attribute_key ][ $index ] ) ? wp_unslash( $_POST[ $key_prefix . $attribute_key ][ $index ] ) : ''; } else { - $value = isset( $_POST[ $key_prefix . $attribute_key ] ) ? stripslashes( $_POST[ $key_prefix . $attribute_key ] ) : ''; + $value = isset( $_POST[ $key_prefix . $attribute_key ] ) ? wp_unslash( $_POST[ $key_prefix . $attribute_key ] ) : ''; + } + + if ( $attribute->is_taxonomy() ) { + // Don't use wc_clean as it destroys sanitized characters. + $value = sanitize_title( $value ); + } else { + $value = html_entity_decode( wc_clean( $value ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // WPCS: sanitization ok. } - $value = $attribute->is_taxonomy() ? sanitize_title( $value ) : wc_clean( $value ); // Don't use wc_clean as it destroys sanitized characters in terms. $attributes[ $attribute_key ] = $value; } } diff --git a/includes/class-wc-form-handler.php b/includes/class-wc-form-handler.php index 8e7bc9e924b..d4dd56c824f 100644 --- a/includes/class-wc-form-handler.php +++ b/includes/class-wc-form-handler.php @@ -887,7 +887,7 @@ class WC_Form_Handler { // Don't use wc_clean as it destroys sanitized characters. $value = sanitize_title( wp_unslash( $_REQUEST[ $taxonomy ] ) ); } else { - $value = wc_clean( wp_unslash( $_REQUEST[ $taxonomy ] ) ); // WPCS: sanitization ok. + $value = html_entity_decode( wc_clean( wp_unslash( $_REQUEST[ $taxonomy ] ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // WPCS: sanitization ok. } // Allow if valid or show error. diff --git a/includes/wc-attribute-functions.php b/includes/wc-attribute-functions.php index f64e6400c34..22b8b1d1b9f 100644 --- a/includes/wc-attribute-functions.php +++ b/includes/wc-attribute-functions.php @@ -332,6 +332,8 @@ function wc_attributes_array_filter_variation( $attribute ) { * @return bool */ function wc_is_attribute_in_product_name( $attribute, $name ) { + $attribute = html_entity_decode( $attribute, ENT_QUOTES, get_bloginfo( 'charset' ) ); + $name = html_entity_decode( $name, ENT_QUOTES, get_bloginfo( 'charset' ) ); $is_in_name = stristr( $name, ' ' . $attribute . ',' ) || 0 === stripos( strrev( $name ), strrev( ' ' . $attribute ) ); return apply_filters( 'woocommerce_is_attribute_in_product_name', $is_in_name, $attribute, $name ); } From 2e08bfdb3369bbb51161455b55567ebf334244d0 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Mon, 20 Nov 2017 21:48:35 +0000 Subject: [PATCH 12/76] Tweak where meta gets sanitized before passing to comparison function --- includes/class-wc-order-item.php | 2 +- includes/wc-attribute-functions.php | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/includes/class-wc-order-item.php b/includes/class-wc-order-item.php index bde21c78e45..38ea6f73ca3 100644 --- a/includes/class-wc-order-item.php +++ b/includes/class-wc-order-item.php @@ -258,7 +258,7 @@ class WC_Order_Item extends WC_Data implements ArrayAccess { $meta->value = rawurldecode( (string) $meta->value ); $attribute_key = str_replace( 'attribute_', '', $meta->key ); $display_key = wc_attribute_label( $attribute_key, $product ); - $display_value = $meta->value; + $display_value = sanitize_text_field( $meta->value ); if ( taxonomy_exists( $attribute_key ) ) { $term = get_term_by( 'slug', $meta->value, $attribute_key ); diff --git a/includes/wc-attribute-functions.php b/includes/wc-attribute-functions.php index 22b8b1d1b9f..f64e6400c34 100644 --- a/includes/wc-attribute-functions.php +++ b/includes/wc-attribute-functions.php @@ -332,8 +332,6 @@ function wc_attributes_array_filter_variation( $attribute ) { * @return bool */ function wc_is_attribute_in_product_name( $attribute, $name ) { - $attribute = html_entity_decode( $attribute, ENT_QUOTES, get_bloginfo( 'charset' ) ); - $name = html_entity_decode( $name, ENT_QUOTES, get_bloginfo( 'charset' ) ); $is_in_name = stristr( $name, ' ' . $attribute . ',' ) || 0 === stripos( strrev( $name ), strrev( ' ' . $attribute ) ); return apply_filters( 'woocommerce_is_attribute_in_product_name', $is_in_name, $attribute, $name ); } From 9681a331e9e8c839dff0d19a6aa4f8999e0cc603 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Mon, 20 Nov 2017 20:19:09 -0200 Subject: [PATCH 13/76] Fixed coding standards --- includes/class-wc-query.php | 227 +++++++++++---------- includes/wc-page-functions.php | 71 +++---- includes/wc-template-functions.php | 309 ++++++++++++----------------- 3 files changed, 278 insertions(+), 329 deletions(-) diff --git a/includes/class-wc-query.php b/includes/class-wc-query.php index 762fdef6807..1234b708d08 100644 --- a/includes/class-wc-query.php +++ b/includes/class-wc-query.php @@ -3,7 +3,7 @@ * Contains the query functions for WooCommerce which alter the front-end post queries and loops * * @version 3.2.0 - * @package WooCommerce/Classes + * @package WooCommerce\Classes * @author Automattic */ @@ -50,7 +50,9 @@ class WC_Query { * Get any errors from querystring. */ public function get_errors() { - if ( ! empty( $_GET['wc_error'] ) && ( $error = sanitize_text_field( $_GET['wc_error'] ) ) && ! wc_has_notice( $error, 'error' ) ) { + $error = ! empty( $_GET['wc_error'] ) ? sanitize_text_field( wp_unslash( $_GET['wc_error'] ) ) : ''; // WPCS: input var ok, CSRF ok. + + if ( $error && ! wc_has_notice( $error, 'error' ) ) { wc_add_notice( $error, 'error' ); } } @@ -81,53 +83,54 @@ class WC_Query { /** * Get page title for an endpoint. - * @param string + * + * @param string $endpoint Endpoint key. * @return string */ public function get_endpoint_title( $endpoint ) { global $wp; switch ( $endpoint ) { - case 'order-pay' : + case 'order-pay': $title = __( 'Pay for order', 'woocommerce' ); - break; - case 'order-received' : + break; + case 'order-received': $title = __( 'Order received', 'woocommerce' ); - break; - case 'orders' : + break; + case 'orders': if ( ! empty( $wp->query_vars['orders'] ) ) { /* translators: %s: page */ $title = sprintf( __( 'Orders (page %d)', 'woocommerce' ), intval( $wp->query_vars['orders'] ) ); } else { $title = __( 'Orders', 'woocommerce' ); } - break; - case 'view-order' : + break; + case 'view-order': $order = wc_get_order( $wp->query_vars['view-order'] ); /* translators: %s: order number */ $title = ( $order ) ? sprintf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ) : ''; - break; - case 'downloads' : + break; + case 'downloads': $title = __( 'Downloads', 'woocommerce' ); - break; - case 'edit-account' : + break; + case 'edit-account': $title = __( 'Account details', 'woocommerce' ); - break; - case 'edit-address' : + break; + case 'edit-address': $title = __( 'Addresses', 'woocommerce' ); - break; - case 'payment-methods' : + break; + case 'payment-methods': $title = __( 'Payment methods', 'woocommerce' ); - break; - case 'add-payment-method' : + break; + case 'add-payment-method': $title = __( 'Add payment method', 'woocommerce' ); - break; - case 'lost-password' : + break; + case 'lost-password': $title = __( 'Lost password', 'woocommerce' ); - break; - default : + break; + default: $title = ''; - break; + break; } return apply_filters( 'woocommerce_endpoint_' . $endpoint . '_title', $title, $endpoint ); @@ -145,7 +148,7 @@ class WC_Query { $myaccount_page_id = get_option( 'woocommerce_myaccount_page_id' ); $checkout_page_id = get_option( 'woocommerce_checkout_page_id' ); - if ( in_array( $page_on_front, array( $myaccount_page_id, $checkout_page_id ) ) ) { + if ( in_array( $page_on_front, array( $myaccount_page_id, $checkout_page_id ), true ) ) { return EP_ROOT | EP_PAGES; } } @@ -170,7 +173,8 @@ class WC_Query { * Add query vars. * * @access public - * @param array $vars + * + * @param array $vars Query vars. * @return array */ public function add_query_vars( $vars ) { @@ -210,10 +214,10 @@ class WC_Query { public function parse_request() { global $wp; - // Map query vars to their keys, or get them if endpoints are not supported + // Map query vars to their keys, or get them if endpoints are not supported. foreach ( $this->get_query_vars() as $key => $var ) { - if ( isset( $_GET[ $var ] ) ) { - $wp->query_vars[ $key ] = $_GET[ $var ]; + if ( isset( $_GET[ $var ] ) ) { // WPCS: input var ok, CSRF ok. + $wp->query_vars[ $key ] = sanitize_text_field( wp_unslash( $_GET[ $var ] ) ); // WPCS: input var ok, CSRF ok. } elseif ( isset( $wp->query_vars[ $var ] ) ) { $wp->query_vars[ $key ] = $wp->query_vars[ $var ]; } @@ -223,8 +227,7 @@ class WC_Query { /** * Are we currently on the front page? * - * @param object $q - * + * @param WP_Query $q Query instance. * @return bool */ private function is_showing_page_on_front( $q ) { @@ -234,8 +237,7 @@ class WC_Query { /** * Is the front page a page we define? * - * @param int $page_id - * + * @param int $page_id Page ID. * @return bool */ private function page_on_front_is( $page_id ) { @@ -245,7 +247,7 @@ class WC_Query { /** * Hook into pre_get_posts to do the main product query. * - * @param object $q query object + * @param WP_Query $q Query instance. */ public function pre_get_posts( $q ) { // We only want to affect the main query. @@ -253,7 +255,7 @@ class WC_Query { return; } - // Fix for endpoints on the homepage + // Fix for endpoints on the homepage. if ( $this->is_showing_page_on_front( $q ) && ! $this->page_on_front_is( $q->get( 'page_id' ) ) ) { $_query = wp_parse_args( $q->query ); if ( ! empty( $_query ) && array_intersect( array_keys( $_query ), array_keys( $this->get_query_vars() ) ) ) { @@ -276,14 +278,14 @@ class WC_Query { } } - // Fix product feeds + // Fix product feeds. if ( $q->is_feed() && $q->is_post_type_archive( 'product' ) ) { $q->is_comment_feed = false; } - // Special check for shops with the product archive on front + // Special check for shops with the product archive on front. if ( $q->is_page() && 'page' === get_option( 'show_on_front' ) && absint( $q->get( 'page_id' ) ) === wc_get_page_id( 'shop' ) ) { - // This is a front-page shop + // This is a front-page shop. $q->set( 'post_type', 'product' ); $q->set( 'page_id', '' ); @@ -291,54 +293,55 @@ class WC_Query { $q->set( 'paged', $q->query['paged'] ); } - // Define a variable so we know this is the front page shop later on + // Define a variable so we know this is the front page shop later on. wc_maybe_define_constant( 'SHOP_IS_ON_FRONT', true ); - // Get the actual WP page to avoid errors and let us use is_front_page() - // This is hacky but works. Awaiting https://core.trac.wordpress.org/ticket/21096 + // Get the actual WP page to avoid errors and let us use is_front_page(). + // This is hacky but works. Awaiting https://core.trac.wordpress.org/ticket/21096. global $wp_post_types; - $shop_page = get_post( wc_get_page_id( 'shop' ) ); + $shop_page = get_post( wc_get_page_id( 'shop' ) ); - $wp_post_types['product']->ID = $shop_page->ID; - $wp_post_types['product']->post_title = $shop_page->post_title; - $wp_post_types['product']->post_name = $shop_page->post_name; - $wp_post_types['product']->post_type = $shop_page->post_type; - $wp_post_types['product']->ancestors = get_ancestors( $shop_page->ID, $shop_page->post_type ); + $wp_post_types['product']->ID = $shop_page->ID; + $wp_post_types['product']->post_title = $shop_page->post_title; + $wp_post_types['product']->post_name = $shop_page->post_name; + $wp_post_types['product']->post_type = $shop_page->post_type; + $wp_post_types['product']->ancestors = get_ancestors( $shop_page->ID, $shop_page->post_type ); - // Fix conditional Functions like is_front_page + // Fix conditional Functions like is_front_page. $q->is_singular = false; $q->is_post_type_archive = true; $q->is_archive = true; $q->is_page = true; - // Remove post type archive name from front page title tag + // Remove post type archive name from front page title tag. add_filter( 'post_type_archive_title', '__return_empty_string', 5 ); - // Fix WP SEO + // Fix WP SEO. if ( class_exists( 'WPSEO_Meta' ) ) { add_filter( 'wpseo_metadesc', array( $this, 'wpseo_metadesc' ) ); add_filter( 'wpseo_metakey', array( $this, 'wpseo_metakey' ) ); } - - // Only apply to product categories, the product post archive, the shop page, product tags, and product attribute taxonomies } elseif ( ! $q->is_post_type_archive( 'product' ) && ! $q->is_tax( get_object_taxonomies( 'product' ) ) ) { + // Only apply to product categories, the product post archive, the shop page, product tags, and product attribute taxonomies. return; } $this->product_query( $q ); - // And remove the pre_get_posts hook + // And remove the pre_get_posts hook. $this->remove_product_query(); } /** * Search post excerpt. + * * @deprecated 3.2.0 - Not needed anymore since WordPress 4.5. + * @param string $deprecated Deprecated. */ - public function search_post_excerpt( $where = '' ) { + public function search_post_excerpt( $deprecated = '' ) { wc_deprecated_function( 'WC_Query::search_post_excerpt', '3.2.0', 'Excerpt added to search query by default since WordPress 4.5.' ); - return $where; + return $deprecated; } /** @@ -346,7 +349,6 @@ class WC_Query { * * Hooked into wpseo_ hook already, so no need for function_exist. * - * @access public * @return string */ public function wpseo_metadesc() { @@ -366,9 +368,10 @@ class WC_Query { } /** - * Query the products, applying sorting/ordering etc. This applies to the main wordpress loop. + * Query the products, applying sorting/ordering etc. + * This applies to the main WordPress loop. * - * @param mixed $q + * @param WP_Query $q Query instance. */ public function product_query( $q ) { if ( ! is_feed() ) { @@ -381,7 +384,7 @@ class WC_Query { } } - // Query vars that affect posts shown + // Query vars that affect posts shown. $q->set( 'meta_query', $this->get_meta_query( $q->get( 'meta_query' ), true ) ); $q->set( 'tax_query', $this->get_tax_query( $q->get( 'tax_query' ), true ) ); $q->set( 'posts_per_page', $q->get( 'posts_per_page' ) ? $q->get( 'posts_per_page' ) : apply_filters( 'loop_shop_per_page', get_option( 'posts_per_page' ) ) ); @@ -391,7 +394,6 @@ class WC_Query { do_action( 'woocommerce_product_query', $q, $this ); } - /** * Remove the query. */ @@ -411,6 +413,7 @@ class WC_Query { /** * Remove the posts_where filter. + * * @deprecated 3.2.0 - Nothing to remove anymore because search_post_excerpt() is deprecated. */ public function remove_posts_where() { @@ -420,19 +423,17 @@ class WC_Query { /** * Returns an array of arguments for ordering products based on the selected values. * - * @access public - * - * @param string $orderby - * @param string $order + * @param string $orderby Order by. + * @param string $order Sorting order. * * @return array */ public function get_catalog_ordering_args( $orderby = '', $order = '' ) { - // Get ordering from query string unless defined + // Get ordering from query string unless defined. if ( ! $orderby ) { - $orderby_value = isset( $_GET['orderby'] ) ? wc_clean( (string) $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) ); + $orderby_value = isset( $_GET['orderby'] ) ? wc_clean( wp_unslash( (string) $_GET['orderby'] ) ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) ); // WPCS: input var ok, CSRF ok. - // Get order + orderby args from string + // Get order + orderby args from string. $orderby_value = explode( '-', $orderby_value ); $orderby = esc_attr( $orderby_value[0] ); $order = ! empty( $orderby_value[1] ) ? $orderby_value[1] : $order; @@ -443,49 +444,49 @@ class WC_Query { $args = array( 'orderby' => 'relevance', 'order' => 'DESC', - 'meta_key' => '', + 'meta_key' => '', // WPCS: slow query ok. ); // Set to default. Menu order for non-searches, relevance for searches. if ( ! is_search() ) { $args['orderby'] = 'menu_order title'; $args['order'] = ( 'DESC' === $order ) ? 'DESC' : 'ASC'; - $args['meta_key'] = ''; + $args['meta_key'] = ''; // WPCS: slow query ok. } switch ( $orderby ) { - case 'rand' : + case 'rand': $args['orderby'] = 'rand'; break; - case 'date' : + case 'date': $args['orderby'] = 'date ID'; $args['order'] = ( 'ASC' === $order ) ? 'ASC' : 'DESC'; break; - case 'price' : + case 'price': if ( 'DESC' === $order ) { add_filter( 'posts_clauses', array( $this, 'order_by_price_desc_post_clauses' ) ); } else { add_filter( 'posts_clauses', array( $this, 'order_by_price_asc_post_clauses' ) ); } break; - case 'popularity' : - $args['meta_key'] = 'total_sales'; + case 'popularity': + $args['meta_key'] = 'total_sales'; // WPCS: slow query ok. - // Sorting handled later though a hook + // Sorting handled later though a hook. add_filter( 'posts_clauses', array( $this, 'order_by_popularity_post_clauses' ) ); break; - case 'rating' : - $args['meta_key'] = '_wc_average_rating'; + case 'rating': + $args['meta_key'] = '_wc_average_rating'; // WPCS: slow query ok. $args['orderby'] = array( 'meta_value_num' => 'DESC', 'ID' => 'ASC', ); break; - case 'title' : + case 'title': $args['orderby'] = 'title'; $args['order'] = ( 'DESC' === $order ) ? 'DESC' : 'ASC'; break; - case 'relevance' : + case 'relevance': $args['orderby'] = 'relevance'; $args['order'] = 'DESC'; break; @@ -497,8 +498,7 @@ class WC_Query { /** * Handle numeric price sorting. * - * @access public - * @param array $args + * @param array $args Query args. * @return array */ public function order_by_price_asc_post_clauses( $args ) { @@ -527,8 +527,7 @@ class WC_Query { /** * Handle numeric price sorting. * - * @access public - * @param array $args + * @param array $args Query args. * @return array */ public function order_by_price_desc_post_clauses( $args ) { @@ -560,8 +559,7 @@ class WC_Query { * * This lets us sort by meta value desc, and have a second orderby param. * - * @access public - * @param array $args + * @param array $args Query args. * @return array */ public function order_by_popularity_post_clauses( $args ) { @@ -574,7 +572,7 @@ class WC_Query { * Order by rating post clauses. * * @deprecated 3.0.0 - * @param array $args + * @param array $args Query args. * @return array */ public function order_by_rating_post_clauses( $args ) { @@ -597,8 +595,8 @@ class WC_Query { /** * Appends meta queries to an array. * - * @param array $meta_query - * @param bool $main_query + * @param array $meta_query Meta query. + * @param bool $main_query If is main query. * @return array */ public function get_meta_query( $meta_query = array(), $main_query = false ) { @@ -611,18 +609,21 @@ class WC_Query { /** * Appends tax queries to an array. - * @param array $tax_query - * @param bool $main_query + * + * @param array $tax_query Tax query. + * @param bool $main_query If is main query. * @return array */ public function get_tax_query( $tax_query = array(), $main_query = false ) { if ( ! is_array( $tax_query ) ) { - $tax_query = array( 'relation' => 'AND' ); + $tax_query = array( + 'relation' => 'AND', + ); } // Layered nav filters on terms. - if ( $main_query && ( $_chosen_attributes = $this->get_layered_nav_chosen_attributes() ) ) { - foreach ( $_chosen_attributes as $taxonomy => $data ) { + if ( $main_query ) { + foreach ( $this->get_layered_nav_chosen_attributes() as $taxonomy => $data ) { $tax_query[] = array( 'taxonomy' => $taxonomy, 'field' => 'slug', @@ -642,11 +643,11 @@ class WC_Query { } // Filter by rating. - if ( isset( $_GET['rating_filter'] ) ) { - $rating_filter = array_filter( array_map( 'absint', explode( ',', $_GET['rating_filter'] ) ) ); + if ( isset( $_GET['rating_filter'] ) ) { // WPCS: input var ok, CSRF ok. + $rating_filter = array_filter( array_map( 'absint', explode( ',', $_GET['rating_filter'] ) ) ); // WPCS: input var ok, CSRF ok, Sanitization ok. $rating_terms = array(); for ( $i = 1; $i <= 5; $i ++ ) { - if ( in_array( $i, $rating_filter ) && isset( $product_visibility_terms[ 'rated-' . $i ] ) ) { + if ( in_array( $i, $rating_filter, true ) && isset( $product_visibility_terms[ 'rated-' . $i ] ) ) { $rating_terms[] = $product_visibility_terms[ 'rated-' . $i ]; } } @@ -675,11 +676,12 @@ class WC_Query { /** * Return a meta query for filtering by price. + * * @return array */ private function price_filter_meta_query() { - if ( isset( $_GET['max_price'] ) || isset( $_GET['min_price'] ) ) { - $meta_query = wc_get_min_max_price_meta_query( $_GET ); + if ( isset( $_GET['max_price'] ) || isset( $_GET['min_price'] ) ) { // WPCS: input var ok, CSRF ok. + $meta_query = wc_get_min_max_price_meta_query( $_GET ); // WPCS: input var ok, CSRF ok. $meta_query['price_filter'] = true; return $meta_query; @@ -702,7 +704,7 @@ class WC_Query { * Returns a meta query to handle product visibility. * * @deprecated 3.0.0 Replaced with taxonomy. - * @param string $compare (default: 'IN') + * @param string $compare Compare type. * @return array */ public function visibility_meta_query( $compare = 'IN' ) { @@ -713,7 +715,7 @@ class WC_Query { * Returns a meta query to handle product stock status. * * @deprecated 3.0.0 Replaced with taxonomy. - * @param string $status (default: 'instock') + * @param string $status Status. * @return array */ public function stock_status_meta_query( $status = 'instock' ) { @@ -722,6 +724,7 @@ class WC_Query { /** * Get the tax query which was used by the main query. + * * @return array */ public static function get_main_tax_query() { @@ -734,6 +737,7 @@ class WC_Query { /** * Get the meta query which was used by the main query. + * * @return array */ public static function get_main_meta_query() { @@ -769,7 +773,7 @@ class WC_Query { } $like = '%' . $wpdb->esc_like( $term ) . '%'; - $sql[] = $wpdb->prepare( "(($wpdb->posts.post_title $like_op %s) $andor_op ($wpdb->posts.post_excerpt $like_op %s) $andor_op ($wpdb->posts.post_content $like_op %s))", $like, $like, $like ); + $sql[] = $wpdb->prepare( "(($wpdb->posts.post_title $like_op %s) $andor_op ($wpdb->posts.post_excerpt $like_op %s) $andor_op ($wpdb->posts.post_content $like_op %s))", $like, $like, $like ); // WPCS: db call ok, cache ok, unprepared SQL ok. } if ( ! empty( $sql ) && ! is_user_logged_in() ) { @@ -781,23 +785,26 @@ class WC_Query { /** * Layered Nav Init. + * + * @return array */ public static function get_layered_nav_chosen_attributes() { if ( ! is_array( self::$_chosen_attributes ) ) { self::$_chosen_attributes = array(); - if ( $attribute_taxonomies = wc_get_attribute_taxonomies() ) { + $attribute_taxonomies = wc_get_attribute_taxonomies(); + if ( $attribute_taxonomies ) { foreach ( $attribute_taxonomies as $tax ) { $attribute = wc_sanitize_taxonomy_name( $tax->attribute_name ); $taxonomy = wc_attribute_taxonomy_name( $attribute ); - $filter_terms = ! empty( $_GET[ 'filter_' . $attribute ] ) ? explode( ',', wc_clean( $_GET[ 'filter_' . $attribute ] ) ) : array(); + $filter_terms = ! empty( $_GET[ 'filter_' . $attribute ] ) ? explode( ',', wc_clean( wp_unslash( $_GET[ 'filter_' . $attribute ] ) ) ) : array(); // WPCS: input var ok, CSRF ok. if ( empty( $filter_terms ) || ! taxonomy_exists( $taxonomy ) ) { continue; } - $query_type = ! empty( $_GET[ 'query_type_' . $attribute ] ) && in_array( $_GET[ 'query_type_' . $attribute ], array( 'and', 'or' ) ) ? wc_clean( $_GET[ 'query_type_' . $attribute ] ) : ''; - self::$_chosen_attributes[ $taxonomy ]['terms'] = array_map( 'sanitize_title', $filter_terms ); // Ensures correct encoding + $query_type = ! empty( $_GET[ 'query_type_' . $attribute ] ) && in_array( wp_unslash( $_GET[ 'query_type_' . $attribute ] ), array( 'and', 'or' ), true ) ? wc_clean( wp_unslash( $_GET[ 'query_type_' . $attribute ] ) ) : ''; // WPCS: input var ok, CSRF ok. + self::$_chosen_attributes[ $taxonomy ]['terms'] = array_map( 'sanitize_title', $filter_terms ); // Ensures correct encoding. self::$_chosen_attributes[ $taxonomy ]['query_type'] = $query_type ? $query_type : apply_filters( 'woocommerce_layered_nav_default_query_type', 'and' ); } } @@ -806,6 +813,8 @@ class WC_Query { } /** + * Layered nav init. + * * @deprecated 2.6.0 */ public function layered_nav_init() { @@ -814,6 +823,7 @@ class WC_Query { /** * Get an unpaginated list all product IDs (both filtered and unfiltered). Makes use of transients. + * * @deprecated 2.6.0 due to performance concerns */ public function get_products_in_view() { @@ -822,11 +832,12 @@ class WC_Query { /** * Layered Nav post filter. + * * @deprecated 2.6.0 due to performance concerns * - * @param $filtered_posts + * @param mixed $deprecated Deprecated. */ - public function layered_nav_query( $filtered_posts ) { + public function layered_nav_query( $deprecated ) { wc_deprecated_function( 'layered_nav_query', '2.6' ); } } diff --git a/includes/wc-page-functions.php b/includes/wc-page-functions.php index 2b28b31087d..17b2d241d9e 100644 --- a/includes/wc-page-functions.php +++ b/includes/wc-page-functions.php @@ -4,30 +4,29 @@ * * Functions related to pages and menus. * - * @author WooThemes + * @author Automattic * @category Core - * @package WooCommerce/Functions + * @package WooCommerce\Functions * @version 2.6.0 */ if ( ! defined( 'ABSPATH' ) ) { - exit; // Exit if accessed directly + exit; // Exit if accessed directly. } /** * Replace a page title with the endpoint title. - * @param string $title + * + * @param string $title Post title. * @return string */ function wc_page_endpoint_title( $title ) { global $wp_query; if ( ! is_null( $wp_query ) && ! is_admin() && is_main_query() && in_the_loop() && is_page() && is_wc_endpoint_url() ) { - $endpoint = WC()->query->get_current_endpoint(); - - if ( $endpoint_title = WC()->query->get_endpoint_title( $endpoint ) ) { - $title = $endpoint_title; - } + $endpoint = WC()->query->get_current_endpoint(); + $endpoint_title = WC()->query->get_endpoint_title( $endpoint ); + $title = $endpoint_title ? $endpoint_title : $title; remove_filter( 'the_title', 'wc_page_endpoint_title' ); } @@ -40,12 +39,11 @@ add_filter( 'the_title', 'wc_page_endpoint_title' ); /** * Retrieve page ids - used for myaccount, edit_address, shop, cart, checkout, pay, view_order, terms. returns -1 if no page is found. * - * @param string $page + * @param string $page Page slug. * @return int */ function wc_get_page_id( $page ) { - - if ( 'pay' == $page || 'thanks' == $page ) { + if ( 'pay' === $page || 'thanks' === $page ) { wc_deprecated_argument( __FUNCTION__, '2.1', 'The "pay" and "thanks" pages are no-longer used - an endpoint is added to the checkout instead. To get a valid link use the WC_Order::get_checkout_payment_url() or WC_Order::get_checkout_order_received_url() methods instead.' ); $page = 'checkout'; @@ -64,7 +62,7 @@ function wc_get_page_id( $page ) { /** * Retrieve page permalink. * - * @param string $page + * @param string $page page slug. * @return string */ function wc_get_page_permalink( $page ) { @@ -78,9 +76,9 @@ function wc_get_page_permalink( $page ) { * * Gets the URL for an endpoint, which varies depending on permalink settings. * - * @param string $endpoint - * @param string $value - * @param string $permalink + * @param string $endpoint Endpoint slug. + * @param string $value Query param value. + * @param string $permalink Permalink. * * @return string */ @@ -91,12 +89,12 @@ function wc_get_endpoint_url( $endpoint, $value = '', $permalink = '' ) { // Map endpoint to options. $query_vars = WC()->query->get_query_vars(); - $endpoint = ! empty( $query_vars[ $endpoint ] ) ? $query_vars[ $endpoint ]: $endpoint; + $endpoint = ! empty( $query_vars[ $endpoint ] ) ? $query_vars[ $endpoint ] : $endpoint; $value = ( get_option( 'woocommerce_myaccount_edit_address_endpoint', 'edit-address' ) === $endpoint ) ? wc_edit_address_i18n( $value ) : $value; if ( get_option( 'permalink_structure' ) ) { if ( strstr( $permalink, '?' ) ) { - $query_string = '?' . parse_url( $permalink, PHP_URL_QUERY ); + $query_string = '?' . wp_parse_url( $permalink, PHP_URL_QUERY ); $permalink = current( explode( '?', $permalink ) ); } else { $query_string = ''; @@ -124,8 +122,8 @@ function wc_nav_menu_items( $items ) { if ( empty( $item->url ) ) { continue; } - $path = parse_url( $item->url, PHP_URL_PATH ); - $query = parse_url( $item->url, PHP_URL_QUERY ); + $path = wp_parse_url( $item->url, PHP_URL_PATH ); + $query = wp_parse_url( $item->url, PHP_URL_QUERY ); if ( strstr( $path, $customer_logout ) || strstr( $query, $customer_logout ) ) { unset( $items[ $key ] ); @@ -142,43 +140,41 @@ add_filter( 'wp_nav_menu_objects', 'wc_nav_menu_items', 10 ); /** * Fix active class in nav for shop page. * - * @param array $menu_items + * @param array $menu_items Menu items. * @return array */ function wc_nav_menu_item_classes( $menu_items ) { - if ( ! is_woocommerce() ) { return $menu_items; } - $shop_page = (int) wc_get_page_id( 'shop' ); + $shop_page = (int) wc_get_page_id( 'shop' ); $page_for_posts = (int) get_option( 'page_for_posts' ); if ( ! empty( $menu_items ) && is_array( $menu_items ) ) { foreach ( $menu_items as $key => $menu_item ) { - $classes = (array) $menu_item->classes; + $menu_id = (int) $menu_item->object_id; - // Unset active class for blog page - if ( $page_for_posts == $menu_item->object_id ) { + // Unset active class for blog page. + if ( $page_for_posts === $menu_id ) { $menu_items[ $key ]->current = false; - if ( in_array( 'current_page_parent', $classes ) ) { - unset( $classes[ array_search( 'current_page_parent', $classes ) ] ); + if ( in_array( 'current_page_parent', $classes, true ) ) { + unset( $classes[ array_search( 'current_page_parent', $classes, true ) ] ); } - if ( in_array( 'current-menu-item', $classes ) ) { - unset( $classes[ array_search( 'current-menu-item', $classes ) ] ); + if ( in_array( 'current-menu-item', $classes, true ) ) { + unset( $classes[ array_search( 'current-menu-item', $classes, true ) ] ); } - - // Set active state if this is the shop page link - } elseif ( is_shop() && $shop_page == $menu_item->object_id && 'page' === $menu_item->object ) { + } elseif ( is_shop() && $shop_page === $menu_id && 'page' === $menu_item->object ) { + // Set active state if this is the shop page link. $menu_items[ $key ]->current = true; $classes[] = 'current-menu-item'; $classes[] = 'current_page_item'; - // Set parent state if this is a product page - } elseif ( is_singular( 'product' ) && $shop_page == $menu_item->object_id ) { + } elseif ( is_singular( 'product' ) && $shop_page === $menu_id ) { + // Set parent state if this is a product page. $classes[] = 'current_page_parent'; } @@ -194,10 +190,9 @@ add_filter( 'wp_nav_menu_objects', 'wc_nav_menu_item_classes', 2 ); /** * Fix active class in wp_list_pages for shop page. * - * https://github.com/woocommerce/woocommerce/issues/177. + * See details in https://github.com/woocommerce/woocommerce/issues/177. * - * @author Jessor, Peter Sterling - * @param string $pages + * @param string $pages Pages list. * @return string */ function wc_list_pages( $pages ) { diff --git a/includes/wc-template-functions.php b/includes/wc-template-functions.php index b728216df5c..f482fa15c95 100644 --- a/includes/wc-template-functions.php +++ b/includes/wc-template-functions.php @@ -4,9 +4,9 @@ * * Functions for the templating system. * - * @author WooThemes + * @author Automattic * @category Core - * @package WooCommerce/Functions + * @package WooCommerce\Functions * @version 2.5.0 */ @@ -20,7 +20,7 @@ if ( ! defined( 'ABSPATH' ) ) { function wc_template_redirect() { global $wp_query, $wp; - if ( ! empty( $_GET['page_id'] ) && '' === get_option( 'permalink_structure' ) && wc_get_page_id( 'shop' ) == $_GET['page_id'] ) { + if ( ! empty( $_GET['page_id'] ) && '' === get_option( 'permalink_structure' ) && wc_get_page_id( 'shop' ) === absint( $_GET['page_id'] ) ) { // WPCS: input var ok, CSRF ok. // When default permalinks are enabled, redirect shop page to post type archive url. wp_safe_redirect( get_post_type_archive_link( 'product' ) ); @@ -33,11 +33,7 @@ function wc_template_redirect() { wp_redirect( wc_get_page_permalink( 'cart' ) ); exit; - } elseif ( - isset( $wp->query_vars['customer-logout'] ) && - ! empty( $_REQUEST['_wpnonce'] ) && - wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'customer-logout' ) - ) { + } elseif ( isset( $wp->query_vars['customer-logout'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_REQUEST['_wpnonce'] ), 'customer-logout' ) ) { // WPCS: input var ok, CSRF ok. // Logout. wp_redirect( str_replace( '&', '&', wp_logout_url( wc_get_page_permalink( 'myaccount' ) ) ) ); @@ -97,8 +93,8 @@ add_action( 'template_redirect', 'wc_send_frame_options_header' ); * @since 2.5.3 */ function wc_prevent_endpoint_indexing() { - if ( is_wc_endpoint_url() || isset( $_GET['download_file'] ) ) { - @header( 'X-Robots-Tag: noindex' ); + if ( is_wc_endpoint_url() || isset( $_GET['download_file'] ) ) { // WPCS: input var ok, CSRF ok. + @header( 'X-Robots-Tag: noindex' ); // @codingStandardsIgnoreLine } } add_action( 'template_redirect', 'wc_prevent_endpoint_indexing' ); @@ -142,7 +138,7 @@ function wc_setup_product_data( $post ) { $the_post = $post; } - if ( empty( $the_post->post_type ) || ! in_array( $the_post->post_type, array( 'product', 'product_variation' ) ) ) { + if ( empty( $the_post->post_type ) || ! in_array( $the_post->post_type, array( 'product', 'product_variation' ), true ) ) { return; } @@ -156,8 +152,6 @@ if ( ! function_exists( 'woocommerce_reset_loop' ) ) { /** * Reset the loop's index and columns when we're done outputting a product loop. - * - * @subpackage Loop */ function woocommerce_reset_loop() { $GLOBALS['woocommerce_loop'] = array( @@ -189,6 +183,7 @@ function wc_products_rss_feed() { if ( $term ) { $feed = add_query_arg( 'product_cat', $term->slug, get_post_type_archive_feed_link( 'product' ) ); + /* translators: %s: category name */ echo ''; } } elseif ( is_tax( 'product_tag' ) ) { @@ -197,7 +192,8 @@ function wc_products_rss_feed() { if ( $term ) { $feed = add_query_arg( 'product_tag', $term->slug, get_post_type_archive_feed_link( 'product' ) ); - echo ''; + /* translators: %s: tag name */ + echo ''; } } } @@ -289,7 +285,7 @@ function wc_product_cat_class( $class = '', $category = null ) { function wc_get_loop_class() { global $woocommerce_loop; - $woocommerce_loop['loop'] = ! empty( $woocommerce_loop['loop'] ) ? $woocommerce_loop['loop'] + 1 : 1; + $woocommerce_loop['loop'] = ! empty( $woocommerce_loop['loop'] ) ? $woocommerce_loop['loop'] + 1 : 1; $woocommerce_loop['columns'] = max( 1, ! empty( $woocommerce_loop['columns'] ) ? $woocommerce_loop['columns'] : apply_filters( 'loop_shop_columns', 4 ) ); if ( 0 === ( $woocommerce_loop['loop'] - 1 ) % $woocommerce_loop['columns'] || 1 === $woocommerce_loop['columns'] ) { @@ -331,7 +327,7 @@ function wc_get_product_cat_class( $class = '', $category = null ) { * @return array */ function wc_product_post_class( $classes, $class = '', $post_id = '' ) { - if ( ! $post_id || ! in_array( get_post_type( $post_id ), array( 'product', 'product_variation' ) ) ) { + if ( ! $post_id || ! in_array( get_post_type( $post_id ), array( 'product', 'product_variation' ), true ) ) { return $classes; } @@ -379,7 +375,8 @@ function wc_product_post_class( $classes, $class = '', $post_id = '' ) { } } - if ( false !== ( $key = array_search( 'hentry', $classes ) ) ) { + $key = array_search( 'hentry', $classes, true ); + if ( false !== $key ) { unset( $classes[ $key ] ); } @@ -398,7 +395,7 @@ function wc_product_post_class( $classes, $class = '', $post_id = '' ) { */ function wc_query_string_form_fields( $values = null, $exclude = array(), $current_key = '', $return = false ) { if ( is_null( $values ) ) { - $values = $_GET; + $values = $_GET; // WPCS: input var ok, CSRF ok. } $html = ''; @@ -440,13 +437,13 @@ if ( ! function_exists( 'woocommerce_content' ) ) { if ( is_singular( 'product' ) ) { - while ( have_posts() ) : the_post(); - + while ( have_posts() ) : + the_post(); wc_get_template_part( 'content', 'single-product' ); - endwhile; - } else { ?> + } else { + ?> @@ -464,7 +461,8 @@ if ( ! function_exists( 'woocommerce_content' ) ) { - + + @@ -474,12 +472,17 @@ if ( ! function_exists( 'woocommerce_content' ) ) { - woocommerce_product_loop_start( false ), 'after' => woocommerce_product_loop_end( false ) ) ) ) : ?> + woocommerce_product_loop_start( false ), + 'after' => woocommerce_product_loop_end( false ), + ) ) ) : + ?> - 1, 'class' => implode( ' ', array_filter( array( - 'button', - 'product_type_' . $product->get_type(), - $product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '', - $product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : '', + 'button', + 'product_type_' . $product->get_type(), + $product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '', + $product->supports( 'ajax_add_to_cart' ) ? 'ajax_add_to_cart' : '', ) ) ), ); @@ -748,8 +749,6 @@ if ( ! function_exists( 'woocommerce_template_loop_product_thumbnail' ) ) { /** * Get the product thumbnail for the loop. - * - * @subpackage Loop */ function woocommerce_template_loop_product_thumbnail() { echo woocommerce_get_product_thumbnail(); // WPCS: XSS ok. @@ -759,8 +758,6 @@ if ( ! function_exists( 'woocommerce_template_loop_price' ) ) { /** * Get the product price for the loop. - * - * @subpackage Loop */ function woocommerce_template_loop_price() { wc_get_template( 'loop/price.php' ); @@ -770,8 +767,6 @@ if ( ! function_exists( 'woocommerce_template_loop_rating' ) ) { /** * Display the average rating in the loop. - * - * @subpackage Loop */ function woocommerce_template_loop_rating() { wc_get_template( 'loop/rating.php' ); @@ -781,8 +776,6 @@ if ( ! function_exists( 'woocommerce_show_product_loop_sale_flash' ) ) { /** * Get the sale flash for the loop. - * - * @subpackage Loop */ function woocommerce_show_product_loop_sale_flash() { wc_get_template( 'loop/sale-flash.php' ); @@ -794,7 +787,6 @@ if ( ! function_exists( 'woocommerce_get_product_thumbnail' ) ) { /** * Get the product thumbnail, or the placeholder if not set. * - * @subpackage Loop * @param string $size (default: 'woocommerce_thumbnail'). * @param int $deprecated1 Deprecated since WooCommerce 2.0 (default: 0). * @param int $deprecated2 Deprecated since WooCommerce 2.0 (default: 0). @@ -813,8 +805,6 @@ if ( ! function_exists( 'woocommerce_result_count' ) ) { /** * Output the result count text (Showing x - x of x results). - * - * @subpackage Loop */ function woocommerce_result_count() { wc_get_template( 'loop/result-count.php' ); @@ -825,8 +815,6 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) { /** * Output the product sorting options. - * - * @subpackage Loop */ function woocommerce_catalog_ordering() { global $wp_query; @@ -835,7 +823,7 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) { return; } - $orderby = isset( $_GET['orderby'] ) ? wc_clean( wp_unslash( $_GET['orderby'] ) ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) ); + $orderby = isset( $_GET['orderby'] ) ? wc_clean( wp_unslash( $_GET['orderby'] ) ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) ); // WPCS: input var ok, CSRF ok. $show_default_orderby = 'menu_order' === apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) ); $catalog_orderby_options = apply_filters( 'woocommerce_catalog_orderby', array( 'menu_order' => __( 'Default sorting', 'woocommerce' ), @@ -847,7 +835,9 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) { ) ); if ( $wp_query->is_search() ) { - $catalog_orderby_options = array_merge( array( 'relevance' => __( 'Relevance', 'woocommerce' ) ), $catalog_orderby_options ); + $catalog_orderby_options = array_merge( array( + 'relevance' => __( 'Relevance', 'woocommerce' ), + ), $catalog_orderby_options ); unset( $catalog_orderby_options['menu_order'] ); if ( 'menu_order' === $orderby ) { $orderby = 'relevance'; @@ -862,7 +852,11 @@ if ( ! function_exists( 'woocommerce_catalog_ordering' ) ) { unset( $catalog_orderby_options['rating'] ); } - wc_get_template( 'loop/orderby.php', array( 'catalog_orderby_options' => $catalog_orderby_options, 'orderby' => $orderby, 'show_default_orderby' => $show_default_orderby ) ); + wc_get_template( 'loop/orderby.php', array( + 'catalog_orderby_options' => $catalog_orderby_options, + 'orderby' => $orderby, + 'show_default_orderby' => $show_default_orderby, + ) ); } } @@ -870,8 +864,6 @@ if ( ! function_exists( 'woocommerce_pagination' ) ) { /** * Output the pagination. - * - * @subpackage Loop */ function woocommerce_pagination() { wc_get_template( 'loop/pagination.php' ); @@ -886,8 +878,6 @@ if ( ! function_exists( 'woocommerce_show_product_images' ) ) { /** * Output the product image before the single product summary. - * - * @subpackage Product */ function woocommerce_show_product_images() { wc_get_template( 'single-product/product-image.php' ); @@ -897,8 +887,6 @@ if ( ! function_exists( 'woocommerce_show_product_thumbnails' ) ) { /** * Output the product thumbnails. - * - * @subpackage Product */ function woocommerce_show_product_thumbnails() { wc_get_template( 'single-product/product-thumbnails.php' ); @@ -909,8 +897,6 @@ if ( ! function_exists( 'woocommerce_output_product_data_tabs' ) ) { /** * Output the product tabs. - * - * @subpackage Product/Tabs */ function woocommerce_output_product_data_tabs() { wc_get_template( 'single-product/tabs/tabs.php' ); @@ -920,8 +906,6 @@ if ( ! function_exists( 'woocommerce_template_single_title' ) ) { /** * Output the product title. - * - * @subpackage Product */ function woocommerce_template_single_title() { wc_get_template( 'single-product/title.php' ); @@ -931,8 +915,6 @@ if ( ! function_exists( 'woocommerce_template_single_rating' ) ) { /** * Output the product rating. - * - * @subpackage Product */ function woocommerce_template_single_rating() { if ( post_type_supports( 'product', 'comments' ) ) { @@ -944,8 +926,6 @@ if ( ! function_exists( 'woocommerce_template_single_price' ) ) { /** * Output the product price. - * - * @subpackage Product */ function woocommerce_template_single_price() { wc_get_template( 'single-product/price.php' ); @@ -955,8 +935,6 @@ if ( ! function_exists( 'woocommerce_template_single_excerpt' ) ) { /** * Output the product short description (excerpt). - * - * @subpackage Product */ function woocommerce_template_single_excerpt() { wc_get_template( 'single-product/short-description.php' ); @@ -966,8 +944,6 @@ if ( ! function_exists( 'woocommerce_template_single_meta' ) ) { /** * Output the product meta. - * - * @subpackage Product */ function woocommerce_template_single_meta() { wc_get_template( 'single-product/meta.php' ); @@ -977,8 +953,6 @@ if ( ! function_exists( 'woocommerce_template_single_sharing' ) ) { /** * Output the product sharing. - * - * @subpackage Product */ function woocommerce_template_single_sharing() { wc_get_template( 'single-product/share.php' ); @@ -988,8 +962,6 @@ if ( ! function_exists( 'woocommerce_show_product_sale_flash' ) ) { /** * Output the product sale flash. - * - * @subpackage Product */ function woocommerce_show_product_sale_flash() { wc_get_template( 'single-product/sale-flash.php' ); @@ -1000,8 +972,6 @@ if ( ! function_exists( 'woocommerce_template_single_add_to_cart' ) ) { /** * Trigger the single product add to cart action. - * - * @subpackage Product */ function woocommerce_template_single_add_to_cart() { global $product; @@ -1012,8 +982,6 @@ if ( ! function_exists( 'woocommerce_simple_add_to_cart' ) ) { /** * Output the simple product add to cart area. - * - * @subpackage Product */ function woocommerce_simple_add_to_cart() { wc_get_template( 'single-product/add-to-cart/simple.php' ); @@ -1023,8 +991,6 @@ if ( ! function_exists( 'woocommerce_grouped_add_to_cart' ) ) { /** * Output the grouped product add to cart area. - * - * @subpackage Product */ function woocommerce_grouped_add_to_cart() { global $product; @@ -1044,8 +1010,6 @@ if ( ! function_exists( 'woocommerce_variable_add_to_cart' ) ) { /** * Output the variable product add to cart area. - * - * @subpackage Product */ function woocommerce_variable_add_to_cart() { global $product; @@ -1068,8 +1032,6 @@ if ( ! function_exists( 'woocommerce_external_add_to_cart' ) ) { /** * Output the external product add to cart area. - * - * @subpackage Product */ function woocommerce_external_add_to_cart() { global $product; @@ -1139,8 +1101,6 @@ if ( ! function_exists( 'woocommerce_product_description_tab' ) ) { /** * Output the description tab content. - * - * @subpackage Product/Tabs */ function woocommerce_product_description_tab() { wc_get_template( 'single-product/tabs/description.php' ); @@ -1150,8 +1110,6 @@ if ( ! function_exists( 'woocommerce_product_additional_information_tab' ) ) { /** * Output the attributes tab content. - * - * @subpackage Product/Tabs */ function woocommerce_product_additional_information_tab() { wc_get_template( 'single-product/tabs/additional-information.php' ); @@ -1162,8 +1120,7 @@ if ( ! function_exists( 'woocommerce_product_reviews_tab' ) ) { /** * Output the reviews tab content. * - * @deprecated 2.4.0 Unused - * @subpackage Product/Tabs + * @deprecated 2.4.0 Unused. */ function woocommerce_product_reviews_tab() { wc_deprecated_function( 'woocommerce_product_reviews_tab', '2.4' ); @@ -1202,6 +1159,7 @@ if ( ! function_exists( 'woocommerce_default_product_tabs' ) ) { // Reviews tab - shows comments. if ( comments_open() ) { $tabs['reviews'] = array( + /* translators: %s: reviews count */ 'title' => sprintf( __( 'Reviews (%d)', 'woocommerce' ), $product->get_review_count() ), 'priority' => 30, 'callback' => 'comments_template', @@ -1224,7 +1182,7 @@ if ( ! function_exists( 'woocommerce_sort_product_tabs' ) ) { // Make sure the $tabs parameter is an array. if ( ! is_array( $tabs ) ) { - trigger_error( 'Function woocommerce_sort_product_tabs() expects an array as the first parameter. Defaulting to empty array.' ); + trigger_error( 'Function woocommerce_sort_product_tabs() expects an array as the first parameter. Defaulting to empty array.' ); // @codingStandardsIgnoreLine $tabs = array(); } @@ -1256,14 +1214,17 @@ if ( ! function_exists( 'woocommerce_comments' ) ) { /** * Output the Review comments template. * - * @subpackage Product * @param WP_Comment $comment Comment object. * @param array $args Arguments. * @param int $depth Depth. */ function woocommerce_comments( $comment, $args, $depth ) { $GLOBALS['comment'] = $comment; // WPCS: override ok. - wc_get_template( 'single-product/review.php', array( 'comment' => $comment, 'args' => $args, 'depth' => $depth ) ); + wc_get_template( 'single-product/review.php', array( + 'comment' => $comment, + 'args' => $args, + 'depth' => $depth, + ) ); } } @@ -1319,15 +1280,13 @@ if ( ! function_exists( 'woocommerce_output_related_products' ) ) { /** * Output the related products. - * - * @subpackage Product */ function woocommerce_output_related_products() { $args = array( - 'posts_per_page' => 4, - 'columns' => 4, - 'orderby' => 'rand', + 'posts_per_page' => 4, + 'columns' => 4, + 'orderby' => 'rand', ); woocommerce_related_products( apply_filters( 'woocommerce_output_related_products_args', $args ) ); @@ -1420,8 +1379,6 @@ if ( ! function_exists( 'woocommerce_shipping_calculator' ) ) { /** * Output the cart shipping calculator. - * - * @subpackage Cart */ function woocommerce_shipping_calculator() { wc_get_template( 'cart/shipping-calculator.php' ); @@ -1432,8 +1389,6 @@ if ( ! function_exists( 'woocommerce_cart_totals' ) ) { /** * Output the cart totals. - * - * @subpackage Cart */ function woocommerce_cart_totals() { if ( is_checkout() ) { @@ -1486,8 +1441,6 @@ if ( ! function_exists( 'woocommerce_button_proceed_to_checkout' ) ) { /** * Output the proceed to checkout button. - * - * @subpackage Cart */ function woocommerce_button_proceed_to_checkout() { wc_get_template( 'cart/proceed-to-checkout-button.php' ); @@ -1498,8 +1451,6 @@ if ( ! function_exists( 'woocommerce_widget_shopping_cart_button_view_cart' ) ) /** * Output the view cart button. - * - * @subpackage Cart */ function woocommerce_widget_shopping_cart_button_view_cart() { echo '' . esc_html__( 'View cart', 'woocommerce' ) . ''; @@ -1510,8 +1461,6 @@ if ( ! function_exists( 'woocommerce_widget_shopping_cart_proceed_to_checkout' ) /** * Output the proceed to checkout button. - * - * @subpackage Cart */ function woocommerce_widget_shopping_cart_proceed_to_checkout() { echo '' . esc_html__( 'Checkout', 'woocommerce' ) . ''; @@ -1546,7 +1495,6 @@ if ( ! function_exists( 'woocommerce_login_form' ) ) { /** * Output the WooCommerce Login Form. * - * @subpackage Forms * @param array $args Arguments. */ function woocommerce_login_form( $args = array() ) { @@ -1567,11 +1515,11 @@ if ( ! function_exists( 'woocommerce_checkout_login_form' ) ) { /** * Output the WooCommerce Checkout Login Form. - * - * @subpackage Checkout */ function woocommerce_checkout_login_form() { - wc_get_template( 'checkout/form-login.php', array( 'checkout' => WC()->checkout() ) ); + wc_get_template( 'checkout/form-login.php', array( + 'checkout' => WC()->checkout(), + ) ); } } @@ -1616,12 +1564,12 @@ if ( ! function_exists( 'woocommerce_order_review' ) ) { /** * Output the Order review table for the checkout. * - * @subpackage Checkout - * * @param bool $deprecated Deprecated param. */ function woocommerce_order_review( $deprecated = false ) { - wc_get_template( 'checkout/review-order.php', array( 'checkout' => WC()->checkout() ) ); + wc_get_template( 'checkout/review-order.php', array( + 'checkout' => WC()->checkout(), + ) ); } } @@ -1629,8 +1577,6 @@ if ( ! function_exists( 'woocommerce_checkout_payment' ) ) { /** * Output the Payment Methods on the checkout. - * - * @subpackage Checkout */ function woocommerce_checkout_payment() { if ( WC()->cart->needs_payment() ) { @@ -1652,11 +1598,11 @@ if ( ! function_exists( 'woocommerce_checkout_coupon_form' ) ) { /** * Output the Coupon form for the checkout. - * - * @subpackage Checkout */ function woocommerce_checkout_coupon_form() { - wc_get_template( 'checkout/form-coupon.php', array( 'checkout' => WC()->checkout() ) ); + wc_get_template( 'checkout/form-coupon.php', array( + 'checkout' => WC()->checkout(), + ) ); } } @@ -1665,7 +1611,6 @@ if ( ! function_exists( 'woocommerce_products_will_display' ) ) { /** * Check if we will be showing products or not (and not sub-categories only). * - * @subpackage Loop * @return bool */ function woocommerce_products_will_display() { @@ -1687,19 +1632,18 @@ if ( ! function_exists( 'woocommerce_products_will_display' ) ) { if ( is_product_category() ) { switch ( get_woocommerce_term_meta( $term->term_id, 'display_type', true ) ) { - case 'subcategories' : + case 'subcategories': // Nothing - we want to continue to see if there are products/subcats. - break; - case 'products' : - case 'both' : + break; + case 'products': + case 'both': return true; - break; - default : + default: // Default - no setting. - if ( get_option( 'woocommerce_category_archive_display' ) != 'subcategories' ) { + if ( get_option( 'woocommerce_category_archive_display' ) !== 'subcategories' ) { return true; } - break; + break; } } @@ -1708,10 +1652,11 @@ if ( ! function_exists( 'woocommerce_products_will_display' ) ) { return true; } - $transient_name = 'wc_products_will_display_' . $term->term_id . '_' . WC_Cache_Helper::get_transient_version( 'product_query' ); + $transient_name = 'wc_products_will_display_' . $term->term_id . '_' . WC_Cache_Helper::get_transient_version( 'product_query' ); + $products_will_display = get_transient( $transient_name ); - if ( false === ( $products_will_display = get_transient( $transient_name ) ) ) { - $has_children = $wpdb->get_col( $wpdb->prepare( "SELECT term_id FROM {$wpdb->term_taxonomy} WHERE parent = %d AND taxonomy = %s", $term->term_id, $term->taxonomy ) ); // WPCS: cache ok. + if ( false === $products_will_display ) { + $has_children = $wpdb->get_col( $wpdb->prepare( "SELECT term_id FROM {$wpdb->term_taxonomy} WHERE parent = %d AND taxonomy = %s", $term->term_id, $term->taxonomy ) ); // WPCS: db call ok, cache ok. if ( $has_children ) { // Check terms have products inside - parents first. If products are found inside, subcats will be shown instead of products so we can return false. @@ -1744,7 +1689,6 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) { /** * Display product sub categories as thumbnails. * - * @subpackage Loop * @param array $args Arguments. * @return null|boolean */ @@ -1777,21 +1721,20 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) { } // Find the category + category parent, if applicable. - $term = get_queried_object(); - $parent_id = empty( $term->term_id ) ? 0 : $term->term_id; + $term = get_queried_object(); + $parent_id = empty( $term->term_id ) ? 0 : $term->term_id; if ( is_product_category() ) { $display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true ); switch ( $display_type ) { - case 'products' : + case 'products': return; - break; - case '' : + case '': if ( '' === get_option( 'woocommerce_category_archive_display' ) ) { return; } - break; + break; } } @@ -1806,7 +1749,9 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) { ) ) ); if ( apply_filters( 'woocommerce_product_subcategories_hide_empty', true ) ) { - $product_categories = wp_list_filter( $product_categories, array( 'count' => 0 ), 'NOT' ); + $product_categories = wp_list_filter( $product_categories, array( + 'count' => 0, + ), 'NOT' ); } if ( $product_categories ) { @@ -1823,16 +1768,16 @@ if ( ! function_exists( 'woocommerce_product_subcategories' ) ) { $display_type = get_woocommerce_term_meta( $term->term_id, 'display_type', true ); switch ( $display_type ) { - case 'subcategories' : + case 'subcategories': $wp_query->post_count = 0; $wp_query->max_num_pages = 0; - break; - case '' : + break; + case '': if ( 'subcategories' === get_option( 'woocommerce_category_archive_display' ) ) { $wp_query->post_count = 0; $wp_query->max_num_pages = 0; } - break; + break; } } @@ -1854,12 +1799,11 @@ if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) { * Show subcategory thumbnails. * * @param mixed $category Category. - * @subpackage Loop */ function woocommerce_subcategory_thumbnail( $category ) { - $small_thumbnail_size = apply_filters( 'subcategory_archive_thumbnail_size', 'woocommerce_thumbnail' ); - $dimensions = wc_get_image_size( $small_thumbnail_size ); - $thumbnail_id = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true ); + $small_thumbnail_size = apply_filters( 'subcategory_archive_thumbnail_size', 'woocommerce_thumbnail' ); + $dimensions = wc_get_image_size( $small_thumbnail_size ); + $thumbnail_id = get_woocommerce_term_meta( $category->term_id, 'thumbnail_id', true ); if ( $thumbnail_id ) { $image = wp_get_attachment_image_src( $thumbnail_id, $small_thumbnail_size ); @@ -1868,7 +1812,8 @@ if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) { $image_sizes = function_exists( 'wp_get_attachment_image_sizes' ) ? wp_get_attachment_image_sizes( $thumbnail_id, $small_thumbnail_size ) : false; } else { $image = wc_placeholder_img_src(); - $image_srcset = $image_sizes = false; + $image_srcset = false; + $image_sizes = false; } if ( $image ) { @@ -1892,7 +1837,6 @@ if ( ! function_exists( 'woocommerce_order_details_table' ) ) { * Displays order details in a table. * * @param mixed $order_id Order ID. - * @subpackage Orders */ function woocommerce_order_details_table( $order_id ) { if ( ! $order_id ) { @@ -1929,7 +1873,6 @@ if ( ! function_exists( 'woocommerce_order_again_button' ) ) { * Display an 'order again' button on the view order page. * * @param object $order Order. - * @subpackage Orders */ function woocommerce_order_again_button( $order ) { if ( ! $order || ! $order->has_status( apply_filters( 'woocommerce_valid_order_statuses_for_order_again', array( 'completed' ) ) ) || ! is_user_logged_in() ) { @@ -1949,12 +1892,9 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) { /** * Outputs a checkout/address form field. * - * @subpackage Forms - * * @param string $key Key. * @param mixed $args Arguments. * @param string $value (default: null). - * * @return string */ function woocommerce_form_field( $key, $args, $value = null ) { @@ -2031,8 +1971,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) { $field_container = '

%3$s

'; switch ( $args['type'] ) { - case 'country' : - + case 'country': $countries = 'shipping_country' === $key ? WC()->countries->get_shipping_countries() : WC()->countries->get_allowed_countries(); if ( 1 === count( $countries ) ) { @@ -2056,7 +1995,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) { } break; - case 'state' : + case 'state': /* Get country this state field is representing */ $for_country = isset( $args['country'] ) ? $args['country'] : WC()->checkout->get_value( 'billing_state' === $key ? 'billing_country' : 'shipping_country' ); $states = WC()->countries->get_states( $for_country ); @@ -2085,30 +2024,27 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) { } break; - case 'textarea' : - + case 'textarea': $field .= ''; break; - case 'checkbox' : - + case 'checkbox': $field = ''; break; - case 'password' : - case 'text' : - case 'email' : - case 'tel' : - case 'number' : - + case 'password': + case 'text': + case 'email': + case 'tel': + case 'number': $field .= ''; break; - case 'select' : - - $options = $field = ''; + case 'select': + $field = ''; + $options = ''; if ( ! empty( $args['options'] ) ) { foreach ( $args['options'] as $option_key => $option_text ) { @@ -2128,8 +2064,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) { } break; - case 'radio' : - + case 'radio': $label_id = current( array_keys( $args['options'] ) ); if ( ! empty( $args['options'] ) ) { @@ -2145,7 +2080,7 @@ if ( ! function_exists( 'woocommerce_form_field' ) ) { if ( ! empty( $field ) ) { $field_html = ''; - if ( $args['label'] && 'checkbox' != $args['type'] ) { + if ( $args['label'] && 'checkbox' !== $args['type'] ) { $field_html .= ''; } @@ -2181,11 +2116,10 @@ if ( ! function_exists( 'get_product_search_form' ) ) { * * The default searchform uses html5. * - * @subpackage Forms * @param bool $echo (default: true). * @return string */ - function get_product_search_form( $echo = true ) { + function get_product_search_form( $echo = true ) { global $product_search_form_index; ob_start(); @@ -2263,7 +2197,7 @@ if ( ! function_exists( 'wc_dropdown_variation_attribute_options' ) ) { 'options' => false, 'attribute' => false, 'product' => false, - 'selected' => false, + 'selected' => false, 'name' => '', 'id' => '', 'class' => '', @@ -2290,10 +2224,12 @@ if ( ! function_exists( 'wc_dropdown_variation_attribute_options' ) ) { if ( ! empty( $options ) ) { if ( $product && taxonomy_exists( $attribute ) ) { // Get terms if this is a taxonomy - ordered. We need the names too. - $terms = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) ); + $terms = wc_get_product_terms( $product->get_id(), $attribute, array( + 'fields' => 'all', + ) ); foreach ( $terms as $term ) { - if ( in_array( $term->slug, $options ) ) { + if ( in_array( $term->slug, $options, true ) ) { $html .= ''; } } @@ -2360,7 +2296,11 @@ if ( ! function_exists( 'woocommerce_account_orders' ) ) { */ function woocommerce_account_orders( $current_page ) { $current_page = empty( $current_page ) ? 1 : absint( $current_page ); - $customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array( 'customer' => get_current_user_id(), 'page' => $current_page, 'paginate' => true ) ) ); + $customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array( + 'customer' => get_current_user_id(), + 'page' => $current_page, + 'paginate' => true, + ) ) ); wc_get_template( 'myaccount/orders.php', @@ -2503,11 +2443,11 @@ if ( ! function_exists( 'wc_display_item_meta' ) ) { $strings = array(); $html = ''; $args = wp_parse_args( $args, array( - 'before' => '
  • ', - 'after' => '
', - 'separator' => '
  • ', - 'echo' => true, - 'autop' => false, + 'before' => '
    • ', + 'after' => '
    ', + 'separator' => '
  • ', + 'echo' => true, + 'autop' => false, ) ); foreach ( $item->get_formatted_meta_data() as $meta_id => $meta ) { @@ -2549,7 +2489,9 @@ if ( ! function_exists( 'wc_display_item_downloads' ) ) { 'show_url' => false, ) ); - if ( is_object( $item ) && $item->is_type( 'line_item' ) && ( $downloads = $item->get_item_downloads() ) ) { + $downloads = is_object( $item ) && $item->is_type( 'line_item' ) ? $item->get_item_downloads() : array(); + + if ( $downloads ) { $i = 0; foreach ( $downloads as $file ) { $i ++; @@ -2557,6 +2499,7 @@ if ( ! function_exists( 'wc_display_item_downloads' ) ) { if ( $args['show_url'] ) { $strings[] = '' . esc_html( $file['name'] ) . ': ' . esc_html( $file['download_url'] ); } else { + /* translators: %d: downloads count */ $prefix = count( $downloads ) > 1 ? sprintf( __( 'Download %d', 'woocommerce' ), $i ) : __( 'Download', 'woocommerce' ); $strings[] = '' . $prefix . ': ' . esc_html( $file['name'] ) . ''; } From f395fcd2e8e089b88e1dfb151fbc09cc7bbc3b52 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Mon, 20 Nov 2017 22:08:23 -0200 Subject: [PATCH 14/76] Fixed missing text domain in setup wizard --- includes/admin/class-wc-admin-setup-wizard.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/class-wc-admin-setup-wizard.php b/includes/admin/class-wc-admin-setup-wizard.php index 50ac35e751d..f3aff414ce7 100644 --- a/includes/admin/class-wc-admin-setup-wizard.php +++ b/includes/admin/class-wc-admin-setup-wizard.php @@ -1664,7 +1664,7 @@ class WC_Admin_Setup_Wizard { $docs_url = 'https://docs.woocommerce.com/documentation/plugins/woocommerce/getting-started/?utm_source=setupwizard&utm_medium=product&utm_content=docs&utm_campaign=woocommerceplugin'; $help_text = sprintf( /* translators: %1$s: link to videos, %2$s: link to docs */ - __( 'Watch our guided tour videos to learn more about WooCommerce, and visit WooCommerce.com to learn more about getting started.' ), + __( 'Watch our guided tour videos to learn more about WooCommerce, and visit WooCommerce.com to learn more about getting started.', 'woocommerce' ), $videos_url, $docs_url ); From d99aec3fd9cfe89c70a73e0cf70c8e51f2a49351 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Mon, 20 Nov 2017 22:16:24 -0200 Subject: [PATCH 15/76] Run grunt checktextdomain by default This will help to find missing or incorrect text domains --- Gruntfile.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index fd287077e7a..2cceaa39244 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -334,9 +334,9 @@ module.exports = function( grunt ) { // Register tasks grunt.registerTask( 'default', [ - 'jshint', - 'uglify', - 'css' + 'js', + 'css', + 'i81n' ]); grunt.registerTask( 'js', [ @@ -358,8 +358,13 @@ module.exports = function( grunt ) { 'shell:apigen' ]); + // Only an alias to 'default' task. grunt.registerTask( 'dev', [ - 'default', + 'default' + ]); + + grunt.registerTask( 'i18n', [ + 'checktextdomain', 'makepot' ]); From e9a8c15099db8f6feeeb2ee155f4ab8a17237180 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Mon, 20 Nov 2017 22:18:07 -0200 Subject: [PATCH 16/76] Fixed typo --- Gruntfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index 2cceaa39244..5e39bd00f32 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -336,7 +336,7 @@ module.exports = function( grunt ) { grunt.registerTask( 'default', [ 'js', 'css', - 'i81n' + 'i18n' ]); grunt.registerTask( 'js', [ From d9913c0d777cb2d394b0315951b56879e4162e1b Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Tue, 21 Nov 2017 10:49:26 +0000 Subject: [PATCH 17/76] Checkout should store fee tax lines Fixes #17815 --- includes/class-wc-checkout.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-checkout.php b/includes/class-wc-checkout.php index 3eea3317ab2..a39595b95c0 100644 --- a/includes/class-wc-checkout.php +++ b/includes/class-wc-checkout.php @@ -469,7 +469,7 @@ class WC_Checkout { * @param WC_Cart $cart */ public function create_order_tax_lines( &$order, $cart ) { - foreach ( array_keys( $cart->get_cart_contents_taxes() + $cart->get_shipping_taxes() ) as $tax_rate_id ) { + foreach ( array_keys( $cart->get_cart_contents_taxes() + $cart->get_shipping_taxes() + $cart->get_fee_taxes() ) as $tax_rate_id ) { if ( $tax_rate_id && apply_filters( 'woocommerce_cart_remove_taxes_zero_rate_id', 'zero-rated' ) !== $tax_rate_id ) { $item = new WC_Order_Item_Tax(); $item->set_props( array( From 163c73ba972eea6b5d4d265a2ee005603a0b5021 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 21 Nov 2017 10:41:43 -0200 Subject: [PATCH 18/76] Updated wp-coding-standards/wpcs version --- composer.json | 2 +- composer.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index be3bd973671..6b5edf1febc 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ }, "require-dev": { "squizlabs/php_codesniffer": "*", - "wp-coding-standards/wpcs": "0.13.1", + "wp-coding-standards/wpcs": "^0.14", "phpunit/phpunit": "6.2.3", "woocommerce/woocommerce-git-hooks": "1.0.3", "wimg/php-compatibility": "^8.0", diff --git a/composer.lock b/composer.lock index 3abf28c7d12..6c3ea1d6aa4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "9a9c7e81cc3a30935c03b1b2d64c201c", + "content-hash": "f8dbe5807f695e87ad3453a8b629b6bf", "packages": [ { "name": "composer/installers", @@ -1783,16 +1783,16 @@ }, { "name": "wp-coding-standards/wpcs", - "version": "0.13.1", + "version": "0.14.0", "source": { "type": "git", "url": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git", - "reference": "1f64b1a0b5b789822d0303436ee4e30e0135e4dc" + "reference": "8cadf48fa1c70b2381988e0a79e029e011a8f41c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/1f64b1a0b5b789822d0303436ee4e30e0135e4dc", - "reference": "1f64b1a0b5b789822d0303436ee4e30e0135e4dc", + "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/8cadf48fa1c70b2381988e0a79e029e011a8f41c", + "reference": "8cadf48fa1c70b2381988e0a79e029e011a8f41c", "shasum": "" }, "require": { @@ -1800,7 +1800,7 @@ "squizlabs/php_codesniffer": "^2.9.0 || ^3.0.2" }, "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.1" + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3" }, "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", @@ -1819,7 +1819,7 @@ "standards", "wordpress" ], - "time": "2017-08-05T16:08:58+00:00" + "time": "2017-11-01T15:10:46+00:00" } ], "aliases": [], From 914ebef33784ba328625bd6b4c2c6f53800e8a89 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 21 Nov 2017 10:41:55 -0200 Subject: [PATCH 19/76] PHPCS custom settings to support minimum WP version and text domain Also makes sure that PHPCompatibility is looking for PHP 5.2+ --- phpcs.ruleset.xml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/phpcs.ruleset.xml b/phpcs.ruleset.xml index 20dcfc81a60..2f7f74f799f 100644 --- a/phpcs.ruleset.xml +++ b/phpcs.ruleset.xml @@ -11,7 +11,14 @@ includes/gateways/simplify-commerce/includes/ includes/libraries/ includes/api/legacy/ + */node_modules/* + */vendor/* + + + + + @@ -28,5 +35,11 @@ - + + + + + + + From 56888d334c2550303bd47af499c3c2f7309b1c97 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 21 Nov 2017 10:47:42 -0200 Subject: [PATCH 20/76] Fixed typo --- phpcs.ruleset.xml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/phpcs.ruleset.xml b/phpcs.ruleset.xml index 2f7f74f799f..54c63a381fb 100644 --- a/phpcs.ruleset.xml +++ b/phpcs.ruleset.xml @@ -18,14 +18,13 @@ - + - @@ -36,7 +35,6 @@ - From 216ddc799aa1d76b07973b8fa98162bcb15335bf Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 21 Nov 2017 10:53:15 -0200 Subject: [PATCH 21/76] Fixed VSCode auto align mistake One more reason to go back to sublime --- includes/wc-template-functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/wc-template-functions.php b/includes/wc-template-functions.php index f482fa15c95..fb4df9e0c7a 100644 --- a/includes/wc-template-functions.php +++ b/includes/wc-template-functions.php @@ -2443,7 +2443,7 @@ if ( ! function_exists( 'wc_display_item_meta' ) ) { $strings = array(); $html = ''; $args = wp_parse_args( $args, array( - 'before' => '
    • ', + 'before' => '
      • ', 'after' => '
      ', 'separator' => '
    • ', 'echo' => true, From 742cd367b0d552202d5bcdd7544eb99fc0e480fc Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Mon, 20 Nov 2017 17:18:29 -0200 Subject: [PATCH 22/76] Prevent Travis builds duplication This commit changes Travis configuration file to specify a list of branches that it should build. This way Travis will only create a new build when a commit is pushed to the master branch and release branches and when tags are created. The behavior for PRs is not modified and PR creation and updates will still trigger builds. Doing this to speed up Travis build by preventing it from running two builds for PR that are created from a branch of the same repository. Before this change, Travis would create a build when the branch is pushed to GitHub (continuous-integration/travis-ci/push) and another one when the PR is created (continuous-integration/travis-ci/pr). For an example, see https://github.com/woocommerce/woocommerce/pull/17680. --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index 170d075ef60..9bfdf909036 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,3 +37,10 @@ script: after_script: - bash tests/bin/travis.sh after + +# Specifies that Travis should create builds for master and release branches and also tags. +branches: + only: + - master + - /^\d+\.\d+(\.\d+)?(-\S*)?$/ + - /^release\// From b96fea3e473cadcabc4aa9278d5e883d5281ea28 Mon Sep 17 00:00:00 2001 From: JeroenSormani Date: Tue, 21 Nov 2017 16:01:23 +0100 Subject: [PATCH 23/76] Add quantity arg to woocommerce_add_cart_item_data filter --- includes/class-wc-cart.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-cart.php b/includes/class-wc-cart.php index 1413ca656db..248079b2efc 100644 --- a/includes/class-wc-cart.php +++ b/includes/class-wc-cart.php @@ -1102,7 +1102,7 @@ class WC_Cart extends WC_Legacy_Cart { } // Load cart item data - may be added by other plugins. - $cart_item_data = (array) apply_filters( 'woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id ); + $cart_item_data = (array) apply_filters( 'woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id, $quantity ); // Generate a ID based on product ID, variation ID, variation data, and other cart item data. $cart_id = $this->generate_cart_id( $product_id, $variation_id, $variation, $cart_item_data ); From 208b2d1b810c22bf217918186a17d471d4fa3693 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Tue, 21 Nov 2017 16:50:33 +0000 Subject: [PATCH 24/76] Slugs are encoded, so decode before outputting to the form Fixes #17845 --- includes/widgets/class-wc-widget-layered-nav.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/widgets/class-wc-widget-layered-nav.php b/includes/widgets/class-wc-widget-layered-nav.php index dd8639b1ef5..190dccac1db 100644 --- a/includes/widgets/class-wc-widget-layered-nav.php +++ b/includes/widgets/class-wc-widget-layered-nav.php @@ -264,7 +264,7 @@ class WC_Widget_Layered_Nav extends WC_Widget { continue; } - echo ''; + echo ''; } echo ''; From 1783953f15a1820d04aff6535f66c9d072fa6511 Mon Sep 17 00:00:00 2001 From: The Dramatist Date: Tue, 21 Nov 2017 23:50:30 +0600 Subject: [PATCH 25/76] Admin metaboxes views translation escaping fix (#17776) * Data escaped and validated. Plus translator comment documentation added. * If it should be int then we should change the empty string default parameter to 0 as in 'if' condition checking 0 and empty string are same. * Extra bracket removed. * Indentation is fixed now. * The taxonomy object should not be assigned to a variable before checking if this is a taxonomy or not. * echo esc_attr__ replaced by esc_attr_e and visually tested. * As I use WordPress VIP Coding Standard, they were marking them as warnings. But now it's fixed again. * Escaping fix * Extra Bracket Fix Again --- includes/abstracts/abstract-wc-data.php | 4 +- .../views/html-order-download-permission.php | 10 +- .../admin/meta-boxes/views/html-order-fee.php | 12 +- .../meta-boxes/views/html-order-item-meta.php | 12 +- .../meta-boxes/views/html-order-item.php | 28 ++--- .../meta-boxes/views/html-order-items.php | 104 ++++++++++-------- .../meta-boxes/views/html-order-refund.php | 7 +- .../meta-boxes/views/html-order-shipping.php | 28 ++--- .../views/html-product-attribute.php | 38 ++++--- .../views/html-product-data-attributes.php | 10 +- .../views/html-product-data-general.php | 19 ++-- .../views/html-product-data-inventory.php | 2 +- .../html-product-data-linked-products.php | 6 +- .../views/html-product-data-panel.php | 4 +- .../views/html-product-data-shipping.php | 3 +- .../views/html-product-data-variations.php | 77 ++++++------- .../views/html-product-download.php | 6 +- .../views/html-product-variation-download.php | 10 +- .../meta-boxes/views/html-variation-admin.php | 64 +++++------ 19 files changed, 231 insertions(+), 213 deletions(-) diff --git a/includes/abstracts/abstract-wc-data.php b/includes/abstracts/abstract-wc-data.php index 8644e15190c..a252e5b9ed2 100644 --- a/includes/abstracts/abstract-wc-data.php +++ b/includes/abstracts/abstract-wc-data.php @@ -285,7 +285,7 @@ abstract class WC_Data { if ( ! $has_setter_or_getter ) { return false; } - + /* translators: %s: $key Key to check */ wc_doing_it_wrong( __FUNCTION__, sprintf( __( 'Generic add/update/get meta methods should not be used for internal meta data, including "%s". Use getters and setters.', 'woocommerce' ), $key ), '3.2.0' ); return true; @@ -400,7 +400,7 @@ abstract class WC_Data { * @param string $value * @param int $meta_id */ - public function update_meta_data( $key, $value, $meta_id = '' ) { + public function update_meta_data( $key, $value, $meta_id = 0 ) { if ( $this->is_internal_meta_key( $key ) ) { $function = 'set_' . $key; diff --git a/includes/admin/meta-boxes/views/html-order-download-permission.php b/includes/admin/meta-boxes/views/html-order-download-permission.php index 13da3f0dce1..e9fe6a28ff5 100644 --- a/includes/admin/meta-boxes/views/html-order-download-permission.php +++ b/includes/admin/meta-boxes/views/html-order-download-permission.php @@ -5,7 +5,7 @@ if ( ! defined( 'ABSPATH' ) ) { ?>

      - +
      get_file_download_path( $download->get_download_id() ) ) ) ); printf( _n( 'Downloaded %s time', 'Downloaded %s times', $download->get_download_count(), 'woocommerce' ), esc_html( $download->get_download_count() ) ) - ?> + ?>

      + @@ -41,10 +41,10 @@ if ( ! defined( 'ABSPATH' ) ) { ?> @@ -65,10 +65,10 @@ if ( ! defined( 'ABSPATH' ) ) { ?> diff --git a/includes/admin/meta-boxes/views/html-order-item-meta.php b/includes/admin/meta-boxes/views/html-order-item-meta.php index 7e2dc47996d..c4e3a8055a1 100644 --- a/includes/admin/meta-boxes/views/html-order-item-meta.php +++ b/includes/admin/meta-boxes/views/html-order-item-meta.php @@ -18,8 +18,9 @@ $hidden_order_itemmeta = apply_filters( 'woocommerce_hidden_order_itemmeta', arr ?>
      get_formatted_meta_data( '' ) ) : ?>
      - - + + - + diff --git a/includes/admin/meta-boxes/views/html-order-fee.php b/includes/admin/meta-boxes/views/html-order-fee.php index b04e1fbb7ff..a300126d93b 100644 --- a/includes/admin/meta-boxes/views/html-order-fee.php +++ b/includes/admin/meta-boxes/views/html-order-fee.php @@ -10,7 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; } ?> -
      @@ -22,7 +22,7 @@ if ( ! defined( 'ABSPATH' ) ) { - +
      - $meta ) : - if ( in_array( $meta->key, $hidden_order_itemmeta ) ) { + $meta ) : + if ( in_array( $meta->key, $hidden_order_itemmeta, true ) ) { continue; } ?> @@ -35,8 +36,9 @@ $hidden_order_itemmeta = apply_filters( 'woocommerce_hidden_order_itemmeta', arr
      get_formatted_meta_data( '' ) ) : ?> - $meta ) : - if ( in_array( $meta->key, $hidden_order_itemmeta ) ) { + $meta ) : + if ( in_array( $meta->key, $hidden_order_itemmeta, true ) ) { continue; } ?> @@ -52,7 +54,7 @@ $hidden_order_itemmeta = apply_filters( 'woocommerce_hidden_order_itemmeta', arr - +
      diff --git a/includes/admin/meta-boxes/views/html-order-item.php b/includes/admin/meta-boxes/views/html-order-item.php index 55bc8f02b16..bbc2823272f 100644 --- a/includes/admin/meta-boxes/views/html-order-item.php +++ b/includes/admin/meta-boxes/views/html-order-item.php @@ -12,7 +12,7 @@ $product = $item->get_product(); $product_link = $product ? admin_url( 'post.php?post=' . $item->get_product_id() . '&action=edit' ) : ''; $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnail', $product->get_image( 'thumbnail', array( 'title' => '' ), false ), $item_id, $item ) : ''; ?> - + ' . wp_kses_post( $thumbnail ) . '
      '; ?> @@ -21,11 +21,11 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai echo $product_link ? '' . esc_html( $item->get_name() ) . '' : '
      ' . esc_html( $item->get_name() ) . '
      '; if ( $product && $product->get_sku() ) { - echo '
      ' . __( 'SKU:', 'woocommerce' ) . ' ' . esc_html( $product->get_sku() ) . '
      '; + echo '
      ' . esc_html__( 'SKU:', 'woocommerce' ) . ' ' . esc_html( $product->get_sku() ) . '
      '; } if ( $item->get_variation_id() ) { - echo '
      ' . __( 'Variation ID:', 'woocommerce' ) . ' '; + echo '
      ' . esc_html__( 'Variation ID:', 'woocommerce' ) . ' '; if ( 'product_variation' === get_post_type( $item->get_variation_id() ) ) { echo esc_html( $item->get_variation_id() ); } else { @@ -38,9 +38,9 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai - + - + @@ -67,10 +67,10 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai ?>
      @@ -91,16 +91,16 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai
      - +
      - +
      @@ -114,7 +114,7 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai
      $order->get_currency() ) ); } else { echo '–'; @@ -137,16 +137,16 @@ $thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnai
      - +
      - +
      - + - - - + + + $tax_item ) : $tax_class = wc_get_tax_class_by_tax_id( $tax_item['rate_id'] ); $tax_class_name = isset( $classes_options[ $tax_class ] ) ? $classes_options[ $tax_class ] : __( 'Tax', 'woocommerce' ); $column_label = ! empty( $tax_item['label'] ) ? $tax_item['label'] : __( 'Tax', 'woocommerce' ); + /* translators: %1$s: tax item name %2$s: tax class name */ $column_tip = sprintf( esc_html__( '%1$s (%2$s)', 'woocommerce' ), $tax_item['name'], $tax_class_name ); ?> - - + +
      @@ -108,7 +109,7 @@ if ( wc_tax_enabled() ) { ?>
        ' . __( 'Coupon(s)', 'woocommerce' ) . ''; + echo '
      • ' . esc_html__( 'Coupon(s)', 'woocommerce' ) . '
      • '; foreach ( $coupons as $item_id => $item ) { $post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' LIMIT 1;", $item->get_code() ) ); @@ -126,7 +127,7 @@ if ( wc_tax_enabled() ) { get_total_discount() ) : ?> - + - + - - + - + ?> + @@ -171,7 +177,7 @@ if ( wc_tax_enabled() ) { get_id() ); ?> - + - + @@ -196,63 +202,63 @@ if ( wc_tax_enabled() ) {

        is_editable() ) : ?> - - + + - + get_total() - $order->get_total_refunded() || 0 < absint( $order->get_item_count() - $order->get_item_count_refunded() ) ) : ?> - + is_editable() ) : ?> - +

        get_total() - $order->get_total_refunded() || 0 < absint( $order->get_item_count() - $order->get_item_count_refunded() ) ) : ?>
        get_total_discount(), array( 'currency' => $order->get_currency() ) ); ?> @@ -138,10 +139,12 @@ if ( wc_tax_enabled() ) { get_shipping_methods() ) : ?>
        get_total_shipping_refunded() ) > 0 ) { + + get_total_shipping_refunded(); + if ( $refunded > 0 ) { echo '' . strip_tags( wc_price( $order->get_shipping_total(), array( 'currency' => $order->get_currency() ) ) ) . ' ' . wc_price( $order->get_shipping_total() - $refunded, array( 'currency' => $order->get_currency() ) ) . ''; } else { echo wc_price( $order->get_shipping_total(), array( 'currency' => $order->get_currency() ) ); @@ -155,15 +158,18 @@ if ( wc_tax_enabled() ) { get_tax_totals() as $code => $tax ) : ?>
        label; ?>:label ); ?>: get_total_tax_refunded_by_rate_id( $tax->rate_id ) ) > 0 ) { + + get_total_tax_refunded_by_rate_id( $tax->rate_id ); + if ( $refunded > 0 ) { echo '' . strip_tags( $tax->formatted_amount ) . ' ' . wc_price( WC_Tax::round( $tax->amount, wc_get_price_decimals() ) - WC_Tax::round( $refunded, wc_get_price_decimals() ), array( 'currency' => $order->get_currency() ) ) . ''; } else { echo $tax->formatted_amount; } - ?>
        :: get_formatted_order_total(); ?> @@ -182,7 +188,7 @@ if ( wc_tax_enabled() ) { get_total_refunded() ) : ?>
        :: -get_total_refunded(), array( 'currency' => $order->get_currency() ) ); ?>
        - + - + - + - + - + - - - - + + + + get_var( "SELECT COUNT(tax_rate_id) FROM {$wpdb->prefix}woocommerce_tax_rates;" ) ) > 100 ) : ?>

        -
        +

        @@ -349,7 +357,7 @@ if ( wc_tax_enabled() ) {
        - +
        diff --git a/includes/admin/meta-boxes/views/html-order-refund.php b/includes/admin/meta-boxes/views/html-order-refund.php index a6ebca280b4..4f2d0cf6e67 100644 --- a/includes/admin/meta-boxes/views/html-order-refund.php +++ b/includes/admin/meta-boxes/views/html-order-refund.php @@ -8,7 +8,7 @@ if ( ! defined( 'ABSPATH' ) ) { */ $who_refunded = new WP_User( $refund->get_refunded_by() ); ?> - + + @@ -59,17 +59,17 @@ if ( ! defined( 'ABSPATH' ) ) {
        get_total(), array( 'currency' => $order->get_currency() ) ); - - if ( $refunded = $order->get_total_refunded_for_item( $item_id, 'shipping' ) ) { + $refunded = $order->get_total_refunded_for_item( $item_id, 'shipping' ); + if ( $refunded ) { echo '-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . ''; } ?>
        @@ -83,17 +83,17 @@ if ( ! defined( 'ABSPATH' ) ) {
        $order->get_currency() ) ) : '–'; - - if ( $refunded = $order->get_tax_refunded_for_item( $item_id, $tax_item_id, 'shipping' ) ) { + $refunded = $order->get_tax_refunded_for_item( $item_id, $tax_item_id, 'shipping' ); + if ( $refunded ) { echo '-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . ''; } ?>

        - +
        get_name() ) ); ?>

        @@ -14,24 +14,26 @@ if ( ! defined( 'ABSPATH' ) ) {
        diff --git a/includes/admin/meta-boxes/views/html-product-data-attributes.php b/includes/admin/meta-boxes/views/html-product-data-attributes.php index 1dbea2d6e7c..e93151809be 100644 --- a/includes/admin/meta-boxes/views/html-product-data-attributes.php +++ b/includes/admin/meta-boxes/views/html-product-data-attributes.php @@ -6,10 +6,10 @@ if ( ! defined( 'ABSPATH' ) ) {
        :: -get_total_refunded(), array( 'currency' => $order->get_currency() ) ); ?>
        :: get_total() - $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); ?>
        @@ -266,9 +272,11 @@ if ( wc_tax_enabled() ) { $gateway_supports_refunds = false !== $payment_gateway && $payment_gateway->supports( 'refunds' ); $gateway_name = false !== $payment_gateway ? ( ! empty( $payment_gateway->method_title ) ? $payment_gateway->method_title : $payment_gateway->get_title() ) : __( 'Payment gateway', 'woocommerce' ); ?> - - - + + + + +
        @@ -280,7 +288,7 @@ if ( wc_tax_enabled() ) {
        -

        +

        @@ -292,7 +300,7 @@ if ( wc_tax_enabled() ) {
        - +
        @@ -306,7 +314,7 @@ if ( wc_tax_enabled() ) {
        -

        +

        @@ -317,10 +325,10 @@ if ( wc_tax_enabled() ) {
         
        @@ -16,11 +16,12 @@ $who_refunded = new WP_User( $refund->get_refunded_by() ); if ( $who_refunded->exists() ) { printf( /* translators: 1: refund id 2: refund date 3: username */ - __( 'Refund #%1$s - %2$s by %3$s', 'woocommerce' ), + esc_html__( 'Refund #%1$s - %2$s by %3$s', 'woocommerce' ), $refund->get_id(), wc_format_datetime( $refund->get_date_created(), get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) ), sprintf( '%2$s', + /* translators: 1: ID who refunded */ sprintf( esc_attr__( 'ID: %d', 'woocommerce' ), absint( $who_refunded->ID ) ), esc_html( $who_refunded->display_name ) ) @@ -28,7 +29,7 @@ $who_refunded = new WP_User( $refund->get_refunded_by() ); } else { printf( /* translators: 1: refund id 2: refund date */ - __( 'Refund #%1$s - %2$s', 'woocommerce' ), + esc_html__( 'Refund #%1$s - %2$s', 'woocommerce' ), $refund->get_id(), wc_format_datetime( $refund->get_date_created(), get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) ) ); diff --git a/includes/admin/meta-boxes/views/html-order-shipping.php b/includes/admin/meta-boxes/views/html-order-shipping.php index e81d1848364..a7a45fc6c98 100644 --- a/includes/admin/meta-boxes/views/html-order-shipping.php +++ b/includes/admin/meta-boxes/views/html-order-shipping.php @@ -9,7 +9,7 @@ if ( ! defined( 'ABSPATH' ) ) { exit; } ?> -
        @@ -21,7 +21,7 @@ if ( ! defined( 'ABSPATH' ) ) { - + - +
        - + is_taxonomy() ) : ?> get_name() ) ); ?> - + - + - + - + - is_taxonomy() && ( $attribute_taxonomy = $attribute->get_taxonomy_object() ) ) : ?> + is_taxonomy() && $attribute_taxonomy = $attribute->get_taxonomy_object() ) : + ?> attribute_type ) : ?> - 'name', @@ -42,18 +44,18 @@ if ( ! defined( 'ABSPATH' ) ) { foreach ( $all_terms as $term ) { $options = $attribute->get_options(); $options = ! empty( $options ) ? $options : array(); - echo ''; + echo ''; } } ?> - - - + + + - attribute_type ) : ?> + attribute_type ) : ?> - ]" cols="5" rows="5" placeholder="">get_options() ) ); ?> + +
        - +
        - +
        - - + + get_downloads( 'edit' ) ) { + $downloadable_files = $product_object->get_downloads( 'edit' ); + if ( $downloadable_files ) { foreach ( $downloadable_files as $key => $file ) { include( 'html-product-download.php' ); } @@ -89,7 +90,7 @@ if ( ! defined( 'ABSPATH' ) ) { ob_start(); include( 'html-product-download.php' ); echo esc_attr( ob_get_clean() ); - ?>"> + ?>"> diff --git a/includes/admin/meta-boxes/views/html-product-data-inventory.php b/includes/admin/meta-boxes/views/html-product-data-inventory.php index 00ad5dd1f7e..e9e4b56202a 100644 --- a/includes/admin/meta-boxes/views/html-product-data-inventory.php +++ b/includes/admin/meta-boxes/views/html-product-data-inventory.php @@ -11,7 +11,7 @@ if ( ! defined( 'ABSPATH' ) ) { woocommerce_wp_text_input( array( 'id' => '_sku', 'value' => $product_object->get_sku( 'edit' ), - 'label' => '' . __( 'SKU', 'woocommerce' ) . '', + 'label' => '' . esc_html__( 'SKU', 'woocommerce' ) . '', 'desc_tip' => true, 'description' => __( 'SKU refers to a Stock-keeping unit, a unique identifier for each distinct product and service that can be purchased.', 'woocommerce' ), ) ); diff --git a/includes/admin/meta-boxes/views/html-product-data-linked-products.php b/includes/admin/meta-boxes/views/html-product-data-linked-products.php index 774fd54cbcf..e9a11034614 100644 --- a/includes/admin/meta-boxes/views/html-product-data-linked-products.php +++ b/includes/admin/meta-boxes/views/html-product-data-linked-products.php @@ -7,7 +7,7 @@ if ( ! defined( 'ABSPATH' ) ) {

        - + get_upsell_ids( 'edit' ); @@ -41,7 +41,7 @@ if ( ! defined( 'ABSPATH' ) ) {

        - + @@ -47,7 +48,7 @@ if ( ! defined( 'ABSPATH' ) ) { 'class' => 'select short', ); ?>

        - +

        -

        Attributes tab.', 'woocommerce' ); ?>

        -

        +

        Attributes tab.', 'woocommerce' ); ?>

        +

        - : + : get_name() ) ] ) ? $default_attributes[ sanitize_title( $attribute->get_name() ) ] : ''; ?> - - - + + + - - - + + + - - - - - - - + + + + + + + - - - - + + + + - - - - + + + + - - + + - +
        - + + - ( / ) + ( / ) « - + - + » @@ -106,24 +108,25 @@ if ( ! defined( 'ABSPATH' ) ) {
        + echo htmlspecialchars( wp_json_encode( wc_list_pluck( $variation_attributes, 'get_data' ) ) ); + ?>" data-total="" data-total_pages="" data-page="1" data-edited="false">
        - - + +
        + - ( / ) + ( / ) « - + -
        - - + + + diff --git a/includes/admin/meta-boxes/views/html-product-variation-download.php b/includes/admin/meta-boxes/views/html-product-variation-download.php index ad802d1db51..6c39752cc0f 100644 --- a/includes/admin/meta-boxes/views/html-product-variation-download.php +++ b/includes/admin/meta-boxes/views/html-product-variation-download.php @@ -5,10 +5,10 @@ if ( ! defined( 'ABSPATH' ) ) { ?> - - - + + + diff --git a/includes/admin/meta-boxes/views/html-variation-admin.php b/includes/admin/meta-boxes/views/html-variation-admin.php index 33e5326e002..5c3701c3d91 100644 --- a/includes/admin/meta-boxes/views/html-variation-admin.php +++ b/includes/admin/meta-boxes/views/html-variation-admin.php @@ -13,7 +13,7 @@ if ( ! defined( 'ABSPATH' ) ) { ?>

        - +
        # @@ -44,14 +44,14 @@ if ( ! defined( 'ABSPATH' ) ) { - - + +

           
        " name="_wc_file_urls[]" value="" />
        - - + + " name="_wc_variation_file_urls[][]" value="" />
        -
        - + + @@ -349,7 +349,7 @@ if ( ! defined( 'ABSPATH' ) ) { ob_start(); include( 'html-product-variation-download.php' ); echo esc_attr( ob_get_clean() ); - ?>"> + ?>"> From f289d0e05c0d57eea6238b20025b1eadd34917fc Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 21 Nov 2017 15:32:57 -0200 Subject: [PATCH 26/76] Fixed how to delete meta data on REST API v2 --- includes/api/class-wc-rest-orders-controller.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/includes/api/class-wc-rest-orders-controller.php b/includes/api/class-wc-rest-orders-controller.php index 5350bf42628..b42e8c97e9c 100644 --- a/includes/api/class-wc-rest-orders-controller.php +++ b/includes/api/class-wc-rest-orders-controller.php @@ -597,8 +597,9 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller { protected function maybe_set_item_meta_data( $item, $posted ) { if ( ! empty( $posted['meta_data'] ) && is_array( $posted['meta_data'] ) ) { foreach ( $posted['meta_data'] as $meta ) { - if ( isset( $meta['key'], $meta['value'] ) ) { - $item->update_meta_data( $meta['key'], $meta['value'], isset( $meta['id'] ) ? $meta['id'] : '' ); + if ( isset( $meta['key'] ) ) { + $value = isset( $meta['value'] ) ? $meta['value'] : null; + $item->update_meta_data( $meta['key'], $value, isset( $meta['id'] ) ? $meta['id'] : '' ); } } } From f0b6e3fc33356d32c7ddbab564c378b96ef8293c Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 21 Nov 2017 15:04:45 -0200 Subject: [PATCH 27/76] Test removing fee_lines from order in REST API --- .../helpers/class-wc-helper-order.php | 10 ++-- tests/unit-tests/api/orders.php | 51 +++++++++++++++++-- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/tests/framework/helpers/class-wc-helper-order.php b/tests/framework/helpers/class-wc-helper-order.php index ed6a053b3b4..329b02efc43 100644 --- a/tests/framework/helpers/class-wc-helper-order.php +++ b/tests/framework/helpers/class-wc-helper-order.php @@ -16,15 +16,15 @@ class WC_Helper_Order { $order = wc_get_order( $order_id ); - // Delete all products in the order - foreach ( $order->get_items() as $item ) : + // Delete all products in the order. + foreach ( $order->get_items() as $item ) { WC_Helper_Product::delete_product( $item['product_id'] ); - endforeach; + } WC_Helper_Shipping::delete_simple_flat_rate(); - // Delete the order post - wp_delete_post( $order_id, true ); + // Delete the order post. + $order->delete( true ); } /** diff --git a/tests/unit-tests/api/orders.php b/tests/unit-tests/api/orders.php index 3fef88b0305..598de78a681 100644 --- a/tests/unit-tests/api/orders.php +++ b/tests/unit-tests/api/orders.php @@ -267,12 +267,13 @@ class WC_Tests_API_Orders extends WC_REST_Unit_Test_Case { /** * Tests updating an order. + * * @since 3.0.0 */ public function test_update_order() { wp_set_current_user( $this->user ); - $order = WC_Helper_Order::create_order(); - $request = new WP_REST_Request( 'POST', '/wc/v2/orders/' . $order->get_id() ); + $order = WC_Helper_Order::create_order(); + $request = new WP_REST_Request( 'PUT', '/wc/v2/orders/' . $order->get_id() ); $request->set_body_params( array( 'payment_method' => 'test-update', 'billing' => array( @@ -288,17 +289,56 @@ class WC_Tests_API_Orders extends WC_REST_Unit_Test_Case { $this->assertEquals( 'Fish', $data['billing']['first_name'] ); $this->assertEquals( 'Face', $data['billing']['last_name'] ); - wp_delete_post( $order->get_id(), true ); + WC_Helper_Order::delete_order( $order->get_id() ); + } + + /** + * Tests updating an order and removing items. + * + * @since 3.0.0 + */ + public function test_update_order_remove_items() { + wp_set_current_user( $this->user ); + $order = WC_Helper_Order::create_order(); + $fee = new WC_Order_Item_Fee(); + $fee->set_props( array( + 'name' => 'Some Fee', + 'tax_status' => 'taxable', + 'total' => '100', + 'tax_class' => '', + ) ); + $order->add_item( $fee ); + $order->save(); + + $request = new WP_REST_Request( 'PUT', '/wc/v2/orders/' . $order->get_id() ); + $fee_data = current( $order->get_items( 'fee' ) ); + + $request->set_body_params( array( + 'fee_lines' => array( + array( + 'id' => $fee_data->get_id(), + 'name' => null, + ), + ), + ) ); + $response = $this->server->dispatch( $request ); + $data = $response->get_data(); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertTrue( empty( $data['fee_lines'] ) ); + + WC_Helper_Order::delete_order( $order->get_id() ); } /** * Tests updating an order without the correct permissions. + * * @since 3.0.0 */ public function test_update_order_without_permission() { wp_set_current_user( 0 ); - $order = WC_Helper_Order::create_order(); - $request = new WP_REST_Request( 'POST', '/wc/v2/orders/' . $order->get_id() ); + $order = WC_Helper_Order::create_order(); + $request = new WP_REST_Request( 'PUT', '/wc/v2/orders/' . $order->get_id() ); $request->set_body_params( array( 'payment_method' => 'test-update', 'billing' => array( @@ -308,6 +348,7 @@ class WC_Tests_API_Orders extends WC_REST_Unit_Test_Case { ) ); $response = $this->server->dispatch( $request ); $this->assertEquals( 401, $response->get_status() ); + WC_Helper_Order::delete_order( $order->get_id() ); } /** From b74fc8963ddcbdb4bb88bf9cfa7322b6da846f4a Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Tue, 21 Nov 2017 16:15:51 -0200 Subject: [PATCH 28/76] Update REST API schema for backwards compatibility with WP 4.9 Closes #17818 --- .../api/class-wc-rest-coupons-controller.php | 2 +- .../class-wc-rest-customers-controller.php | 2 +- ...class-wc-rest-order-refunds-controller.php | 8 +++---- .../api/class-wc-rest-orders-controller.php | 24 +++++++++---------- ...-wc-rest-product-variations-controller.php | 2 +- .../api/class-wc-rest-products-controller.php | 2 +- ...class-wc-rest-order-refunds-controller.php | 6 ++--- .../v1/class-wc-rest-orders-controller.php | 14 +++++------ 8 files changed, 30 insertions(+), 30 deletions(-) diff --git a/includes/api/class-wc-rest-coupons-controller.php b/includes/api/class-wc-rest-coupons-controller.php index f76ce441cfa..5e03716fa0c 100644 --- a/includes/api/class-wc-rest-coupons-controller.php +++ b/includes/api/class-wc-rest-coupons-controller.php @@ -507,7 +507,7 @@ class WC_REST_Coupons_Controller extends WC_REST_Legacy_Coupons_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/includes/api/class-wc-rest-customers-controller.php b/includes/api/class-wc-rest-customers-controller.php index 09bae50aaa6..f48cfe0e807 100644 --- a/includes/api/class-wc-rest-customers-controller.php +++ b/includes/api/class-wc-rest-customers-controller.php @@ -354,7 +354,7 @@ class WC_REST_Customers_Controller extends WC_REST_Customers_V1_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/includes/api/class-wc-rest-order-refunds-controller.php b/includes/api/class-wc-rest-order-refunds-controller.php index 8daa66b51ef..e98dd2872bc 100644 --- a/includes/api/class-wc-rest-order-refunds-controller.php +++ b/includes/api/class-wc-rest-order-refunds-controller.php @@ -401,7 +401,7 @@ class WC_REST_Order_Refunds_Controller extends WC_REST_Orders_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -422,12 +422,12 @@ class WC_REST_Order_Refunds_Controller extends WC_REST_Orders_Controller { ), 'name' => array( 'description' => __( 'Product name.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'product_id' => array( 'description' => __( 'Product ID.', 'woocommerce' ), - 'type' => 'integer', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'variation_id' => array( @@ -513,7 +513,7 @@ class WC_REST_Order_Refunds_Controller extends WC_REST_Orders_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/includes/api/class-wc-rest-orders-controller.php b/includes/api/class-wc-rest-orders-controller.php index 5350bf42628..48f0adbc334 100644 --- a/includes/api/class-wc-rest-orders-controller.php +++ b/includes/api/class-wc-rest-orders-controller.php @@ -1118,7 +1118,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -1139,12 +1139,12 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller { ), 'name' => array( 'description' => __( 'Product name.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'product_id' => array( 'description' => __( 'Product ID.', 'woocommerce' ), - 'type' => 'integer', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'variation_id' => array( @@ -1230,7 +1230,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -1321,7 +1321,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -1345,12 +1345,12 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller { ), 'method_title' => array( 'description' => __( 'Shipping method name.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'method_id' => array( 'description' => __( 'Shipping method ID.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'total' => array( @@ -1407,7 +1407,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -1431,7 +1431,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller { ), 'name' => array( 'description' => __( 'Fee name.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'tax_class' => array( @@ -1505,7 +1505,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), @@ -1529,7 +1529,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller { ), 'code' => array( 'description' => __( 'Coupon code.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'discount' => array( @@ -1563,7 +1563,7 @@ class WC_REST_Orders_Controller extends WC_REST_Legacy_Orders_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/includes/api/class-wc-rest-product-variations-controller.php b/includes/api/class-wc-rest-product-variations-controller.php index 390f6c7b82d..6fda040bf94 100644 --- a/includes/api/class-wc-rest-product-variations-controller.php +++ b/includes/api/class-wc-rest-product-variations-controller.php @@ -945,7 +945,7 @@ class WC_REST_Product_Variations_Controller extends WC_REST_Products_Controller ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/includes/api/class-wc-rest-products-controller.php b/includes/api/class-wc-rest-products-controller.php index bd3de8a4f2e..4e601c4af49 100644 --- a/includes/api/class-wc-rest-products-controller.php +++ b/includes/api/class-wc-rest-products-controller.php @@ -1991,7 +1991,7 @@ class WC_REST_Products_Controller extends WC_REST_Legacy_Products_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), ), diff --git a/includes/api/v1/class-wc-rest-order-refunds-controller.php b/includes/api/v1/class-wc-rest-order-refunds-controller.php index afcb97c5bd9..1dce1562984 100644 --- a/includes/api/v1/class-wc-rest-order-refunds-controller.php +++ b/includes/api/v1/class-wc-rest-order-refunds-controller.php @@ -378,7 +378,7 @@ class WC_REST_Order_Refunds_V1_Controller extends WC_REST_Orders_V1_Controller { ), 'name' => array( 'description' => __( 'Product name.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), @@ -390,7 +390,7 @@ class WC_REST_Order_Refunds_V1_Controller extends WC_REST_Orders_V1_Controller { ), 'product_id' => array( 'description' => __( 'Product ID.', 'woocommerce' ), - 'type' => 'integer', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'variation_id' => array( @@ -486,7 +486,7 @@ class WC_REST_Order_Refunds_V1_Controller extends WC_REST_Orders_V1_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), diff --git a/includes/api/v1/class-wc-rest-orders-controller.php b/includes/api/v1/class-wc-rest-orders-controller.php index 83325f8f550..f73d107d844 100644 --- a/includes/api/v1/class-wc-rest-orders-controller.php +++ b/includes/api/v1/class-wc-rest-orders-controller.php @@ -1211,7 +1211,7 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller { ), 'name' => array( 'description' => __( 'Product name.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), @@ -1223,7 +1223,7 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller { ), 'product_id' => array( 'description' => __( 'Product ID.', 'woocommerce' ), - 'type' => 'integer', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'variation_id' => array( @@ -1319,7 +1319,7 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller { ), 'value' => array( 'description' => __( 'Meta value.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), 'readonly' => true, ), @@ -1397,12 +1397,12 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller { ), 'method_title' => array( 'description' => __( 'Shipping method name.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'method_id' => array( 'description' => __( 'Shipping method ID.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'total' => array( @@ -1457,7 +1457,7 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller { ), 'name' => array( 'description' => __( 'Fee name.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'tax_class' => array( @@ -1528,7 +1528,7 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller { ), 'code' => array( 'description' => __( 'Coupon code.', 'woocommerce' ), - 'type' => 'string', + 'type' => 'mixed', 'context' => array( 'view', 'edit' ), ), 'discount' => array( From 47154cf29ace9cea03aaa73a3aa93ac1cf670069 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Tue, 21 Nov 2017 18:09:07 -0200 Subject: [PATCH 29/76] Don't run PHPCS on the code coverage Travis job PR #17680 added a new PHP 7.1 Travis build job to generate code coverage report. PHPCS was configured to run on all PHP 7.1 build jobs. So this means that after #17680 was merged, Travis started running PHPCS twice. This commit fixes this issue by setting a new environment variable called `$RUN_PHPCS` and using this variable, instead of the PHP version, to decide when to run PHPCS. --- .travis.yml | 4 ++-- tests/bin/phpcs.sh | 2 +- tests/bin/travis.sh | 4 ++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 170d075ef60..2594b7baf39 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ sudo: false php: - 5.6 - 7.0 - - 7.1 env: - WP_VERSION=latest WP_MULTISITE=0 @@ -20,6 +19,8 @@ matrix: dist: precise - php: 5.2 dist: precise + - php: 7.1 + env: WP_VERSION=latest WP_MULTISITE=0 RUN_PHPCS=1 - php: 7.1 env: WP_VERSION=latest WP_MULTISITE=0 RUN_CODE_COVERAGE=1 allow_failures: @@ -27,7 +28,6 @@ matrix: before_script: - export PATH="$HOME/.composer/vendor/bin:$PATH" - - if [[ $TRAVIS_PHP_VERSION == '7.1' ]]; then composer install; fi - bash tests/bin/install.sh woocommerce_test root '' localhost $WP_VERSION - bash tests/bin/travis.sh before diff --git a/tests/bin/phpcs.sh b/tests/bin/phpcs.sh index 5a3a973cd6e..c8d25115cec 100755 --- a/tests/bin/phpcs.sh +++ b/tests/bin/phpcs.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -if [[ $TRAVIS_PHP_VERSION == '7.1' ]]; then +if [[ ${RUN_PHPCS} == 1 ]]; then CHANGED_FILES=`git diff --name-only --diff-filter=ACMR $TRAVIS_COMMIT_RANGE | grep \\\\.php | awk '{print}' ORS=' '` IGNORE="tests/cli/,apigen/,includes/gateways/simplify-commerce/includes/,includes/libraries/,includes/api/legacy/" diff --git a/tests/bin/travis.sh b/tests/bin/travis.sh index 46de86aabb0..bd7e3fda61f 100755 --- a/tests/bin/travis.sh +++ b/tests/bin/travis.sh @@ -15,6 +15,10 @@ if [ $1 == 'before' ]; then composer global require "phpunit/phpunit=6.2.*" fi + if [[ ${RUN_PHPCS} == 1 ]]; then + composer install + fi + # Remove Xdebug from PHP runtime for all PHP version except 7.1 to speed up builds. # We need Xdebug enabled in the PHP 7.1 build job as it is used to generate code coverage. if [[ ${RUN_CODE_COVERAGE} != 1 ]]; then From cea8982ac304de3d12b3b5a516375a45cb0ee43e Mon Sep 17 00:00:00 2001 From: Shiva Poudel Date: Wed, 22 Nov 2017 11:34:03 +0545 Subject: [PATCH 30/76] Fix - Default shipping class not loading from localize script --- assets/js/admin/wc-shipping-classes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/admin/wc-shipping-classes.js b/assets/js/admin/wc-shipping-classes.js index eefd8374b89..526076c431f 100644 --- a/assets/js/admin/wc-shipping-classes.js +++ b/assets/js/admin/wc-shipping-classes.js @@ -145,7 +145,7 @@ classes = _.indexBy( model.get( 'classes' ), 'term_id' ), changes = {}, size = _.size( classes ), - newRow = _.extend( {}, data.default_class, { + newRow = _.extend( {}, data.default_shipping_class, { term_id: 'new-' + size + '-' + Date.now(), editing: true, newRow : true From 15230e295c9352248605fd5bb6feb66703acae39 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Wed, 22 Nov 2017 10:49:28 +0000 Subject: [PATCH 31/76] Add precision after multiplying quantity Closes #17860 Has no effect on core it seems because we only store prices to the DP setting. This would be to correct precision added by plugins. --- 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 8a0c128701f..fadaa07ffee 100644 --- a/includes/class-wc-cart-totals.php +++ b/includes/class-wc-cart-totals.php @@ -227,7 +227,7 @@ final class WC_Cart_Totals { $item->taxable = 'taxable' === $cart_item['data']->get_tax_status(); $item->price_includes_tax = wc_prices_include_tax(); $item->quantity = $cart_item['quantity']; - $item->price = wc_add_number_precision_deep( $cart_item['data']->get_price() ) * $cart_item['quantity']; + $item->price = wc_add_number_precision_deep( $cart_item['data']->get_price() * $cart_item['quantity'] ); $item->product = $cart_item['data']; $item->tax_rates = $this->get_item_tax_rates( $item ); $this->items[ $cart_item_key ] = $item; From 90535fee367bf0d1fc923b16747f6d544c6c4c29 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Wed, 22 Nov 2017 11:02:02 +0000 Subject: [PATCH 32/76] Exclude spam comments from counts Fixes #17852 --- includes/class-wc-comments.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/includes/class-wc-comments.php b/includes/class-wc-comments.php index 22f31cb186b..e3a1e4597ed 100644 --- a/includes/class-wc-comments.php +++ b/includes/class-wc-comments.php @@ -227,7 +227,7 @@ class WC_Comments { GROUP BY comment_approved ", ARRAY_A ); - $total = 0; + $total = 0; $approved = array( '0' => 'moderated', '1' => 'approved', @@ -238,7 +238,7 @@ class WC_Comments { foreach ( (array) $count as $row ) { // Don't count post-trashed toward totals. - if ( 'post-trashed' !== $row['comment_approved'] && 'trash' !== $row['comment_approved'] ) { + if ( 'post-trashed' !== $row['comment_approved'] && 'trash' !== $row['comment_approved'] && 'spam' !== $row['comment_approved'] ) { $total += $row['num_comments']; } if ( isset( $approved[ $row['comment_approved'] ] ) ) { @@ -247,7 +247,8 @@ class WC_Comments { } $stats['total_comments'] = $total; - $stats['all'] = $total; + $stats['all'] = $total; + foreach ( $approved as $key ) { if ( empty( $stats[ $key ] ) ) { $stats[ $key ] = 0; From 2b1243ea04af405799926eb6b9d0d69ba2632947 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Wed, 22 Nov 2017 11:30:22 +0000 Subject: [PATCH 33/76] Confirm navigation if nonce has expired in reports. Closes #17850 --- includes/admin/reports/class-wc-admin-report.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/includes/admin/reports/class-wc-admin-report.php b/includes/admin/reports/class-wc-admin-report.php index b634b8c7a0e..1885d2d3fc1 100644 --- a/includes/admin/reports/class-wc-admin-report.php +++ b/includes/admin/reports/class-wc-admin-report.php @@ -658,8 +658,12 @@ class WC_Admin_Report { return; } - if ( ! isset( $_GET['wc_reports_nonce'] ) || ! wp_verify_nonce( $_GET['wc_reports_nonce'], 'custom_range' ) ) { - wp_safe_redirect( remove_query_arg( array( 'start_date', 'end_date', 'range', 'wc_reports_nonce' ) ) ); + if ( ! isset( $_GET['wc_reports_nonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['wc_reports_nonce'] ), 'custom_range' ) ) { // WPCS: input var ok, CSRF ok. + wp_die( + /* translators: %1$s: open link, %2$s: close link */ + sprintf( esc_html__( 'This report link has expired. %1$sClick here to view the filtered report%2$s.', 'woocommerce' ), '', '' ), // @codingStandardsIgnoreLine. + esc_attr__( 'Confirm navigation', 'woocommerce' ) + ); exit; } } From 39e86db7a75199bd116b51c5329f3c7200468493 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Wed, 22 Nov 2017 11:39:57 +0000 Subject: [PATCH 34/76] Use an action/option rather than cron to queue rule flushing Closes #17851 --- includes/admin/class-wc-admin-settings.php | 4 ++-- includes/class-wc-post-types.php | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/includes/admin/class-wc-admin-settings.php b/includes/admin/class-wc-admin-settings.php index 861784851bc..90e95a4b39a 100644 --- a/includes/admin/class-wc-admin-settings.php +++ b/includes/admin/class-wc-admin-settings.php @@ -83,11 +83,11 @@ class WC_Admin_Settings { self::add_message( __( 'Your settings have been saved.', 'woocommerce' ) ); self::check_download_folder_protection(); - // Clear any unwanted data and flush rules + // Clear any unwanted data and flush rules on next init. + add_option( 'woocommerce_queue_flush_rewrite_rules', 'true' ); delete_transient( 'woocommerce_cache_excluded_uris' ); WC()->query->init_query_vars(); WC()->query->add_endpoints(); - wp_schedule_single_event( time(), 'woocommerce_flush_rewrite_rules' ); do_action( 'woocommerce_settings_saved' ); } diff --git a/includes/class-wc-post-types.php b/includes/class-wc-post-types.php index 3e8c0dc8577..ee8e33626fa 100644 --- a/includes/class-wc-post-types.php +++ b/includes/class-wc-post-types.php @@ -29,6 +29,7 @@ class WC_Post_types { add_action( 'init', array( __CLASS__, 'register_post_status' ), 9 ); add_action( 'init', array( __CLASS__, 'support_jetpack_omnisearch' ) ); add_filter( 'rest_api_allowed_post_types', array( __CLASS__, 'rest_api_allowed_post_types' ) ); + add_action( 'woocommerce_after_register_post_type', array( __CLASS__, 'maybe_flush_rewrite_rules' ) ); add_action( 'woocommerce_flush_rewrite_rules', array( __CLASS__, 'flush_rewrite_rules' ) ); } @@ -529,6 +530,18 @@ class WC_Post_types { } } + /** + * Flush rules if the event is queued. + * + * @since 3.3.0 + */ + public static function maybe_flush_rewrite_rules() { + if ( 'true' === get_option( 'woocommerce_queue_flush_rewrite_rules' ) ) { + delete_option( 'woocommerce_queue_flush_rewrite_rules' ); + self::flush_rewrite_rules(); + } + } + /** * Flush rewrite rules. */ From d8050f99b1588c1b2d9c3abf81335ebb625efacd Mon Sep 17 00:00:00 2001 From: Ahmed Ali Date: Wed, 22 Nov 2017 14:33:21 +0200 Subject: [PATCH 35/76] fixing typo replace add to cart to be remove from cart --- includes/class-wc-ajax.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/class-wc-ajax.php b/includes/class-wc-ajax.php index b30e967edbb..1a153806b82 100644 --- a/includes/class-wc-ajax.php +++ b/includes/class-wc-ajax.php @@ -388,7 +388,7 @@ class WC_AJAX { } /** - * AJAX add to cart. + * AJAX remove from cart. */ public static function remove_from_cart() { ob_start(); From d39a034f14324d59e5b535bdcaab1525c5014007 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 22 Nov 2017 13:55:48 -0200 Subject: [PATCH 36/76] Drop support for legacy WP versions --- includes/class-wc-geolocation.php | 29 +--- includes/vendor/class-requests-ipv6.php | 188 ------------------------ 2 files changed, 1 insertion(+), 216 deletions(-) delete mode 100644 includes/vendor/class-requests-ipv6.php diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index 121dced12ea..d99c49fd76b 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -66,33 +66,6 @@ class WC_Geolocation { return $new_value; } - /** - * Check if is a valid IP address. - * - * @since 3.0.6 - * @param string $ip_address IP address. - * @return string|bool The valid IP address, otherwise false. - */ - private static function is_ip_address( $ip_address ) { - // WP 4.7+ only. - if ( function_exists( 'rest_is_ip_address' ) ) { - return rest_is_ip_address( $ip_address ); - } - - // Support for WordPress 4.4 to 4.6. - if ( ! class_exists( 'Requests_IPv6', false ) ) { - include_once( dirname( __FILE__ ) . '/vendor/class-requests-ipv6.php' ); - } - - $ipv4_pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/'; - - if ( ! preg_match( $ipv4_pattern, $ip_address ) && ! Requests_IPv6::check_ipv6( $ip_address ) ) { - return false; - } - - return $ip_address; - } - /** * Get current user IP Address. * @return string @@ -103,7 +76,7 @@ class WC_Geolocation { } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { // Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2 // Make sure we always only send through the first IP in the list which should always be the client IP. - return (string) self::is_ip_address( trim( current( explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) ); + return (string) rest_is_ip_address( trim( current( explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) ); } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { return $_SERVER['REMOTE_ADDR']; } diff --git a/includes/vendor/class-requests-ipv6.php b/includes/vendor/class-requests-ipv6.php deleted file mode 100644 index f3eb9029773..00000000000 --- a/includes/vendor/class-requests-ipv6.php +++ /dev/null @@ -1,188 +0,0 @@ - FF01:0:0:0:0:0:0:101 - * ::1 -> 0:0:0:0:0:0:0:1 - * - * @author Alexander Merz - * @author elfrink at introweb dot nl - * @author Josh Peck - * @copyright 2003-2005 The PHP Group - * @license http://www.opensource.org/licenses/bsd-license.php - * @param string $ip An IPv6 address - * @return string The uncompressed IPv6 address - */ - public static function uncompress( $ip ) { - if ( substr_count( $ip, '::' ) !== 1 ) { - return $ip; - } - - list($ip1, $ip2) = explode( '::', $ip ); - $c1 = ( '' == $ip1 ) ? -1 : substr_count( $ip1, ':' ); - $c2 = ( '' == $ip2 ) ? -1 : substr_count( $ip2, ':' ); - - if ( strpos( $ip2, '.' ) !== false ) { - $c2++; - } - // :: - if ( -1 === $c1 && -1 === $c2 ) { - $ip = '0:0:0:0:0:0:0:0'; - } // ::xxx - elseif ( -1 === $c1 ) { - $fill = str_repeat( '0:', 7 - $c2 ); - $ip = str_replace( '::', $fill, $ip ); - } // xxx:: - elseif ( -1 === $c2 ) { - $fill = str_repeat( ':0', 7 - $c1 ); - $ip = str_replace( '::', $fill, $ip ); - } // xxx::xxx - else { - $fill = ':' . str_repeat( '0:', 6 - $c2 - $c1 ); - $ip = str_replace( '::', $fill, $ip ); - } - return $ip; - } - - /** - * Compresses an IPv6 address - * - * RFC 4291 allows you to compress consecutive zero pieces in an address to - * '::'. This method expects a valid IPv6 address and compresses consecutive - * zero pieces to '::'. - * - * Example: FF01:0:0:0:0:0:0:101 -> FF01::101 - * 0:0:0:0:0:0:0:1 -> ::1 - * - * @see uncompress() - * @param string $ip An IPv6 address - * @return string The compressed IPv6 address - */ - public static function compress( $ip ) { - // Prepare the IP to be compressed - $ip = self::uncompress( $ip ); - $ip_parts = self::split_v6_v4( $ip ); - - // Replace all leading zeros - $ip_parts[0] = preg_replace( '/(^|:)0+([0-9])/', '\1\2', $ip_parts[0] ); - - // Find bunches of zeros - if ( preg_match_all( '/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE ) ) { - $max = 0; - $pos = null; - foreach ( $matches[0] as $match ) { - if ( strlen( $match[0] ) > $max ) { - $max = strlen( $match[0] ); - $pos = $match[1]; - } - } - - $ip_parts[0] = substr_replace( $ip_parts[0], '::', $pos, $max ); - } - - if ( '' !== $ip_parts[1] ) { - return implode( ':', $ip_parts ); - } else { - return $ip_parts[0]; - } - } - - /** - * Splits an IPv6 address into the IPv6 and IPv4 representation parts - * - * RFC 4291 allows you to represent the last two parts of an IPv6 address - * using the standard IPv4 representation - * - * Example: 0:0:0:0:0:0:13.1.68.3 - * 0:0:0:0:0:FFFF:129.144.52.38 - * - * @param string $ip An IPv6 address - * @return string[] [0] contains the IPv6 represented part, and [1] the IPv4 represented part - */ - protected static function split_v6_v4( $ip ) { - if ( strpos( $ip, '.' ) !== false ) { - $pos = strrpos( $ip, ':' ); - $ipv6_part = substr( $ip, 0, $pos ); - $ipv4_part = substr( $ip, $pos + 1 ); - return array( $ipv6_part, $ipv4_part ); - } else { - return array( $ip, '' ); - } - } - - /** - * Checks an IPv6 address - * - * Checks if the given IP is a valid IPv6 address - * - * @param string $ip An IPv6 address - * @return bool true if $ip is a valid IPv6 address - */ - public static function check_ipv6( $ip ) { - $ip = self::uncompress( $ip ); - list($ipv6, $ipv4) = self::split_v6_v4( $ip ); - $ipv6 = explode( ':', $ipv6 ); - $ipv4 = explode( '.', $ipv4 ); - if ( count( $ipv6 ) === 8 && count( $ipv4 ) === 1 || count( $ipv6 ) === 6 && count( $ipv4 ) === 4 ) { - foreach ( $ipv6 as $ipv6_part ) { - // The section can't be empty - if ( '' === $ipv6_part ) { - return false; - } - - // Nor can it be over four characters - if ( strlen( $ipv6_part ) > 4 ) { - return false; - } - - // Remove leading zeros (this is safe because of the above) - $ipv6_part = ltrim( $ipv6_part, '0' ); - if ( '' === $ipv6_part ) { - $ipv6_part = '0'; - } - - // Check the value is valid - $value = hexdec( $ipv6_part ); - if ( dechex( $value ) !== strtolower( $ipv6_part ) || $value < 0 || $value > 0xFFFF ) { - return false; - } - } - if ( count( $ipv4 ) === 4 ) { - foreach ( $ipv4 as $ipv4_part ) { - $value = (int) $ipv4_part; - if ( (string) $value !== $ipv4_part || $value < 0 || $value > 0xFF ) { - return false; - } - } - } - return true; - } else { - return false; - } - } -} From 21833d797b5c23aed66858848313cbaed47625b1 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 22 Nov 2017 13:57:48 -0200 Subject: [PATCH 37/76] Updated "Tested up to" and "Requires at least" --- phpcs.ruleset.xml | 2 +- readme.txt | 4 ++-- woocommerce.php | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/phpcs.ruleset.xml b/phpcs.ruleset.xml index 54c63a381fb..09ebcf4dcce 100644 --- a/phpcs.ruleset.xml +++ b/phpcs.ruleset.xml @@ -15,7 +15,7 @@ */vendor/* - + diff --git a/readme.txt b/readme.txt index b9a33734207..a866d40eddc 100644 --- a/readme.txt +++ b/readme.txt @@ -1,8 +1,8 @@ === WooCommerce === Contributors: automattic, mikejolley, jameskoster, claudiosanches, jshreve, coderkevin, claudiulodro, woothemes, iCaleb Tags: ecommerce, e-commerce, store, sales, sell, shop, cart, checkout, downloadable, downloads, paypal, storefront, woo commerce -Requires at least: 4.5 -Tested up to: 4.8 +Requires at least: 4.7 +Tested up to: 4.9 Stable tag: 3.2.0 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html diff --git a/woocommerce.php b/woocommerce.php index f82f3244ed9..58379d17a47 100644 --- a/woocommerce.php +++ b/woocommerce.php @@ -6,8 +6,6 @@ * Version: 3.3-dev * Author: Automattic * Author URI: https://woocommerce.com - * Requires at least: 4.5 - * Tested up to: 4.7 * * Text Domain: woocommerce * Domain Path: /i18n/languages/ From 4f2e1ee8d4d3589f8e9ae7d176eff1cfd6c35a0e Mon Sep 17 00:00:00 2001 From: ragulka Date: Wed, 22 Nov 2017 17:03:58 +0100 Subject: [PATCH 38/76] Ensure refund is deleted when exception is thrown during wc_create_refund --- includes/class-wc-ajax.php | 3 --- includes/wc-order-functions.php | 3 +++ tests/framework/class-wc-unit-test-case.php | 15 +++++++++++++++ tests/unit-tests/order/crud.php | 15 +++++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/includes/class-wc-ajax.php b/includes/class-wc-ajax.php index b30e967edbb..31d74b30f46 100644 --- a/includes/class-wc-ajax.php +++ b/includes/class-wc-ajax.php @@ -1735,9 +1735,6 @@ class WC_AJAX { wp_send_json_success( $response_data ); } catch ( Exception $e ) { - if ( $refund && is_a( $refund, 'WC_Order_Refund' ) ) { - wp_delete_post( $refund->get_id(), true ); - } wp_send_json_error( array( 'error' => $e->getMessage() ) ); } } diff --git a/includes/wc-order-functions.php b/includes/wc-order-functions.php index 1f75eda82a8..d784027bb7b 100644 --- a/includes/wc-order-functions.php +++ b/includes/wc-order-functions.php @@ -587,6 +587,9 @@ function wc_create_refund( $args = array() ) { do_action( 'woocommerce_order_refunded', $order->get_id(), $refund->get_id() ); } catch ( Exception $e ) { + if ( isset( $refund ) && is_a( $refund, 'WC_Order_Refund' ) ) { + wp_delete_post( $refund->get_id(), true ); + } return new WP_Error( 'error', $e->getMessage() ); } diff --git a/tests/framework/class-wc-unit-test-case.php b/tests/framework/class-wc-unit-test-case.php index 85048e4bb74..380a93e9d50 100644 --- a/tests/framework/class-wc-unit-test-case.php +++ b/tests/framework/class-wc-unit-test-case.php @@ -81,6 +81,21 @@ class WC_Unit_Test_Case extends WP_UnitTestCase { $this->assertInstanceOf( 'WP_Error', $actual, $message ); } + /** + * Throws an exception with an optional message and code. + * + * Note: can't use `throwException` as that's reserved. + * + * @since 3.3-dev + * @param string $message + * @param int $code + * @throws \Exception + */ + public function throwAnException( $message = null, $code = null ) { + $message = $message ? $message : "We're all doomed!"; + throw new Exception( $message, $code ); + } + /** * Backport assertNotFalse to PHPUnit 3.6.12 which only runs in PHP 5.2. * diff --git a/tests/unit-tests/order/crud.php b/tests/unit-tests/order/crud.php index cba252a558c..2eae94850d7 100644 --- a/tests/unit-tests/order/crud.php +++ b/tests/unit-tests/order/crud.php @@ -1656,6 +1656,21 @@ class WC_Tests_CRUD_Orders extends WC_Unit_Test_Case { $this->assertEquals( 4, $object->get_remaining_refund_items() ); } + /** + * Test that if an exception is thrown when creating a refund, the refund is deleted from database. + */ + function test_refund_exception() { + $order = WC_Helper_Order::create_order(); + add_action( 'woocommerce_create_refund', array( $this, 'throwAnException' ) ); + $refund = wc_create_refund( array( + 'order_id' => $order->get_id(), + 'amount' => $order->get_total(), + 'line_items' => array(), + ) ); + remove_action( 'woocommerce_create_refund', array( $this, 'throwAnException' ) ); + $this->assertEmpty( $order->get_refunds() ); + } + /** * Test apply_coupon and remove_coupon with a fixed discount coupon. * @since 3.2.0 From 4fb3624604ab0334c8c67c92ec3a2fb05ea8bbb5 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 22 Nov 2017 14:13:59 -0200 Subject: [PATCH 39/76] Fixed coding standards --- includes/class-wc-geolocation.php | 131 +++++++++++++++++------------- 1 file changed, 76 insertions(+), 55 deletions(-) diff --git a/includes/class-wc-geolocation.php b/includes/class-wc-geolocation.php index d99c49fd76b..3c2537fada9 100644 --- a/includes/class-wc-geolocation.php +++ b/includes/class-wc-geolocation.php @@ -21,11 +21,21 @@ if ( ! defined( 'ABSPATH' ) ) { */ class WC_Geolocation { - /** URL to the geolocation database we're using */ - const GEOLITE_DB = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz'; + /** + * GeoLite IPv4 DB. + */ + const GEOLITE_DB = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz'; + + /** + * GeoLite IPv6 DB. + */ const GEOLITE_IPV6_DB = 'http://geolite.maxmind.com/download/geoip/database/GeoIPv6.dat.gz'; - /** @var array API endpoints for looking up user IP address */ + /** + * API endpoints for looking up user IP address. + * + * @var array + */ private static $ip_lookup_apis = array( 'icanhazip' => 'http://icanhazip.com', 'ipify' => 'http://api.ipify.org/', @@ -35,7 +45,11 @@ class WC_Geolocation { 'ip.appspot' => 'http://ip.appspot.com', ); - /** @var array API endpoints for geolocating an IP address */ + /** + * API endpoints for geolocating an IP address + * + * @var array + */ private static $geoip_apis = array( 'freegeoip' => 'https://freegeoip.net/json/%s', 'ipinfo.io' => 'https://ipinfo.io/%s/json', @@ -46,7 +60,7 @@ class WC_Geolocation { * Hook in tabs. */ public static function init() { - // Only download the database from MaxMind if the geolocation function is enabled, or a plugin specifically requests it + // Only download the database from MaxMind if the geolocation function is enabled, or a plugin specifically requests it. if ( 'geolocation' === get_option( 'woocommerce_default_customer_address' ) || apply_filters( 'woocommerce_geolocation_update_database_periodically', false ) ) { add_action( 'woocommerce_geoip_updater', array( __CLASS__, 'update_database' ) ); } @@ -55,8 +69,9 @@ class WC_Geolocation { /** * Maybe trigger a DB update for the first time. - * @param string $new_value - * @param string $old_value + * + * @param string $new_value New value. + * @param string $old_value Old value. * @return string */ public static function maybe_update_database( $new_value, $old_value ) { @@ -68,17 +83,18 @@ class WC_Geolocation { /** * Get current user IP Address. + * * @return string */ public static function get_ip_address() { - if ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) { - return $_SERVER['HTTP_X_REAL_IP']; - } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { + if ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) { // WPCS: input var ok, CSRF ok. + return sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_REAL_IP'] ) ); // WPCS: input var ok, CSRF ok. + } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { // WPCS: input var ok, CSRF ok. // Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2 // Make sure we always only send through the first IP in the list which should always be the client IP. - return (string) rest_is_ip_address( trim( current( explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) ); - } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { - return $_SERVER['REMOTE_ADDR']; + return (string) rest_is_ip_address( trim( current( explode( ',', sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) ) ) ); // WPCS: input var ok, CSRF ok. + } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { // @codingStandardsIgnoreLine + return sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ); // @codingStandardsIgnoreLine } return ''; } @@ -87,6 +103,7 @@ class WC_Geolocation { * Get user IP Address using an external service. * This is used mainly as a fallback for users on localhost where * get_ip_address() will be a local IP and non-geolocatable. + * * @return string */ public static function get_external_ip_address() { @@ -121,8 +138,9 @@ class WC_Geolocation { /** * Geolocate an IP address. - * @param string $ip_address - * @param bool $fallback If true, fallbacks to alternative IP detection (can be slower). + * + * @param string $ip_address IP Address. + * @param bool $fallback If true, fallbacks to alternative IP detection (can be slower). * @param bool $api_fallback If true, uses geolocation APIs if the database file doesn't exist (can be slower). * @return array */ @@ -131,19 +149,19 @@ class WC_Geolocation { $country_code = apply_filters( 'woocommerce_geolocate_ip', false, $ip_address, $fallback, $api_fallback ); if ( false === $country_code ) { - // If GEOIP is enabled in CloudFlare, we can use that (Settings -> CloudFlare Settings -> Settings Overview) - if ( ! empty( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) { - $country_code = sanitize_text_field( strtoupper( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ); - // WP.com VIP has a variable available. - } elseif ( ! empty( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) { - $country_code = sanitize_text_field( strtoupper( $_SERVER['GEOIP_COUNTRY_CODE'] ) ); - // VIP Go has a variable available also. - } elseif ( ! empty( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) { - $country_code = sanitize_text_field( strtoupper( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ); + // If GEOIP is enabled in CloudFlare, we can use that (Settings -> CloudFlare Settings -> Settings Overview). + if ( ! empty( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) { // WPCS: input var ok, CSRF ok. + $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_CF_IPCOUNTRY'] ) ) ); // WPCS: input var ok, CSRF ok. + } elseif ( ! empty( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok. + // WP.com VIP has a variable available. + $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['GEOIP_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. + } elseif ( ! empty( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) { // WPCS: input var ok, CSRF ok. + // VIP Go has a variable available also. + $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_COUNTRY_CODE'] ) ) ); // WPCS: input var ok, CSRF ok. } else { $ip_address = $ip_address ? $ip_address : self::get_ip_address(); - if ( self::is_IPv6( $ip_address ) ) { + if ( self::is_ipv6( $ip_address ) ) { $database = self::get_local_database_path( 'v6' ); } else { $database = self::get_local_database_path(); @@ -158,7 +176,7 @@ class WC_Geolocation { } if ( ! $country_code && $fallback ) { - // May be a local environment - find external IP + // May be a local environment - find external IP. return self::geolocate_ip( self::get_external_ip_address(), false, $api_fallback ); } } @@ -172,11 +190,12 @@ class WC_Geolocation { /** * Path to our local db. - * @param string $version + * + * @param string $version Version. * @return string */ public static function get_local_database_path( $version = 'v4' ) { - $version = ( 'v4' == $version ) ? '' : 'v6'; + $version = 'v4' === $version ? '' : 'v6'; $upload_dir = wp_upload_dir(); return apply_filters( 'woocommerce_geolocation_local_database_path', $upload_dir['basedir'] . '/GeoIP' . $version . '.dat', $version ); @@ -193,7 +212,7 @@ class WC_Geolocation { return; } - require_once( ABSPATH . 'wp-admin/includes/file.php' ); + require_once ABSPATH . 'wp-admin/includes/file.php'; $tmp_databases = array( 'v4' => download_url( self::GEOLITE_DB ), @@ -202,20 +221,20 @@ class WC_Geolocation { foreach ( $tmp_databases as $tmp_database_version => $tmp_database_path ) { if ( ! is_wp_error( $tmp_database_path ) ) { - $gzhandle = @gzopen( $tmp_database_path, 'r' ); - $handle = @fopen( self::get_local_database_path( $tmp_database_version ), 'w' ); + $gzhandle = @gzopen( $tmp_database_path, 'r' ); // @codingStandardsIgnoreLine + $handle = @fopen( self::get_local_database_path( $tmp_database_version ), 'w' ); // @codingStandardsIgnoreLine if ( $gzhandle && $handle ) { - while ( $string = gzread( $gzhandle, 4096 ) ) { - fwrite( $handle, $string, strlen( $string ) ); + while ( $string = gzread( $gzhandle, 4096 ) ) { // @codingStandardsIgnoreLine + fwrite( $handle, $string, strlen( $string ) ); // @codingStandardsIgnoreLine } gzclose( $gzhandle ); $s_array = fstat( $handle ); - fclose( $handle ); + fclose( $handle ); // @codingStandardsIgnoreLine if ( ! isset( $s_array['size'] ) || 0 === $s_array['size'] ) { $logger->notice( 'Empty database file, deleting local copy.', array( 'source' => 'geolocation' ) ); // Delete empty DB, we do not want to keep empty files around. - @unlink( self::get_local_database_path( $tmp_database_version ) ); + @unlink( self::get_local_database_path( $tmp_database_version ) ); // @codingStandardsIgnoreLine // Reschedule download of DB. wp_clear_scheduled_hook( 'woocommerce_geoip_updater' ); wp_schedule_event( strtotime( 'first tuesday of next month' ), 'monthly', 'woocommerce_geoip_updater' ); @@ -223,7 +242,7 @@ class WC_Geolocation { } else { $logger->notice( 'Unable to open database file', array( 'source' => 'geolocation' ) ); } - @unlink( $tmp_database_path ); + @unlink( $tmp_database_path ); // @codingStandardsIgnoreLine } else { $logger->notice( 'Unable to download GeoIP Database: ' . $tmp_database_path->get_error_message(), @@ -235,17 +254,18 @@ class WC_Geolocation { /** * Use MAXMIND GeoLite database to geolocation the user. - * @param string $ip_address + * + * @param string $ip_address IP address. * @return string */ private static function geolocate_via_db( $ip_address ) { if ( ! class_exists( 'WC_Geo_IP', false ) ) { - include_once( WC_ABSPATH . 'includes/class-wc-geo-ip.php' ); + include_once WC_ABSPATH . 'includes/class-wc-geo-ip.php'; } $gi = new WC_Geo_IP(); - if ( self::is_IPv6( $ip_address ) ) { + if ( self::is_ipv6( $ip_address ) ) { $database = self::get_local_database_path( 'v6' ); if ( ! self::get_file_size( $database ) ) { return false; @@ -274,14 +294,14 @@ class WC_Geolocation { * @return bool|int */ private static function get_file_size( $filename ) { - $handle = @fopen( $filename, 'r' ); - $s_array = fstat( $handle ); - @fclose( $handle ); + $handle = @fopen( $filename, 'r' ); // @codingStandardsIgnoreLine + $s_array = fstat( $handle ); // @codingStandardsIgnoreLine + @fclose( $handle ); // @codingStandardsIgnoreLine if ( ! isset( $s_array['size'] ) || 0 === $s_array['size'] ) { $logger = wc_get_logger(); $logger->notice( 'Empty database file, deleting local copy.', array( 'source' => 'geolocation' ) ); // Delete the file as we do not want to keep empty files around. - @unlink( $filename ); + @unlink( $filename ); // @codingStandardsIgnoreLine return false; } return $s_array['size']; @@ -289,7 +309,8 @@ class WC_Geolocation { /** * Use APIs to Geolocate the user. - * @param string $ip_address + * + * @param string $ip_address IP address. * @return string|bool */ private static function geolocate_via_api( $ip_address ) { @@ -306,21 +327,21 @@ class WC_Geolocation { if ( ! is_wp_error( $response ) && $response['body'] ) { switch ( $service_name ) { - case 'ipinfo.io' : + case 'ipinfo.io': $data = json_decode( $response['body'] ); $country_code = isset( $data->country ) ? $data->country : ''; - break; - case 'ip-api.com' : + break; + case 'ip-api.com': $data = json_decode( $response['body'] ); - $country_code = isset( $data->countryCode ) ? $data->countryCode : ''; - break; - case 'freegeoip' : + $country_code = isset( $data->countryCode ) ? $data->countryCode : ''; // @codingStandardsIgnoreLine + break; + case 'freegeoip': $data = json_decode( $response['body'] ); $country_code = isset( $data->country_code ) ? $data->country_code : ''; - break; - default : + break; + default: $country_code = apply_filters( 'woocommerce_geolocation_geoip_response_' . $service_name, '', $response['body'] ); - break; + break; } $country_code = sanitize_text_field( strtoupper( $country_code ) ); @@ -342,10 +363,10 @@ class WC_Geolocation { * * @since 2.4.0 * - * @param string $ip_address + * @param string $ip_address IP Address. * @return bool */ - private static function is_IPv6( $ip_address ) { + private static function is_ipv6( $ip_address ) { return false !== filter_var( $ip_address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ); } } From d27410eaccf9927735442578b8964c57b67b26bd Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 22 Nov 2017 14:47:22 -0200 Subject: [PATCH 40/76] Introduced new wc_deprecated_hook function as alias to _deprecated_hook --- .../abstract-wc-deprecated-hooks.php | 2 +- includes/wc-deprecated-functions.php | 54 ++++++++++++++----- 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/includes/abstracts/abstract-wc-deprecated-hooks.php b/includes/abstracts/abstract-wc-deprecated-hooks.php index 25edecb787b..0b9fa67641e 100644 --- a/includes/abstracts/abstract-wc-deprecated-hooks.php +++ b/includes/abstracts/abstract-wc-deprecated-hooks.php @@ -81,7 +81,7 @@ abstract class WC_Deprecated_Hooks { * @param string $new_hook */ protected function display_notice( $old_hook, $new_hook ) { - wc_deprecated_function( sprintf( 'The "%s" hook uses out of date data structures and', esc_html( $old_hook ) ), WC_VERSION, esc_html( $new_hook ) ); + wc_deprecated_hook( esc_html( $old_hook ), WC_VERSION, esc_html( $new_hook ) ); } /** diff --git a/includes/wc-deprecated-functions.php b/includes/wc-deprecated-functions.php index f4946b4f033..18ce91b1be2 100644 --- a/includes/wc-deprecated-functions.php +++ b/includes/wc-deprecated-functions.php @@ -4,10 +4,10 @@ * * Where functions come to die. * - * @author WooThemes - * @category Core - * @package WooCommerce/Functions - * @version 2.1.0 + * @author Automattic + * @category Core + * @package WooCommerce\Functions + * @version 3.3.0 */ if ( ! defined( 'ABSPATH' ) ) { @@ -17,17 +17,20 @@ if ( ! defined( 'ABSPATH' ) ) { /** * Runs a deprecated action with notice only if used. * - * @since 3.0.0 - * @param string $action - * @param array $args - * @param string $deprecated_in - * @param string $replacement + * @since 3.0.0 + * @param string $tag The name of the action hook. + * @param array $args Array of additional function arguments to be passed to do_action(). + * @param string $version The version of WooCommerce that deprecated the hook. + * @param string $replacement The hook that should have been used. + * @param string $message A message regarding the change. */ -function wc_do_deprecated_action( $action, $args, $deprecated_in, $replacement ) { - if ( has_action( $action ) ) { - wc_deprecated_function( 'Action: ' . $action, $deprecated_in, $replacement ); - do_action_ref_array( $action, $args ); +function wc_do_deprecated_action( $tag, $args, $version, $replacement = null, $message = null ) { + if ( ! has_action( $tag ) ) { + return; } + + wc_deprecated_hook( $tag, $version, $replacement, $message ); + do_action_ref_array( $tag, $args ); } /** @@ -51,6 +54,31 @@ function wc_deprecated_function( $function, $version, $replacement = null ) { // @codingStandardsIgnoreEnd } +/** + * Wrapper for deprecated hook so we can apply some extra logic. + * + * @since 3.3.0 + * @param string $hook The hook that was used. + * @param string $version The version of WordPress that deprecated the hook. + * @param string $replacement The hook that should have been used. + * @param string $message A message regarding the change. + */ +function wc_deprecated_hook( $hook, $version, $replacement = null, $message = null ) { + // @codingStandardsIgnoreStart + if ( is_ajax() ) { + do_action( 'deprecated_hook_run', $hook, $replacement, $version, $message ); + + $message = empty( $message ) ? '' : ' ' . $message; + $log_string = "{$hook} is deprecated since version {$version}"; + $log_string .= $replacement ? "! Use {$replacement} instead." : ' with no alternative available.'; + + error_log( $log_string . $message ); + } else { + _deprecated_hook( $hook, $version, $replacement, $message ); + } + // @codingStandardsIgnoreEnd +} + /** * When catching an exception, this allows us to log it if unexpected. * From 11772ca0156670d7066e212a4e0031a15d6afaaa Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 22 Nov 2017 14:55:12 -0200 Subject: [PATCH 41/76] Fixed coding standards --- .../abstract-wc-deprecated-hooks.php | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/includes/abstracts/abstract-wc-deprecated-hooks.php b/includes/abstracts/abstract-wc-deprecated-hooks.php index 0b9fa67641e..69e902c4a9a 100644 --- a/includes/abstracts/abstract-wc-deprecated-hooks.php +++ b/includes/abstracts/abstract-wc-deprecated-hooks.php @@ -1,4 +1,12 @@ Date: Wed, 22 Nov 2017 15:21:32 -0200 Subject: [PATCH 42/76] Display correct deprecated version for hooks --- .../abstract-wc-deprecated-hooks.php | 27 +++++++++--- includes/class-wc-deprecated-action-hooks.php | 23 ++++++++++ includes/class-wc-deprecated-filter-hooks.php | 43 +++++++++++++++++++ 3 files changed, 88 insertions(+), 5 deletions(-) diff --git a/includes/abstracts/abstract-wc-deprecated-hooks.php b/includes/abstracts/abstract-wc-deprecated-hooks.php index 69e902c4a9a..77acca23686 100644 --- a/includes/abstracts/abstract-wc-deprecated-hooks.php +++ b/includes/abstracts/abstract-wc-deprecated-hooks.php @@ -25,6 +25,13 @@ abstract class WC_Deprecated_Hooks { */ protected $deprecated_hooks = array(); + /** + * Array of versions on each hook has been deprecated. + * + * @var array + */ + protected $deprecated_version = array(); + /** * Constructor. */ @@ -43,7 +50,7 @@ abstract class WC_Deprecated_Hooks { /** * Get old hooks to map to new hook. * - * @param string $new_hook New hook. + * @param string $new_hook New hook name. * @return array */ public function get_old_hooks( $new_hook ) { @@ -72,14 +79,24 @@ abstract class WC_Deprecated_Hooks { /** * If the old hook is in-use, trigger it. * - * @param string $new_hook New hook. - * @param string $old_hook Old hook. + * @param string $new_hook New hook name. + * @param string $old_hook Old hook name. * @param array $new_callback_args New callback args. * @param mixed $return_value Returned value. * @return mixed */ abstract public function handle_deprecated_hook( $new_hook, $old_hook, $new_callback_args, $return_value ); + /** + * Get deprecated version. + * + * @param string $old_hook Old hook name. + * @return string + */ + protected function get_deprecated_version( $old_hook ) { + return ! empty( $this->deprecated_version[ $old_hook ] ) ? $this->deprecated_version[ $old_hook ] : WC_VERSION; + } + /** * Display a deprecated notice for old hooks. * @@ -87,13 +104,13 @@ abstract class WC_Deprecated_Hooks { * @param string $new_hook New hook. */ protected function display_notice( $old_hook, $new_hook ) { - wc_deprecated_hook( esc_html( $old_hook ), WC_VERSION, esc_html( $new_hook ) ); + wc_deprecated_hook( esc_html( $old_hook ), esc_html( $this->get_deprecated_version( $old_hook ) ), esc_html( $new_hook ) ); } /** * Fire off a legacy hook with it's args. * - * @param string $old_hook Old hook. + * @param string $old_hook Old hook name. * @param array $new_callback_args New callback args. * @return mixed */ diff --git a/includes/class-wc-deprecated-action-hooks.php b/includes/class-wc-deprecated-action-hooks.php index 8c625f83ea0..cdb89993a0c 100644 --- a/includes/class-wc-deprecated-action-hooks.php +++ b/includes/class-wc-deprecated-action-hooks.php @@ -37,6 +37,29 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { 'woocommerce_order_details_after_order_table_items' => 'woocommerce_order_items_table' ); + /** + * Array of versions on each hook has been deprecated. + * + * @var array + */ + protected $deprecated_version = array( + 'woocommerce_order_add_shipping' => '3.0.0', + 'woocommerce_order_add_coupon' => '3.0.0', + 'woocommerce_order_add_tax' => '3.0.0', + 'woocommerce_order_add_fee' => '3.0.0', + 'woocommerce_add_shipping_order_item' => '3.0.0', + 'woocommerce_add_order_item_meta' => '3.0.0', + 'woocommerce_add_order_fee_meta' => '3.0.0', + 'woocommerce_order_edit_product' => '3.0.0', + 'woocommerce_order_update_coupon' => '3.0.0', + 'woocommerce_order_update_shipping' => '3.0.0', + 'woocommerce_order_update_fee' => '3.0.0', + 'woocommerce_order_update_tax' => '3.0.0', + 'woocommerce_payment_token_created' => '3.0.0', + 'woocommerce_create_product_variation' => '3.0.0', + 'woocommerce_order_items_table' => '3.0.0', + ); + /** * Hook into the new hook so we can handle deprecated hooks once fired. * @param string $hook_name diff --git a/includes/class-wc-deprecated-filter-hooks.php b/includes/class-wc-deprecated-filter-hooks.php index 3ad8d6fda5d..34682ca267e 100644 --- a/includes/class-wc-deprecated-filter-hooks.php +++ b/includes/class-wc-deprecated-filter-hooks.php @@ -54,6 +54,49 @@ class WC_Deprecated_Filter_Hooks extends WC_Deprecated_Hooks { 'woocommerce_credit_card_type_labels' => 'wocommerce_credit_card_type_labels', ); + /** + * Array of versions on each hook has been deprecated. + * + * @var array + */ + protected $deprecated_version = array( + 'woocommerce_email_order_schema_markup' => '3.0.0', + 'add_to_cart_fragments' => '3.0.0', + 'add_to_cart_redirect' => '3.0.0', + 'woocommerce_product_width' => '3.0.0', + 'woocommerce_product_height' => '3.0.0', + 'woocommerce_product_length' => '3.0.0', + 'woocommerce_product_weight' => '3.0.0', + 'woocommerce_get_sku' => '3.0.0', + 'woocommerce_get_price' => '3.0.0', + 'woocommerce_get_regular_price' => '3.0.0', + 'woocommerce_get_sale_price' => '3.0.0', + 'woocommerce_product_tax_class' => '3.0.0', + 'woocommerce_get_stock_quantity' => '3.0.0', + 'woocommerce_get_product_attributes' => '3.0.0', + 'woocommerce_product_gallery_attachment_ids' => '3.0.0', + 'woocommerce_product_review_count' => '3.0.0', + 'woocommerce_product_files' => '3.0.0', + 'woocommerce_get_currency' => '3.0.0', + 'woocommerce_order_amount_discount_total' => '3.0.0', + 'woocommerce_order_amount_discount_tax' => '3.0.0', + 'woocommerce_order_amount_shipping_total' => '3.0.0', + 'woocommerce_order_amount_shipping_tax' => '3.0.0', + 'woocommerce_order_amount_cart_tax' => '3.0.0', + 'woocommerce_order_amount_total' => '3.0.0', + 'woocommerce_order_amount_total_tax' => '3.0.0', + 'woocommerce_order_amount_total_discount' => '3.0.0', + 'woocommerce_order_amount_subtotal' => '3.0.0', + 'woocommerce_order_tax_totals' => '3.0.0', + 'woocommerce_refund_amount' => '3.0.0', + 'woocommerce_refund_reason' => '3.0.0', + 'default_checkout_country' => '3.0.0', + 'default_checkout_state' => '3.0.0', + 'default_checkout_postcode' => '3.0.0', + 'woocommerce_debug_posting' => '3.0.0', + 'wocommerce_credit_card_type_labels' => '3.0.0', + ); + /** * Hook into the new hook so we can handle deprecated hooks once fired. * @param string $hook_name From 4b5f0c98d7f15628e3a972bb012fc079e441e9f8 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 22 Nov 2017 15:25:27 -0200 Subject: [PATCH 43/76] Fixed coding standards --- includes/class-wc-deprecated-action-hooks.php | 61 +++++++++++-------- includes/class-wc-deprecated-filter-hooks.php | 27 +++++--- 2 files changed, 51 insertions(+), 37 deletions(-) diff --git a/includes/class-wc-deprecated-action-hooks.php b/includes/class-wc-deprecated-action-hooks.php index cdb89993a0c..86b56e57f0c 100644 --- a/includes/class-wc-deprecated-action-hooks.php +++ b/includes/class-wc-deprecated-action-hooks.php @@ -1,12 +1,18 @@ array( + 'woocommerce_new_order_item' => array( 'woocommerce_order_add_shipping', 'woocommerce_order_add_coupon', 'woocommerce_order_add_tax', @@ -25,16 +31,16 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { 'woocommerce_add_order_item_meta', 'woocommerce_add_order_fee_meta', ), - 'woocommerce_update_order_item' => array( + 'woocommerce_update_order_item' => array( 'woocommerce_order_edit_product', 'woocommerce_order_update_coupon', 'woocommerce_order_update_shipping', 'woocommerce_order_update_fee', 'woocommerce_order_update_tax', ), - 'woocommerce_new_payment_token' => 'woocommerce_payment_token_created', - 'woocommerce_new_product_variation' => 'woocommerce_create_product_variation', - 'woocommerce_order_details_after_order_table_items' => 'woocommerce_order_items_table' + 'woocommerce_new_payment_token' => 'woocommerce_payment_token_created', + 'woocommerce_new_product_variation' => 'woocommerce_create_product_variation', + 'woocommerce_order_details_after_order_table_items' => 'woocommerce_order_items_table', ); /** @@ -62,7 +68,8 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { /** * Hook into the new hook so we can handle deprecated hooks once fired. - * @param string $hook_name + * + * @param string $hook_name Hook name. */ public function hook_in( $hook_name ) { add_action( $hook_name, array( $this, 'maybe_handle_deprecated_hook' ), -1000, 8 ); @@ -71,10 +78,10 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { /** * If the old hook is in-use, trigger it. * - * @param string $new_hook - * @param string $old_hook - * @param array $new_callback_args - * @param mixed $return_value + * @param string $new_hook New hook name. + * @param string $old_hook Old hook name. + * @param array $new_callback_args New callback args. + * @param mixed $return_value Returned value. * @return mixed */ public function handle_deprecated_hook( $new_hook, $old_hook, $new_callback_args, $return_value ) { @@ -88,14 +95,14 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { /** * Fire off a legacy hook with it's args. * - * @param string $old_hook - * @param array $new_callback_args + * @param string $old_hook Old hook name. + * @param array $new_callback_args New callback args. * @return mixed */ protected function trigger_hook( $old_hook, $new_callback_args ) { switch ( $old_hook ) { - case 'woocommerce_order_add_shipping' : - case 'woocommerce_order_add_fee' : + case 'woocommerce_order_add_shipping': + case 'woocommerce_order_add_fee': $item_id = $new_callback_args[0]; $item = $new_callback_args[1]; $order_id = $new_callback_args[2]; @@ -103,7 +110,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { do_action( $old_hook, $order_id, $item_id, $item ); } break; - case 'woocommerce_order_add_coupon' : + case 'woocommerce_order_add_coupon': $item_id = $new_callback_args[0]; $item = $new_callback_args[1]; $order_id = $new_callback_args[2]; @@ -111,7 +118,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { do_action( $old_hook, $order_id, $item_id, $item->get_code(), $item->get_discount(), $item->get_discount_tax() ); } break; - case 'woocommerce_order_add_tax' : + case 'woocommerce_order_add_tax': $item_id = $new_callback_args[0]; $item = $new_callback_args[1]; $order_id = $new_callback_args[2]; @@ -119,7 +126,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { do_action( $old_hook, $order_id, $item_id, $item->get_rate_id(), $item->get_tax_total(), $item->get_shipping_tax_total() ); } break; - case 'woocommerce_add_shipping_order_item' : + case 'woocommerce_add_shipping_order_item': $item_id = $new_callback_args[0]; $item = $new_callback_args[1]; $order_id = $new_callback_args[2]; @@ -127,7 +134,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { do_action( $old_hook, $order_id, $item_id, $item->legacy_package_key ); } break; - case 'woocommerce_add_order_item_meta' : + case 'woocommerce_add_order_item_meta': $item_id = $new_callback_args[0]; $item = $new_callback_args[1]; $order_id = $new_callback_args[2]; @@ -135,7 +142,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { do_action( $old_hook, $item_id, $item->legacy_values, $item->legacy_cart_item_key ); } break; - case 'woocommerce_add_order_fee_meta' : + case 'woocommerce_add_order_fee_meta': $item_id = $new_callback_args[0]; $item = $new_callback_args[1]; $order_id = $new_callback_args[2]; @@ -143,7 +150,7 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { do_action( $old_hook, $order_id, $item_id, $item->legacy_fee, $item->legacy_fee_key ); } break; - case 'woocommerce_order_edit_product' : + case 'woocommerce_order_edit_product': $item_id = $new_callback_args[0]; $item = $new_callback_args[1]; $order_id = $new_callback_args[2]; @@ -151,15 +158,15 @@ class WC_Deprecated_Action_Hooks extends WC_Deprecated_Hooks { do_action( $old_hook, $order_id, $item_id, $item, $item->get_product() ); } break; - case 'woocommerce_order_update_coupon' : - case 'woocommerce_order_update_shipping' : - case 'woocommerce_order_update_fee' : - case 'woocommerce_order_update_tax' : + case 'woocommerce_order_update_coupon': + case 'woocommerce_order_update_shipping': + case 'woocommerce_order_update_fee': + case 'woocommerce_order_update_tax': if ( ! is_a( $item, 'WC_Order_Item_Product' ) ) { do_action( $old_hook, $order_id, $item_id, $item ); } break; - default : + default: do_action_ref_array( $old_hook, $new_callback_args ); break; } diff --git a/includes/class-wc-deprecated-filter-hooks.php b/includes/class-wc-deprecated-filter-hooks.php index 34682ca267e..ed4e76d0018 100644 --- a/includes/class-wc-deprecated-filter-hooks.php +++ b/includes/class-wc-deprecated-filter-hooks.php @@ -1,12 +1,18 @@ Date: Wed, 22 Nov 2017 10:28:02 -0800 Subject: [PATCH 44/76] Fix legacy API include paths --- includes/legacy/class-wc-legacy-api.php | 72 ++++++++++++------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/includes/legacy/class-wc-legacy-api.php b/includes/legacy/class-wc-legacy-api.php index 1025abfb90a..2c1000dd3c7 100644 --- a/includes/legacy/class-wc-legacy-api.php +++ b/includes/legacy/class-wc-legacy-api.php @@ -128,23 +128,23 @@ class WC_Legacy_API { public function includes() { // API server / response handlers. - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-exception.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-server.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v3/interface-wc-api-handler.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-json-handler.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-exception.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-server.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/interface-wc-api-handler.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-json-handler.php' ); // Authentication. - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-authentication.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-authentication.php' ); $this->authentication = new WC_API_Authentication(); - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-resource.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-coupons.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-customers.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-orders.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-products.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-reports.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-taxes.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v3/class-wc-api-webhooks.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-resource.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-coupons.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-customers.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-orders.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-products.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-reports.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-taxes.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v3/class-wc-api-webhooks.php' ); // Allow plugins to load other response handlers or resource classes. do_action( 'woocommerce_api_loaded' ); @@ -186,20 +186,20 @@ class WC_Legacy_API { private function handle_v1_rest_api_request() { // Include legacy required files for v1 REST API request. - include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-server.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v1/interface-wc-api-handler.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-json-handler.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-xml-handler.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-server.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v1/interface-wc-api-handler.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-json-handler.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-xml-handler.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-authentication.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-authentication.php' ); $this->authentication = new WC_API_Authentication(); - include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-resource.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-coupons.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-customers.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-orders.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-products.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v1/class-wc-api-reports.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-resource.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-coupons.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-customers.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-orders.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-products.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v1/class-wc-api-reports.php' ); // Allow plugins to load other response handlers or resource classes. do_action( 'woocommerce_api_loaded' ); @@ -232,21 +232,21 @@ class WC_Legacy_API { * @deprecated 2.6.0 */ private function handle_v2_rest_api_request() { - include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-exception.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-server.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v2/interface-wc-api-handler.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-json-handler.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-exception.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-server.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/interface-wc-api-handler.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-json-handler.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-authentication.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-authentication.php' ); $this->authentication = new WC_API_Authentication(); - include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-resource.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-coupons.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-customers.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-orders.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-products.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-reports.php' ); - include_once( dirname( __FILE__ ) . '/api/legacy/v2/class-wc-api-webhooks.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-resource.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-coupons.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-customers.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-orders.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-products.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-reports.php' ); + include_once( dirname( __FILE__ ) . '/../api/legacy/v2/class-wc-api-webhooks.php' ); // allow plugins to load other response handlers or resource classes. do_action( 'woocommerce_api_loaded' ); From bf42bfeb93be31aab61a9b0b07c9aad1d8927d59 Mon Sep 17 00:00:00 2001 From: Claudio Sanches Date: Wed, 22 Nov 2017 17:00:02 -0200 Subject: [PATCH 45/76] Fixed unit tests --- tests/unit-tests/util/deprecated-hooks.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit-tests/util/deprecated-hooks.php b/tests/unit-tests/util/deprecated-hooks.php index c60998c228c..1f7c3f7ffc3 100644 --- a/tests/unit-tests/util/deprecated-hooks.php +++ b/tests/unit-tests/util/deprecated-hooks.php @@ -40,6 +40,7 @@ class WC_Tests_Deprecated_Hooks extends WC_Unit_Test_Case { function setUp() { add_filter( 'deprecated_function_trigger_error', '__return_false' ); + add_filter( 'deprecated_hook_trigger_error', '__return_false' ); $this->handlers = WC()->deprecated_hook_handlers; } From 18e7b25eab127e924e6ccabf7c90d3ecbf9ddfe9 Mon Sep 17 00:00:00 2001 From: urosmil Date: Thu, 23 Nov 2017 11:00:03 +0100 Subject: [PATCH 46/76] Filter for line items in abstract-wc-order.php (#17759) * Filter for line items in abstract-wc-order.php When creating custom product class there are places where line items is only value that can be handled. This is one of that places causing subtotal values after checkout not to be calculated and displayed. * Extension to woocommerce_order_get_items filter This is extension to filter as get_items() is used for different classes and types. This way it would be possible to distinct which type is called for items. * Removed filtering inside subtotal function $types parameter is added as parameter for filter inside get_items() function so previous commit is reverted as there is no need for it. --- includes/abstracts/abstract-wc-order.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/includes/abstracts/abstract-wc-order.php b/includes/abstracts/abstract-wc-order.php index 8ab766b18d1..f1864a48d24 100644 --- a/includes/abstracts/abstract-wc-order.php +++ b/includes/abstracts/abstract-wc-order.php @@ -708,7 +708,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order { } } - return apply_filters( 'woocommerce_order_get_items', $items, $this ); + return apply_filters( 'woocommerce_order_get_items', $items, $this, $types ); } /** @@ -1599,7 +1599,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order { public function get_subtotal_to_display( $compound = false, $tax_display = '' ) { $tax_display = $tax_display ? $tax_display : get_option( 'woocommerce_tax_display_cart' ); $subtotal = 0; - + if ( ! $compound ) { foreach ( $this->get_items() as $item ) { $subtotal += $item->get_subtotal(); From 51867ac7c30abcde84d67fcbe2849c18cd195048 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Thu, 23 Nov 2017 09:05:44 -0200 Subject: [PATCH 47/76] Remove Xdebug from PHP 5.3 Travis build job as well --- tests/bin/travis.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/bin/travis.sh b/tests/bin/travis.sh index bd7e3fda61f..a01b750b028 100755 --- a/tests/bin/travis.sh +++ b/tests/bin/travis.sh @@ -6,9 +6,6 @@ if [ $1 == 'before' ]; then # Composer install fails in PHP 5.2 [[ ${TRAVIS_PHP_VERSION} == '5.2' ]] && exit; - # No Xdebug and therefore no coverage in PHP 5.3 - [[ ${TRAVIS_PHP_VERSION} == '5.3' ]] && exit; - if [[ ${TRAVIS_PHP_VERSION:0:2} == "5." ]]; then composer global require "phpunit/phpunit=4.8.*" else From 6ef391666f1f4e53944802fdbebce9db5822e571 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Thu, 23 Nov 2017 11:08:10 +0000 Subject: [PATCH 48/76] Only remove base taxes in cart totals class if item is taxable Fixes #17880 --- 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 fadaa07ffee..9fa29c98433 100644 --- a/includes/class-wc-cart-totals.php +++ b/includes/class-wc-cart-totals.php @@ -423,7 +423,7 @@ final class WC_Cart_Totals { * @return object */ protected function remove_item_base_taxes( $item ) { - if ( $item->price_includes_tax ) { + if ( $item->price_includes_tax && $item->taxable ) { $base_tax_rates = WC_Tax::get_base_tax_rates( $item->product->get_tax_class( 'unfiltered' ) ); // Work out a new base price without the shop's base tax. @@ -449,7 +449,7 @@ final class WC_Cart_Totals { * @return object */ protected function adjust_non_base_location_price( $item ) { - if ( $item->price_includes_tax ) { + if ( $item->price_includes_tax && $item->taxable ) { $base_tax_rates = WC_Tax::get_base_tax_rates( $item->product->get_tax_class( 'unfiltered' ) ); if ( $item->tax_rates !== $base_tax_rates ) { From 4fea2eb21110b044a05aefb4a74259402851a5a8 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Thu, 23 Nov 2017 09:13:09 -0200 Subject: [PATCH 49/76] Disable Xdebug before calling composer --- tests/bin/travis.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/bin/travis.sh b/tests/bin/travis.sh index a01b750b028..782d9729877 100755 --- a/tests/bin/travis.sh +++ b/tests/bin/travis.sh @@ -6,6 +6,12 @@ if [ $1 == 'before' ]; then # Composer install fails in PHP 5.2 [[ ${TRAVIS_PHP_VERSION} == '5.2' ]] && exit; + # Remove Xdebug from PHP runtime for all PHP version except 7.1 to speed up builds. + # We need Xdebug enabled in the PHP 7.1 build job as it is used to generate code coverage. + if [[ ${RUN_CODE_COVERAGE} != 1 ]]; then + phpenv config-rm xdebug.ini + fi + if [[ ${TRAVIS_PHP_VERSION:0:2} == "5." ]]; then composer global require "phpunit/phpunit=4.8.*" else @@ -16,12 +22,6 @@ if [ $1 == 'before' ]; then composer install fi - # Remove Xdebug from PHP runtime for all PHP version except 7.1 to speed up builds. - # We need Xdebug enabled in the PHP 7.1 build job as it is used to generate code coverage. - if [[ ${RUN_CODE_COVERAGE} != 1 ]]; then - phpenv config-rm xdebug.ini - fi - fi if [ $1 == 'after' ]; then From 5a4e85b5f5fb69545e07fc86c29f5cb622f889ec Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Thu, 23 Nov 2017 11:17:23 +0000 Subject: [PATCH 50/76] Tweak total_comments --- includes/class-wc-comments.php | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/includes/class-wc-comments.php b/includes/class-wc-comments.php index e3a1e4597ed..bc5b721589b 100644 --- a/includes/class-wc-comments.php +++ b/includes/class-wc-comments.php @@ -218,7 +218,10 @@ class WC_Comments { $stats = get_transient( 'wc_count_comments' ); if ( ! $stats ) { - $stats = array(); + $stats = array( + 'total_comments' => 0, + 'all' => 0, + ); $count = $wpdb->get_results( " SELECT comment_approved, COUNT(*) AS num_comments @@ -227,7 +230,6 @@ class WC_Comments { GROUP BY comment_approved ", ARRAY_A ); - $total = 0; $approved = array( '0' => 'moderated', '1' => 'approved', @@ -238,17 +240,17 @@ class WC_Comments { foreach ( (array) $count as $row ) { // Don't count post-trashed toward totals. - if ( 'post-trashed' !== $row['comment_approved'] && 'trash' !== $row['comment_approved'] && 'spam' !== $row['comment_approved'] ) { - $total += $row['num_comments']; + if ( ! in_array( $row['comment_approved'], array( 'post-trashed', 'trash', 'spam' ), true ) ) { + $stats['all'] += $row['num_comments']; + $stats['total_comments'] += $row['num_comments']; + } elseif ( ! in_array( $row['comment_approved'], array( 'post-trashed', 'trash' ), true ) ) { + $stats['total_comments'] += $row['num_comments']; } if ( isset( $approved[ $row['comment_approved'] ] ) ) { $stats[ $approved[ $row['comment_approved'] ] ] = $row['num_comments']; } } - $stats['total_comments'] = $total; - $stats['all'] = $total; - foreach ( $approved as $key ) { if ( empty( $stats[ $key ] ) ) { $stats[ $key ] = 0; From 8ac49d448bfb9f21c2ff64409629bcdc01d5f8eb Mon Sep 17 00:00:00 2001 From: The Dramatist Date: Thu, 23 Nov 2017 17:49:12 +0600 Subject: [PATCH 51/76] Unused parameter removed form get_filters method of WC_Helper class. (#17888) --- includes/admin/helper/class-wc-helper.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/includes/admin/helper/class-wc-helper.php b/includes/admin/helper/class-wc-helper.php index ab14291d400..d50c0e4fb5c 100644 --- a/includes/admin/helper/class-wc-helper.php +++ b/includes/admin/helper/class-wc-helper.php @@ -321,11 +321,9 @@ class WC_Helper { /** * Get available subscriptions filters. * - * @param array Optional subscriptions array to generate counts. - * * @return array An array of filter keys and labels. */ - public static function get_filters( $subscriptions = null ) { + public static function get_filters() { $filters = array( 'all' => __( 'All', 'woocommerce' ), 'active' => __( 'Active', 'woocommerce' ), From f5d2a1d98b03e09eb504cec5991819f04215788d Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Thu, 23 Nov 2017 11:41:31 -0200 Subject: [PATCH 52/76] Remove three PHPCS VIP rules that don't apply to WooCommerce This commit removes the following PHPCS VIP rules: - WordPress.VIP.DirectDatabaseQuery.NoCaching - WordPress.VIP.DirectDatabaseQuery.SchemaChange - WordPress.VIP.FileSystemWritesDisallow.file_ops_fwrite --- phpcs.ruleset.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/phpcs.ruleset.xml b/phpcs.ruleset.xml index 54c63a381fb..7daa25127bc 100644 --- a/phpcs.ruleset.xml +++ b/phpcs.ruleset.xml @@ -22,8 +22,11 @@ - + + + + From 322619cdc54624f04e1fbf501442cbf313e1cfd0 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Thu, 23 Nov 2017 12:06:00 -0200 Subject: [PATCH 53/76] Exclude two more PHPCS VIP rules --- phpcs.ruleset.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/phpcs.ruleset.xml b/phpcs.ruleset.xml index dc52acab818..b1ebe085dfa 100644 --- a/phpcs.ruleset.xml +++ b/phpcs.ruleset.xml @@ -27,6 +27,8 @@ + + From e12fa54bc652c2fab2fa7606539bf4c8016b6bbb Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Thu, 23 Nov 2017 10:41:31 -0200 Subject: [PATCH 54/76] phpcbf automatic coding standard fixes --- includes/class-wc-install.php | 304 +++++++++-------- .../abstract-wc-order-data-store-cpt.php | 83 +++-- .../class-wc-order-data-store-cpt.php | 213 ++++++------ includes/wc-update-functions.php | 322 ++++++++++-------- 4 files changed, 503 insertions(+), 419 deletions(-) diff --git a/includes/class-wc-install.php b/includes/class-wc-install.php index 12f1d4a840a..0941bea8acd 100644 --- a/includes/class-wc-install.php +++ b/includes/class-wc-install.php @@ -128,7 +128,7 @@ class WC_Install { * Init background updates */ public static function init_background_updater() { - include_once( dirname( __FILE__ ) . '/class-wc-background-updater.php' ); + include_once dirname( __FILE__ ) . '/class-wc-background-updater.php'; self::$background_updater = new WC_Background_Updater(); } @@ -202,7 +202,7 @@ class WC_Install { * @since 3.2.0 */ private static function remove_admin_notices() { - include_once( dirname( __FILE__ ) . '/admin/class-wc-admin-notices.php' ); + include_once dirname( __FILE__ ) . '/admin/class-wc-admin-notices.php'; WC_Admin_Notices::remove_all_notices(); } @@ -319,6 +319,7 @@ class WC_Install { /** * Update DB version to current. + * * @param string $version */ public static function update_db_version( $version = null ) { @@ -328,6 +329,7 @@ class WC_Install { /** * Add more cron schedules. + * * @param array $schedules * @return array */ @@ -368,30 +370,32 @@ class WC_Install { * Create pages that the plugin relies on, storing page IDs in variables. */ public static function create_pages() { - include_once( dirname( __FILE__ ) . '/admin/wc-admin-functions.php' ); + include_once dirname( __FILE__ ) . '/admin/wc-admin-functions.php'; - $pages = apply_filters( 'woocommerce_create_pages', array( - 'shop' => array( - 'name' => _x( 'shop', 'Page slug', 'woocommerce' ), - 'title' => _x( 'Shop', 'Page title', 'woocommerce' ), - 'content' => '', - ), - '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( - 'name' => _x( 'checkout', 'Page slug', 'woocommerce' ), - 'title' => _x( 'Checkout', 'Page title', 'woocommerce' ), - 'content' => '[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']', - ), - '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' ) . ']', - ), - ) ); + $pages = apply_filters( + 'woocommerce_create_pages', array( + 'shop' => array( + 'name' => _x( 'shop', 'Page slug', 'woocommerce' ), + 'title' => _x( 'Shop', 'Page title', 'woocommerce' ), + 'content' => '', + ), + '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( + 'name' => _x( 'checkout', 'Page slug', 'woocommerce' ), + 'title' => _x( 'Checkout', 'Page title', 'woocommerce' ), + 'content' => '[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']', + ), + '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' ) . ']', + ), + ) + ); foreach ( $pages as $key => $page ) { wc_create_page( esc_sql( $page['name'] ), 'woocommerce_' . $key . '_page_id', $page['title'], $page['content'], ! empty( $page['parent'] ) ? wc_get_page_id( $page['parent'] ) : '' ); @@ -407,7 +411,7 @@ class WC_Install { */ private static function create_options() { // Include settings so that we can run through defaults - include_once( dirname( __FILE__ ) . '/admin/class-wc-admin-settings.php' ); + include_once dirname( __FILE__ ) . '/admin/class-wc-admin-settings.php'; $settings = WC_Admin_Settings::get_settings_pages(); @@ -433,7 +437,7 @@ class WC_Install { */ public static function create_terms() { $taxonomies = array( - 'product_type' => array( + 'product_type' => array( 'simple', 'grouped', 'variable', @@ -465,21 +469,21 @@ class WC_Install { * Set up the database tables which the plugin needs to function. * * Tables: - * woocommerce_attribute_taxonomies - Table for storing attribute taxonomies - these are user defined - * woocommerce_termmeta - Term meta table - sadly WordPress does not have termmeta so we need our own - * woocommerce_downloadable_product_permissions - Table for storing user and guest download permissions. - * KEY(order_id, product_id, download_id) used for organizing downloads on the My Account page - * woocommerce_order_items - Order line items are stored in a table to make them easily queryable for reports - * woocommerce_order_itemmeta - Order line item meta is stored in a table for storing extra data. - * woocommerce_tax_rates - Tax Rates are stored inside 2 tables making tax queries simple and efficient. - * woocommerce_tax_rate_locations - Each rate can be applied to more than one postcode/city hence the second table. + * woocommerce_attribute_taxonomies - Table for storing attribute taxonomies - these are user defined + * woocommerce_termmeta - Term meta table - sadly WordPress does not have termmeta so we need our own + * woocommerce_downloadable_product_permissions - Table for storing user and guest download permissions. + * KEY(order_id, product_id, download_id) used for organizing downloads on the My Account page + * woocommerce_order_items - Order line items are stored in a table to make them easily queryable for reports + * woocommerce_order_itemmeta - Order line item meta is stored in a table for storing extra data. + * woocommerce_tax_rates - Tax Rates are stored inside 2 tables making tax queries simple and efficient. + * woocommerce_tax_rate_locations - Each rate can be applied to more than one postcode/city hence the second table. */ private static function create_tables() { global $wpdb; $wpdb->hide_errors(); - require_once( ABSPATH . 'wp-admin/includes/upgrade.php' ); + require_once ABSPATH . 'wp-admin/includes/upgrade.php'; /** * Before updating with DBDELTA, remove any primary keys which could be @@ -717,52 +721,60 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( } // Customer role - add_role( 'customer', __( 'Customer', 'woocommerce' ), array( - 'read' => true, - ) ); + add_role( + 'customer', + __( 'Customer', 'woocommerce' ), + array( + 'read' => true, + ) + ); // Shop manager role - add_role( 'shop_manager', __( 'Shop manager', 'woocommerce' ), array( - 'level_9' => true, - 'level_8' => true, - 'level_7' => true, - 'level_6' => true, - 'level_5' => true, - 'level_4' => true, - 'level_3' => true, - 'level_2' => true, - 'level_1' => true, - 'level_0' => true, - 'read' => true, - 'read_private_pages' => true, - 'read_private_posts' => true, - 'edit_users' => true, - 'edit_posts' => true, - 'edit_pages' => true, - 'edit_published_posts' => true, - 'edit_published_pages' => true, - 'edit_private_pages' => true, - 'edit_private_posts' => true, - 'edit_others_posts' => true, - 'edit_others_pages' => true, - 'publish_posts' => true, - 'publish_pages' => true, - 'delete_posts' => true, - 'delete_pages' => true, - 'delete_private_pages' => true, - 'delete_private_posts' => true, - 'delete_published_pages' => true, - 'delete_published_posts' => true, - 'delete_others_posts' => true, - 'delete_others_pages' => true, - 'manage_categories' => true, - 'manage_links' => true, - 'moderate_comments' => true, - 'upload_files' => true, - 'export' => true, - 'import' => true, - 'list_users' => true, - ) ); + add_role( + 'shop_manager', + __( 'Shop manager', 'woocommerce' ), + array( + 'level_9' => true, + 'level_8' => true, + 'level_7' => true, + 'level_6' => true, + 'level_5' => true, + 'level_4' => true, + 'level_3' => true, + 'level_2' => true, + 'level_1' => true, + 'level_0' => true, + 'read' => true, + 'read_private_pages' => true, + 'read_private_posts' => true, + 'edit_users' => true, + 'edit_posts' => true, + 'edit_pages' => true, + 'edit_published_posts' => true, + 'edit_published_pages' => true, + 'edit_private_pages' => true, + 'edit_private_posts' => true, + 'edit_others_posts' => true, + 'edit_others_pages' => true, + 'publish_posts' => true, + 'publish_pages' => true, + 'delete_posts' => true, + 'delete_pages' => true, + 'delete_private_pages' => true, + 'delete_private_posts' => true, + 'delete_published_pages' => true, + 'delete_published_posts' => true, + 'delete_others_posts' => true, + 'delete_others_pages' => true, + 'manage_categories' => true, + 'manage_links' => true, + 'moderate_comments' => true, + 'upload_files' => true, + 'export' => true, + 'import' => true, + 'list_users' => true, + ) + ); $capabilities = self::get_core_capabilities(); @@ -779,7 +791,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( * * @return array */ - private static function get_core_capabilities() { + private static function get_core_capabilities() { $capabilities = array(); $capabilities['core'] = array( @@ -860,27 +872,27 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( $files = array( array( - 'base' => $upload_dir['basedir'] . '/woocommerce_uploads', - 'file' => 'index.html', - 'content' => '', + 'base' => $upload_dir['basedir'] . '/woocommerce_uploads', + 'file' => 'index.html', + 'content' => '', ), array( - 'base' => WC_LOG_DIR, - 'file' => '.htaccess', - 'content' => 'deny from all', + 'base' => WC_LOG_DIR, + 'file' => '.htaccess', + 'content' => 'deny from all', ), array( - 'base' => WC_LOG_DIR, - 'file' => 'index.html', - 'content' => '', + 'base' => WC_LOG_DIR, + 'file' => 'index.html', + 'content' => '', ), ); if ( 'redirect' !== $download_method ) { $files[] = array( - 'base' => $upload_dir['basedir'] . '/woocommerce_uploads', - 'file' => '.htaccess', - 'content' => 'deny from all', + 'base' => $upload_dir['basedir'] . '/woocommerce_uploads', + 'file' => '.htaccess', + 'content' => 'deny from all', ); } @@ -897,8 +909,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( /** * Show action links on the plugin screen. * - * @param mixed $links Plugin Action links - * @return array + * @param mixed $links Plugin Action links + * @return array */ public static function plugin_action_links( $links ) { $action_links = array( @@ -911,9 +923,9 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( /** * Show row meta on the plugin screen. * - * @param mixed $links Plugin Row Meta - * @param mixed $file Plugin Base file - * @return array + * @param mixed $links Plugin Row Meta + * @param mixed $file Plugin Base file + * @return array */ public static function plugin_row_meta( $links, $file ) { if ( WC_PLUGIN_BASENAME == $file ) { @@ -931,6 +943,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( /** * Uninstall tables when MU blog is deleted. + * * @param array $tables * @return string[] */ @@ -956,6 +969,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( /** * Get slug from path + * * @param string $key * @return string */ @@ -968,8 +982,9 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( /** * Install a plugin from .org in the background via a cron job (used by * installer - opt in). + * * @param string $plugin_to_install_id - * @param array $plugin_to_install + * @param array $plugin_to_install * @since 2.6.0 */ public static function background_installer( $plugin_to_install_id, $plugin_to_install ) { @@ -977,14 +992,14 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( wp_clear_scheduled_hook( 'woocommerce_plugin_background_installer', func_get_args() ); if ( ! empty( $plugin_to_install['repo-slug'] ) ) { - require_once( ABSPATH . 'wp-admin/includes/file.php' ); - require_once( ABSPATH . 'wp-admin/includes/plugin-install.php' ); - require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ); - require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); + require_once ABSPATH . 'wp-admin/includes/file.php'; + require_once ABSPATH . 'wp-admin/includes/plugin-install.php'; + require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + require_once ABSPATH . 'wp-admin/includes/plugin.php'; WP_Filesystem(); - $skin = new Automatic_Upgrader_Skin; + $skin = new Automatic_Upgrader_Skin(); $upgrader = new WP_Upgrader( $skin ); $installed_plugins = array_map( array( __CLASS__, 'format_plugin_slug' ), array_keys( get_plugins() ) ); $plugin_slug = $plugin_to_install['repo-slug']; @@ -1004,24 +1019,27 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( ob_start(); try { - $plugin_information = plugins_api( 'plugin_information', array( - 'slug' => $plugin_to_install['repo-slug'], - 'fields' => array( - 'short_description' => false, - 'sections' => false, - 'requires' => false, - 'rating' => false, - 'ratings' => false, - 'downloaded' => false, - 'last_updated' => false, - 'added' => false, - 'tags' => false, - 'homepage' => false, - 'donate_link' => false, - 'author_profile' => false, - 'author' => false, - ), - ) ); + $plugin_information = plugins_api( + 'plugin_information', + array( + 'slug' => $plugin_to_install['repo-slug'], + 'fields' => array( + 'short_description' => false, + 'sections' => false, + 'requires' => false, + 'rating' => false, + 'ratings' => false, + 'downloaded' => false, + 'last_updated' => false, + 'added' => false, + 'tags' => false, + 'homepage' => false, + 'donate_link' => false, + 'author_profile' => false, + 'author' => false, + ), + ) + ); if ( is_wp_error( $plugin_information ) ) { throw new Exception( $plugin_information->get_error_message() ); @@ -1040,17 +1058,19 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( throw new Exception( $working_dir->get_error_message() ); } - $result = $upgrader->install_package( array( - 'source' => $working_dir, - 'destination' => WP_PLUGIN_DIR, - 'clear_destination' => false, - 'abort_if_destination_exists' => false, - 'clear_working' => true, - 'hook_extra' => array( - 'type' => 'plugin', - 'action' => 'install', - ), - ) ); + $result = $upgrader->install_package( + array( + 'source' => $working_dir, + 'destination' => WP_PLUGIN_DIR, + 'clear_destination' => false, + 'abort_if_destination_exists' => false, + 'clear_working' => true, + 'hook_extra' => array( + 'type' => 'plugin', + 'action' => 'install', + ), + ) + ); if ( is_wp_error( $result ) ) { throw new Exception( $result->get_error_message() ); @@ -1116,18 +1136,20 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( $theme = wp_get_theme( $theme_slug ); if ( ! $theme->exists() ) { - require_once( ABSPATH . 'wp-admin/includes/file.php' ); - include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ); - include_once( ABSPATH . 'wp-admin/includes/theme.php' ); + require_once ABSPATH . 'wp-admin/includes/file.php'; + include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + include_once ABSPATH . 'wp-admin/includes/theme.php'; WP_Filesystem(); - $skin = new Automatic_Upgrader_Skin; + $skin = new Automatic_Upgrader_Skin(); $upgrader = new Theme_Upgrader( $skin ); - $api = themes_api( 'theme_information', array( - 'slug' => $theme_slug, - 'fields' => array( 'sections' => false ), - ) ); + $api = themes_api( + 'theme_information', array( + 'slug' => $theme_slug, + 'fields' => array( 'sections' => false ), + ) + ); $result = $upgrader->install( $api->download_link ); if ( is_wp_error( $result ) ) { diff --git a/includes/data-stores/abstract-wc-order-data-store-cpt.php b/includes/data-stores/abstract-wc-order-data-store-cpt.php index 5cc063748e4..f7221506a61 100644 --- a/includes/data-stores/abstract-wc-order-data-store-cpt.php +++ b/includes/data-stores/abstract-wc-order-data-store-cpt.php @@ -46,6 +46,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme /** * Method to create a new order in the database. + * * @param WC_Order $order */ public function create( &$order ) { @@ -53,18 +54,23 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme $order->set_date_created( current_time( 'timestamp', true ) ); $order->set_currency( $order->get_currency() ? $order->get_currency() : get_woocommerce_currency() ); - $id = wp_insert_post( apply_filters( 'woocommerce_new_order_data', array( - 'post_date' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ), - 'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ), - 'post_type' => $order->get_type( 'edit' ), - 'post_status' => 'wc-' . ( $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' ) ), - 'ping_status' => 'closed', - 'post_author' => 1, - 'post_title' => $this->get_post_title(), - 'post_password' => uniqid( 'order_' ), - 'post_parent' => $order->get_parent_id( 'edit' ), - 'post_excerpt' => $this->get_post_excerpt( $order ), - ) ), true ); + $id = wp_insert_post( + apply_filters( + 'woocommerce_new_order_data', + array( + 'post_date' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getOffsetTimestamp() ), + 'post_date_gmt' => gmdate( 'Y-m-d H:i:s', $order->get_date_created( 'edit' )->getTimestamp() ), + 'post_type' => $order->get_type( 'edit' ), + 'post_status' => 'wc-' . ( $order->get_status( 'edit' ) ? $order->get_status( 'edit' ) : apply_filters( 'woocommerce_default_order_status', 'pending' ) ), + 'ping_status' => 'closed', + 'post_author' => 1, + 'post_title' => $this->get_post_title(), + 'post_password' => uniqid( 'order_' ), + 'post_parent' => $order->get_parent_id( 'edit' ), + 'post_excerpt' => $this->get_post_excerpt( $order ), + ) + ), true + ); if ( $id && ! is_wp_error( $id ) ) { $order->set_id( $id ); @@ -89,12 +95,14 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme throw new Exception( __( 'Invalid order.', 'woocommerce' ) ); } - $order->set_props( array( - 'parent_id' => $post_object->post_parent, - 'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null, - 'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null, - 'status' => $post_object->post_status, - ) ); + $order->set_props( + array( + 'parent_id' => $post_object->post_parent, + 'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null, + 'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null, + 'status' => $post_object->post_status, + ) + ); $this->read_order_data( $order, $post_object ); $order->read_meta_data(); @@ -112,6 +120,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme /** * Method to update an order in the database. + * * @param WC_Order $order */ public function update( &$order ) { @@ -155,14 +164,18 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme /** * Method to delete an order from the database. + * * @param WC_Order $order - * @param array $args Array of args to pass to the delete method. + * @param array $args Array of args to pass to the delete method. */ public function delete( &$order, $args = array() ) { $id = $order->get_id(); - $args = wp_parse_args( $args, array( - 'force_delete' => false, - ) ); + $args = wp_parse_args( + $args, + array( + 'force_delete' => false, + ) + ); if ( ! $id ) { return; @@ -217,17 +230,19 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme protected function read_order_data( &$order, $post_object ) { $id = $order->get_id(); - $order->set_props( array( - 'currency' => get_post_meta( $id, '_order_currency', true ), - 'discount_total' => get_post_meta( $id, '_cart_discount', true ), - 'discount_tax' => get_post_meta( $id, '_cart_discount_tax', true ), - 'shipping_total' => get_post_meta( $id, '_order_shipping', true ), - 'shipping_tax' => get_post_meta( $id, '_order_shipping_tax', true ), - 'cart_tax' => get_post_meta( $id, '_order_tax', true ), - 'total' => get_post_meta( $id, '_order_total', true ), - 'version' => get_post_meta( $id, '_order_version', true ), - 'prices_include_tax' => metadata_exists( 'post', $id, '_prices_include_tax' ) ? 'yes' === get_post_meta( $id, '_prices_include_tax', true ) : 'yes' === get_option( 'woocommerce_prices_include_tax' ), - ) ); + $order->set_props( + array( + 'currency' => get_post_meta( $id, '_order_currency', true ), + 'discount_total' => get_post_meta( $id, '_cart_discount', true ), + 'discount_tax' => get_post_meta( $id, '_cart_discount_tax', true ), + 'shipping_total' => get_post_meta( $id, '_order_shipping', true ), + 'shipping_tax' => get_post_meta( $id, '_order_shipping_tax', true ), + 'cart_tax' => get_post_meta( $id, '_order_tax', true ), + 'total' => get_post_meta( $id, '_order_total', true ), + 'version' => get_post_meta( $id, '_order_version', true ), + 'prices_include_tax' => metadata_exists( 'post', $id, '_prices_include_tax' ) ? 'yes' === get_post_meta( $id, '_prices_include_tax', true ) : 'yes' === get_option( 'woocommerce_prices_include_tax' ), + ) + ); // Gets extra data associated with the order if needed. foreach ( $order->get_extra_data_keys() as $key ) { @@ -291,7 +306,7 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme * Read order items of a specific type from the database for this order. * * @param WC_Order $order - * @param string $type + * @param string $type * @return array */ public function read_items( $order, $type ) { diff --git a/includes/data-stores/class-wc-order-data-store-cpt.php b/includes/data-stores/class-wc-order-data-store-cpt.php index f82a7c4368d..03fcf866bee 100644 --- a/includes/data-stores/class-wc-order-data-store-cpt.php +++ b/includes/data-stores/class-wc-order-data-store-cpt.php @@ -14,6 +14,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement /** * Data stored in meta keys, but not considered "meta" for an order. + * * @since 3.0.0 * @var array */ @@ -70,6 +71,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement /** * Method to create a new order in the database. + * * @param WC_Order $order */ public function create( &$order ) { @@ -99,44 +101,47 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement $date_paid = get_post_meta( $id, '_paid_date', true ); } - $order->set_props( array( - 'order_key' => get_post_meta( $id, '_order_key', true ), - 'customer_id' => get_post_meta( $id, '_customer_user', true ), - 'billing_first_name' => get_post_meta( $id, '_billing_first_name', true ), - 'billing_last_name' => get_post_meta( $id, '_billing_last_name', true ), - 'billing_company' => get_post_meta( $id, '_billing_company', true ), - 'billing_address_1' => get_post_meta( $id, '_billing_address_1', true ), - 'billing_address_2' => get_post_meta( $id, '_billing_address_2', true ), - 'billing_city' => get_post_meta( $id, '_billing_city', true ), - 'billing_state' => get_post_meta( $id, '_billing_state', true ), - 'billing_postcode' => get_post_meta( $id, '_billing_postcode', true ), - 'billing_country' => get_post_meta( $id, '_billing_country', true ), - 'billing_email' => get_post_meta( $id, '_billing_email', true ), - 'billing_phone' => get_post_meta( $id, '_billing_phone', true ), - 'shipping_first_name' => get_post_meta( $id, '_shipping_first_name', true ), - 'shipping_last_name' => get_post_meta( $id, '_shipping_last_name', true ), - 'shipping_company' => get_post_meta( $id, '_shipping_company', true ), - 'shipping_address_1' => get_post_meta( $id, '_shipping_address_1', true ), - 'shipping_address_2' => get_post_meta( $id, '_shipping_address_2', true ), - 'shipping_city' => get_post_meta( $id, '_shipping_city', true ), - 'shipping_state' => get_post_meta( $id, '_shipping_state', true ), - 'shipping_postcode' => get_post_meta( $id, '_shipping_postcode', true ), - 'shipping_country' => get_post_meta( $id, '_shipping_country', true ), - 'payment_method' => get_post_meta( $id, '_payment_method', true ), - 'payment_method_title' => get_post_meta( $id, '_payment_method_title', true ), - 'transaction_id' => get_post_meta( $id, '_transaction_id', true ), - 'customer_ip_address' => get_post_meta( $id, '_customer_ip_address', true ), - 'customer_user_agent' => get_post_meta( $id, '_customer_user_agent', true ), - 'created_via' => get_post_meta( $id, '_created_via', true ), - 'date_completed' => $date_completed, - 'date_paid' => $date_paid, - 'cart_hash' => get_post_meta( $id, '_cart_hash', true ), - 'customer_note' => $post_object->post_excerpt, - ) ); + $order->set_props( + array( + 'order_key' => get_post_meta( $id, '_order_key', true ), + 'customer_id' => get_post_meta( $id, '_customer_user', true ), + 'billing_first_name' => get_post_meta( $id, '_billing_first_name', true ), + 'billing_last_name' => get_post_meta( $id, '_billing_last_name', true ), + 'billing_company' => get_post_meta( $id, '_billing_company', true ), + 'billing_address_1' => get_post_meta( $id, '_billing_address_1', true ), + 'billing_address_2' => get_post_meta( $id, '_billing_address_2', true ), + 'billing_city' => get_post_meta( $id, '_billing_city', true ), + 'billing_state' => get_post_meta( $id, '_billing_state', true ), + 'billing_postcode' => get_post_meta( $id, '_billing_postcode', true ), + 'billing_country' => get_post_meta( $id, '_billing_country', true ), + 'billing_email' => get_post_meta( $id, '_billing_email', true ), + 'billing_phone' => get_post_meta( $id, '_billing_phone', true ), + 'shipping_first_name' => get_post_meta( $id, '_shipping_first_name', true ), + 'shipping_last_name' => get_post_meta( $id, '_shipping_last_name', true ), + 'shipping_company' => get_post_meta( $id, '_shipping_company', true ), + 'shipping_address_1' => get_post_meta( $id, '_shipping_address_1', true ), + 'shipping_address_2' => get_post_meta( $id, '_shipping_address_2', true ), + 'shipping_city' => get_post_meta( $id, '_shipping_city', true ), + 'shipping_state' => get_post_meta( $id, '_shipping_state', true ), + 'shipping_postcode' => get_post_meta( $id, '_shipping_postcode', true ), + 'shipping_country' => get_post_meta( $id, '_shipping_country', true ), + 'payment_method' => get_post_meta( $id, '_payment_method', true ), + 'payment_method_title' => get_post_meta( $id, '_payment_method_title', true ), + 'transaction_id' => get_post_meta( $id, '_transaction_id', true ), + 'customer_ip_address' => get_post_meta( $id, '_customer_ip_address', true ), + 'customer_user_agent' => get_post_meta( $id, '_customer_user_agent', true ), + 'created_via' => get_post_meta( $id, '_created_via', true ), + 'date_completed' => $date_completed, + 'date_paid' => $date_paid, + 'cart_hash' => get_post_meta( $id, '_cart_hash', true ), + 'customer_note' => $post_object->post_excerpt, + ) + ); } /** * Method to update an order in the database. + * * @param WC_Order $order */ public function update( &$order ) { @@ -201,7 +206,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement } $address_props = array( - 'billing' => array( + 'billing' => array( '_billing_first_name' => 'billing_first_name', '_billing_last_name' => 'billing_last_name', '_billing_company' => 'billing_company', @@ -275,13 +280,16 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement public function get_total_refunded( $order ) { global $wpdb; - $total = $wpdb->get_var( $wpdb->prepare( " - SELECT SUM( postmeta.meta_value ) - FROM $wpdb->postmeta AS postmeta - INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) - WHERE postmeta.meta_key = '_refund_amount' - AND postmeta.post_id = posts.ID - ", $order->get_id() ) ); + $total = $wpdb->get_var( + $wpdb->prepare( + "SELECT SUM( postmeta.meta_value ) + FROM $wpdb->postmeta AS postmeta + INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) + WHERE postmeta.meta_key = '_refund_amount' + AND postmeta.post_id = posts.ID", + $order->get_id() + ) + ); return $total; } @@ -295,14 +303,17 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement public function get_total_tax_refunded( $order ) { global $wpdb; - $total = $wpdb->get_var( $wpdb->prepare( " - SELECT SUM( order_itemmeta.meta_value ) - FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta - INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) - INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'tax' ) - WHERE order_itemmeta.order_item_id = order_items.order_item_id - AND order_itemmeta.meta_key IN ('tax_amount', 'shipping_tax_amount') - ", $order->get_id() ) ); + $total = $wpdb->get_var( + $wpdb->prepare( + "SELECT SUM( order_itemmeta.meta_value ) + FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta + INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) + INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'tax' ) + WHERE order_itemmeta.order_item_id = order_items.order_item_id + AND order_itemmeta.meta_key IN ('tax_amount', 'shipping_tax_amount')", + $order->get_id() + ) + ); return abs( $total ); } @@ -316,14 +327,17 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement public function get_total_shipping_refunded( $order ) { global $wpdb; - $total = $wpdb->get_var( $wpdb->prepare( " - SELECT SUM( order_itemmeta.meta_value ) - FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta - INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) - INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'shipping' ) - WHERE order_itemmeta.order_item_id = order_items.order_item_id - AND order_itemmeta.meta_key IN ('cost') - ", $order->get_id() ) ); + $total = $wpdb->get_var( + $wpdb->prepare( + "SELECT SUM( order_itemmeta.meta_value ) + FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta + INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) + INNER JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON ( order_items.order_id = posts.ID AND order_items.order_item_type = 'shipping' ) + WHERE order_itemmeta.order_item_id = order_items.order_item_id + AND order_itemmeta.meta_key IN ('cost')", + $order->get_id() + ) + ); return abs( $total ); } @@ -368,19 +382,19 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement /** * Generate meta query for wc_get_orders. * - * @param array $values + * @param array $values * @param string $relation * @return array */ private function get_orders_generate_customer_meta_query( $values, $relation = 'or' ) { $meta_query = array( - 'relation' => strtoupper( $relation ), + 'relation' => strtoupper( $relation ), 'customer_emails' => array( 'key' => '_billing_email', 'value' => array(), 'compare' => 'IN', ), - 'customer_ids' => array( + 'customer_ids' => array( 'key' => '_customer_user', 'value' => array(), 'compare' => 'IN', @@ -424,13 +438,16 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement public function get_unpaid_orders( $date ) { global $wpdb; - $unpaid_orders = $wpdb->get_col( $wpdb->prepare( " - SELECT posts.ID - FROM {$wpdb->posts} AS posts - WHERE posts.post_type IN ('" . implode( "','", wc_get_order_types() ) . "') - AND posts.post_status = 'wc-pending' - AND posts.post_modified < %s - ", date( 'Y-m-d H:i:s', absint( $date ) ) ) ); + $unpaid_orders = $wpdb->get_col( + $wpdb->prepare( + "SELECT posts.ID + FROM {$wpdb->posts} AS posts + WHERE posts.post_type IN ('" . implode( "','", wc_get_order_types() ) . "') + AND posts.post_status = 'wc-pending' + AND posts.post_modified < %s", + date( 'Y-m-d H:i:s', absint( $date ) ) + ) + ); return $unpaid_orders; } @@ -448,36 +465,42 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement * Searches on meta data can be slow - this lets you choose what fields to search. * 3.0.0 added _billing_address and _shipping_address meta which contains all address data to make this faster. * This however won't work on older orders unless updated, so search a few others (expand this using the filter if needed). + * * @var array */ - $search_fields = array_map( 'wc_clean', apply_filters( 'woocommerce_shop_order_search_fields', array( - '_billing_address_index', - '_shipping_address_index', - '_billing_last_name', - '_billing_email', - ) ) ); - $order_ids = array(); + $search_fields = array_map( + 'wc_clean', apply_filters( + 'woocommerce_shop_order_search_fields', array( + '_billing_address_index', + '_shipping_address_index', + '_billing_last_name', + '_billing_email', + ) + ) + ); + $order_ids = array(); if ( is_numeric( $term ) ) { $order_ids[] = absint( $term ); } if ( ! empty( $search_fields ) ) { - $order_ids = array_unique( array_merge( - $order_ids, - $wpdb->get_col( - $wpdb->prepare( "SELECT DISTINCT p1.post_id FROM {$wpdb->postmeta} p1 WHERE p1.meta_value LIKE '%%%s%%'", $wpdb->esc_like( wc_clean( $term ) ) ) . " AND p1.meta_key IN ('" . implode( "','", array_map( 'esc_sql', $search_fields ) ) . "')" - ), - $wpdb->get_col( - $wpdb->prepare( " - SELECT order_id - FROM {$wpdb->prefix}woocommerce_order_items as order_items - WHERE order_item_name LIKE '%%%s%%' - ", - $wpdb->esc_like( wc_clean( $term ) ) + $order_ids = array_unique( + array_merge( + $order_ids, + $wpdb->get_col( + $wpdb->prepare( "SELECT DISTINCT p1.post_id FROM {$wpdb->postmeta} p1 WHERE p1.meta_value LIKE '%%%s%%'", $wpdb->esc_like( wc_clean( $term ) ) ) . " AND p1.meta_key IN ('" . implode( "','", array_map( 'esc_sql', $search_fields ) ) . "')" + ), + $wpdb->get_col( + $wpdb->prepare( + "SELECT order_id + FROM {$wpdb->prefix}woocommerce_order_items as order_items + WHERE order_item_name LIKE '%%%s%%'", + $wpdb->esc_like( wc_clean( $term ) ) + ) ) ) - ) ); + ); } return apply_filters( 'woocommerce_shop_order_search_results', $order_ids, $term, $search_fields ); @@ -498,7 +521,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement * Stores information about whether permissions were generated yet. * * @param WC_Order|int $order - * @param bool $set + * @param bool $set */ public function set_download_permissions_granted( $order, $set ) { $order_id = WC_Order_Factory::get_order_id( $order ); @@ -520,7 +543,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement * Stores information about whether sales were recorded. * * @param WC_Order|int $order - * @param bool $set + * @param bool $set */ public function set_recorded_sales( $order, $set ) { $order_id = WC_Order_Factory::get_order_id( $order ); @@ -542,7 +565,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement * Stores information about whether coupon counts were updated. * * @param WC_Order|int $order - * @param bool $set + * @param bool $set */ public function set_recorded_coupon_usage_counts( $order, $set ) { $order_id = WC_Order_Factory::get_order_id( $order ); @@ -564,7 +587,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement * Stores information about whether stock was reduced. * * @param WC_Order|int $order - * @param bool $set + * @param bool $set */ public function set_stock_reduced( $order, $set ) { $order_id = WC_Order_Factory::get_order_id( $order ); @@ -654,7 +677,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement } if ( isset( $query_vars['customer'] ) && '' !== $query_vars['customer'] && array() !== $query_vars['customer'] ) { - $values = is_array( $query_vars['customer'] ) ? $query_vars['customer'] : array( $query_vars['customer'] ); + $values = is_array( $query_vars['customer'] ) ? $query_vars['customer'] : array( $query_vars['customer'] ); $customer_query = $this->get_orders_generate_customer_meta_query( $values ); if ( is_wp_error( $customer_query ) ) { $wp_query_args['errors'][] = $customer_query; @@ -684,8 +707,8 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement if ( ! empty( $args['errors'] ) ) { $query = (object) array( - 'posts' => array(), - 'found_posts' => 0, + 'posts' => array(), + 'found_posts' => 0, 'max_num_pages' => 0, ); } else { diff --git a/includes/wc-update-functions.php b/includes/wc-update-functions.php index bdff8145818..424e34e0e8f 100644 --- a/includes/wc-update-functions.php +++ b/includes/wc-update-functions.php @@ -50,16 +50,16 @@ function wc_update_200_file_paths() { */ function wc_update_200_permalinks() { // Setup default permalinks if shop page is defined. - $permalinks = get_option( 'woocommerce_permalinks' ); - $shop_page_id = wc_get_page_id( 'shop' ); + $permalinks = get_option( 'woocommerce_permalinks' ); + $shop_page_id = wc_get_page_id( 'shop' ); if ( empty( $permalinks ) && $shop_page_id > 0 ) { - $base_slug = $shop_page_id > 0 && get_post( $shop_page_id ) ? get_page_uri( $shop_page_id ) : 'shop'; + $base_slug = $shop_page_id > 0 && get_post( $shop_page_id ) ? get_page_uri( $shop_page_id ) : 'shop'; - $category_base = get_option( 'woocommerce_prepend_shop_page_to_urls' ) == 'yes' ? trailingslashit( $base_slug ) : ''; - $category_slug = get_option( 'woocommerce_product_category_slug' ) ? get_option( 'woocommerce_product_category_slug' ) : _x( 'product-category', 'slug', 'woocommerce' ); - $tag_slug = get_option( 'woocommerce_product_tag_slug' ) ? get_option( 'woocommerce_product_tag_slug' ) : _x( 'product-tag', 'slug', 'woocommerce' ); + $category_base = get_option( 'woocommerce_prepend_shop_page_to_urls' ) == 'yes' ? trailingslashit( $base_slug ) : ''; + $category_slug = get_option( 'woocommerce_product_category_slug' ) ? get_option( 'woocommerce_product_category_slug' ) : _x( 'product-category', 'slug', 'woocommerce' ); + $tag_slug = get_option( 'woocommerce_product_tag_slug' ) ? get_option( 'woocommerce_product_tag_slug' ) : _x( 'product-tag', 'slug', 'woocommerce' ); if ( 'yes' == get_option( 'woocommerce_prepend_shop_page_to_products' ) ) { $product_base = trailingslashit( $base_slug ); @@ -76,10 +76,10 @@ function wc_update_200_permalinks() { } $permalinks = array( - 'product_base' => untrailingslashit( $product_base ), - 'category_base' => untrailingslashit( $category_base . $category_slug ), - 'attribute_base' => untrailingslashit( $category_base ), - 'tag_base' => untrailingslashit( $category_base . $tag_slug ), + 'product_base' => untrailingslashit( $product_base ), + 'category_base' => untrailingslashit( $category_base . $category_slug ), + 'attribute_base' => untrailingslashit( $category_base ), + 'tag_base' => untrailingslashit( $category_base . $tag_slug ), ); update_option( 'woocommerce_permalinks', $permalinks ); @@ -119,7 +119,7 @@ function wc_update_200_taxrates() { global $wpdb; // Update tax rates. - $loop = 0; + $loop = 0; $tax_rates = get_option( 'woocommerce_tax_rates' ); if ( $tax_rates ) { @@ -219,10 +219,9 @@ function wc_update_200_line_items() { // Now its time for the massive update to line items - move them to the new DB tables. // Reverse with UPDATE `wpwc_postmeta` SET meta_key = '_order_items' WHERE meta_key = '_order_items_old'. - $order_item_rows = $wpdb->get_results( " - SELECT meta_value, post_id FROM {$wpdb->postmeta} - WHERE meta_key = '_order_items' - " ); + $order_item_rows = $wpdb->get_results( + "SELECT meta_value, post_id FROM {$wpdb->postmeta} WHERE meta_key = '_order_items'" + ); foreach ( $order_item_rows as $order_item_row ) { @@ -231,21 +230,24 @@ function wc_update_200_line_items() { foreach ( $order_items as $order_item ) { if ( ! isset( $order_item['line_total'] ) && isset( $order_item['taxrate'] ) && isset( $order_item['cost'] ) ) { - $order_item['line_tax'] = number_format( ( $order_item['cost'] * $order_item['qty'] ) * ( $order_item['taxrate'] / 100 ), 2, '.', '' ); - $order_item['line_total'] = $order_item['cost'] * $order_item['qty']; - $order_item['line_subtotal_tax'] = $order_item['line_tax']; - $order_item['line_subtotal'] = $order_item['line_total']; + $order_item['line_tax'] = number_format( ( $order_item['cost'] * $order_item['qty'] ) * ( $order_item['taxrate'] / 100 ), 2, '.', '' ); + $order_item['line_total'] = $order_item['cost'] * $order_item['qty']; + $order_item['line_subtotal_tax'] = $order_item['line_tax']; + $order_item['line_subtotal'] = $order_item['line_total']; } - $order_item['line_tax'] = isset( $order_item['line_tax'] ) ? $order_item['line_tax'] : 0; - $order_item['line_total'] = isset( $order_item['line_total'] ) ? $order_item['line_total'] : 0; - $order_item['line_subtotal_tax'] = isset( $order_item['line_subtotal_tax'] ) ? $order_item['line_subtotal_tax'] : 0; - $order_item['line_subtotal'] = isset( $order_item['line_subtotal'] ) ? $order_item['line_subtotal'] : 0; + $order_item['line_tax'] = isset( $order_item['line_tax'] ) ? $order_item['line_tax'] : 0; + $order_item['line_total'] = isset( $order_item['line_total'] ) ? $order_item['line_total'] : 0; + $order_item['line_subtotal_tax'] = isset( $order_item['line_subtotal_tax'] ) ? $order_item['line_subtotal_tax'] : 0; + $order_item['line_subtotal'] = isset( $order_item['line_subtotal'] ) ? $order_item['line_subtotal'] : 0; - $item_id = wc_add_order_item( $order_item_row->post_id, array( - 'order_item_name' => $order_item['name'], - 'order_item_type' => 'line_item', - ) ); + $item_id = wc_add_order_item( + $order_item_row->post_id, + array( + 'order_item_name' => $order_item['name'], + 'order_item_type' => 'line_item', + ) + ); // Add line item meta. if ( $item_id ) { @@ -274,19 +276,25 @@ function wc_update_200_line_items() { // Insert meta rows at once. if ( count( $meta_rows ) > 0 ) { - $wpdb->query( $wpdb->prepare( " - INSERT INTO {$wpdb->prefix}woocommerce_order_itemmeta ( order_item_id, meta_key, meta_value ) - VALUES " . implode( ',', $meta_rows ) . '; - ', $order_item_row->post_id ) ); + $wpdb->query( + $wpdb->prepare( + "INSERT INTO {$wpdb->prefix}woocommerce_order_itemmeta ( order_item_id, meta_key, meta_value ) + VALUES " . implode( ',', $meta_rows ) . ';', + $order_item_row->post_id + ) + ); } // Delete from DB (rename). - $wpdb->query( $wpdb->prepare( " - UPDATE {$wpdb->postmeta} - SET meta_key = '_order_items_old' - WHERE meta_key = '_order_items' - AND post_id = %d - ", $order_item_row->post_id ) ); + $wpdb->query( + $wpdb->prepare( + "UPDATE {$wpdb->postmeta} + SET meta_key = '_order_items_old' + WHERE meta_key = '_order_items' + AND post_id = %d", + $order_item_row->post_id + ) + ); } unset( $meta_rows, $item_id, $order_item ); @@ -295,10 +303,10 @@ function wc_update_200_line_items() { // Do the same kind of update for order_taxes - move to lines. // Reverse with UPDATE `wpwc_postmeta` SET meta_key = '_order_taxes' WHERE meta_key = '_order_taxes_old'. - $order_tax_rows = $wpdb->get_results( " - SELECT meta_value, post_id FROM {$wpdb->postmeta} - WHERE meta_key = '_order_taxes' - " ); + $order_tax_rows = $wpdb->get_results( + "SELECT meta_value, post_id FROM {$wpdb->postmeta} + WHERE meta_key = '_order_taxes'" + ); foreach ( $order_tax_rows as $order_tax_row ) { @@ -311,10 +319,12 @@ function wc_update_200_line_items() { continue; } - $item_id = wc_add_order_item( $order_tax_row->post_id, array( - 'order_item_name' => $order_tax['label'], - 'order_item_type' => 'tax', - ) ); + $item_id = wc_add_order_item( + $order_tax_row->post_id, array( + 'order_item_name' => $order_tax['label'], + 'order_item_type' => 'tax', + ) + ); // Add line item meta. if ( $item_id ) { @@ -324,12 +334,15 @@ function wc_update_200_line_items() { } // Delete from DB (rename). - $wpdb->query( $wpdb->prepare( " - UPDATE {$wpdb->postmeta} - SET meta_key = '_order_taxes_old' - WHERE meta_key = '_order_taxes' - AND post_id = %d - ", $order_tax_row->post_id ) ); + $wpdb->query( + $wpdb->prepare( + "UPDATE {$wpdb->postmeta} + SET meta_key = '_order_taxes_old' + WHERE meta_key = '_order_taxes' + AND post_id = %d", + $order_tax_row->post_id + ) + ); unset( $tax_amount ); } @@ -347,11 +360,13 @@ function wc_update_200_images() { // cleaning up afterwards like nice people do. foreach ( array( 'catalog', 'single', 'thumbnail' ) as $value ) { - $old_settings = array_filter( array( - 'width' => get_option( 'woocommerce_' . $value . '_image_width' ), - 'height' => get_option( 'woocommerce_' . $value . '_image_height' ), - 'crop' => get_option( 'woocommerce_' . $value . '_image_crop' ), - ) ); + $old_settings = array_filter( + array( + 'width' => get_option( 'woocommerce_' . $value . '_image_width' ), + 'height' => get_option( 'woocommerce_' . $value . '_image_height' ), + 'crop' => get_option( 'woocommerce_' . $value . '_image_crop' ), + ) + ); if ( ! empty( $old_settings ) && update_option( 'shop_' . $value . '_image_size', $old_settings ) ) { @@ -521,8 +536,8 @@ function wc_update_220_shipping() { */ function wc_update_220_order_status() { global $wpdb; - $wpdb->query( " - UPDATE {$wpdb->posts} as posts + $wpdb->query( + "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) @@ -530,11 +545,10 @@ function wc_update_220_order_status() { WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' - AND term.slug LIKE 'pending%'; - " + AND term.slug LIKE 'pending%';" ); - $wpdb->query( " - UPDATE {$wpdb->posts} as posts + $wpdb->query( + "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) @@ -542,11 +556,10 @@ function wc_update_220_order_status() { WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' - AND term.slug LIKE 'processing%'; - " + AND term.slug LIKE 'processing%';" ); - $wpdb->query( " - UPDATE {$wpdb->posts} as posts + $wpdb->query( + "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) @@ -554,11 +567,10 @@ function wc_update_220_order_status() { WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' - AND term.slug LIKE 'on-hold%'; - " + AND term.slug LIKE 'on-hold%';" ); - $wpdb->query( " - UPDATE {$wpdb->posts} as posts + $wpdb->query( + "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) @@ -566,11 +578,10 @@ function wc_update_220_order_status() { WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' - AND term.slug LIKE 'completed%'; - " + AND term.slug LIKE 'completed%';" ); - $wpdb->query( " - UPDATE {$wpdb->posts} as posts + $wpdb->query( + "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) @@ -578,11 +589,10 @@ function wc_update_220_order_status() { WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' - AND term.slug LIKE 'cancelled%'; - " + AND term.slug LIKE 'cancelled%';" ); - $wpdb->query( " - UPDATE {$wpdb->posts} as posts + $wpdb->query( + "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) @@ -590,11 +600,10 @@ function wc_update_220_order_status() { WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' - AND term.slug LIKE 'refunded%'; - " + AND term.slug LIKE 'refunded%';" ); - $wpdb->query( " - UPDATE {$wpdb->posts} as posts + $wpdb->query( + "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) @@ -602,8 +611,7 @@ function wc_update_220_order_status() { WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' - AND term.slug LIKE 'failed%'; - " + AND term.slug LIKE 'failed%';" ); } @@ -615,15 +623,15 @@ function wc_update_220_order_status() { function wc_update_220_variations() { global $wpdb; // Update variations which manage stock. - $update_variations = $wpdb->get_results( " - SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent FROM {$wpdb->posts} as posts + $update_variations = $wpdb->get_results( + "SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent FROM {$wpdb->posts} as posts LEFT OUTER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_stock' LEFT OUTER JOIN {$wpdb->postmeta} as postmeta2 ON posts.ID = postmeta2.post_id AND postmeta2.meta_key = '_manage_stock' WHERE posts.post_type = 'product_variation' AND postmeta.meta_value IS NOT NULL AND postmeta.meta_value != '' - AND postmeta2.meta_value IS NULL - " ); + AND postmeta2.meta_value IS NULL" + ); foreach ( $update_variations as $variation ) { $parent_backorders = get_post_meta( $variation->variation_parent, '_backorders', true ); @@ -735,7 +743,10 @@ function wc_update_240_shipping_methods() { $has_classes = count( WC()->shipping->get_shipping_classes() ) > 0; $cost_key = $has_classes ? 'no_class_cost' : 'cost'; $min_fee = $shipping_method->get_option( 'minimum_fee' ); - $math_cost_strings = array( 'cost' => array(), 'no_class_cost' => array() ); + $math_cost_strings = array( + 'cost' => array(), + 'no_class_cost' => array(), + ); $math_cost_strings[ $cost_key ][] = $shipping_method->get_option( 'cost' ); if ( $fee = $shipping_method->get_option( 'fee' ) ) { @@ -798,7 +809,7 @@ function wc_update_240_api_keys() { // Get user data. foreach ( $api_users as $_user ) { - $user = get_userdata( $_user->user_id ); + $user = get_userdata( $_user->user_id ); $apps_keys[] = array( 'user_id' => $user->ID, 'permissions' => $user->woocommerce_api_key_permissions, @@ -844,12 +855,14 @@ function wc_update_240_webhooks() { * Webhooks. * Make sure order.update webhooks get the woocommerce_order_edit_status hook. */ - $order_update_webhooks = get_posts( array( - 'posts_per_page' => -1, - 'post_type' => 'shop_webhook', - 'meta_key' => '_topic', - 'meta_value' => 'order.updated', - ) ); + $order_update_webhooks = get_posts( + array( + 'posts_per_page' => -1, + 'post_type' => 'shop_webhook', + 'meta_key' => '_topic', + 'meta_value' => 'order.updated', + ) + ); foreach ( $order_update_webhooks as $order_update_webhook ) { $webhook = new WC_Webhook( $order_update_webhook->ID ); $webhook->set_topic( 'order.updated' ); @@ -867,11 +880,13 @@ function wc_update_240_refunds() { * Refunds for full refunded orders. * Update fully refunded orders to ensure they have a refund line item so reports add up. */ - $refunded_orders = get_posts( array( - 'posts_per_page' => -1, - 'post_type' => 'shop_order', - 'post_status' => array( 'wc-refunded' ), - ) ); + $refunded_orders = get_posts( + array( + 'posts_per_page' => -1, + 'post_type' => 'shop_order', + 'post_status' => array( 'wc-refunded' ), + ) + ); // Ensure emails are disabled during this update routine. remove_all_actions( 'woocommerce_order_status_refunded_notification' ); @@ -881,22 +896,27 @@ function wc_update_240_refunds() { foreach ( $refunded_orders as $refunded_order ) { $order_total = get_post_meta( $refunded_order->ID, '_order_total', true ); - $refunded_total = $wpdb->get_var( $wpdb->prepare( " - SELECT SUM( postmeta.meta_value ) - FROM $wpdb->postmeta AS postmeta - INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) - WHERE postmeta.meta_key = '_refund_amount' - AND postmeta.post_id = posts.ID - ", $refunded_order->ID ) ); + $refunded_total = $wpdb->get_var( + $wpdb->prepare( + "SELECT SUM( postmeta.meta_value ) + FROM $wpdb->postmeta AS postmeta + INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) + WHERE postmeta.meta_key = '_refund_amount' + AND postmeta.post_id = posts.ID", + $refunded_order->ID + ) + ); if ( $order_total > $refunded_total ) { - wc_create_refund( array( - 'amount' => $order_total - $refunded_total, - 'reason' => __( 'Order fully refunded', 'woocommerce' ), - 'order_id' => $refunded_order->ID, - 'line_items' => array(), - 'date' => $refunded_order->post_modified, - ) ); + wc_create_refund( + array( + 'amount' => $order_total - $refunded_total, + 'reason' => __( 'Order fully refunded', 'woocommerce' ), + 'order_id' => $refunded_order->ID, + 'line_items' => array(), + 'date' => $refunded_order->post_modified, + ) + ); } } @@ -921,13 +941,13 @@ function wc_update_241_variations() { global $wpdb; // Select variations that don't have any _stock_status implemented on WooCommerce 2.2. - $update_variations = $wpdb->get_results( " - SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent + $update_variations = $wpdb->get_results( + "SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent FROM {$wpdb->posts} as posts LEFT OUTER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_stock_status' WHERE posts.post_type = 'product_variation' - AND postmeta.meta_value IS NULL - " ); + AND postmeta.meta_value IS NULL" + ); foreach ( $update_variations as $variation ) { // Get the parent _stock_status. @@ -1065,11 +1085,13 @@ function wc_update_260_zone_methods() { // Move data. foreach ( $old_methods as $old_method ) { - $wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zone_methods', array( - 'zone_id' => $old_method->zone_id, - 'method_id' => $old_method->shipping_method_type, - 'method_order' => $old_method->shipping_method_order, - ) ); + $wpdb->insert( + $wpdb->prefix . 'woocommerce_shipping_zone_methods', array( + 'zone_id' => $old_method->zone_id, + 'method_id' => $old_method->shipping_method_type, + 'method_order' => $old_method->shipping_method_order, + ) + ); $new_instance_id = $wpdb->insert_id; @@ -1130,13 +1152,13 @@ function wc_update_260_refunds() { /** * Refund item qty should be negative. */ - $wpdb->query( " - UPDATE {$wpdb->prefix}woocommerce_order_itemmeta as item_meta - LEFT JOIN {$wpdb->prefix}woocommerce_order_items as items ON item_meta.order_item_id = items.order_item_id - LEFT JOIN {$wpdb->posts} as posts ON items.order_id = posts.ID - SET item_meta.meta_value = item_meta.meta_value * -1 - WHERE item_meta.meta_value > 0 AND item_meta.meta_key = '_qty' AND posts.post_type = 'shop_order_refund' - " ); + $wpdb->query( + "UPDATE {$wpdb->prefix}woocommerce_order_itemmeta as item_meta + LEFT JOIN {$wpdb->prefix}woocommerce_order_items as items ON item_meta.order_item_id = items.order_item_id + LEFT JOIN {$wpdb->posts} as posts ON items.order_id = posts.ID + SET item_meta.meta_value = item_meta.meta_value * -1 + WHERE item_meta.meta_value > 0 AND item_meta.meta_key = '_qty' AND posts.post_type = 'shop_order_refund'" + ); } /** @@ -1158,12 +1180,14 @@ function wc_update_300_webhooks() { * Make sure product.update webhooks get the woocommerce_product_quick_edit_save * and woocommerce_product_bulk_edit_save hooks. */ - $product_update_webhooks = get_posts( array( - 'posts_per_page' => -1, - 'post_type' => 'shop_webhook', - 'meta_key' => '_topic', - 'meta_value' => 'product.updated', - ) ); + $product_update_webhooks = get_posts( + array( + 'posts_per_page' => -1, + 'post_type' => 'shop_webhook', + 'meta_key' => '_topic', + 'meta_value' => 'product.updated', + ) + ); foreach ( $product_update_webhooks as $product_update_webhook ) { $webhook = new WC_Webhook( $product_update_webhook->ID ); $webhook->set_topic( 'product.updated' ); @@ -1197,12 +1221,14 @@ function wc_update_300_grouped_products() { foreach ( $parents as $parent_id ) { $parent = wc_get_product( $parent_id ); if ( $parent && $parent->is_type( 'grouped' ) ) { - $children_ids = get_posts( array( - 'post_parent' => $parent_id, - 'posts_per_page' => -1, - 'post_type' => 'product', - 'fields' => 'ids', - ) ); + $children_ids = get_posts( + array( + 'post_parent' => $parent_id, + 'posts_per_page' => -1, + 'post_type' => 'product', + 'fields' => 'ids', + ) + ); update_post_meta( $parent_id, '_children', $children_ids ); // Update children to remove the parent. @@ -1373,12 +1399,10 @@ function wc_update_320_mexican_states() { foreach ( $mx_states as $old => $new ) { $wpdb->query( $wpdb->prepare( - " - UPDATE $wpdb->postmeta - SET meta_value = %s - WHERE meta_key IN ( '_billing_state', '_shipping_state' ) - AND meta_value = %s - ", + "UPDATE $wpdb->postmeta + SET meta_value = %s + WHERE meta_key IN ( '_billing_state', '_shipping_state' ) + AND meta_value = %s", $new, $old ) ); From de5a21dcb014093f384b262baacd9528b177f82d Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Thu, 23 Nov 2017 11:55:25 -0200 Subject: [PATCH 55/76] Fix PHPCS violations in includes/class-wc-install.php --- includes/class-wc-install.php | 62 +++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/includes/class-wc-install.php b/includes/class-wc-install.php index 0941bea8acd..08fd070495b 100644 --- a/includes/class-wc-install.php +++ b/includes/class-wc-install.php @@ -320,7 +320,7 @@ class WC_Install { /** * Update DB version to current. * - * @param string $version + * @param string|null $version New WooCommerce DB version or null. */ public static function update_db_version( $version = null ) { delete_option( 'woocommerce_db_version' ); @@ -330,7 +330,7 @@ class WC_Install { /** * Add more cron schedules. * - * @param array $schedules + * @param array $schedules List of WP scheduled cron jobs. * @return array */ public static function cron_schedules( $schedules ) { @@ -410,7 +410,7 @@ class WC_Install { * Sets up the default options used on the settings page. */ private static function create_options() { - // Include settings so that we can run through defaults + // Include settings so that we can run through defaults. include_once dirname( __FILE__ ) . '/admin/class-wc-admin-settings.php'; $settings = WC_Admin_Settings::get_settings_pages(); @@ -509,7 +509,7 @@ class WC_Install { /** * Get Table schema. * - * https://github.com/woocommerce/woocommerce/wiki/Database-Description/ + * See https://github.com/woocommerce/woocommerce/wiki/Database-Description/ * * A note on indexes; Indexes have a maximum size of 767 bytes. Historically, we haven't need to be concerned about that. * As of WordPress 4.2, however, we moved to utf8mb4, which uses 4 bytes per character. This means that an index which @@ -717,10 +717,10 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( } if ( ! isset( $wp_roles ) ) { - $wp_roles = new WP_Roles(); + $wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine } - // Customer role + // Customer role. add_role( 'customer', __( 'Customer', 'woocommerce' ), @@ -729,7 +729,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( ) ); - // Shop manager role + // Shop manager role. add_role( 'shop_manager', __( 'Shop manager', 'woocommerce' ), @@ -804,7 +804,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( foreach ( $capability_types as $capability_type ) { $capabilities[ $capability_type ] = array( - // Post type + // Post type. "edit_{$capability_type}", "read_{$capability_type}", "delete_{$capability_type}", @@ -819,7 +819,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( "edit_private_{$capability_type}s", "edit_published_{$capability_type}s", - // Terms + // Terms. "manage_{$capability_type}_terms", "edit_{$capability_type}_terms", "delete_{$capability_type}_terms", @@ -831,7 +831,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( } /** - * woocommerce_remove_roles function. + * Remove WooCommerce roles. */ public static function remove_roles() { global $wp_roles; @@ -841,7 +841,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( } if ( ! isset( $wp_roles ) ) { - $wp_roles = new WP_Roles(); + $wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine } $capabilities = self::get_core_capabilities(); @@ -861,12 +861,12 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( * Create files/directories. */ private static function create_files() { - // Bypass if filesystem is read-only and/or non-standard upload system is used + // Bypass if filesystem is read-only and/or non-standard upload system is used. if ( apply_filters( 'woocommerce_install_skip_create_files', false ) ) { return; } - // Install files and folders for uploading files and prevent hotlinking + // Install files and folders for uploading files and prevent hotlinking. $upload_dir = wp_upload_dir(); $download_method = get_option( 'woocommerce_file_download_method', 'force' ); @@ -898,7 +898,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( foreach ( $files as $file ) { if ( wp_mkdir_p( $file['base'] ) && ! file_exists( trailingslashit( $file['base'] ) . $file['file'] ) ) { - if ( $file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'w' ) ) { + $file_handle = @fopen( trailingslashit( $file['base'] ) . $file['file'], 'w' ); + if ( $file_handle ) { fwrite( $file_handle, $file['content'] ); fclose( $file_handle ); } @@ -909,7 +910,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( /** * Show action links on the plugin screen. * - * @param mixed $links Plugin Action links + * @param mixed $links Plugin Action links. * @return array */ public static function plugin_action_links( $links ) { @@ -923,8 +924,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( /** * Show row meta on the plugin screen. * - * @param mixed $links Plugin Row Meta - * @param mixed $file Plugin Base file + * @param mixed $links Plugin Row Meta. + * @param mixed $file Plugin Base file. * @return array */ public static function plugin_row_meta( $links, $file ) { @@ -944,7 +945,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( /** * Uninstall tables when MU blog is deleted. * - * @param array $tables + * @param array $tables List of tables that will be deleted by WP. * @return string[] */ public static function wpmu_drop_tables( $tables ) { @@ -970,7 +971,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( /** * Get slug from path * - * @param string $key + * @param string $key Plugin relative path. Example: woocommerce/woocommerce.php. * @return string */ private static function format_plugin_slug( $key ) { @@ -983,8 +984,9 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( * Install a plugin from .org in the background via a cron job (used by * installer - opt in). * - * @param string $plugin_to_install_id - * @param array $plugin_to_install + * @param string $plugin_to_install_id Plugin ID. + * @param array $plugin_to_install Plugin information. + * @throws Exception If unable to proceed with plugin installation. * @since 2.6.0 */ public static function background_installer( $plugin_to_install_id, $plugin_to_install ) { @@ -1007,7 +1009,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( $installed = false; $activate = false; - // See if the plugin is installed already + // See if the plugin is installed already. if ( in_array( $plugin_to_install['repo-slug'], $installed_plugins ) ) { $installed = true; $activate = ! is_plugin_active( $plugin ); @@ -1015,7 +1017,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( // Install this thing! if ( ! $installed ) { - // Suppress feedback + // Suppress feedback. ob_start(); try { @@ -1082,6 +1084,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( WC_Admin_Notices::add_custom_notice( $plugin_to_install_id . '_install_error', sprintf( + // translators: 1: plugin name, 2: error message, 3: URL to install plugin manually. __( '%1$s could not be installed (%2$s). Please install it manually by clicking here.', 'woocommerce' ), $plugin_to_install['name'], $e->getMessage(), @@ -1090,13 +1093,13 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( ); } - // Discard feedback + // Discard feedback. ob_end_clean(); } wp_clean_plugins_cache(); - // Activate this thing + // Activate this thing. if ( $activate ) { try { $result = activate_plugin( $plugin ); @@ -1108,6 +1111,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( WC_Admin_Notices::add_custom_notice( $plugin_to_install_id . '_install_error', sprintf( + // translators: 1: plugin name, 2: URL to WP plugin page. __( '%1$s was installed but could not be activated. Please activate it manually by clicking here.', 'woocommerce' ), $plugin_to_install['name'], admin_url( 'plugins.php' ) @@ -1121,7 +1125,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( /** * Install a theme from .org in the background via a cron job (used by installer - opt in). * - * @param string $theme_slug + * @param string $theme_slug Theme slug. + * @throws Exception If unable to proceed with theme installation. * @since 3.1.0 */ public static function theme_background_installer( $theme_slug ) { @@ -1129,7 +1134,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( wp_clear_scheduled_hook( 'woocommerce_theme_background_installer', func_get_args() ); if ( ! empty( $theme_slug ) ) { - // Suppress feedback + // Suppress feedback. ob_start(); try { @@ -1166,6 +1171,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( WC_Admin_Notices::add_custom_notice( $theme_slug . '_install_error', sprintf( + // translators: 1: theme slug, 2: error message, 3: URL to install theme manually. __( '%1$s could not be installed (%2$s). Please install it manually by clicking here.', 'woocommerce' ), $theme_slug, $e->getMessage(), @@ -1174,7 +1180,7 @@ CREATE TABLE {$wpdb->prefix}woocommerce_termmeta ( ); } - // Discard feedback + // Discard feedback. ob_end_clean(); } } From 5f0e722ca44239d00d6fedbd87616fc09504bc41 Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Thu, 23 Nov 2017 12:17:21 -0200 Subject: [PATCH 56/76] Fix PHPCS violations in includes/wc-update-functions.php --- includes/wc-update-functions.php | 51 +++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/includes/wc-update-functions.php b/includes/wc-update-functions.php index 424e34e0e8f..612fcabdef8 100644 --- a/includes/wc-update-functions.php +++ b/includes/wc-update-functions.php @@ -64,7 +64,8 @@ function wc_update_200_permalinks() { if ( 'yes' == get_option( 'woocommerce_prepend_shop_page_to_products' ) ) { $product_base = trailingslashit( $base_slug ); } else { - if ( ( $product_slug = get_option( 'woocommerce_product_slug' ) ) !== false && ! empty( $product_slug ) ) { + $product_slug = get_option( 'woocommerce_product_slug' ); + if ( false !== $product_slug && ! empty( $product_slug ) ) { $product_base = trailingslashit( $product_slug ); } else { $product_base = trailingslashit( _x( 'product', 'slug', 'woocommerce' ) ); @@ -279,7 +280,7 @@ function wc_update_200_line_items() { $wpdb->query( $wpdb->prepare( "INSERT INTO {$wpdb->prefix}woocommerce_order_itemmeta ( order_item_id, meta_key, meta_value ) - VALUES " . implode( ',', $meta_rows ) . ';', + VALUES " . implode( ',', $meta_rows ) . ';', // @codingStandardsIgnoreLine $order_item_row->post_id ) ); @@ -747,9 +748,11 @@ function wc_update_240_shipping_methods() { 'cost' => array(), 'no_class_cost' => array(), ); - $math_cost_strings[ $cost_key ][] = $shipping_method->get_option( 'cost' ); - if ( $fee = $shipping_method->get_option( 'fee' ) ) { + $math_cost_strings[ $cost_key ][] = $shipping_method->get_option( 'cost' ); + $fee = $shipping_method->get_option( 'fee' ); + + if ( $fee ) { $math_cost_strings[ $cost_key ][] = strstr( $fee, '%' ) ? '[fee percent="' . str_replace( '%', '', $fee ) . '" min="' . esc_attr( $min_fee ) . '"]' : $fee; } @@ -758,7 +761,9 @@ function wc_update_240_shipping_methods() { $math_cost_strings[ $rate_key ] = $math_cost_strings['no_class_cost']; } - if ( $flat_rates = array_filter( (array) get_option( $flat_rate_option_key, array() ) ) ) { + $flat_rates = array_filter( (array) get_option( $flat_rate_option_key, array() ) ); + + if ( $flat_rates ) { foreach ( $flat_rates as $shipping_class => $rate ) { $rate_key = 'class_cost_' . $shipping_class; if ( $rate['cost'] || $rate['fee'] ) { @@ -1267,39 +1272,57 @@ function wc_update_300_product_visibility() { WC_Install::create_terms(); - if ( $featured_term = get_term_by( 'name', 'featured', 'product_visibility' ) ) { + $featured_term = get_term_by( 'name', 'featured', 'product_visibility' ); + + if ( $featured_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_featured' AND meta_value = 'yes';", $featured_term->term_taxonomy_id ) ); } - if ( $exclude_search_term = get_term_by( 'name', 'exclude-from-search', 'product_visibility' ) ) { + $exclude_search_term = get_term_by( 'name', 'exclude-from-search', 'product_visibility' ); + + if ( $exclude_search_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_visibility' AND meta_value IN ('hidden', 'catalog');", $exclude_search_term->term_taxonomy_id ) ); } - if ( $exclude_catalog_term = get_term_by( 'name', 'exclude-from-catalog', 'product_visibility' ) ) { + $exclude_catalog_term = get_term_by( 'name', 'exclude-from-catalog', 'product_visibility' ); + + if ( $exclude_catalog_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_visibility' AND meta_value IN ('hidden', 'search');", $exclude_catalog_term->term_taxonomy_id ) ); } - if ( $outofstock_term = get_term_by( 'name', 'outofstock', 'product_visibility' ) ) { + $outofstock_term = get_term_by( 'name', 'outofstock', 'product_visibility' ); + + if ( $outofstock_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_stock_status' AND meta_value = 'outofstock';", $outofstock_term->term_taxonomy_id ) ); } - if ( $rating_term = get_term_by( 'name', 'rated-1', 'product_visibility' ) ) { + $rating_term = get_term_by( 'name', 'rated-1', 'product_visibility' ); + + if ( $rating_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 1;", $rating_term->term_taxonomy_id ) ); } - if ( $rating_term = get_term_by( 'name', 'rated-2', 'product_visibility' ) ) { + $rating_term = get_term_by( 'name', 'rated-2', 'product_visibility' ); + + if ( $rating_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 2;", $rating_term->term_taxonomy_id ) ); } - if ( $rating_term = get_term_by( 'name', 'rated-3', 'product_visibility' ) ) { + $rating_term = get_term_by( 'name', 'rated-3', 'product_visibility' ); + + if ( $rating_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 3;", $rating_term->term_taxonomy_id ) ); } - if ( $rating_term = get_term_by( 'name', 'rated-4', 'product_visibility' ) ) { + $rating_term = get_term_by( 'name', 'rated-4', 'product_visibility' ); + + if ( $rating_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 4;", $rating_term->term_taxonomy_id ) ); } - if ( $rating_term = get_term_by( 'name', 'rated-5', 'product_visibility' ) ) { + $rating_term = get_term_by( 'name', 'rated-5', 'product_visibility' ); + + if ( $rating_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_wc_average_rating' AND ROUND( meta_value ) = 5;", $rating_term->term_taxonomy_id ) ); } } From 5cc84925e35d1f6c2ad7f43c55a8c9d593b945fb Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Thu, 23 Nov 2017 12:17:54 -0200 Subject: [PATCH 57/76] Typo --- includes/wc-update-functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/wc-update-functions.php b/includes/wc-update-functions.php index 612fcabdef8..087c33faca0 100644 --- a/includes/wc-update-functions.php +++ b/includes/wc-update-functions.php @@ -211,7 +211,7 @@ function wc_update_200_taxrates() { } /** - * Upadte order item line items for 2.0 + * Update order item line items for 2.0 * * @return void */ From cd3d61bf98024508c3ae2bbba6e2f852dfecc10f Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Thu, 23 Nov 2017 14:26:12 +0000 Subject: [PATCH 58/76] Add back category filtering which somehow was removed --- .../class-wc-admin-list-table-products.php | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/includes/admin/list-tables/class-wc-admin-list-table-products.php b/includes/admin/list-tables/class-wc-admin-list-table-products.php index dcd44e706fb..591c8bcbc8b 100644 --- a/includes/admin/list-tables/class-wc-admin-list-table-products.php +++ b/includes/admin/list-tables/class-wc-admin-list-table-products.php @@ -299,22 +299,29 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table { * Render any custom filters and search inputs for the list table. */ protected function render_filters() { - $current_category_slug = isset( $_REQUEST['product_cat'] ) ? wc_clean( wp_unslash( $_REQUEST['product_cat'] ) ) : false; // WPCS: input var ok, sanitization ok. - $current_product_type = isset( $_REQUEST['product_type'] ) ? wc_clean( wp_unslash( $_REQUEST['product_type'] ) ) : false; // WPCS: input var ok, sanitization ok. - // @codingStandardsIgnoreStart - $current_category = $current_category_slug ? get_term_by( 'slug', $current_category_slug, 'product_cat' ): false; - // @codingStandardsIgnoreEnd - ?> - - '; - $output .= ''; + if ( $categories_count <= apply_filters( 'woocommerce_product_category_filter_threshold', 100 ) ) { + wc_product_dropdown_categories( array( + 'option_select_text' => __( 'Filter by category', 'woocommerce' ), + ) ); + } else { + $current_category_slug = isset( $_GET['product_cat'] ) ? wc_clean( wp_unslash( $_GET['product_cat'] ) ) : false; // WPCS: input var ok, CSRF ok. + $current_category = $current_category_slug ? get_term_by( 'slug', $current_category_slug, 'product_cat' ) : false; + ?> + + '; foreach ( $terms as $term ) { $output .= ' + + includes/**/abstract-*.php + From e006e14d2365371ec49c88bf1f2550b3a7e2c96f Mon Sep 17 00:00:00 2001 From: Rodrigo Primo Date: Mon, 27 Nov 2017 11:00:42 -0200 Subject: [PATCH 74/76] Ignore PHPCS in two instances Ignoring PHPCS in two lines of the code where apparently it is not possible to fix the violations. I tried using what @claudiosanches suggested in this comment https://github.com/woocommerce/woocommerce/pull/17909#issuecomment-347168029 but both tags didn't work. Lets revisit this when PHPCS 3.2.0 is released and we can selectively disable rules (see https://github.com/squizlabs/PHP_CodeSniffer/issues/604). --- includes/data-stores/class-wc-order-data-store-cpt.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/includes/data-stores/class-wc-order-data-store-cpt.php b/includes/data-stores/class-wc-order-data-store-cpt.php index e4a662094ec..fa3724dea32 100644 --- a/includes/data-stores/class-wc-order-data-store-cpt.php +++ b/includes/data-stores/class-wc-order-data-store-cpt.php @@ -446,11 +446,13 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement $unpaid_orders = $wpdb->get_col( $wpdb->prepare( + // @codingStandardsIgnoreStart "SELECT posts.ID FROM {$wpdb->posts} AS posts WHERE posts.post_type IN ('" . implode( "','", wc_get_order_types() ) . "') AND posts.post_status = 'wc-pending' AND posts.post_modified < %s", + // @codingStandardsIgnoreEnd date( 'Y-m-d H:i:s', absint( $date ) ) ) ); @@ -496,7 +498,7 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement $order_ids, $wpdb->get_col( $wpdb->prepare( - "SELECT DISTINCT p1.post_id FROM {$wpdb->postmeta} p1 WHERE p1.meta_value LIKE %s AND p1.meta_key IN ('" . implode( "','", array_map( 'esc_sql', $search_fields ) ) . "')", + "SELECT DISTINCT p1.post_id FROM {$wpdb->postmeta} p1 WHERE p1.meta_value LIKE %s AND p1.meta_key IN ('" . implode( "','", array_map( 'esc_sql', $search_fields ) ) . "')", // @codingStandardsIgnoreLine '%' . $wpdb->esc_like( wc_clean( $term ) ) . '%' ) ), From 7463182c3f902fbad0280bb1b0e0cf747b1f59ad Mon Sep 17 00:00:00 2001 From: Manos Psychogyiopoulos Date: Mon, 27 Nov 2017 17:22:19 +0200 Subject: [PATCH 75/76] Change abstract importer methods visibility --- includes/import/abstract-wc-product-importer.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/import/abstract-wc-product-importer.php b/includes/import/abstract-wc-product-importer.php index f98ea8ef8ca..b5cd21e9336 100644 --- a/includes/import/abstract-wc-product-importer.php +++ b/includes/import/abstract-wc-product-importer.php @@ -133,7 +133,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface { public function get_params() { return $this->params; } - + /** * Get file pointer position from the last read. * @@ -503,7 +503,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface { * @param int $product_id Product ID. * @return int */ - protected function get_attachment_id_from_url( $url, $product_id ) { + public function get_attachment_id_from_url( $url, $product_id ) { if ( empty( $url ) ) { return 0; } @@ -590,7 +590,7 @@ abstract class WC_Product_Importer implements WC_Importer_Interface { * @param string $name Attribute name. * @return int */ - protected function get_attribute_taxonomy_id( $raw_name ) { + public function get_attribute_taxonomy_id( $raw_name ) { global $wpdb, $wc_product_attributes; // These are exported as labels, so convert the label to a name if possible first. From b133461d885c2b40aba79b10f9c7d047e0a965f7 Mon Sep 17 00:00:00 2001 From: Jonathan Belcher Date: Mon, 27 Nov 2017 16:36:02 -0500 Subject: [PATCH 76/76] Add npm scripts for grunt build commands --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index ba6a4afaf71..79e33ee055f 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "license": "GPL-3.0+", "main": "Gruntfile.js", "scripts": { + "build": "grunt", + "build-watch": "grunt watch", "test": "cross-env NODE_CONFIG_DIR='./tests/e2e-tests/config' BABEL_ENV=commonjs mocha \"tests/e2e-tests\" --compilers js:babel-register --recursive", "test:grep": "cross-env NODE_CONFIG_DIR='./tests/e2e-tests/config' BABEL_ENV=commonjs mocha \"tests/e2e-tests\" --compilers js:babel-register --grep ", "test:single": "cross-env NODE_CONFIG_DIR='./tests/e2e-tests/config' BABEL_ENV=commonjs mocha --compilers js:babel-register"