Merge pull request #1 from woocommerce/master

Merge updates
This commit is contained in:
Rami Yushuvaev 2016-10-11 01:32:42 +03:00 committed by GitHub
commit 4dbed6dd40
31 changed files with 5681 additions and 3280 deletions

View File

@ -243,7 +243,6 @@ module.exports = function( grunt ) {
'!includes/gateways/simplify-commerce/includes/Simplify/**', // Exclude simplify commerce SDK
'!includes/libraries/**', // Exclude libraries/
'!node_modules/**', // Exclude node_modules/
'!tests/**', // Exclude tests/
'!tmp/**', // Exclude tmp/
'!vendor/**' // Exclude vendor/
]

File diff suppressed because one or more lines are too long

View File

@ -71,7 +71,7 @@
.addons-banner-block-item-icon {
background: #f7f7f7;
height: 183px;
height: 143px;
}
.addons-banner-block-item-content {
@ -86,6 +86,10 @@
margin-top: 0;
}
.addons-banner-block-item-content p {
margin: 0 0 auto;
}
.addons-column-section {
display: flex;
flex-direction: row;

File diff suppressed because one or more lines are too long

View File

@ -16,8 +16,9 @@
/**
* Global styles
*/
p.demo_store {
position: fixed;
p.demo_store,
.woocommerce-store-notice {
position: absolute;
top: 0;
left: 0;
right: 0;
@ -30,8 +31,11 @@ p.demo_store {
color: $primarytext;
z-index: 99998;
box-shadow: 0 1px 1em rgba(0, 0, 0, 0.2);
display: none;
a {
color: $primarytext;
text-decoration: underline;
}
}

View File

@ -12,4 +12,17 @@ jQuery( function( $ ) {
$( this ).val( min );
}
});
// Set a cookie and hide the store notice when the dismiss button is clicked
jQuery( '.woocommerce-store-notice__dismiss-link' ).click( function() {
jQuery.cookie( 'store_notice', 'hidden', { path: '/' } );
jQuery( '.woocommerce-store-notice' ).hide();
});
// Check the value of that cookie and show/hide the notice accordingly
if ( 'hidden' === jQuery.cookie( 'store_notice' ) ) {
jQuery( '.woocommerce-store-notice' ).hide();
} else {
jQuery( '.woocommerce-store-notice' ).show();
}
});

View File

@ -1 +1 @@
jQuery(function(a){a(".woocommerce-ordering").on("change","select.orderby",function(){a(this).closest("form").submit()}),a("input.qty:not(.product-quantity input.qty)").each(function(){var b=parseFloat(a(this).attr("min"));b>=0&&parseFloat(a(this).val())<b&&a(this).val(b)})});
jQuery(function(a){a(".woocommerce-ordering").on("change","select.orderby",function(){a(this).closest("form").submit()}),a("input.qty:not(.product-quantity input.qty)").each(function(){var b=parseFloat(a(this).attr("min"));b>=0&&parseFloat(a(this).val())<b&&a(this).val(b)}),jQuery(".woocommerce-store-notice__dismiss-link").click(function(){jQuery.cookie("store_notice","hidden",{path:"/"}),jQuery(".woocommerce-store-notice").hide()}),"hidden"===jQuery.cookie("store_notice")?jQuery(".woocommerce-store-notice").hide():jQuery(".woocommerce-store-notice").show()});

File diff suppressed because it is too large Load Diff

View File

@ -287,9 +287,11 @@ class WC_Admin_Addons {
<div class="addons-small-dark-items">
<?php foreach ( $block->items as $item ) : ?>
<div class="addons-small-dark-item">
<div class="addons-small-dark-item-icon">
<img class="addons-img" src="<?php echo esc_url( $item->image ); ?>" />
</div>
<?php if ( $item->image ) : ?>
<div class="addons-small-dark-item-icon">
<img class="addons-img" src="<?php echo esc_url( $item->image ); ?>" />
</div>
<?php endif; ?>
<?php
self::output_button(
$item->href,

View File

@ -187,7 +187,7 @@ class WC_Admin_Help {
'</a>'
) . '</p>' .
'<p>' . sprintf(
__( 'For further assistance with WooCommerce core you can use the %1$scommunity forum%2$s. If you need help with premium add-ons sold by WooCommerce, please %3$suse our helpdesk%4$s.', 'woocommerce' ),
__( 'For further assistance with WooCommerce core you can use the %1$scommunity forum%2$s. If you need help with premium extensions sold by WooCommerce, please %3$suse our helpdesk%4$s.', 'woocommerce' ),
'<a href="https://wordpress.org/support/plugin/woocommerce">',
'</a>',
'<a href="https://woocommerce.com/my-account/tickets/?utm_source=helptab&utm_medium=product&utm_content=tickets&utm_campaign=woocommerceplugin">',

View File

@ -38,9 +38,6 @@ class WC_Admin_Menus {
add_filter( 'menu_order', array( $this, 'menu_order' ) );
add_filter( 'custom_menu_order', array( $this, 'custom_menu_order' ) );
// Rename taxonomies at Appearance > Menus > Pages
add_filter( 'nav_menu_meta_box_object', array( $this, 'rename_nav_menu_meta_boxes' ) );
// Add endpoints custom URLs in Appearance > Menus > Pages
add_action( 'admin_init', array( $this, 'add_nav_menu_meta_boxes' ) );
@ -104,7 +101,7 @@ class WC_Admin_Menus {
* Addons menu item.
*/
public function addons_menu() {
add_submenu_page( 'woocommerce', __( 'WooCommerce Add-ons/Extensions', 'woocommerce' ), __( 'Add-ons', 'woocommerce' ) , 'manage_woocommerce', 'wc-addons', array( $this, 'addons_page' ) );
add_submenu_page( 'woocommerce', __( 'WooCommerce Extensions', 'woocommerce' ), __( 'Extensions', 'woocommerce' ) , 'manage_woocommerce', 'wc-addons', array( $this, 'addons_page' ) );
}
/**
@ -228,23 +225,6 @@ class WC_Admin_Menus {
WC_Admin_Addons::output();
}
/**
* Rename taxonomies in admin menus meta boxes.
* @param object $tax
* @return object
*/
public function rename_nav_menu_meta_boxes( $tax ) {
if ( isset( $tax->name ) ) {
if ( 'product_cat' === $tax->name ) {
$tax->labels->name = __( 'Product Categories', 'woocommerce' );
} elseif ( 'product_tag' === $tax->name ) {
$tax->labels->name = __( 'Product Tags', 'woocommerce' );
}
}
return $tax;
}
/**
* Add custom nav meta box.
*

View File

@ -75,7 +75,8 @@ class WC_Meta_Box_Coupon_Data {
woocommerce_wp_checkbox( array( 'id' => 'free_shipping', 'label' => __( 'Allow free shipping', 'woocommerce' ), 'description' => sprintf( __( 'Check this box if the coupon grants free shipping. A <a href="%s" target="_blank">free shipping method</a> must be enabled in your shipping zone and be set to require "a valid free shipping coupon" (see the "Free Shipping Requires" setting).', 'woocommerce' ), 'https://docs.woocommerce.com/document/free-shipping/' ) ) );
// Expiry date
woocommerce_wp_text_input( array( 'id' => 'expiry_date', 'value' => date( 'Y-m-d', $coupon->get_date_expires() ), 'label' => __( 'Coupon expiry date', 'woocommerce' ), 'placeholder' => _x( 'YYYY-MM-DD', 'placeholder', 'woocommerce' ), 'description' => '', 'class' => 'date-picker', 'custom_attributes' => array( 'pattern' => "[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" ) ) );
$expiry_date = $coupon->get_date_expires() ? date( 'Y-m-d', $coupon->get_date_expires() ) : '';
woocommerce_wp_text_input( array( 'id' => 'expiry_date', 'value' => esc_attr( $expiry_date ), 'label' => __( 'Coupon expiry date', 'woocommerce' ), 'placeholder' => _x( 'YYYY-MM-DD', 'placeholder', 'woocommerce' ), 'description' => '', 'class' => 'date-picker', 'custom_attributes' => array( 'pattern' => "[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])" ) ) );
do_action( 'woocommerce_coupon_options' );

View File

@ -13,7 +13,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="wrap woocommerce wc_addons_wrap">
<div class="icon32 icon32-posts-product" id="icon-woocommerce"><br /></div>
<h1>
<?php _e( 'WooCommerce Add-ons/Extensions', 'woocommerce' ); ?>
<?php _e( 'WooCommerce Extensions', 'woocommerce' ); ?>
</h1>
<?php if ( $sections ) : ?>
<ul class="subsubsub">

View File

@ -170,6 +170,24 @@ class WC_REST_Order_Notes_Controller extends WC_REST_Controller {
'type' => 'order_note',
);
// Allow filter by order note type.
if ( 'customer' === $request['type'] ) {
$args['meta_query'] = array(
array(
'key' => 'is_customer_note',
'value' => 1,
'compare' => '=',
),
);
} elseif ( 'internal' === $request['type'] ) {
$args['meta_query'] = array(
array(
'key' => 'is_customer_note',
'compare' => 'NOT EXISTS',
),
);
}
remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
$notes = get_comments( $args );
@ -411,8 +429,17 @@ class WC_REST_Order_Notes_Controller extends WC_REST_Controller {
* @return array
*/
public function get_collection_params() {
return array(
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
$params = array();
$params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
$params['type'] = array(
'default' => 'any',
'description' => __( 'Limit result to customers or internal notes.', 'woocommerce' ),
'type' => 'string',
'enum' => array( 'any', 'customer', 'internal' ),
'sanitize_callback' => 'sanitize_key',
'validate_callback' => 'rest_validate_request_arg',
);
return $params;
}
}

View File

@ -669,7 +669,7 @@ class WC_REST_Orders_Controller extends WC_REST_Posts_Controller {
* @return bool True if the item resource ID is null, false otherwise.
*/
protected function item_is_null( $item ) {
$keys = array( 'product_id', 'method_id', 'title', 'code' );
$keys = array( 'product_id', 'method_id', 'method_title', 'name', 'code' );
foreach ( $keys as $key ) {
if ( array_key_exists( $key, $item ) && is_null( $item[ $key ] ) ) {

View File

@ -23,17 +23,17 @@ if ( ! defined( 'ABSPATH' ) ) {
class WC_REST_Product_Variations_Controller extends WC_REST_Products_Controller {
/**
* Endpoint namespace.
*
* @var string
*/
* Endpoint namespace.
*
* @var string
*/
protected $namespace = 'wc/v1';
/**
* Route base.
*
* @var string
*/
* Route base.
*
* @var string
*/
protected $rest_base = 'products/(?P<product_id>[\d]+)/variations';
/**
@ -625,7 +625,7 @@ class WC_REST_Product_Variations_Controller extends WC_REST_Products_Controller
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $base, $variation->get_variation_id() ) ),
),
'collection' => array(
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $base) ),
'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $base ) ),
),
'up' => array(
'href' => rest_url( sprintf( '/%s/products/%d', $this->namespace, $product_id ) ),

View File

@ -1228,7 +1228,7 @@ class WC_Cart {
}
// Order cart items by price so coupon logic is 'fair' for customers and not based on order added to cart.
uasort( $cart, array( $this, 'sort_by_subtotal' ) );
uasort( $cart, apply_filters( 'woocommerce_sort_by_subtotal_callback', array( $this, 'sort_by_subtotal' ) ) );
/**
* Calculate totals for items.

View File

@ -378,7 +378,7 @@ class WC_Coupon extends WC_Legacy_Coupon {
// Handle the limit_usage_to_x_items option
if ( $this->is_type( array( 'percent_product', 'fixed_product' ) ) ) {
if ( $discounting_amount ) {
if ( '' === $this->get_limit_usage_to_x_items() ) {
if ( ! $this->get_limit_usage_to_x_items() ) {
$limit_usage_qty = $cart_item_qty;
} else {
$limit_usage_qty = min( $this->get_limit_usage_to_x_items(), $cart_item_qty );

View File

@ -485,7 +485,7 @@ class WC_Form_Handler {
$product = wc_get_product( $cart_item['product_id'] );
$item_removed_title = apply_filters( 'woocommerce_cart_item_removed_title', $product ? $product->get_title() : __( 'Item', 'woocommerce' ), $cart_item );
$item_removed_title = apply_filters( 'woocommerce_cart_item_removed_title', $product ? sprintf( _x( '&ldquo;%s&rdquo;', 'Item name in quotes', 'woocommerce' ), $product->get_title() ) : __( 'Item', 'woocommerce' ), $cart_item );
// Don't show undo link if removed item is out of stock.
if ( $product->is_in_stock() && $product->has_enough_stock( $cart_item['quantity'] ) ) {

View File

@ -443,8 +443,8 @@ CREATE TABLE {$wpdb->prefix}woocommerce_sessions (
session_key char(32) NOT NULL,
session_value longtext NOT NULL,
session_expiry bigint(20) NOT NULL,
UNIQUE KEY session_id (session_id),
PRIMARY KEY (session_key)
PRIMARY KEY (session_key),
UNIQUE KEY session_id (session_id)
) $collate;
CREATE TABLE {$wpdb->prefix}woocommerce_api_keys (
key_id bigint(20) NOT NULL auto_increment,

View File

@ -98,6 +98,7 @@ class WC_Logger {
$result = false;
if ( $this->open( $handle ) && is_resource( $this->_handles[ $handle ] ) ) {
$message = apply_filters( 'woocommerce_logger_add_message', $message, $handle );
$time = date_i18n( 'm-d-Y @ H:i:s -' ); // Grab Time
$result = fwrite( $this->_handles[ $handle ], $time . " " . $message . "\n" );
}

View File

@ -62,7 +62,7 @@ class WC_Post_types {
'update_count_callback' => '_wc_term_recount',
'label' => __( 'Categories', 'woocommerce' ),
'labels' => array(
'name' => __( 'Categories', 'woocommerce' ),
'name' => __( 'Product Categories', 'woocommerce' ),
'singular_name' => __( 'Category', 'woocommerce' ),
'menu_name' => _x( 'Categories', 'Admin menu name', 'woocommerce' ),
'search_items' => __( 'Search Categories', 'woocommerce' ),
@ -98,7 +98,7 @@ class WC_Post_types {
'update_count_callback' => '_wc_term_recount',
'label' => __( 'Product Tags', 'woocommerce' ),
'labels' => array(
'name' => __( 'Tags', 'woocommerce' ),
'name' => __( 'Product Tags', 'woocommerce' ),
'singular_name' => __( 'Tag', 'woocommerce' ),
'menu_name' => _x( 'Tags', 'Admin menu name', 'woocommerce' ),
'search_items' => __( 'Search Tags', 'woocommerce' ),
@ -135,7 +135,7 @@ class WC_Post_types {
'update_count_callback' => '_update_post_term_count',
'label' => __( 'Shipping Classes', 'woocommerce' ),
'labels' => array(
'name' => __( 'Shipping Classes', 'woocommerce' ),
'name' => __( 'Product Shipping Classes', 'woocommerce' ),
'singular_name' => __( 'Shipping Class', 'woocommerce' ),
'menu_name' => _x( 'Shipping Classes', 'Admin menu name', 'woocommerce' ),
'search_items' => __( 'Search Shipping Classes', 'woocommerce' ),
@ -175,7 +175,7 @@ class WC_Post_types {
'hierarchical' => true,
'update_count_callback' => '_update_post_term_count',
'labels' => array(
'name' => $label,
'name' => sprintf( _x( 'Product %s', 'Product Attribute', 'woocommerce' ), $label ),
'singular_name' => $label,
'search_items' => sprintf( __( 'Search %s', 'woocommerce' ), $label ),
'all_items' => sprintf( __( 'All %s', 'woocommerce' ), $label ),

View File

@ -52,17 +52,17 @@ class WC_Payment_Gateway_CC extends WC_Payment_Gateway {
$cvc_field = '<p class="form-row form-row-last">
<label for="' . esc_attr( $this->id ) . '-card-cvc">' . __( 'Card Code', 'woocommerce' ) . ' <span class="required">*</span></label>
<input id="' . esc_attr( $this->id ) . '-card-cvc" class="input-text wc-credit-card-form-card-cvc" type="text" autocomplete="off" placeholder="' . esc_attr__( 'CVC', 'woocommerce' ) . '" ' . $this->field_name( 'card-cvc' ) . ' style="width:100px" />
<input id="' . esc_attr( $this->id ) . '-card-cvc" class="input-text wc-credit-card-form-card-cvc" inputmode="numeric" autocomplete="off" autocorrect="no" autocapitalize="no" spellcheck="no" type="tel" maxlength="4" placeholder="' . esc_attr__( 'CVC', 'woocommerce' ) . '" ' . $this->field_name( 'card-cvc' ) . ' style="width:100px" />
</p>';
$default_fields = array(
'card-number-field' => '<p class="form-row form-row-wide">
<label for="' . esc_attr( $this->id ) . '-card-number">' . __( 'Card Number', 'woocommerce' ) . ' <span class="required">*</span></label>
<input id="' . esc_attr( $this->id ) . '-card-number" class="input-text wc-credit-card-form-card-number" type="text" maxlength="20" autocomplete="off" placeholder="&bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull;" ' . $this->field_name( 'card-number' ) . ' />
<input id="' . esc_attr( $this->id ) . '-card-number" class="input-text wc-credit-card-form-card-number" inputmode="numeric" autocomplete="cc-number" autocorrect="no" autocapitalize="no" spellcheck="no" type="tel" placeholder="&bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull; &bull;&bull;&bull;&bull;" ' . $this->field_name( 'card-number' ) . ' />
</p>',
'card-expiry-field' => '<p class="form-row form-row-first">
<label for="' . esc_attr( $this->id ) . '-card-expiry">' . __( 'Expiry (MM/YY)', 'woocommerce' ) . ' <span class="required">*</span></label>
<input id="' . esc_attr( $this->id ) . '-card-expiry" class="input-text wc-credit-card-form-card-expiry" type="text" autocomplete="off" placeholder="' . esc_attr__( 'MM / YY', 'woocommerce' ) . '" ' . $this->field_name( 'card-expiry' ) . ' />
<input id="' . esc_attr( $this->id ) . '-card-expiry" class="input-text wc-credit-card-form-card-expiry" inputmode="numeric" autocomplete="cc-exp" autocorrect="no" autocapitalize="no" spellcheck="no" type="tel" placeholder="' . esc_attr__( 'MM / YY', 'woocommerce' ) . '" ' . $this->field_name( 'card-expiry' ) . ' />
</p>',
);

View File

@ -277,19 +277,8 @@ class WC_Shortcode_My_Account {
return false;
}
$key = wp_generate_password( 20, false );
do_action( 'retrieve_password_key', $user_login, $key );
// Now insert the key, hashed, into the DB.
if ( empty( $wp_hasher ) ) {
require_once ABSPATH . 'wp-includes/class-phpass.php';
$wp_hasher = new PasswordHash( 8, true );
}
$hashed = $wp_hasher->HashPassword( $key );
$wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user_login ) );
// Get password reset key (function introduced in WordPress 4.4).
$key = get_password_reset_key( $user_data );
// Send email notification
WC()->mailer(); // load email classes
@ -305,40 +294,19 @@ class WC_Shortcode_My_Account {
*
* @param string $key Hash to validate sending user's password
* @param string $login The user login
* @return WP_USER|bool User's database row on success, false for invalid keys
* @return WP_User|bool User's database row on success, false for invalid keys
*/
public static function check_password_reset_key( $key, $login ) {
global $wpdb, $wp_hasher;
// Check for the password reset key.
// Get user data or an error message in case of invalid or expired key.
$user = check_password_reset_key( $key, $login );
$key = preg_replace( '/[^a-z0-9]/i', '', $key );
if ( empty( $key ) || ! is_string( $key ) ) {
wc_add_notice( __( 'Invalid key', 'woocommerce' ), 'error' );
if ( is_wp_error( $user ) ) {
wc_add_notice( $user->get_error_message(), 'error' );
return false;
}
if ( empty( $login ) || ! is_string( $login ) ) {
wc_add_notice( __( 'Invalid key', 'woocommerce' ), 'error' );
return false;
}
$user = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->users WHERE user_login = %s", $login ) );
if ( ! empty( $user ) ) {
if ( empty( $wp_hasher ) ) {
require_once ABSPATH . 'wp-includes/class-phpass.php';
$wp_hasher = new PasswordHash( 8, true );
}
$valid = $wp_hasher->CheckPassword( $key, $user->user_activation_key );
}
if ( empty( $user ) || empty( $valid ) ) {
wc_add_notice( __( 'Invalid key', 'woocommerce' ), 'error' );
return false;
}
return get_userdata( $user->ID );
return $user;
}
/**

View File

@ -434,6 +434,9 @@ function wc_scheduled_sales() {
// Sync parent
if ( $parent ) {
// Clear prices transient for variable products.
delete_transient( 'wc_var_prices_' . $parent );
// Grouped products need syncing via a function
$this_product = wc_get_product( $product_id );
if ( $this_product->is_type( 'simple' ) ) {

View File

@ -494,7 +494,7 @@ if ( ! function_exists( 'woocommerce_demo_store' ) ) {
$notice = __( 'This is a demo store for testing purposes &mdash; no orders shall be fulfilled.', 'woocommerce' );
}
echo apply_filters( 'woocommerce_demo_store', '<p class="demo_store">' . wp_kses_post( $notice ) . '</p>', $notice );
echo apply_filters( 'woocommerce_demo_store', '<p class="woocommerce-store-notice demo_store">' . wp_kses_post( $notice ) . ' <a href="#" class="woocommerce-store-notice__dismiss-link">' . __( 'Dismiss', 'woocommerce' ) . '</a></p>', $notice );
}
}

View File

@ -219,9 +219,11 @@ class WC_Widget_Layered_Nav extends WC_Widget {
$term_counts = $this->get_filtered_term_product_counts( wp_list_pluck( $terms, 'term_id' ), $taxonomy, $query_type );
$_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes();
$taxonomy_filter_name = str_replace( 'pa_', '', $taxonomy );
$taxonomy_label = wc_attribute_label( $taxonomy );
$any_label = apply_filters( 'woocommerce_layered_nav_any_label', sprintf( __( 'Any %s', 'woocommerce' ), $taxonomy_label ), $taxonomy_label, $taxonomy );
echo '<select class="dropdown_layered_nav_' . esc_attr( $taxonomy_filter_name ) . '">';
echo '<option value="">' . sprintf( __( 'Any %s', 'woocommerce' ), wc_attribute_label( $taxonomy ) ) . '</option>';
echo '<option value="">' . esc_html( $any_label ) . '</option>';
foreach ( $terms as $term ) {

View File

@ -128,7 +128,7 @@ For extending or theming WooCommerce, see our [codex](https://docs.woocommerce.c
If you get stuck, you can ask for help in the [WooCommerce Plugin Forum](https://wordpress.org/support/plugin/woocommerce).
For help with premium add-ons from WooThemes, use [our helpdesk](https://support.woothemes.com/).
For help with premium extensions from WooThemes, use [our helpdesk](https://support.woothemes.com/).
= Will WooCommerce work with my theme? =
@ -179,6 +179,7 @@ Yes you can! Join in on our [GitHub repository](http://github.com/woocommerce/wo
* Removed internal scroll from log viewer.
* Add reply-to to admin emails.
* When deleting a tax rate class, remove it's tax rates.
* Made the store notice dismissible.
[See changelog for all versions](https://raw.githubusercontent.com/woocommerce/woocommerce/master/CHANGELOG.txt).

View File

@ -54,7 +54,7 @@ do_action( 'woocommerce_before_account_downloads', $has_downloads ); ?>
</a>
<?php break;
case 'download-file' : ?>
<a href="<?php echo esc_url( get_permalink( $download['product_id'] ) ); ?>" class="woocommerce-MyAccount-downloads-file">
<a href="<?php echo esc_url( $download['download_url'] ); ?>" class="woocommerce-MyAccount-downloads-file">
<?php echo esc_html( $download['file_name'] ); ?>
</a>
<?php break;

View File

@ -221,7 +221,7 @@ class WC_Helper_Product {
$taxonomy_data = array(
'labels' => array(
'name' => __( 'size', 'woocommerce' ),
)
),
);
register_taxonomy( 'pa_size', array( 'product' ), $taxonomy_data );

View File

@ -16,9 +16,9 @@ class WC_Tests_CouponCRUD extends WC_Unit_Test_Case {
function get_function_name( $function ) {
if ( 'exclude_product_ids' === $function ) {
$function = 'excluded_product_ids';
} else if ( 'exclude_product_categories' === $function ) {
} elseif ( 'exclude_product_categories' === $function ) {
$function = 'excluded_product_categories';
} else if ( 'customer_email' === $function ) {
} elseif ( 'customer_email' === $function ) {
$function = 'email_restrictions';
}