Merge branch 'master' into fix/16347

This commit is contained in:
Claudio Sanches 2017-08-07 16:36:36 -03:00 committed by GitHub
commit 53ea3c8b96
17 changed files with 135 additions and 114 deletions

View File

@ -79,7 +79,7 @@
render: function() {
var template = wp.template( this._target );
this.$el.attr( 'tabindex' , '0' ).append(
this.$el.append(
template( this._string )
);
@ -88,7 +88,8 @@
}).append( this.$el );
this.resizeContent();
this.$el.focus();
this.$( '.wc-backbone-modal-content' ).attr( 'tabindex' , '0' ).focus();
$( document.body ).trigger( 'init_tooltips' );
$( document.body ).trigger( 'wc_backbone_modal_loaded', this._target );

View File

@ -1342,7 +1342,7 @@ S2.define('select2/selection/base',[
BaseSelection.prototype.render = function () {
var $selection = $(
'<span class="select2-selection" role="combobox" ' +
'<span class="select2-selection" ' +
' aria-haspopup="true" aria-expanded="false">' +
'</span>'
);
@ -1389,9 +1389,7 @@ S2.define('select2/selection/base',[
});
container.on('results:focus', function (params) {
if (searchHidden) {
self.$selection.attr('aria-activedescendant', params.data._resultId);
}
self.$selection.attr('aria-activedescendant', params.data._resultId);
});
container.on('selection:update', function (params) {
@ -1401,9 +1399,7 @@ S2.define('select2/selection/base',[
container.on('open', function () {
// When the dropdown is open, aria-expanded="true"
self.$selection.attr('aria-expanded', 'true');
if (searchHidden) {
self.$selection.attr('aria-owns', resultsId);
}
self.$selection.attr('aria-owns', resultsId);
self._attachCloseHandler(container);
});
@ -1534,6 +1530,9 @@ S2.define('select2/selection/single',[
.attr('aria-readonly', 'true');
this.$selection.attr('aria-labelledby', id);
// This makes single non-search selects work in screen readers. If it causes problems elsewhere, remove.
this.$selection.attr('role', 'combobox');
this.$selection.on('mousedown', function (evt) {
// Only respond to left clicks
if (evt.which !== 1) {
@ -1874,7 +1873,7 @@ S2.define('select2/selection/search',[
Search.prototype.render = function (decorated) {
var $search = $(
'<li class="select2-search select2-search--inline">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
'<input class="select2-search__field" type="text" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="off"' +
' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
'</li>'
@ -3940,7 +3939,7 @@ S2.define('select2/dropdown/search',[
'<span class="select2-search select2-search--dropdown">' +
'<input class="select2-search__field" type="text" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="off"' +
' spellcheck="false" role="combobox" aria-autocomplete="list" />' +
' spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" />' +
'</span>'
);

File diff suppressed because one or more lines are too long

View File

@ -1342,7 +1342,7 @@ S2.define('select2/selection/base',[
BaseSelection.prototype.render = function () {
var $selection = $(
'<span class="select2-selection" role="combobox" ' +
'<span class="select2-selection" ' +
' aria-haspopup="true" aria-expanded="false">' +
'</span>'
);
@ -1389,9 +1389,7 @@ S2.define('select2/selection/base',[
});
container.on('results:focus', function (params) {
if (searchHidden) {
self.$selection.attr('aria-activedescendant', params.data._resultId);
}
self.$selection.attr('aria-activedescendant', params.data._resultId);
});
container.on('selection:update', function (params) {
@ -1401,9 +1399,7 @@ S2.define('select2/selection/base',[
container.on('open', function () {
// When the dropdown is open, aria-expanded="true"
self.$selection.attr('aria-expanded', 'true');
if (searchHidden) {
self.$selection.attr('aria-owns', resultsId);
}
self.$selection.attr('aria-owns', resultsId);
self._attachCloseHandler(container);
});
@ -1534,6 +1530,9 @@ S2.define('select2/selection/single',[
.attr('aria-readonly', 'true');
this.$selection.attr('aria-labelledby', id);
// This makes single non-search selects work in screen readers. If it causes problems elsewhere, remove.
this.$selection.attr('role', 'combobox');
this.$selection.on('mousedown', function (evt) {
// Only respond to left clicks
if (evt.which !== 1) {
@ -1874,7 +1873,7 @@ S2.define('select2/selection/search',[
Search.prototype.render = function (decorated) {
var $search = $(
'<li class="select2-search select2-search--inline">' +
'<input class="select2-search__field" type="search" tabindex="-1"' +
'<input class="select2-search__field" type="text" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="off"' +
' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
'</li>'
@ -3940,7 +3939,7 @@ S2.define('select2/dropdown/search',[
'<span class="select2-search select2-search--dropdown">' +
'<input class="select2-search__field" type="text" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="off"' +
' spellcheck="false" role="combobox" aria-autocomplete="list" />' +
' spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" />' +
'</span>'
);

File diff suppressed because one or more lines are too long

View File

@ -992,8 +992,8 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
$found_tax_classes = array();
foreach ( $this->get_items() as $item ) {
if ( $_product = $item->get_product() ) {
$found_tax_classes[] = $_product->get_tax_class();
if ( ( $product = $item->get_product() ) && ( $product->is_taxable() || $product->is_shipping_taxable() ) ) {
$found_tax_classes[] = $product->get_tax_class();
}
}

View File

@ -1032,40 +1032,33 @@ class WC_Admin_Post_Types {
$stock_status = ! empty( $_REQUEST['_stock_status'] ) ? wc_clean( $_REQUEST['_stock_status'] ) : 'instock';
$stock_amount = 'yes' === $manage_stock ? wc_stock_amount( $_REQUEST['_stock'] ) : '';
$product->set_manage_stock( $manage_stock );
$product->set_backorders( $backorders );
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
// Apply product type constraints to stock status
if ( $product->is_type( 'external' ) ) {
// External always in stock
$stock_status = 'instock';
} elseif ( $product->is_type( 'variable' ) ) {
// Stock status is always determined by children
foreach ( $product->get_children() as $child_id ) {
$child = wc_get_product( $child_id );
if ( ! $product->get_manage_stock() ) {
$child->set_stock_status( $stock_status );
$child->save();
}
}
$product = WC_Product_Variable::sync( $product, false );
}
$product->set_manage_stock( $manage_stock );
$product->set_backorders( $backorders );
$product->save();
if ( ! $product->is_type( 'variable' ) ) {
wc_update_product_stock_status( $post_id, $stock_status );
}
wc_update_product_stock( $post_id, $stock_amount );
} else {
$product->save();
wc_update_product_stock_status( $post_id, $stock_status );
$product->set_stock_quantity( $stock_amount );
}
// Apply product type constraints to stock status.
if ( $product->is_type( 'external' ) ) {
// External products are always in stock.
$product->set_stock_status( 'instock' );
} elseif ( $product->is_type( 'variable' ) && ! $product->get_manage_stock() ) {
// Stock status is determined by children.
foreach ( $product->get_children() as $child_id ) {
$child = wc_get_product( $child_id );
if ( ! $product->get_manage_stock() ) {
$child->set_stock_status( $stock_status );
$child->save();
}
}
$product = WC_Product_Variable::sync( $product, false );
} else {
$product->set_stock_status( $stock_status );
}
$product->save();
do_action( 'woocommerce_product_quick_edit_save', $product );
}
@ -1243,9 +1236,8 @@ class WC_Admin_Post_Types {
$was_managing_stock = $product->get_manage_stock() ? 'yes' : 'no';
$stock_status = $product->get_stock_status();
$backorders = $product->get_backorders();
$backorders = ! empty( $_REQUEST['_backorders'] ) ? wc_clean( $_REQUEST['_backorders'] ) : $backorders;
$stock_status = ! empty( $_REQUEST['_stock_status'] ) ? wc_clean( $_REQUEST['_stock_status'] ) : $stock_status;
$backorders = ! empty( $_REQUEST['_backorders'] ) ? wc_clean( $_REQUEST['_backorders'] ) : $backorders;
$stock_status = ! empty( $_REQUEST['_stock_status'] ) ? wc_clean( $_REQUEST['_stock_status'] ) : $stock_status;
if ( ! empty( $_REQUEST['_manage_stock'] ) ) {
$manage_stock = 'yes' === wc_clean( $_REQUEST['_manage_stock'] ) && 'grouped' !== $product->get_type() ? 'yes' : 'no';
@ -1255,40 +1247,33 @@ class WC_Admin_Post_Types {
$stock_amount = 'yes' === $manage_stock && ! empty( $_REQUEST['change_stock'] ) ? wc_stock_amount( $_REQUEST['_stock'] ) : $product->get_stock_quantity();
$product->set_manage_stock( $manage_stock );
$product->set_backorders( $backorders );
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
// Apply product type constraints to stock status
if ( $product->is_type( 'external' ) ) {
// External always in stock
$stock_status = 'instock';
} elseif ( $product->is_type( 'variable' ) ) {
// Stock status is always determined by children
foreach ( $product->get_children() as $child_id ) {
$child = wc_get_product( $child_id );
if ( ! $product->get_manage_stock() ) {
$child->set_stock_status( $stock_status );
$child->save();
}
}
$product = WC_Product_Variable::sync( $product, false );
}
$product->set_manage_stock( $manage_stock );
$product->set_backorders( $backorders );
$product->save();
if ( ! $product->is_type( 'variable' ) ) {
wc_update_product_stock_status( $post_id, $stock_status );
}
wc_update_product_stock( $post_id, $stock_amount );
} else {
$product->save();
wc_update_product_stock_status( $post_id, $stock_status );
$product->set_stock_quantity( $stock_amount );
}
// Apply product type constraints to stock status.
if ( $product->is_type( 'external' ) ) {
// External products are always in stock.
$product->set_stock_status( 'instock' );
} elseif ( $product->is_type( 'variable' ) && ! $product->get_manage_stock() ) {
// Stock status is determined by children.
foreach ( $product->get_children() as $child_id ) {
$child = wc_get_product( $child_id );
if ( ! $product->get_manage_stock() ) {
$child->set_stock_status( $stock_status );
$child->save();
}
}
$product = WC_Product_Variable::sync( $product, false );
} else {
$product->set_stock_status( $stock_status );
}
$product->save();
do_action( 'woocommerce_product_bulk_edit_save', $product );
}

View File

@ -21,6 +21,7 @@ class WC_Cache_Helper {
public static function init() {
add_action( 'template_redirect', array( __CLASS__, 'geolocation_ajax_redirect' ) );
add_action( 'wp', array( __CLASS__, 'prevent_caching' ) );
add_filter( 'nocache_headers', array( __CLASS__, 'set_nocache_constants' ) );
add_action( 'admin_notices', array( __CLASS__, 'notices' ) );
add_action( 'delete_version_transients', array( __CLASS__, 'delete_version_transients' ) );
}
@ -155,19 +156,22 @@ class WC_Cache_Helper {
if ( ! is_blog_installed() ) {
return;
}
$page_ids = array_filter( array( wc_get_page_id( 'cart' ), wc_get_page_id( 'checkout' ), wc_get_page_id( 'myaccount' ) ) );
$current_page_id = get_queried_object_id();
$page_ids = array_filter( array( wc_get_page_id( 'cart' ), wc_get_page_id( 'checkout' ), wc_get_page_id( 'myaccount' ) ) );
if ( isset( $_GET['download_file'] ) || in_array( $current_page_id, $page_ids ) ) {
self::nocache();
if ( isset( $_GET['download_file'] ) || isset( $_GET['add-to-cart'] ) || is_page( $page_ids ) ) {
nocache_headers();
}
}
/**
* Set nocache constants and headers.
* @access private
* Set constants to prevent caching by some plugins.
*
* Hooked into nocache_headers filter but does not change headers.
*
* @param array $value
* @return array
*/
private static function nocache() {
public static function set_nocache_constants( $value ) {
if ( ! defined( 'DONOTCACHEPAGE' ) ) {
define( "DONOTCACHEPAGE", true );
}
@ -177,7 +181,7 @@ class WC_Cache_Helper {
if ( ! defined( 'DONOTCACHEDB' ) ) {
define( "DONOTCACHEDB", true );
}
nocache_headers();
return $value;
}
/**

View File

@ -775,7 +775,9 @@ class WC_Cart {
$found_tax_classes = array();
foreach ( WC()->cart->get_cart() as $item ) {
$found_tax_classes[] = $item['data']->get_tax_class();
if ( $item['data'] && ( $item['data']->is_taxable() || $item['data']->is_shipping_taxable() ) ) {
$found_tax_classes[] = $item['data']->get_tax_class();
}
}
return array_unique( $found_tax_classes );

View File

@ -67,6 +67,8 @@ class WC_Form_Handler {
return;
}
nocache_headers();
$user_id = get_current_user_id();
if ( $user_id <= 0 ) {
@ -179,6 +181,8 @@ class WC_Form_Handler {
return;
}
nocache_headers();
$errors = new WP_Error();
$user = new stdClass();
@ -274,6 +278,7 @@ class WC_Form_Handler {
*/
public static function checkout_action() {
if ( isset( $_POST['woocommerce_checkout_place_order'] ) || isset( $_POST['woocommerce_checkout_update_totals'] ) ) {
nocache_headers();
if ( WC()->cart->is_empty() ) {
wp_redirect( wc_get_page_permalink( 'cart' ) );
@ -295,7 +300,7 @@ class WC_Form_Handler {
global $wp;
if ( isset( $_POST['woocommerce_pay'] ) && isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'woocommerce-pay' ) ) {
nocache_headers();
ob_start();
// Pay for existing order
@ -374,6 +379,7 @@ class WC_Form_Handler {
*/
public static function add_payment_method_action() {
if ( isset( $_POST['woocommerce_add_payment_method'], $_POST['payment_method'], $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'woocommerce-add-payment-method' ) ) {
nocache_headers();
ob_start();
$payment_method_id = wc_clean( wp_unslash( $_POST['payment_method'] ) );
@ -418,6 +424,7 @@ class WC_Form_Handler {
global $wp;
if ( isset( $wp->query_vars['delete-payment-method'] ) ) {
nocache_headers();
$token_id = absint( $wp->query_vars['delete-payment-method'] );
$token = WC_Payment_Tokens::get( $token_id );
@ -442,6 +449,7 @@ class WC_Form_Handler {
global $wp;
if ( isset( $wp->query_vars['set-default-payment-method'] ) ) {
nocache_headers();
$token_id = absint( $wp->query_vars['set-default-payment-method'] );
$token = WC_Payment_Tokens::get( $token_id );
@ -463,20 +471,19 @@ class WC_Form_Handler {
* Remove from cart/update.
*/
public static function update_cart_action() {
if ( ! ( isset( $_REQUEST['apply_coupon'] ) || isset( $_REQUEST['remove_coupon'] ) || isset( $_REQUEST['remove_item'] ) || isset( $_REQUEST['undo_item'] ) || isset( $_REQUEST['update_cart'] ) || isset( $_REQUEST['proceed'] ) ) ) {
return;
}
nocache_headers();
if ( ! empty( $_POST['apply_coupon'] ) && ! empty( $_POST['coupon_code'] ) ) {
// Add Discount
WC()->cart->add_discount( sanitize_text_field( $_POST['coupon_code'] ) );
} elseif ( isset( $_GET['remove_coupon'] ) ) {
// Remove Coupon Codes
WC()->cart->remove_coupon( wc_clean( $_GET['remove_coupon'] ) );
} elseif ( ! empty( $_GET['remove_item'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'woocommerce-cart' ) ) {
// Remove from cart
} elseif ( ! empty( $_GET['remove_item'] ) && wp_verify_nonce( wc_get_var( $_REQUEST['_wpnonce'] ), 'woocommerce-cart' ) ) {
$cart_item_key = sanitize_text_field( $_GET['remove_item'] );
if ( $cart_item = WC()->cart->get_cart_item( $cart_item_key ) ) {
@ -515,7 +522,7 @@ class WC_Form_Handler {
}
// Update Cart - checks apply_coupon too because they are in the same form
if ( ( ! empty( $_POST['apply_coupon'] ) || ! empty( $_POST['update_cart'] ) || ! empty( $_POST['proceed'] ) ) && isset( $_POST['_wpnonce'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'woocommerce-cart' ) ) {
if ( ( ! empty( $_POST['apply_coupon'] ) || ! empty( $_POST['update_cart'] ) || ! empty( $_POST['proceed'] ) ) && wp_verify_nonce( wc_get_var( $_POST['_wpnonce'] ), 'woocommerce-cart' ) ) {
$cart_updated = false;
$cart_totals = isset( $_POST['cart'] ) ? $_POST['cart'] : '';
@ -577,12 +584,13 @@ class WC_Form_Handler {
* Place a previous order again.
*/
public static function order_again() {
// Nothing to do
if ( ! isset( $_GET['order_again'] ) || ! is_user_logged_in() || ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], 'woocommerce-order_again' ) ) {
return;
}
nocache_headers();
if ( apply_filters( 'woocommerce_empty_cart_when_order_again', true ) ) {
WC()->cart->empty_cart();
}
@ -662,6 +670,7 @@ class WC_Form_Handler {
*/
public static function cancel_order() {
if ( isset( $_GET['cancel_order'] ) && isset( $_GET['order'] ) && isset( $_GET['order_id'] ) ) {
nocache_headers();
$order_key = $_GET['order'];
$order_id = absint( $_GET['order_id'] );
@ -708,6 +717,8 @@ class WC_Form_Handler {
return;
}
nocache_headers();
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_REQUEST['add-to-cart'] ) );
$was_added_to_cart = false;
$adding_to_cart = wc_get_product( $product_id );

View File

@ -400,7 +400,9 @@ class WC_Post_Data {
if ( in_array( get_post_type( $order_id ), wc_get_order_types() ) ) {
// Clean up user.
$order = wc_get_order( $order_id );
$customer_id = $order->get_customer_id();
// Check for `get_customer_id`, since this may be e.g. a refund order (which doesn't implement it).
$customer_id = is_callable( array( $order, 'get_customer_id' ) ) ? $order->get_customer_id() : 0;
if ( $customer_id > 0 && 'shop_order' === $order->get_type() ) {
$customer = new WC_Customer( $customer_id );

View File

@ -553,11 +553,16 @@ class WC_Tax {
'tax_class' => $tax_class,
) );
} else {
} 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();
// No tax classes = no taxable items.
if ( empty( $cart_tax_classes ) ) {
return array();
}
// If multiple classes are found, use the first one found unless a standard rate item is found. This will be the first listed in the 'additional tax class' section.
if ( sizeof( $cart_tax_classes ) > 1 && ! in_array( '', $cart_tax_classes ) ) {
$tax_classes = self::get_tax_class_slugs();

View File

@ -143,5 +143,6 @@ abstract class Abstract_WC_Order_Item_Type_Data_Store extends WC_Data_Store_WP i
*/
public function clear_cache( &$item ) {
wp_cache_delete( 'item-' . $item->get_id(), 'order-items' );
wp_cache_delete( 'order-items-' . $item->get_order_id(), 'orders' );
}
}

View File

@ -1690,5 +1690,17 @@ function wc_make_phone_clickable( $phone ) {
* @return mixed value sanitized by wc_clean
*/
function wc_get_post_data_by_key( $key, $default = '' ) {
return wc_clean( isset( $_POST[ $key ] ) ? $_POST[ $key ] : $default );
return wc_clean( wc_get_var( $_POST[ $key ], $default ) );
}
/**
* Get data if set, otherwise return a default value or null. Prevents notices when data is not set.
*
* @since 3.2.0
* @param mixed $var
* @param string $default
* @return mixed value sanitized by wc_clean
*/
function wc_get_var( &$var, $default = null ) {
return isset( $var ) ? $var : $default;
}

View File

@ -745,7 +745,7 @@ function wc_get_min_max_price_meta_query( $args ) {
'key' => '_price',
'value' => array( $min, $max ),
'compare' => 'BETWEEN',
'type' => 'NUMERIC',
'type' => 'DECIMAL(10,' . wc_get_price_decimals() . ')',
);
}

View File

@ -631,7 +631,7 @@ class WC_Tests_Product_Functions extends WC_Unit_Test_Case {
'key' => '_price',
'value' => array( 10, 100 ),
'compare' => 'BETWEEN',
'type' => 'NUMERIC',
'type' => 'DECIMAL(10,2)',
), $meta_query );
}

View File

@ -63,7 +63,7 @@ class WC_Tests_Tax extends WC_Unit_Test_Case {
$tax_rates = WC_Tax::get_shipping_tax_rates();
$this->assertEquals( $tax_rates, array( $tax_rate_id => array( 'rate' => '20.0000', 'label' => 'VAT', 'shipping' => 'yes', 'compound' => 'no' ) ) );
$this->assertEquals( $tax_rates, array( $tax_rate_id => array( 'rate' => '20.0000', 'label' => 'VAT', 'shipping' => 'yes', 'compound' => 'no' ) ), print_r( $tax_rates, true ) );
WC_Tax::_delete_tax_rate( $tax_rate_id );
}