Merge branch 'master' into order-data-store

# Conflicts:
#	includes/admin/meta-boxes/class-wc-meta-box-order-data.php
This commit is contained in:
Mike Jolley 2016-11-21 14:45:46 +00:00
commit 32de28355a
54 changed files with 6319 additions and 908 deletions

File diff suppressed because one or more lines are too long

View File

@ -830,6 +830,12 @@ ul.wc_coupon_list_block {
padding: 0 2% 0 0;
float: left;
> h3 {
span {
display: block;
}
}
&:last-child {
padding-right: 0;
}
@ -951,7 +957,8 @@ ul.wc_coupon_list_block {
float: right;
}
}
a.edit_address, .billing-same-as-shipping, .load_customer_shipping, .load_customer_billing {
a.edit_address {
width: 14px;
height: 0;
padding: 14px 0 0;
@ -977,27 +984,24 @@ ul.wc_coupon_list_block {
-webkit-font-smoothing: antialiased;
}
}
.billing-same-as-shipping {
&::after {
content: '\e008';
}
}
.load_customer_shipping {
&::after {
content: '\e03a';
}
}
.load_customer_billing {
&::after {
content: '\e03a';
}
}
a.edit_address {
&::after {
font-family: 'Dashicons';
content: '\f464';
}
}
.billing-same-as-shipping,
.load_customer_shipping,
.load_customer_billing {
font-size: 13px;
display: inline-block;
font-weight: normal;
}
.load_customer_shipping {
margin-right: .3em;
}
}
}

View File

@ -170,11 +170,13 @@
// Upon gaining focus
.on( 'focusin touchstart', '.variations select', function() {
$( this ).find( 'option:selected' ).attr( 'selected', 'selected' );
if ( 'ontouchstart' in window || navigator.maxTouchPoints ) {
$( this ).find( 'option:selected' ).attr( 'selected', 'selected' );
if ( ! $use_ajax ) {
$form.trigger( 'woocommerce_variation_select_focusin' );
$form.trigger( 'check_variations', [ $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' ), true ] );
if ( ! $use_ajax ) {
$form.trigger( 'woocommerce_variation_select_focusin' );
$form.trigger( 'check_variations', [ $( this ).data( 'attribute_name' ) || $( this ).attr( 'name' ), true ] );
}
}
} )

File diff suppressed because one or more lines are too long

View File

@ -1,17 +1,17 @@
/* global wc_add_to_cart_params */
/*!
* WooCommerce Add to Cart JS
*/
jQuery( function( $ ) {
/* global wc_add_to_cart_params */
if ( typeof wc_add_to_cart_params === 'undefined' ) {
return false;
}
// Ajax add to cart
// Ajax add to cart.
$( document ).on( 'click', '.add_to_cart_button', function() {
// AJAX add to cart request
// AJAX add to cart request.
var $thisbutton = $( this );
if ( $thisbutton.is( '.ajax_add_to_cart' ) ) {
@ -26,23 +26,19 @@ jQuery( function( $ ) {
var data = {};
$.each( $thisbutton.data(), function( key, value ) {
data[key] = value;
data[ key ] = value;
});
// Trigger event
// Trigger event.
$( document.body ).trigger( 'adding_to_cart', [ $thisbutton, data ] );
// Ajax action
// Ajax action.
$.post( wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'add_to_cart' ), data, function( response ) {
if ( ! response ) {
return;
}
var this_page = window.location.toString();
this_page = this_page.replace( 'add-to-cart', 'added-to-cart' );
if ( response.error && response.product_url ) {
window.location = response.product_url;
return;
@ -56,59 +52,9 @@ jQuery( function( $ ) {
} else {
$thisbutton.removeClass( 'loading' );
var fragments = response.fragments;
var cart_hash = response.cart_hash;
// Block fragments class
if ( fragments ) {
$.each( fragments, function( key ) {
$( key ).addClass( 'updating' );
});
}
// Block widgets and fragments
$( '.shop_table.cart, .updating, .cart_totals' ).fadeTo( '400', '0.6' ).block({
message: null,
overlayCSS: {
opacity: 0.6
}
});
// Changes button classes
$thisbutton.addClass( 'added' );
// View cart text
if ( ! wc_add_to_cart_params.is_cart && $thisbutton.parent().find( '.added_to_cart' ).length === 0 ) {
$thisbutton.after( ' <a href="' + wc_add_to_cart_params.cart_url + '" class="added_to_cart wc-forward" title="' +
wc_add_to_cart_params.i18n_view_cart + '">' + wc_add_to_cart_params.i18n_view_cart + '</a>' );
}
// Replace fragments
if ( fragments ) {
$.each( fragments, function( key, value ) {
$( key ).replaceWith( value );
});
}
// Unblock
$( '.widget_shopping_cart, .updating' ).stop( true ).css( 'opacity', '1' ).unblock();
// Cart page elements
$( '.shop_table.cart' ).load( this_page + ' .shop_table.cart:eq(0) > *', function() {
$( '.shop_table.cart' ).stop( true ).css( 'opacity', '1' ).unblock();
$( document.body ).trigger( 'cart_page_refreshed' );
});
$( '.cart_totals' ).load( this_page + ' .cart_totals:eq(0) > *', function() {
$( '.cart_totals' ).stop( true ).css( 'opacity', '1' ).unblock();
});
// Trigger event so themes can refresh other areas
$( document.body ).trigger( 'added_to_cart', [ fragments, cart_hash, $thisbutton ] );
$( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash, $thisbutton ] );
}
});
@ -119,4 +65,64 @@ jQuery( function( $ ) {
return true;
});
// On "added_to_cart"
$( document.body ).on( 'added_to_cart', function( event, fragments, cart_hash, $button ) {
var page = window.location.toString().replace( 'add-to-cart', 'added-to-cart' );
$button = typeof $button === 'undefined' ? false : $button;
if ( $button ) {
$button.removeClass( 'loading' );
}
// Block fragments class.
if ( fragments ) {
$.each( fragments, function( key ) {
$( key ).addClass( 'updating' );
});
}
// Block widgets and fragments.
$( '.shop_table.cart, .updating, .cart_totals' )
.fadeTo( '400', '0.6' )
.block({
message: null,
overlayCSS: {
opacity: 0.6
}
});
if ( $button ) {
// Changes button classes.
$button.addClass( 'added' );
// View cart text.
if ( ! wc_add_to_cart_params.is_cart && $button.parent().find( '.added_to_cart' ).length === 0 ) {
$button.after( ' <a href="' + wc_add_to_cart_params.cart_url + '" class="added_to_cart wc-forward" title="' +
wc_add_to_cart_params.i18n_view_cart + '">' + wc_add_to_cart_params.i18n_view_cart + '</a>' );
}
}
// Replace fragments.
if ( fragments ) {
$.each( fragments, function( key, value ) {
$( key ).replaceWith( value );
});
}
// Unblock.
$( '.widget_shopping_cart, .updating' ).stop( true ).css( 'opacity', '1' ).unblock();
// Cart page elements.
$( '.shop_table.cart' ).load( page + ' .shop_table.cart:eq(0) > *', function() {
$( '.shop_table.cart' ).stop( true ).css( 'opacity', '1' ).unblock();
$( document.body ).trigger( 'cart_page_refreshed' );
});
$( '.cart_totals' ).load( page + ' .cart_totals:eq(0) > *', function() {
$( '.cart_totals' ).stop( true ).css( 'opacity', '1' ).unblock();
});
});
});

View File

@ -1,4 +1,4 @@
/*!
* WooCommerce Add to Cart JS
*/
jQuery(function(a){return"undefined"!=typeof wc_add_to_cart_params&&void a(document).on("click",".add_to_cart_button",function(){var b=a(this);if(b.is(".ajax_add_to_cart")){if(!b.attr("data-product_id"))return!0;b.removeClass("added"),b.addClass("loading");var c={};return a.each(b.data(),function(a,b){c[a]=b}),a(document.body).trigger("adding_to_cart",[b,c]),a.post(wc_add_to_cart_params.wc_ajax_url.toString().replace("%%endpoint%%","add_to_cart"),c,function(c){if(c){var d=window.location.toString();if(d=d.replace("add-to-cart","added-to-cart"),c.error&&c.product_url)return void(window.location=c.product_url);if("yes"===wc_add_to_cart_params.cart_redirect_after_add)return void(window.location=wc_add_to_cart_params.cart_url);b.removeClass("loading");var e=c.fragments,f=c.cart_hash;e&&a.each(e,function(b){a(b).addClass("updating")}),a(".shop_table.cart, .updating, .cart_totals").fadeTo("400","0.6").block({message:null,overlayCSS:{opacity:.6}}),b.addClass("added"),wc_add_to_cart_params.is_cart||0!==b.parent().find(".added_to_cart").length||b.after(' <a href="'+wc_add_to_cart_params.cart_url+'" class="added_to_cart wc-forward" title="'+wc_add_to_cart_params.i18n_view_cart+'">'+wc_add_to_cart_params.i18n_view_cart+"</a>"),e&&a.each(e,function(b,c){a(b).replaceWith(c)}),a(".widget_shopping_cart, .updating").stop(!0).css("opacity","1").unblock(),a(".shop_table.cart").load(d+" .shop_table.cart:eq(0) > *",function(){a(".shop_table.cart").stop(!0).css("opacity","1").unblock(),a(document.body).trigger("cart_page_refreshed")}),a(".cart_totals").load(d+" .cart_totals:eq(0) > *",function(){a(".cart_totals").stop(!0).css("opacity","1").unblock()}),a(document.body).trigger("added_to_cart",[e,f,b])}}),!1}return!0})});
jQuery(function(a){return"undefined"!=typeof wc_add_to_cart_params&&(a(document).on("click",".add_to_cart_button",function(){var b=a(this);if(b.is(".ajax_add_to_cart")){if(!b.attr("data-product_id"))return!0;b.removeClass("added"),b.addClass("loading");var c={};return a.each(b.data(),function(a,b){c[a]=b}),a(document.body).trigger("adding_to_cart",[b,c]),a.post(wc_add_to_cart_params.wc_ajax_url.toString().replace("%%endpoint%%","add_to_cart"),c,function(c){if(c)return c.error&&c.product_url?void(window.location=c.product_url):"yes"===wc_add_to_cart_params.cart_redirect_after_add?void(window.location=wc_add_to_cart_params.cart_url):void a(document.body).trigger("added_to_cart",[c.fragments,c.cart_hash,b])}),!1}return!0}),void a(document.body).on("added_to_cart",function(b,c,d,e){var f=window.location.toString().replace("add-to-cart","added-to-cart");e="undefined"!=typeof e&&e,e&&e.removeClass("loading"),c&&a.each(c,function(b){a(b).addClass("updating")}),a(".shop_table.cart, .updating, .cart_totals").fadeTo("400","0.6").block({message:null,overlayCSS:{opacity:.6}}),e&&(e.addClass("added"),wc_add_to_cart_params.is_cart||0!==e.parent().find(".added_to_cart").length||e.after(' <a href="'+wc_add_to_cart_params.cart_url+'" class="added_to_cart wc-forward" title="'+wc_add_to_cart_params.i18n_view_cart+'">'+wc_add_to_cart_params.i18n_view_cart+"</a>")),c&&a.each(c,function(b,c){a(b).replaceWith(c)}),a(".widget_shopping_cart, .updating").stop(!0).css("opacity","1").unblock(),a(".shop_table.cart").load(f+" .shop_table.cart:eq(0) > *",function(){a(".shop_table.cart").stop(!0).css("opacity","1").unblock(),a(document.body).trigger("cart_page_refreshed")}),a(".cart_totals").load(f+" .cart_totals:eq(0) > *",function(){a(".cart_totals").stop(!0).css("opacity","1").unblock()})}))});

View File

@ -158,6 +158,7 @@ return array(
'BG',
'BY',
'CH',
'CY',
'CZ',
'DE',
'DK',

View File

@ -22,7 +22,7 @@ abstract class WC_Legacy_Payment_Token extends WC_Data {
* @deprecated 2.7.0 - Init a token class with an ID.
*/
public function read( $token_id ) {
//wc_soft_deprecated_function( 'WC_Payment_Token::read', '2.7', '2.8', 'Init a token class with an ID.' );
// wc_soft_deprecated_function( 'WC_Payment_Token::read', '2.7', '2.8', 'Init a token class with an ID.' );
$this->set_id( $token_id );
$data_store = WC_Data_Store::load( 'payment-token' );
$data_store->read( $this );
@ -33,7 +33,7 @@ abstract class WC_Legacy_Payment_Token extends WC_Data {
* @deprecated 2.7.0 - Use ::save instead.
*/
public function update() {
//wc_soft_deprecated_function( 'WC_Payment_Token::update', '2.7', '2.8', 'Use ::save instead.' );
// wc_soft_deprecated_function( 'WC_Payment_Token::update', '2.7', '2.8', 'Use ::save instead.' );
$data_store = WC_Data_Store::load( 'payment-token' );
try {
$data_store->update( $this );
@ -47,7 +47,7 @@ abstract class WC_Legacy_Payment_Token extends WC_Data {
* @deprecated 2.7.0 - Use ::save instead.
*/
public function create() {
//wc_soft_deprecated_function( 'WC_Payment_Token::create', '2.7', '2.8', 'Use ::save instead.' );
// wc_soft_deprecated_function( 'WC_Payment_Token::create', '2.7', '2.8', 'Use ::save instead.' );
$data_store = WC_Data_Store::load( 'payment-token' );
try {
$data_store->create( $this );

View File

@ -189,7 +189,7 @@ if ( ! defined( 'ABSPATH' ) ) {
* @param string $gateway_id
*/
public function set_gateway_id( $gateway_id ) {
$this->set_prop( 'gateway_id', $gateway_id);
$this->set_prop( 'gateway_id', $gateway_id );
}
/**

View File

@ -39,7 +39,7 @@ class WC_Product extends WC_Abstract_Legacy_Product {
'date_modified' => '',
'status' => false,
'featured' => false,
'catalog_visibility' => 'hidden',
'catalog_visibility' => 'visible',
'description' => '',
'short_description' => '',
'sku' => '',
@ -1788,7 +1788,7 @@ class WC_Product extends WC_Abstract_Legacy_Product {
} else {
return '';
}
return $attribute_object->is_taxonomy() ? implode( ', ', wc_get_product_terms( $this->get_id(), $attribute_object->get_name(), array( 'fields' => 'names' ) ) ) : wc_implode_text_attributes( $attribute_object->get_options() );
return $attribute_object->is_taxonomy() ? implode( ', ', wc_get_object_terms( $this->get_id(), $attribute_object->get_name(), 'name' ) ) : wc_implode_text_attributes( $attribute_object->get_options() );
}
/**

View File

@ -251,7 +251,7 @@ class WC_Admin_Duplicate_Product {
$taxonomies = array_diff( get_object_taxonomies( $post_type ), $exclude );
foreach ( $taxonomies as $taxonomy ) {
$post_terms = wp_get_object_terms( $id, $taxonomy );
$post_terms = wc_get_object_terms( $id, $taxonomy );
$post_terms_count = sizeof( $post_terms );
for ( $i = 0; $i < $post_terms_count; $i++ ) {

View File

@ -2,14 +2,14 @@
/**
* Post Types Admin
*
* @author WooThemes
* @author WooCommerce
* @category Admin
* @package WooCommerce/Admin
* @version 2.4.0
* @version 2.7.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
exit;
}
if ( ! class_exists( 'WC_Admin_Post_Types' ) ) :
@ -44,8 +44,6 @@ class WC_Admin_Post_Types {
add_filter( 'manage_edit-shop_coupon_sortable_columns', array( $this, 'shop_coupon_sortable_columns' ) );
add_filter( 'manage_edit-shop_order_sortable_columns', array( $this, 'shop_order_sortable_columns' ) );
add_filter( 'bulk_actions-edit-shop_order', array( $this, 'shop_order_bulk_actions' ) );
add_filter( 'list_table_primary_column', array( $this, 'list_table_primary_column' ), 10, 2 );
add_filter( 'post_row_actions', array( $this, 'row_actions' ), 2, 100 );
@ -55,9 +53,12 @@ class WC_Admin_Post_Types {
// Bulk / quick edit
add_action( 'bulk_edit_custom_box', array( $this, 'bulk_edit' ), 10, 2 );
add_action( 'quick_edit_custom_box', array( $this, 'quick_edit' ), 10, 2 );
add_action( 'save_post', array( $this, 'bulk_and_quick_edit_save_post' ), 10, 2 );
add_action( 'save_post', array( $this, 'bulk_and_quick_edit_hook' ), 10, 2 );
add_action( 'woocommerce_product_bulk_and_quick_edit', array( $this, 'bulk_and_quick_edit_save_post' ), 10, 2 );
add_action( 'admin_footer', array( $this, 'bulk_admin_footer' ), 10 );
add_filter( 'bulk_actions-edit-shop_order', array( $this, 'shop_order_bulk_actions' ) );
add_action( 'load-edit.php', array( $this, 'bulk_action' ) );
add_filter( 'handle_bulk_actions-edit-shop_order', 'handle_shop_order_bulk_actions', 10, 3 );
add_action( 'admin_notices', array( $this, 'bulk_admin_notices' ) );
// Order Search
@ -336,8 +337,6 @@ class WC_Admin_Post_Types {
echo apply_filters( 'the_excerpt', $post->post_excerpt );
}
$this->_render_product_row_actions( $post, $title );
get_inline_data( $post );
/* Custom inline data for woocommerce. */
@ -436,70 +435,6 @@ class WC_Admin_Post_Types {
}
}
/**
* Render product row actions for old version of WordPress.
* Since WordPress 4.3 we don't have to build the row actions.
*
* @param WP_Post $post
* @param string $title
*/
private function _render_product_row_actions( $post, $title ) {
global $wp_version;
if ( version_compare( $wp_version, '4.3-beta', '>=' ) ) {
return;
}
$post_type_object = get_post_type_object( $post->post_type );
$can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID );
// Get actions
$actions = array();
$actions['id'] = 'ID: ' . $post->ID;
if ( $can_edit_post && 'trash' != $post->post_status ) {
$actions['edit'] = '<a href="' . get_edit_post_link( $post->ID, true ) . '" aria-label="' . esc_attr( __( 'Edit this item', 'woocommerce' ) ) . '">' . __( 'Edit', 'woocommerce' ) . '</a>';
$actions['inline hide-if-no-js'] = '<a href="#" class="editinline" aria-label="' . esc_attr( __( 'Edit this item inline', 'woocommerce' ) ) . '">' . __( 'Quick&nbsp;Edit', 'woocommerce' ) . '</a>';
}
if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) {
if ( 'trash' == $post->post_status ) {
$actions['untrash'] = '<a aria-label="' . esc_attr( __( 'Restore this item from the Trash', 'woocommerce' ) ) . '" href="' . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ) . '">' . __( 'Restore', 'woocommerce' ) . '</a>';
} elseif ( EMPTY_TRASH_DAYS ) {
$actions['trash'] = '<a class="submitdelete" aria-label="' . esc_attr( __( 'Move this item to the Trash', 'woocommerce' ) ) . '" href="' . get_delete_post_link( $post->ID ) . '">' . __( 'Trash', 'woocommerce' ) . '</a>';
}
if ( 'trash' == $post->post_status || ! EMPTY_TRASH_DAYS ) {
$actions['delete'] = '<a class="submitdelete" aria-label="' . esc_attr( __( 'Delete this item permanently', 'woocommerce' ) ) . '" href="' . get_delete_post_link( $post->ID, '', true ) . '">' . __( 'Delete permanently', 'woocommerce' ) . '</a>';
}
}
if ( $post_type_object->public ) {
if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) {
if ( $can_edit_post ) {
/* translators: %s: product title */
$actions['view'] = '<a href="' . esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) . '" aria-label="' . esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;', 'woocommerce' ), $title ) ) . '" rel="permalink">' . __( 'Preview', 'woocommerce' ) . '</a>';
}
} elseif ( 'trash' != $post->post_status ) {
/* translators: %s: product title */
$actions['view'] = '<a href="' . get_permalink( $post->ID ) . '" aria-label="' . esc_attr( sprintf( __( 'View &#8220;%s&#8221;', 'woocommerce' ), $title ) ) . '" rel="permalink">' . __( 'View', 'woocommerce' ) . '</a>';
}
}
$actions = apply_filters( 'post_row_actions', $actions, $post );
echo '<div class="row-actions">';
$i = 0;
$action_count = sizeof( $actions );
foreach ( $actions as $action => $link ) {
++$i;
( $i == $action_count ) ? $sep = '' : $sep = ' | ';
echo '<span class="' . $action . '">' . $link . $sep . '</span>';
}
echo '</div>';
}
/**
* Output custom columns for coupons.
*
@ -518,8 +453,6 @@ class WC_Admin_Post_Types {
_post_states( $post );
echo '</strong>';
$this->_render_shop_coupon_row_actions( $post, $title );
break;
case 'type' :
echo esc_html( wc_get_coupon_type( get_post_meta( $post->ID, 'discount_type', true ) ) );
@ -573,57 +506,6 @@ class WC_Admin_Post_Types {
}
}
/**
* Render shop_coupon row actions for old version of WordPress.
* Since WordPress 4.3 we don't have to build the row actions.
*
* @param WP_Post $post
* @param string $title
*/
private function _render_shop_coupon_row_actions( $post, $title ) {
global $wp_version;
if ( version_compare( $wp_version, '4.3-beta', '>=' ) ) {
return;
}
$post_type_object = get_post_type_object( $post->post_type );
// Get actions
$actions = array();
if ( current_user_can( $post_type_object->cap->edit_post, $post->ID ) ) {
$actions['edit'] = '<a href="' . admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=edit', $post->ID ) ) . '">' . __( 'Edit', 'woocommerce' ) . '</a>';
}
if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) {
if ( 'trash' == $post->post_status ) {
$actions['untrash'] = "<a title='" . esc_attr( __( 'Restore this item from the Trash', 'woocommerce' ) ) . "' href='" . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore', 'woocommerce' ) . "</a>";
} elseif ( EMPTY_TRASH_DAYS ) {
$actions['trash'] = "<a class='submitdelete' title='" . esc_attr( __( 'Move this item to the Trash', 'woocommerce' ) ) . "' href='" . get_delete_post_link( $post->ID ) . "'>" . __( 'Trash', 'woocommerce' ) . "</a>";
}
if ( 'trash' == $post->post_status || ! EMPTY_TRASH_DAYS ) {
$actions['delete'] = "<a class='submitdelete' title='" . esc_attr( __( 'Delete this item permanently', 'woocommerce' ) ) . "' href='" . get_delete_post_link( $post->ID, '', true ) . "'>" . __( 'Delete permanently', 'woocommerce' ) . "</a>";
}
}
$actions = apply_filters( 'post_row_actions', $actions, $post );
echo '<div class="row-actions">';
$i = 0;
$action_count = sizeof( $actions );
foreach ( $actions as $action => $link ) {
++$i;
( $i == $action_count ) ? $sep = '' : $sep = ' | ';
echo "<span class='$action'>$link$sep</span>";
}
echo '</div>';
}
/**
* Output custom columns for coupons.
* @param string $column
@ -888,21 +770,6 @@ class WC_Admin_Post_Types {
return wp_parse_args( $custom, $columns );
}
/**
* Remove edit from the bulk actions.
*
* @param array $actions
* @return array
*/
public function shop_order_bulk_actions( $actions ) {
if ( isset( $actions['edit'] ) ) {
unset( $actions['edit'] );
}
return $actions;
}
/**
* Set list table primary column for products and orders.
* Support for WordPress 4.3.
@ -1013,6 +880,20 @@ class WC_Admin_Post_Types {
include( WC()->plugin_path() . '/includes/admin/views/html-quick-edit-product.php' );
}
/**
* Offers a way to hook into save post without causing an infinite loop
* when quick/bulk saving product info.
*
* @since 2.7.0
* @param int $post_id
* @param object $post
*/
public function bulk_and_quick_edit_hook( $post_id, $post ) {
remove_action( 'save_post', array( $this, 'bulk_and_quick_edit_hook' ) );
do_action( 'woocommerce_product_bulk_and_quick_edit', $post_id, $post );
add_action( 'save_post', array( $this, 'bulk_and_quick_edit_hook' ), 10, 2 );
}
/**
* Quick and bulk edit saving.
*
@ -1021,7 +902,6 @@ class WC_Admin_Post_Types {
* @return int
*/
public function bulk_and_quick_edit_save_post( $post_id, $post ) {
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
@ -1062,98 +942,90 @@ class WC_Admin_Post_Types {
$this->bulk_edit_save( $post_id, $product );
}
// Clear transient
wc_delete_product_transients( $post_id );
return $post_id;
}
/**
* Quick edit. @todo CRUDIFY
* Quick edit.
*
* @param integer $post_id
* @param integer $post_id
* @param WC_Product $product
*/
private function quick_edit_save( $post_id, $product ) {
global $wpdb;
$old_regular_price = $product->regular_price;
$old_sale_price = $product->sale_price;
$data_store = $product->get_data_store();
$old_regular_price = $product->get_regular_price();
$old_sale_price = $product->get_sale_price();
// Save fields
if ( isset( $_REQUEST['_sku'] ) ) {
$sku = get_post_meta( $post_id, '_sku', true );
$sku = $product->get_sku();
$new_sku = (string) wc_clean( $_REQUEST['_sku'] );
if ( $new_sku !== $sku ) {
if ( ! empty( $new_sku ) ) {
$unique_sku = wc_product_has_unique_sku( $post_id, $new_sku );
if ( $unique_sku ) {
update_post_meta( $post_id, '_sku', $new_sku );
$product->set_sku( $new_sku );
}
} else {
update_post_meta( $post_id, '_sku', '' );
$product->set_sku( '' );
}
}
}
if ( isset( $_REQUEST['_weight'] ) ) {
update_post_meta( $post_id, '_weight', wc_clean( $_REQUEST['_weight'] ) );
$product->set_weight( wc_clean( $_REQUEST['_weight'] ) );
}
if ( isset( $_REQUEST['_length'] ) ) {
update_post_meta( $post_id, '_length', wc_clean( $_REQUEST['_length'] ) );
$product->set_length( wc_clean( $_REQUEST['_length'] ) );
}
if ( isset( $_REQUEST['_width'] ) ) {
update_post_meta( $post_id, '_width', wc_clean( $_REQUEST['_width'] ) );
$product->set_width( wc_clean( $_REQUEST['_width'] ) );
}
if ( isset( $_REQUEST['_height'] ) ) {
update_post_meta( $post_id, '_height', wc_clean( $_REQUEST['_height'] ) );
$product->set_height( wc_clean( $_REQUEST['_height'] ) );
}
if ( ! empty( $_REQUEST['_shipping_class'] ) ) {
$shipping_class = '_no_shipping_class' == $_REQUEST['_shipping_class'] ? '' : wc_clean( $_REQUEST['_shipping_class'] );
wp_set_object_terms( $post_id, $shipping_class, 'product_shipping_class' );
$shipping_class = '_no_shipping_class' == $_REQUEST['_shipping_class'] ? '' : wc_clean( $_REQUEST['_shipping_class'] );
$shipping_class_id = $data_store->get_shipping_class_id_by_slug( $shipping_class );
if ( $shipping_class_id ) {
$product->set_shipping_class_id( $shipping_class_id );
}
}
if ( isset( $_REQUEST['_visibility'] ) ) {
if ( update_post_meta( $post_id, '_visibility', wc_clean( $_REQUEST['_visibility'] ) ) ) {
do_action( 'woocommerce_product_set_visibility', $post_id, wc_clean( $_REQUEST['_visibility'] ) );
}
$product->set_catalog_visibility( wc_clean( $_REQUEST['_visibility'] ) );
}
if ( isset( $_REQUEST['_featured'] ) ) {
if ( update_post_meta( $post_id, '_featured', 'yes' ) ) {
delete_transient( 'wc_featured_products' );
}
$product->set_featured( true );
} else {
if ( update_post_meta( $post_id, '_featured', 'no' ) ) {
delete_transient( 'wc_featured_products' );
}
$product->set_featured( false );
}
if ( isset( $_REQUEST['_tax_status'] ) ) {
update_post_meta( $post_id, '_tax_status', wc_clean( $_REQUEST['_tax_status'] ) );
$product->set_tax_status( wc_clean( $_REQUEST['_tax_status'] ) );
}
if ( isset( $_REQUEST['_tax_class'] ) ) {
update_post_meta( $post_id, '_tax_class', wc_clean( $_REQUEST['_tax_class'] ) );
$product->set_tax_class( wc_clean( $_REQUEST['_tax_class'] ) );
}
if ( $product->is_type( 'simple' ) || $product->is_type( 'external' ) ) {
if ( isset( $_REQUEST['_regular_price'] ) ) {
$new_regular_price = ( '' === $_REQUEST['_regular_price'] ) ? '' : wc_format_decimal( $_REQUEST['_regular_price'] );
update_post_meta( $post_id, '_regular_price', $new_regular_price );
$product->set_regular_price( $new_regular_price );
} else {
$new_regular_price = null;
}
if ( isset( $_REQUEST['_sale_price'] ) ) {
$new_sale_price = ( '' === $_REQUEST['_sale_price'] ) ? '' : wc_format_decimal( $_REQUEST['_sale_price'] );
update_post_meta( $post_id, '_sale_price', $new_sale_price );
$product->set_sale_price( $new_sale_price );
} else {
$new_sale_price = null;
}
@ -1168,19 +1040,13 @@ class WC_Admin_Post_Types {
}
if ( $price_changed ) {
update_post_meta( $post_id, '_sale_price_dates_from', '' );
update_post_meta( $post_id, '_sale_price_dates_to', '' );
if ( ! is_null( $new_sale_price ) && '' !== $new_sale_price ) {
update_post_meta( $post_id, '_price', $new_sale_price );
} else {
update_post_meta( $post_id, '_price', $new_regular_price );
}
$product->set_date_on_sale_to( '' );
$product->set_date_on_sale_from( '' );
}
}
// Handle Stock Data
$manage_stock = ! empty( $_REQUEST['_manage_stock'] ) && 'grouped' !== $product->product_type ? 'yes' : 'no';
$manage_stock = ! empty( $_REQUEST['_manage_stock'] ) && 'grouped' !== $product->get_type() ? 'yes' : 'no';
$backorders = ! empty( $_REQUEST['_backorders'] ) ? wc_clean( $_REQUEST['_backorders'] ) : 'no';
$stock_status = ! empty( $_REQUEST['_stock_status'] ) ? wc_clean( $_REQUEST['_stock_status'] ) : 'instock';
$stock_amount = 'yes' === $manage_stock ? wc_stock_amount( $_REQUEST['_stock'] ) : '';
@ -1188,30 +1054,34 @@ class WC_Admin_Post_Types {
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
// Apply product type constraints to stock status
if ( 'external' === $product->product_type ) {
if ( $product->is_type( 'external' ) ) {
// External always in stock
$stock_status = 'instock';
} elseif ( 'variable' === $product->product_type ) {
} elseif ( $product->is_type( 'variable' ) ) {
// Stock status is always determined by children
foreach ( $product->get_children() as $child_id ) {
if ( 'yes' !== get_post_meta( $child_id, '_manage_stock', true ) ) {
wc_update_product_stock_status( $child_id, $stock_status );
$child = wc_get_product( $child_id );
if ( ! $product->get_manage_stock() ) {
$child->set_stock_status( $stock_status );
$child->save();
}
}
WC_Product_Variable::sync_stock_status( $post_id );
$product = WC_Product_Variable::sync( $product, false );
}
update_post_meta( $post_id, '_manage_stock', $manage_stock );
update_post_meta( $post_id, '_backorders', $backorders );
$product->set_manage_stock( $manage_stock );
$product->set_backorders( $backorders );
$product->save();
if ( 'variable' !== $product->product_type ) {
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 );
}
@ -1220,33 +1090,33 @@ class WC_Admin_Post_Types {
/**
* Bulk edit.
*
* @param integer $post_id
* @param WC_Product $product
*/
public function bulk_edit_save( $post_id, $product ) {
$old_regular_price = $product->regular_price;
$old_sale_price = $product->sale_price;
$old_regular_price = $product->get_regular_price();
$old_sale_price = $product->get_sale_price();
// Save fields
if ( ! empty( $_REQUEST['change_weight'] ) && isset( $_REQUEST['_weight'] ) ) {
update_post_meta( $post_id, '_weight', wc_clean( stripslashes( $_REQUEST['_weight'] ) ) );
$product->set_weight( wc_clean( stripslashes( $_REQUEST['_weight'] ) ) );
}
if ( ! empty( $_REQUEST['change_dimensions'] ) ) {
if ( isset( $_REQUEST['_length'] ) ) {
update_post_meta( $post_id, '_length', wc_clean( stripslashes( $_REQUEST['_length'] ) ) );
$product->set_length( wc_clean( stripslashes( $_REQUEST['_length'] ) ) );
}
if ( isset( $_REQUEST['_width'] ) ) {
update_post_meta( $post_id, '_width', wc_clean( stripslashes( $_REQUEST['_width'] ) ) );
$product->set_width( wc_clean( stripslashes( $_REQUEST['_width'] ) ) );
}
if ( isset( $_REQUEST['_height'] ) ) {
update_post_meta( $post_id, '_height', wc_clean( stripslashes( $_REQUEST['_height'] ) ) );
$product->set_height( wc_clean( stripslashes( $_REQUEST['_height'] ) ) );
}
}
if ( ! empty( $_REQUEST['_tax_status'] ) ) {
update_post_meta( $post_id, '_tax_status', wc_clean( $_REQUEST['_tax_status'] ) );
$product->set_tax_status( wc_clean( $_REQUEST['_tax_status'] ) );
}
if ( ! empty( $_REQUEST['_tax_class'] ) ) {
@ -1254,33 +1124,31 @@ class WC_Admin_Post_Types {
if ( 'standard' == $tax_class ) {
$tax_class = '';
}
update_post_meta( $post_id, '_tax_class', $tax_class );
$product->set_tax_class( $tax_class );
}
if ( ! empty( $_REQUEST['_shipping_class'] ) ) {
$shipping_class = '_no_shipping_class' == $_REQUEST['_shipping_class'] ? '' : wc_clean( $_REQUEST['_shipping_class'] );
wp_set_object_terms( $post_id, $shipping_class, 'product_shipping_class' );
$shipping_class = '_no_shipping_class' == $_REQUEST['_shipping_class'] ? '' : wc_clean( $_REQUEST['_shipping_class'] );
$shipping_class_id = $data_store->get_shipping_class_id_by_slug( $shipping_class );
if ( $shipping_class_id ) {
$product->set_shipping_class_id( $shipping_class_id );
}
}
if ( ! empty( $_REQUEST['_visibility'] ) ) {
if ( update_post_meta( $post_id, '_visibility', wc_clean( $_REQUEST['_visibility'] ) ) ) {
do_action( 'woocommerce_product_set_visibility', $post_id, wc_clean( $_REQUEST['_visibility'] ) );
}
$product->set_catalog_visibility( wc_clean( $_REQUEST['_visibility'] ) );
}
if ( ! empty( $_REQUEST['_featured'] ) ) {
if ( update_post_meta( $post_id, '_featured', stripslashes( $_REQUEST['_featured'] ) ) ) {
delete_transient( 'wc_featured_products' );
}
$product->set_featured( stripslashes( $_REQUEST['_featured'] ) );
}
// Sold Individually
if ( ! empty( $_REQUEST['_sold_individually'] ) ) {
if ( 'yes' === $_REQUEST['_sold_individually'] ) {
update_post_meta( $post_id, '_sold_individually', 'yes' );
$product->set_sold_individually( 'yes' );
} else {
update_post_meta( $post_id, '_sold_individually', '' );
$product->set_sold_individually( '' );
}
}
@ -1299,7 +1167,6 @@ class WC_Admin_Post_Types {
$price_changed = false;
if ( ! empty( $_REQUEST['change_regular_price'] ) ) {
$change_regular_price = absint( $_REQUEST['change_regular_price'] );
$regular_price = esc_attr( stripslashes( $_REQUEST['_regular_price'] ) );
@ -1331,13 +1198,11 @@ class WC_Admin_Post_Types {
if ( isset( $new_price ) && $new_price != $old_regular_price ) {
$price_changed = true;
$new_price = round( $new_price, wc_get_price_decimals() );
update_post_meta( $post_id, '_regular_price', $new_price );
$product->regular_price = $new_price;
$product->set_regular_price( $new_price );
}
}
if ( ! empty( $_REQUEST['change_sale_price'] ) ) {
$change_sale_price = absint( $_REQUEST['change_sale_price'] );
$sale_price = esc_attr( stripslashes( $_REQUEST['_sale_price'] ) );
@ -1377,32 +1242,24 @@ class WC_Admin_Post_Types {
if ( isset( $new_price ) && $new_price != $old_sale_price ) {
$price_changed = true;
$new_price = ! empty( $new_price ) || '0' === $new_price ? round( $new_price, wc_get_price_decimals() ) : '';
update_post_meta( $post_id, '_sale_price', $new_price );
$product->sale_price = $new_price;
$product->set_sale_price( $new_price );
}
}
if ( $price_changed ) {
update_post_meta( $post_id, '_sale_price_dates_from', '' );
update_post_meta( $post_id, '_sale_price_dates_to', '' );
$product->set_date_on_sale_to( '' );
$product->set_date_on_sale_from( '' );
if ( $product->regular_price < $product->sale_price ) {
$product->sale_price = '';
update_post_meta( $post_id, '_sale_price', '' );
}
if ( $product->sale_price ) {
update_post_meta( $post_id, '_price', $product->sale_price );
} else {
update_post_meta( $post_id, '_price', $product->regular_price );
if ( $product->get_regular_price() < $product->get_sale_price() ) {
$product->set_sale_price( '' );
}
}
}
// Handle Stock Data
$was_managing_stock = get_post_meta( $post_id, '_manage_stock', true );
$stock_status = get_post_meta( $post_id, '_stock_status', true );
$backorders = get_post_meta( $post_id, '_stock_status', true );
$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;
@ -1418,30 +1275,34 @@ class WC_Admin_Post_Types {
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
// Apply product type constraints to stock status
if ( 'external' === $product->product_type ) {
if ( $product->is_type( 'external' ) ) {
// External always in stock
$stock_status = 'instock';
} elseif ( 'variable' === $product->product_type ) {
} elseif ( $product->is_type( 'variable' ) ) {
// Stock status is always determined by children
foreach ( $product->get_children() as $child_id ) {
if ( 'yes' !== get_post_meta( $child_id, '_manage_stock', true ) ) {
wc_update_product_stock_status( $child_id, $stock_status );
$child = wc_get_product( $child_id );
if ( ! $product->get_manage_stock() ) {
$child->set_stock_status( $stock_status );
$child->save();
}
}
WC_Product_Variable::sync_stock_status( $post_id );
$product = WC_Product_Variable::sync( $product, false );
}
update_post_meta( $post_id, '_manage_stock', $manage_stock );
update_post_meta( $post_id, '_backorders', $backorders );
$product->set_manage_stock( $manage_stock );
$product->set_backorders( $backorders );
$product->save();
if ( 'variable' !== $product->product_type ) {
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 );
}
@ -1450,24 +1311,30 @@ class WC_Admin_Post_Types {
/**
* Add extra bulk action options to mark orders as complete or processing.
* Fallback for old versions of WordPress.
* See: https://core.trac.wordpress.org/ticket/16031.
*
* Using Javascript until WordPress core fixes: https://core.trac.wordpress.org/ticket/16031.
* @todo Remove when start require at least 4.7.
*/
public function bulk_admin_footer() {
global $post_type;
global $post_type, $wp_version;
if ( 'shop_order' == $post_type ) {
if ( version_compare( $wp_version, '4.7-beta', '>=' ) ) {
return;
}
if ( 'shop_order' === $post_type ) {
?>
<script type="text/javascript">
jQuery(function() {
jQuery('<option>').val('mark_processing').text('<?php _e( 'Mark processing', 'woocommerce' )?>').appendTo('select[name="action"]');
jQuery('<option>').val('mark_processing').text('<?php _e( 'Mark processing', 'woocommerce' )?>').appendTo('select[name="action2"]');
jQuery( function( $ ) {
$( '<option>' ).val( 'mark_processing' ).text( '<?php _e( 'Mark processing', 'woocommerce' ); ?>' ).appendTo( 'select[name="action"]' );
$( '<option>' ).val( 'mark_processing' ).text( '<?php _e( 'Mark processing', 'woocommerce' ); ?>' ).appendTo( 'select[name="action2"]' );
jQuery('<option>').val('mark_on-hold').text('<?php _e( 'Mark on-hold', 'woocommerce' )?>').appendTo('select[name="action"]');
jQuery('<option>').val('mark_on-hold').text('<?php _e( 'Mark on-hold', 'woocommerce' )?>').appendTo('select[name="action2"]');
$( '<option>' ).val( 'mark_on-hold' ).text( '<?php _e( 'Mark on-hold', 'woocommerce' ); ?>' ).appendTo( 'select[name="action"]' );
$( '<option>' ).val( 'mark_on-hold' ).text( '<?php _e( 'Mark on-hold', 'woocommerce' ); ?>' ).appendTo( 'select[name="action2"]' );
jQuery('<option>').val('mark_completed').text('<?php _e( 'Mark complete', 'woocommerce' )?>').appendTo('select[name="action"]');
jQuery('<option>').val('mark_completed').text('<?php _e( 'Mark complete', 'woocommerce' )?>').appendTo('select[name="action2"]');
$( '<option>' ).val( 'mark_completed' ).text( '<?php _e( 'Mark complete', 'woocommerce' ); ?>' ).appendTo( 'select[name="action"]' );
$( '<option>' ).val( 'mark_completed' ).text( '<?php _e( 'Mark complete', 'woocommerce' ); ?>' ).appendTo( 'select[name="action2"]' );
});
</script>
<?php
@ -1476,48 +1343,96 @@ class WC_Admin_Post_Types {
/**
* Process the new bulk actions for changing order status.
*
* @todo Remove when start require at least 4.7.
*/
public function bulk_action() {
global $wp_version;
if ( version_compare( $wp_version, '4.7-beta', '>=' ) || empty( $_REQUEST['post'] ) ) {
return;
}
$wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
$action = $wp_list_table->current_action();
$ids = wp_unslash( $_REQUEST['post'] );
$sendback = $this->handle_shop_order_bulk_actions( '', $action, $ids );
// Bail out if this is not a status-changing action
if ( strpos( $action, 'mark_' ) === false ) {
if ( empty( $sendback ) ) {
return;
}
$order_statuses = wc_get_order_statuses();
$new_status = substr( $action, 5 ); // get the status name from action
$report_action = 'marked_' . $new_status;
// Sanity check: bail out if this is actually not a status, or is
// not a registered status
if ( ! isset( $order_statuses[ 'wc-' . $new_status ] ) ) {
return;
}
$changed = 0;
$post_ids = array_map( 'absint', (array) $_REQUEST['post'] );
foreach ( $post_ids as $post_id ) {
$order = wc_get_order( $post_id );
$order->update_status( $new_status, __( 'Order status changed by bulk edit:', 'woocommerce' ), true );
do_action( 'woocommerce_order_edit_status', $post_id, $new_status );
$changed++;
}
$sendback = add_query_arg( array( 'post_type' => 'shop_order', $report_action => true, 'changed' => $changed, 'ids' => join( ',', $post_ids ) ), '' );
if ( isset( $_GET['post_status'] ) ) {
$sendback = add_query_arg( 'post_status', sanitize_text_field( $_GET['post_status'] ), $sendback );
}
wp_redirect( esc_url_raw( $sendback ) );
wp_redirect( $sendback );
exit();
}
/**
* Manipulate shop order bulk actions.
*
* @param array $actions List of actions.
* @return array
*/
public function shop_order_bulk_actions( $actions ) {
if ( isset( $actions['edit'] ) ) {
unset( $actions['edit'] );
}
$actions['mark_processing'] = __( 'Mark processing', 'woocommerce' );
$actions['mark_on-hold'] = __( 'Mark on-hold', 'woocommerce' );
$actions['mark_completed'] = __( 'Mark complete', 'woocommerce' );
return $actions;
}
/**
* Handle shop order bulk actions.
*
* @since 2.7.0
* @param string $redirect_to URL to redirect to.
* @param string $action Action name.
* @param array $ids List of ids.
* @return string
*/
public function handle_shop_order_bulk_actions( $redirect_to, $action, $ids ) {
// Bail out if this is not a status-changing action.
if ( false === strpos( $action, 'mark_' ) ) {
return $redirect_to;
}
$order_statuses = wc_get_order_statuses();
$new_status = substr( $action, 5 ); // Get the status name from action.
$report_action = 'marked_' . $new_status;
// Sanity check: bail out if this is actually not a status, or is
// not a registered status.
if ( ! isset( $order_statuses[ 'wc-' . $new_status ] ) ) {
return $redirect_to;
}
$changed = 0;
$ids = array_map( 'absint', $ids );
foreach ( $ids as $id ) {
$order = wc_get_order( $id );
$order->update_status( $new_status, __( 'Order status changed by bulk edit:', 'woocommerce' ), true );
do_action( 'woocommerce_order_edit_status', $id, $new_status );
$changed++;
}
$redirect_to = add_query_arg( array(
'post_type' => 'shop_order',
$report_action => true,
'changed' => $changed,
'ids' => join( ',', $ids ),
), $redirect_to );
return esc_url_raw( $redirect_to );
}
/**
* Show confirmation message that order status changed for number of orders.
*/

View File

@ -270,7 +270,9 @@ class WC_Meta_Box_Order_Data {
<h3>
<?php _e( 'Billing details', 'woocommerce' ); ?>
<a href="#" class="edit_address"><?php _e( 'Edit', 'woocommerce' ); ?></a>
<a href="#" class="tips load_customer_billing" data-tip="<?php esc_attr_e( 'Load billing address', 'woocommerce' ); ?>" style="display:none;"><?php _e( 'Load billing address', 'woocommerce' ); ?></a>
<span>
<a href="#" class="load_customer_billing" style="display:none;"><?php _e( 'Load billing address', 'woocommerce' ); ?></a>
</span>
</h3>
<?php
// Display values
@ -290,8 +292,12 @@ class WC_Meta_Box_Order_Data {
$field_name = 'billing_' . $key;
if ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
echo '<p><strong>' . esc_html( $field['label'] ) . ':</strong> ' . make_clickable( esc_html( $order->{"get_$field_name"}( 'edit' ) ) ) . '</p>';
$field_value = $order->{"get_$field_name"}( 'edit' );
} else {
$field_value = $order->get_meta( '_' . $field_name );
}
echo '<p><strong>' . esc_html( $field['label'] ) . ':</strong> ' . make_clickable( esc_html( $field_value ) ) . '</p>';
}
echo '</div>';
@ -354,8 +360,10 @@ class WC_Meta_Box_Order_Data {
<h3>
<?php _e( 'Shipping details', 'woocommerce' ); ?>
<a href="#" class="edit_address"><?php _e( 'Edit', 'woocommerce' ); ?></a>
<a href="#" class="tips billing-same-as-shipping" data-tip="<?php esc_attr_e( 'Copy from billing', 'woocommerce' ); ?>" style="display:none;"><?php _e( 'Copy from billing', 'woocommerce' ); ?></a>
<a href="#" class="tips load_customer_shipping" data-tip="<?php esc_attr_e( 'Load shipping address', 'woocommerce' ); ?>" style="display:none;"><?php _e( 'Load shipping address', 'woocommerce' ); ?></a>
<span>
<a href="#" class="load_customer_shipping" style="display:none;"><?php _e( 'Load shipping address', 'woocommerce' ); ?></a>
<a href="#" class="billing-same-as-shipping" style="display:none;"><?php _e( 'Copy billing address', 'woocommerce' ); ?></a>
</span>
</h3>
<?php
// Display values
@ -376,8 +384,12 @@ class WC_Meta_Box_Order_Data {
$field_name = 'shipping_' . $key;
if ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
echo '<p><strong>' . esc_html( $field['label'] ) . ':</strong> ' . make_clickable( esc_html( $order->{"get_$field_name"}( 'edit' ) ) ) . '</p>';
$field_value = $order->{"get_$field_name"}( 'edit' );
} else {
$field_value = $order->get_meta( '_' . $field_name );
}
echo '<p><strong>' . esc_html( $field['label'] ) . ':</strong> ' . make_clickable( esc_html( $field_value ) ) . '</p>';
}
}
@ -465,7 +477,11 @@ class WC_Meta_Box_Order_Data {
$field['id'] = '_billing_' . $key;
}
$props[ 'billing_' . $key ] = wc_clean( $_POST[ $field['id'] ] );
if ( is_callable( array( $order, 'set_billing_' . $key ) ) ) {
$props[ 'billing_' . $key ] = wc_clean( $_POST[ $field['id'] ] );
} else {
$order->update_meta_data( $field['id'], wc_clean( $_POST[ $field['id'] ] ) );
}
}
}
@ -476,7 +492,11 @@ class WC_Meta_Box_Order_Data {
$field['id'] = '_shipping_' . $key;
}
$props[ 'shipping_' . $key ] = wc_clean( $_POST[ $field['id'] ] );
if ( is_callable( array( $order, 'set_shipping_' . $key ) ) ) {
$props[ 'shipping_' . $key ] = wc_clean( $_POST[ $field['id'] ] );
} else {
$order->update_meta_data( $field['id'], wc_clean( $_POST[ $field['id'] ] ) );
}
}
}

View File

@ -35,7 +35,9 @@
$all_terms = get_terms( $attribute->get_taxonomy(), apply_filters( 'woocommerce_product_attribute_terms', $args ) );
if ( $all_terms ) {
foreach ( $all_terms as $term ) {
echo '<option value="' . esc_attr( $term->term_id ) . '" ' . selected( in_array( $term->term_id, $attribute->get_options() ), true, false ) . '>' . esc_attr( apply_filters( 'woocommerce_product_attribute_term_name', $term->name, $term ) ) . '</option>';
$options = $attribute->get_options();
$options = ! empty( $options ) ? $options : array();
echo '<option value="' . esc_attr( $term->term_id ) . '" ' . selected( in_array( $term->term_id, $options ), true, false ) . '>' . esc_attr( apply_filters( 'woocommerce_product_attribute_term_name', $term->name, $term ) ) . '</option>';
}
}
?>

View File

@ -30,7 +30,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<option value=""><?php
/* translators: %s: attribute label */
echo sprintf( __( 'Any %s&hellip;', 'woocommerce' ), esc_html( wc_attribute_label( $attribute->get_name() ) ) );
?>&hellip;</option>
?></option>
<?php if ( $attribute->is_taxonomy() ) : ?>
<?php foreach ( $attribute->get_terms() as $option ) : ?>
<option <?php selected( $selected_value, $option->slug ); ?> value="<?php echo esc_attr( $option->slug ); ?>"><?php echo esc_html( apply_filters( 'woocommerce_variation_option_name', $option->name ) ); ?></option>

View File

@ -320,7 +320,7 @@ class WC_REST_Customers_Controller extends WC_REST_Controller {
$this->update_customer_meta_fields( $customer, $request );
$customer->save();
$user_data = get_user_by( 'id', $customer->get_id() );
$user_data = get_userdata( $customer->get_id() );
$this->update_additional_fields_for_object( $user_data, $request );
/**
@ -532,7 +532,7 @@ class WC_REST_Customers_Controller extends WC_REST_Controller {
if ( isset( $request['meta_data'] ) ) {
if ( is_array( $request['meta_data'] ) ) {
foreach ( $request['meta_data'] as $meta ) {
$coupon->update_meta_data( $meta['key'], $meta['value'], $meta['id'] );
$customer->update_meta_data( $meta['key'], $meta['value'], $meta['id'] );
}
}
}
@ -551,7 +551,7 @@ class WC_REST_Customers_Controller extends WC_REST_Controller {
if ( isset( $request['billing'] ) ) {
foreach ( array_keys( $schema['properties']['billing']['properties'] ) as $field ) {
if ( isset( $request['billing'][ $field ] ) && is_callable( array( $customer, "set_billing_{$field}" ) ) ) {
$customer->{"set_billing_{$field}"}( $request['billing'][ $field ] );
$customer->{"set_billing_{$field}"}( $request['billing'][ $field ] );
}
}
}
@ -560,7 +560,7 @@ class WC_REST_Customers_Controller extends WC_REST_Controller {
if ( isset( $request['shipping'] ) ) {
foreach ( array_keys( $schema['properties']['shipping']['properties'] ) as $field ) {
if ( isset( $request['shipping'][ $field ] ) && is_callable( array( $customer, "set_shipping_{$field}" ) ) ) {
$customer->{"set_shipping_{$field}"}( $request['shipping'][ $field ] );
$customer->{"set_shipping_{$field}"}( $request['shipping'][ $field ] );
}
}
}

View File

@ -260,14 +260,12 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
protected function get_taxonomy_terms( $product, $taxonomy = 'cat' ) {
$terms = array();
if ( $_terms = get_the_terms( $product->get_id(), 'product_' . $taxonomy ) ) {
foreach ( $_terms as $term ) {
$terms[] = array(
'id' => $term->term_id,
'name' => $term->name,
'slug' => $term->slug,
);
}
foreach ( wc_get_object_terms( $product->get_id(), 'product_' . $taxonomy ) as $term ) {
$terms[] = array(
'id' => $term->term_id,
'name' => $term->name,
'slug' => $term->slug,
);
}
return $terms;
@ -381,7 +379,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
*/
protected function get_attribute_options( $product_id, $attribute ) {
if ( isset( $attribute['is_taxonomy'] ) && $attribute['is_taxonomy'] ) {
return wc_get_product_terms( $product_id, $attribute['name'], array( 'fields' => 'names' ) );
return wc_get_object_terms( $product_id, $attribute['name'], 'name' );
} elseif ( isset( $attribute['value'] ) ) {
return array_map( 'trim', explode( '|', $attribute['value'] ) );
}

View File

@ -124,56 +124,47 @@ class WC_API_Customers extends WC_API_Resource {
$id = $this->validate_request( $id, 'customer', 'read' );
if ( is_wp_error( $id ) )
if ( is_wp_error( $id ) ) {
return $id;
}
$customer = new WP_User( $id );
// get info about user's last order
$last_order = $wpdb->get_row( "SELECT id, post_date_gmt
FROM $wpdb->posts AS posts
LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
WHERE meta.meta_key = '_customer_user'
AND meta.meta_value = {$customer->ID}
AND posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", array_keys( wc_get_order_statuses() ) ) . "' )
" );
$customer = new WC_Customer( $id );
$last_order = $customer->get_last_order();
$customer_data = array(
'id' => $customer->ID,
'created_at' => $this->server->format_datetime( $customer->user_registered ),
'email' => $customer->user_email,
'first_name' => $customer->first_name,
'last_name' => $customer->last_name,
'username' => $customer->user_login,
'id' => $customer->get_id(),
'created_at' => $this->server->format_datetime( $customer->get_date_created() ),
'email' => $customer->get_email(),
'first_name' => $customer->get_first_name(),
'last_name' => $customer->get_last_name(),
'username' => $customer->get_username(),
'last_order_id' => is_object( $last_order ) ? $last_order->get_id() : null,
'last_order_date' => is_object( $last_order ) ? $this->server->format_datetime( $last_order->post_date_gmt ) : null,
'orders_count' => (int) $customer->_order_count,
'total_spent' => wc_format_decimal( $customer->_money_spent, 2 ),
'avatar_url' => $this->get_avatar_url( $customer->customer_email ),
'last_order_date' => is_object( $last_order ) ? $this->server->format_datetime( $last_order->get_date_created() ) : null,
'orders_count' => $customer->get_order_count(),
'total_spent' => wc_format_decimal( $customer->get_total_spent(), 2 ),
'avatar_url' => $customer->get_avatar_url(),
'billing_address' => array(
'first_name' => $customer->billing_first_name,
'last_name' => $customer->billing_last_name,
'company' => $customer->billing_company,
'address_1' => $customer->billing_address_1,
'address_2' => $customer->billing_address_2,
'city' => $customer->billing_city,
'state' => $customer->billing_state,
'postcode' => $customer->billing_postcode,
'country' => $customer->billing_country,
'email' => $customer->billing_email,
'phone' => $customer->billing_phone,
'first_name' => $customer->get_billing_first_name(),
'last_name' => $customer->get_billing_last_name(),
'company' => $customer->get_billing_company(),
'address_1' => $customer->get_billing_address_1(),
'address_2' => $customer->get_billing_address_2(),
'city' => $customer->get_billing_city(),
'state' => $customer->get_billing_state(),
'postcode' => $customer->get_billing_postcode(),
'country' => $customer->get_billing_country(),
'email' => $customer->get_billing_email(),
'phone' => $customer->get_billing_phone(),
),
'shipping_address' => array(
'first_name' => $customer->shipping_first_name,
'last_name' => $customer->shipping_last_name,
'company' => $customer->shipping_company,
'address_1' => $customer->shipping_address_1,
'address_2' => $customer->shipping_address_2,
'city' => $customer->shipping_city,
'state' => $customer->shipping_state,
'postcode' => $customer->shipping_postcode,
'country' => $customer->shipping_country,
'first_name' => $customer->get_shipping_first_name(),
'last_name' => $customer->get_shipping_last_name(),
'company' => $customer->get_shipping_company(),
'address_1' => $customer->get_shipping_address_1(),
'address_2' => $customer->get_shipping_address_2(),
'city' => $customer->get_shipping_city(),
'state' => $customer->get_shipping_state(),
'postcode' => $customer->get_shipping_postcode(),
'country' => $customer->get_shipping_country(),
),
);
@ -258,20 +249,21 @@ class WC_API_Customers extends WC_API_Resource {
$id = $this->validate_request( $id, 'customer', 'read' );
if ( is_wp_error( $id ) )
if ( is_wp_error( $id ) ) {
return $id;
}
$order_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id
FROM $wpdb->posts AS posts
LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
WHERE meta.meta_key = '_customer_user'
AND meta.meta_value = '%s'
AND posts.post_type = 'shop_order'
AND posts.post_status = IN ( '" . implode( "','", array_keys( wc_get_order_statuses() ) ) . "' )
", $id ) );
$order_ids = wc_get_orders( array(
'customer' => $id,
'limit' => -1,
'orderby' => 'date',
'order' => 'ASC',
'return' => 'ids',
) );
if ( empty( $order_ids ) )
if ( empty( $order_ids ) ) {
return array( 'orders' => array() );
}
$orders = array();
@ -413,28 +405,6 @@ class WC_API_Customers extends WC_API_Resource {
$query->query_where .= sprintf( " AND user_registered <= STR_TO_DATE( '%s', '%%Y-%%m-%%d %%h:%%i:%%s' )", esc_sql( $this->created_at_max ) );
}
/**
* Wrapper for @see get_avatar() which doesn't simply return
* the URL so we need to pluck it from the HTML img tag
*
* @since 2.1
* @param string $email the customer's email
* @return string the URL to the customer's avatar
*/
private function get_avatar_url( $email ) {
$avatar_html = get_avatar( $email );
// Get the URL of the avatar from the provided HTML
preg_match( '/src=["|\'](.+)[\&|"|\']/U', $avatar_html, $matches );
if ( isset( $matches[1] ) && ! empty( $matches[1] ) ) {
return esc_url_raw( $matches[1] );
}
return null;
}
/**
* Validate the request by checking:
*

View File

@ -312,8 +312,8 @@ class WC_API_Products extends WC_API_Resource {
'related_ids' => array_map( 'absint', array_values( wc_get_related_products( $product->get_id() ) ) ),
'upsell_ids' => array_map( 'absint', $product->get_upsell_ids() ),
'cross_sell_ids' => array_map( 'absint', $product->get_cross_sell_ids() ),
'categories' => wp_get_post_terms( $product->get_id(), 'product_cat', array( 'fields' => 'names' ) ),
'tags' => wp_get_post_terms( $product->get_id(), 'product_tag', array( 'fields' => 'names' ) ),
'categories' => wc_get_object_terms( $product->get_id(), 'product_cat', 'name' ),
'tags' => wc_get_object_terms( $product->get_id(), 'product_tag', 'name' ),
'images' => $this->get_images( $product ),
'featured_src' => wp_get_attachment_url( get_post_thumbnail_id( $product->get_id() ) ),
'attributes' => $this->get_attributes( $product ),
@ -456,7 +456,7 @@ class WC_API_Products extends WC_API_Resource {
*/
protected function get_attribute_options( $product_id, $attribute ) {
if ( isset( $attribute['is_taxonomy'] ) && $attribute['is_taxonomy'] ) {
return wc_get_product_terms( $product_id, $attribute['name'], array( 'fields' => 'names' ) );
return wc_get_object_terms( $product_id, $attribute['name'], 'name' );
} elseif ( isset( $attribute['value'] ) ) {
return array_map( 'trim', explode( '|', $attribute['value'] ) );
}

View File

@ -146,57 +146,44 @@ class WC_API_Customers extends WC_API_Resource {
return $id;
}
$customer = new WP_User( $id );
// Get info about user's last order
$last_order = $wpdb->get_row( "SELECT id, post_date_gmt
FROM $wpdb->posts AS posts
LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
WHERE meta.meta_key = '_customer_user'
AND meta.meta_value = {$customer->ID}
AND posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", array_keys( wc_get_order_statuses() ) ) . "' )
ORDER BY posts.ID DESC
" );
$roles = array_values( $customer->roles );
$customer = new WC_Customer( $id );
$last_order = $customer->get_last_order();
$customer_data = array(
'id' => $customer->ID,
'created_at' => $this->server->format_datetime( $customer->user_registered ),
'email' => $customer->user_email,
'first_name' => $customer->first_name,
'last_name' => $customer->last_name,
'username' => $customer->user_login,
'role' => $roles[0],
'id' => $customer->get_id(),
'created_at' => $this->server->format_datetime( $customer->get_date_created() ),
'email' => $customer->get_email(),
'first_name' => $customer->get_first_name(),
'last_name' => $customer->get_last_name(),
'username' => $customer->get_username(),
'role' => $customer->get_role(),
'last_order_id' => is_object( $last_order ) ? $last_order->get_id() : null,
'last_order_date' => is_object( $last_order ) ? $this->server->format_datetime( $last_order->post_date_gmt ) : null,
'orders_count' => wc_get_customer_order_count( $customer->ID ),
'total_spent' => wc_format_decimal( wc_get_customer_total_spent( $customer->ID ), 2 ),
'avatar_url' => $this->get_avatar_url( $customer->customer_email ),
'last_order_date' => is_object( $last_order ) ? $this->server->format_datetime( $last_order->get_date_created() ) : null,
'orders_count' => $customer->get_order_count(),
'total_spent' => wc_format_decimal( $customer->get_total_spent(), 2 ),
'avatar_url' => $customer->get_avatar_url(),
'billing_address' => array(
'first_name' => $customer->billing_first_name,
'last_name' => $customer->billing_last_name,
'company' => $customer->billing_company,
'address_1' => $customer->billing_address_1,
'address_2' => $customer->billing_address_2,
'city' => $customer->billing_city,
'state' => $customer->billing_state,
'postcode' => $customer->billing_postcode,
'country' => $customer->billing_country,
'email' => $customer->billing_email,
'phone' => $customer->billing_phone,
'first_name' => $customer->get_billing_first_name(),
'last_name' => $customer->get_billing_last_name(),
'company' => $customer->get_billing_company(),
'address_1' => $customer->get_billing_address_1(),
'address_2' => $customer->get_billing_address_2(),
'city' => $customer->get_billing_city(),
'state' => $customer->get_billing_state(),
'postcode' => $customer->get_billing_postcode(),
'country' => $customer->get_billing_country(),
'email' => $customer->get_billing_email(),
'phone' => $customer->get_billing_phone(),
),
'shipping_address' => array(
'first_name' => $customer->shipping_first_name,
'last_name' => $customer->shipping_last_name,
'company' => $customer->shipping_company,
'address_1' => $customer->shipping_address_1,
'address_2' => $customer->shipping_address_2,
'city' => $customer->shipping_city,
'state' => $customer->shipping_state,
'postcode' => $customer->shipping_postcode,
'country' => $customer->shipping_country,
'first_name' => $customer->get_shipping_first_name(),
'last_name' => $customer->get_shipping_last_name(),
'company' => $customer->get_shipping_company(),
'address_1' => $customer->get_shipping_address_1(),
'address_2' => $customer->get_shipping_address_2(),
'city' => $customer->get_shipping_city(),
'state' => $customer->get_shipping_state(),
'postcode' => $customer->get_shipping_postcode(),
'country' => $customer->get_shipping_country(),
),
);
@ -216,10 +203,10 @@ class WC_API_Customers extends WC_API_Resource {
if ( is_email( $email ) ) {
$customer = get_user_by( 'email', $email );
if ( ! is_object( $customer ) ) {
throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer Email', 'woocommerce' ), 404 );
throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer email', 'woocommerce' ), 404 );
}
} else {
throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer Email', 'woocommerce' ), 404 );
throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer email', 'woocommerce' ), 404 );
}
return $this->get_customer( $customer->ID, $fields );
@ -301,37 +288,47 @@ class WC_API_Customers extends WC_API_Resource {
* @since 2.2
* @param int $id the customer ID
* @param array $data
* @param WC_Customer $customer
*/
protected function update_customer_data( $id, $data ) {
protected function update_customer_data( $id, $data, $customer ) {
// Customer first name.
if ( isset( $data['first_name'] ) ) {
update_user_meta( $id, 'first_name', wc_clean( $data['first_name'] ) );
$customer->set_first_name( wc_clean( $data['first_name'] ) );
}
// Customer last name.
if ( isset( $data['last_name'] ) ) {
update_user_meta( $id, 'last_name', wc_clean( $data['last_name'] ) );
$customer->set_last_name( wc_clean( $data['last_name'] ) );
}
// Customer billing address.
if ( isset( $data['billing_address'] ) ) {
foreach ( $this->get_customer_billing_address() as $address ) {
if ( isset( $data['billing_address'][ $address ] ) ) {
update_user_meta( $id, 'billing_' . $address, wc_clean( $data['billing_address'][ $address ] ) );
foreach ( $this->get_customer_billing_address() as $field ) {
if ( isset( $data['billing_address'][ $field ] ) ) {
if ( is_callable( array( $customer, "set_billing_{$field}" ) ) ) {
$customer->{"set_billing_{$field}"}( $data['billing_address'][ $field ] );
} else {
$customer->update_meta_data( 'billing_' . $field, wc_clean( $data['billing_address'][ $field ] ), $meta['id'] );
}
}
}
}
// Customer shipping address.
if ( isset( $data['shipping_address'] ) ) {
foreach ( $this->get_customer_shipping_address() as $address ) {
if ( isset( $data['shipping_address'][ $address ] ) ) {
update_user_meta( $id, 'shipping_' . $address, wc_clean( $data['shipping_address'][ $address ] ) );
foreach ( $this->get_customer_shipping_address() as $field ) {
if ( isset( $data['shipping_address'][ $field ] ) ) {
if ( is_callable( array( $customer, "set_shipping_{$field}" ) ) ) {
$customer->{"set_shipping_{$field}"}( $data['shipping_address'][ $field ] );
} else {
$customer->update_meta_data( 'shipping_' . $field, wc_clean( $data['shipping_address'][ $field ] ), $meta['id'] );
}
}
}
}
do_action( 'woocommerce_api_update_customer_data', $id, $data );
do_action( 'woocommerce_api_update_customer_data', $id, $data, $customer );
}
/**
@ -361,29 +358,27 @@ class WC_API_Customers extends WC_API_Resource {
throw new WC_API_Exception( 'woocommerce_api_missing_customer_email', sprintf( __( 'Missing parameter %s', 'woocommerce' ), 'email' ), 400 );
}
// Sets the username.
$data['username'] = ! empty( $data['username'] ) ? $data['username'] : '';
// Create customer.
$customer = new WC_Customer;
$customer->set_username( ! empty( $data['username'] ) ? $data['username'] : '' );
$customer->set_password( ! empty( $data['password'] ) ? $data['password'] : '' );
$customer->set_email( $data['email'] );
$customer->save();
// Sets the password.
$data['password'] = ! empty( $data['password'] ) ? $data['password'] : '';
// Attempts to create the new customer
$id = wc_create_new_customer( $data['email'], $data['username'], $data['password'] );
// Checks for an error in the customer creation.
if ( is_wp_error( $id ) ) {
throw new WC_API_Exception( $id->get_error_code(), $id->get_error_message(), 400 );
if ( ! $customer->get_id() ) {
throw new WC_API_Exception( 'woocommerce_api_user_cannot_create_customer', __( 'This resource cannot be created.', 'woocommerce' ), 400 );
}
// Added customer data.
$this->update_customer_data( $id, $data );
$this->update_customer_data( $customer->get_id(), $data, $customer );
$customer->save();
do_action( 'woocommerce_api_create_customer', $id, $data );
do_action( 'woocommerce_api_create_customer', $customer->get_id(), $data );
$this->server->send_status( 201 );
return $this->get_customer( $id );
} catch ( WC_API_Exception $e ) {
return $this->get_customer( $customer->get_id() );
} catch ( Exception $e ) {
return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
}
}
@ -414,23 +409,27 @@ class WC_API_Customers extends WC_API_Resource {
$data = apply_filters( 'woocommerce_api_edit_customer_data', $data, $this );
$customer = new WC_Customer( $id );
// Customer email.
if ( isset( $data['email'] ) ) {
wp_update_user( array( 'ID' => $id, 'user_email' => sanitize_email( $data['email'] ) ) );
$customer->set_email( $data['email'] );
}
// Customer password.
if ( isset( $data['password'] ) ) {
wp_update_user( array( 'ID' => $id, 'user_pass' => wc_clean( $data['password'] ) ) );
$customer->set_password( $data['password'] );
}
// Update customer data.
$this->update_customer_data( $id, $data );
$this->update_customer_data( $customer->get_id(), $data, $customer );
do_action( 'woocommerce_api_edit_customer', $id, $data );
$customer->save();
return $this->get_customer( $id );
} catch ( WC_API_Exception $e ) {
do_action( 'woocommerce_api_edit_customer', $customer->get_id(), $data );
return $this->get_customer( $customer->get_id() );
} catch ( Exception $e ) {
return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
}
}
@ -474,14 +473,13 @@ class WC_API_Customers extends WC_API_Resource {
return $id;
}
$order_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id
FROM $wpdb->posts AS posts
LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
WHERE meta.meta_key = '_customer_user'
AND meta.meta_value = '%s'
AND posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", array_keys( wc_get_order_statuses() ) ) . "' )
", $id ) );
$order_ids = wc_get_orders( array(
'customer' => $id,
'limit' => -1,
'orderby' => 'date',
'order' => 'ASC',
'return' => 'ids',
) );
if ( empty( $order_ids ) ) {
return array( 'orders' => array() );
@ -681,29 +679,6 @@ class WC_API_Customers extends WC_API_Resource {
}
}
/**
* Wrapper for @see get_avatar() which doesn't simply return
* the URL so we need to pluck it from the HTML img tag
*
* Kudos to https://github.com/WP-API/WP-API for offering a better solution
*
* @since 2.1
* @param string $email the customer's email
* @return string the URL to the customer's avatar
*/
private function get_avatar_url( $email ) {
$avatar_html = get_avatar( $email );
// Get the URL of the avatar from the provided HTML
preg_match( '/src=["|\'](.+)[\&|"|\']/U', $avatar_html, $matches );
if ( isset( $matches[1] ) && ! empty( $matches[1] ) ) {
return esc_url_raw( $matches[1] );
}
return null;
}
/**
* Validate the request by checking:
*

View File

@ -230,7 +230,7 @@ class WC_API_Orders extends WC_API_Resource {
'total' => wc_format_decimal( $order->get_line_total( $item, false, false ), $dp ),
'total_tax' => wc_format_decimal( $item->get_total_tax(), $dp ),
'price' => wc_format_decimal( $order->get_item_total( $item, false, false ), $dp ),
'quantity' => $item->get_qty(),
'quantity' => $item->get_quantity(),
'tax_class' => $item->get_tax_class(),
'name' => $item->get_name(),
'product_id' => $item->get_variation_id() ? $item->get_variation_id() : $item->get_product_id(),

View File

@ -732,8 +732,8 @@ class WC_API_Products extends WC_API_Resource {
'upsell_ids' => array_map( 'absint', $product->get_upsell_ids() ),
'cross_sell_ids' => array_map( 'absint', $product->get_cross_sell_ids() ),
'parent_id' => $product->get_parent_id(),
'categories' => wp_get_post_terms( $product->get_id(), 'product_cat', array( 'fields' => 'names' ) ),
'tags' => wp_get_post_terms( $product->get_id(), 'product_tag', array( 'fields' => 'names' ) ),
'categories' => wc_get_object_terms( $product->get_id(), 'product_cat', 'name' ),
'tags' => wc_get_object_terms( $product->get_id(), 'product_tag', 'name' ),
'images' => $this->get_images( $product ),
'featured_src' => wp_get_attachment_url( get_post_thumbnail_id( $product->get_id() ) ),
'attributes' => $this->get_attributes( $product ),
@ -1477,9 +1477,10 @@ class WC_API_Products extends WC_API_Resource {
// Shipping class
if ( isset( $data['shipping_class'] ) ) {
$shipping_class_term = get_term_by( 'slug', wc_clean( $data['shipping_class'] ), 'product_shipping_class' );
if ( $shipping_class_term ) {
$product->set_shipping_class_id( $shipping_class_term->term_id );
$data_store = $product->get_data_store();
$shipping_class_id = $data_store->get_shipping_class_id_by_slug( wc_clean( $data['shipping_class'] ) );
if ( $shipping_class_id ) {
$product->set_shipping_class_id( $shipping_class_id );
}
}
@ -1781,7 +1782,7 @@ class WC_API_Products extends WC_API_Resource {
*/
protected function get_attribute_options( $product_id, $attribute ) {
if ( isset( $attribute['is_taxonomy'] ) && $attribute['is_taxonomy'] ) {
return wc_get_product_terms( $product_id, $attribute['name'], array( 'fields' => 'names' ) );
return wc_get_object_terms( $product_id, $attribute['name'], 'name' );
} elseif ( isset( $attribute['value'] ) ) {
return array_map( 'trim', explode( '|', $attribute['value'] ) );
}

View File

@ -146,58 +146,45 @@ class WC_API_Customers extends WC_API_Resource {
return $id;
}
$customer = new WP_User( $id );
// Get info about user's last order
$last_order = $wpdb->get_row( "SELECT id, post_date_gmt
FROM $wpdb->posts AS posts
LEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id
WHERE meta.meta_key = '_customer_user'
AND meta.meta_value = {$customer->ID}
AND posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", array_keys( wc_get_order_statuses() ) ) . "' )
ORDER BY posts.ID DESC
" );
$roles = array_values( $customer->roles );
$customer = new WC_Customer( $id );
$last_order = $customer->get_last_order();
$customer_data = array(
'id' => $customer->ID,
'created_at' => $this->server->format_datetime( $customer->user_registered ),
'last_update' => $this->server->format_datetime( get_user_meta( $customer->ID, 'last_update', true ) ),
'email' => $customer->user_email,
'first_name' => $customer->first_name,
'last_name' => $customer->last_name,
'username' => $customer->user_login,
'role' => $roles[0],
'id' => $customer->get_id(),
'created_at' => $this->server->format_datetime( $customer->get_date_created() ),
'last_update' => $this->server->format_datetime( $customer->get_date_modified() ),
'email' => $customer->get_email(),
'first_name' => $customer->get_first_name(),
'last_name' => $customer->get_last_name(),
'username' => $customer->get_username(),
'role' => $customer->get_role(),
'last_order_id' => is_object( $last_order ) ? $last_order->get_id() : null,
'last_order_date' => is_object( $last_order ) ? $this->server->format_datetime( $last_order->post_date_gmt ) : null,
'orders_count' => wc_get_customer_order_count( $customer->ID ),
'total_spent' => wc_format_decimal( wc_get_customer_total_spent( $customer->ID ), 2 ),
'avatar_url' => $this->get_avatar_url( $customer->customer_email ),
'last_order_date' => is_object( $last_order ) ? $this->server->format_datetime( $last_order->get_date_created() ) : null,
'orders_count' => $customer->get_order_count(),
'total_spent' => wc_format_decimal( $customer->get_total_spent(), 2 ),
'avatar_url' => $customer->get_avatar_url(),
'billing_address' => array(
'first_name' => $customer->billing_first_name,
'last_name' => $customer->billing_last_name,
'company' => $customer->billing_company,
'address_1' => $customer->billing_address_1,
'address_2' => $customer->billing_address_2,
'city' => $customer->billing_city,
'state' => $customer->billing_state,
'postcode' => $customer->billing_postcode,
'country' => $customer->billing_country,
'email' => $customer->billing_email,
'phone' => $customer->billing_phone,
'first_name' => $customer->get_billing_first_name(),
'last_name' => $customer->get_billing_last_name(),
'company' => $customer->get_billing_company(),
'address_1' => $customer->get_billing_address_1(),
'address_2' => $customer->get_billing_address_2(),
'city' => $customer->get_billing_city(),
'state' => $customer->get_billing_state(),
'postcode' => $customer->get_billing_postcode(),
'country' => $customer->get_billing_country(),
'email' => $customer->get_billing_email(),
'phone' => $customer->get_billing_phone(),
),
'shipping_address' => array(
'first_name' => $customer->shipping_first_name,
'last_name' => $customer->shipping_last_name,
'company' => $customer->shipping_company,
'address_1' => $customer->shipping_address_1,
'address_2' => $customer->shipping_address_2,
'city' => $customer->shipping_city,
'state' => $customer->shipping_state,
'postcode' => $customer->shipping_postcode,
'country' => $customer->shipping_country,
'first_name' => $customer->get_shipping_first_name(),
'last_name' => $customer->get_shipping_last_name(),
'company' => $customer->get_shipping_company(),
'address_1' => $customer->get_shipping_address_1(),
'address_2' => $customer->get_shipping_address_2(),
'city' => $customer->get_shipping_city(),
'state' => $customer->get_shipping_state(),
'postcode' => $customer->get_shipping_postcode(),
'country' => $customer->get_shipping_country(),
),
);
@ -217,10 +204,10 @@ class WC_API_Customers extends WC_API_Resource {
if ( is_email( $email ) ) {
$customer = get_user_by( 'email', $email );
if ( ! is_object( $customer ) ) {
throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer Email', 'woocommerce' ), 404 );
throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer email', 'woocommerce' ), 404 );
}
} else {
throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer Email', 'woocommerce' ), 404 );
throw new WC_API_Exception( 'woocommerce_api_invalid_customer_email', __( 'Invalid customer email', 'woocommerce' ), 404 );
}
return $this->get_customer( $customer->ID, $fields );
@ -302,37 +289,47 @@ class WC_API_Customers extends WC_API_Resource {
* @since 2.2
* @param int $id the customer ID
* @param array $data
* @param WC_Customer $customer
*/
protected function update_customer_data( $id, $data ) {
protected function update_customer_data( $id, $data, $customer ) {
// Customer first name.
if ( isset( $data['first_name'] ) ) {
update_user_meta( $id, 'first_name', wc_clean( $data['first_name'] ) );
$customer->set_first_name( wc_clean( $data['first_name'] ) );
}
// Customer last name.
if ( isset( $data['last_name'] ) ) {
update_user_meta( $id, 'last_name', wc_clean( $data['last_name'] ) );
$customer->set_last_name( wc_clean( $data['last_name'] ) );
}
// Customer billing address.
if ( isset( $data['billing_address'] ) ) {
foreach ( $this->get_customer_billing_address() as $address ) {
if ( isset( $data['billing_address'][ $address ] ) ) {
update_user_meta( $id, 'billing_' . $address, wc_clean( $data['billing_address'][ $address ] ) );
foreach ( $this->get_customer_billing_address() as $field ) {
if ( isset( $data['billing_address'][ $field ] ) ) {
if ( is_callable( array( $customer, "set_billing_{$field}" ) ) ) {
$customer->{"set_billing_{$field}"}( $data['billing_address'][ $field ] );
} else {
$customer->update_meta_data( 'billing_' . $field, wc_clean( $data['billing_address'][ $field ] ), $meta['id'] );
}
}
}
}
// Customer shipping address.
if ( isset( $data['shipping_address'] ) ) {
foreach ( $this->get_customer_shipping_address() as $address ) {
if ( isset( $data['shipping_address'][ $address ] ) ) {
update_user_meta( $id, 'shipping_' . $address, wc_clean( $data['shipping_address'][ $address ] ) );
foreach ( $this->get_customer_shipping_address() as $field ) {
if ( isset( $data['shipping_address'][ $field ] ) ) {
if ( is_callable( array( $customer, "set_shipping_{$field}" ) ) ) {
$customer->{"set_shipping_{$field}"}( $data['shipping_address'][ $field ] );
} else {
$customer->update_meta_data( 'shipping_' . $field, wc_clean( $data['shipping_address'][ $field ] ), $meta['id'] );
}
}
}
}
do_action( 'woocommerce_api_update_customer_data', $id, $data );
do_action( 'woocommerce_api_update_customer_data', $id, $data, $customer );
}
/**
@ -362,29 +359,27 @@ class WC_API_Customers extends WC_API_Resource {
throw new WC_API_Exception( 'woocommerce_api_missing_customer_email', sprintf( __( 'Missing parameter %s', 'woocommerce' ), 'email' ), 400 );
}
// Sets the username.
$data['username'] = ! empty( $data['username'] ) ? $data['username'] : '';
// Create customer.
$customer = new WC_Customer;
$customer->set_username( ! empty( $data['username'] ) ? $data['username'] : '' );
$customer->set_password( ! empty( $data['password'] ) ? $data['password'] : '' );
$customer->set_email( $data['email'] );
$customer->save();
// Sets the password.
$data['password'] = ! empty( $data['password'] ) ? $data['password'] : '';
// Attempts to create the new customer
$id = wc_create_new_customer( $data['email'], $data['username'], $data['password'] );
// Checks for an error in the customer creation.
if ( is_wp_error( $id ) ) {
throw new WC_API_Exception( $id->get_error_code(), $id->get_error_message(), 400 );
if ( ! $customer->get_id() ) {
throw new WC_API_Exception( 'woocommerce_api_user_cannot_create_customer', __( 'This resource cannot be created.', 'woocommerce' ), 400 );
}
// Added customer data.
$this->update_customer_data( $id, $data );
$this->update_customer_data( $customer->get_id(), $data, $customer );
$customer->save();
do_action( 'woocommerce_api_create_customer', $id, $data );
do_action( 'woocommerce_api_create_customer', $customer->get_id(), $data );
$this->server->send_status( 201 );
return $this->get_customer( $id );
} catch ( WC_API_Exception $e ) {
return $this->get_customer( $customer->get_id() );
} catch ( Exception $e ) {
return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
}
}
@ -415,23 +410,27 @@ class WC_API_Customers extends WC_API_Resource {
$data = apply_filters( 'woocommerce_api_edit_customer_data', $data, $this );
$customer = new WC_Customer( $id );
// Customer email.
if ( isset( $data['email'] ) ) {
wp_update_user( array( 'ID' => $id, 'user_email' => sanitize_email( $data['email'] ) ) );
$customer->set_email( $data['email'] );
}
// Customer password.
if ( isset( $data['password'] ) ) {
wp_update_user( array( 'ID' => $id, 'user_pass' => wc_clean( $data['password'] ) ) );
$customer->set_password( $data['password'] );
}
// Update customer data.
$this->update_customer_data( $id, $data );
$this->update_customer_data( $customer->get_id(), $data, $customer );
do_action( 'woocommerce_api_edit_customer', $id, $data );
$customer->save();
return $this->get_customer( $id );
} catch ( WC_API_Exception $e ) {
do_action( 'woocommerce_api_edit_customer', $customer->get_id(), $data );
return $this->get_customer( $customer->get_id() );
} catch ( Exception $e ) {
return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );
}
}
@ -670,29 +669,6 @@ class WC_API_Customers extends WC_API_Resource {
}
}
/**
* Wrapper for @see get_avatar() which doesn't simply return
* the URL so we need to pluck it from the HTML img tag
*
* Kudos to https://github.com/WP-API/WP-API for offering a better solution
*
* @since 2.1
* @param string $email the customer's email
* @return string the URL to the customer's avatar
*/
private function get_avatar_url( $email ) {
$avatar_html = get_avatar( $email );
// Get the URL of the avatar from the provided HTML
preg_match( '/src=["|\'](.+)[\&|"|\']/U', $avatar_html, $matches );
if ( isset( $matches[1] ) && ! empty( $matches[1] ) ) {
return esc_url_raw( $matches[1] );
}
return null;
}
/**
* Validate the request by checking:
*

View File

@ -236,7 +236,7 @@ class WC_API_Orders extends WC_API_Resource {
'total' => wc_format_decimal( $order->get_line_total( $item, false, false ), $dp ),
'total_tax' => wc_format_decimal( $item->get_total_tax(), $dp ),
'price' => wc_format_decimal( $order->get_item_total( $item, false, false ), $dp ),
'quantity' => $item->get_qty(),
'quantity' => $item->get_quantity(),
'tax_class' => $item->get_tax_class(),
'name' => $item->get_name(),
'product_id' => $item->get_variation_id() ? $item->get_variation_id() : $item->get_product_id(),

View File

@ -1177,8 +1177,8 @@ class WC_API_Products extends WC_API_Resource {
'upsell_ids' => array_map( 'absint', $product->get_upsell_ids() ),
'cross_sell_ids' => array_map( 'absint', $product->get_cross_sell_ids() ),
'parent_id' => $product->get_parent_id(),
'categories' => wp_get_post_terms( $product->get_id(), 'product_cat', array( 'fields' => 'names' ) ),
'tags' => wp_get_post_terms( $product->get_id(), 'product_tag', array( 'fields' => 'names' ) ),
'categories' => wc_get_object_terms( $product->get_id(), 'product_cat', 'name' ),
'tags' => wc_get_object_terms( $product->get_id(), 'product_tag', 'name' ),
'images' => $this->get_images( $product ),
'featured_src' => wp_get_attachment_url( get_post_thumbnail_id( $product->get_id() ) ),
'attributes' => $this->get_attributes( $product ),
@ -1976,9 +1976,10 @@ class WC_API_Products extends WC_API_Resource {
// Shipping class
if ( isset( $data['shipping_class'] ) ) {
$shipping_class_term = get_term_by( 'slug', wc_clean( $data['shipping_class'] ), 'product_shipping_class' );
if ( $shipping_class_term ) {
$product->set_shipping_class_id( $shipping_class_term->term_id );
$data_store = $product->get_data_store();
$shipping_class_id = $data_store->get_shipping_class_id_by_slug( wc_clean( $data['shipping_class'] ) );
if ( $shipping_class_id ) {
$product->set_shipping_class_id( $shipping_class_id );
}
}
@ -2340,7 +2341,7 @@ class WC_API_Products extends WC_API_Resource {
*/
protected function get_attribute_options( $product_id, $attribute ) {
if ( isset( $attribute['is_taxonomy'] ) && $attribute['is_taxonomy'] ) {
return wc_get_product_terms( $product_id, $attribute['name'], array( 'fields' => 'names' ) );
return wc_get_object_terms( $product_id, $attribute['name'], 'name' );
} elseif ( isset( $attribute['value'] ) ) {
return array_map( 'trim', explode( '|', $attribute['value'] ) );
}

View File

@ -662,7 +662,7 @@ class WC_AJAX {
$attribute_field_name = 'attribute_' . sanitize_title( $attribute->get_name() );
if ( $attribute->is_taxonomy() ) {
$options = wc_get_product_terms( $post_id, $attribute->get_name(), array( 'fields' => 'slugs' ) );
$options = wc_get_object_terms( $post_id, $attribute->get_name(), 'slug' );
} else {
$options = $attribute->get_options();
}

View File

@ -2043,6 +2043,7 @@ class WC_Cart {
/**
* Gets the cart contents total (after calculation).
*
* @todo deprecate? It's unused.
* @return string formatted price
*/
public function get_cart_total() {

View File

@ -258,10 +258,11 @@ class WC_Comments {
}
/**
* Remove order notes from wp_count_comments().
* Remove order notes and webhook delivery logs from wp_count_comments().
*
* @since 2.2
* @param object $stats
* @param int $post_id
* @param object $stats Comment stats.
* @param int $post_id Post ID.
* @return object
*/
public static function wp_count_comments( $stats, $post_id ) {
@ -273,14 +274,25 @@ class WC_Comments {
if ( ! $stats ) {
$stats = array();
$count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} WHERE comment_type != 'order_note' GROUP BY comment_approved", ARRAY_A );
$count = $wpdb->get_results( "
SELECT comment_approved, COUNT(*) AS num_comments
FROM {$wpdb->comments}
WHERE comment_type NOT IN ('order_note', 'webhook_delivery')
GROUP BY comment_approved
", ARRAY_A );
$total = 0;
$approved = array( '0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed' );
$approved = array(
'0' => 'moderated',
'1' => 'approved',
'spam' => 'spam',
'trash' => 'trash',
'post-trashed' => 'post-trashed',
);
foreach ( (array) $count as $row ) {
// Don't count post-trashed toward totals
if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] ) {
// Don't count post-trashed toward totals.
if ( 'post-trashed' !== $row['comment_approved'] && 'trash' !== $row['comment_approved'] ) {
$total += $row['num_comments'];
}
if ( isset( $approved[ $row['comment_approved'] ] ) ) {

View File

@ -98,19 +98,24 @@ class WC_Countries {
'EE' => array(),
'FI' => array(),
'FR' => array(),
'GP' => array(),
'GF' => array(),
'IS' => array(),
'IL' => array(),
'KR' => array(),
'MQ' => array(),
'NL' => array(),
'NO' => array(),
'PL' => array(),
'PT' => array(),
'RE' => array(),
'SG' => array(),
'SK' => array(),
'SI' => array(),
'LK' => array(),
'SE' => array(),
'VN' => array(),
'YT' => array(),
);
// Load only the state files the shop owner wants/needs.

View File

@ -181,7 +181,7 @@ class WC_Frontend_Scripts {
// Password strength meter.
// Load in checkout, account login and edit account page.
if ( ( 'no' === get_option( 'woocommerce_registration_generate_password' ) && ! is_user_logged_in() ) || is_edit_account_page() ) {
if ( ( 'no' === get_option( 'woocommerce_registration_generate_password' ) && ! is_user_logged_in() ) || is_edit_account_page() || is_lost_password_page() ) {
self::enqueue_script( 'wc-password-strength-meter' );
}
}

View File

@ -352,7 +352,7 @@ class WC_Product_Variable extends WC_Product {
// Otherwise revert to status the children have.
} else {
$this->set_stock_status( $product->child_is_in_stock() ? 'instock' : 'outofstock' );
$this->set_stock_status( $this->child_is_in_stock() ? 'instock' : 'outofstock' );
}
}

View File

@ -631,32 +631,7 @@ class WC_Query {
public static function get_main_tax_query() {
global $wp_the_query;
$args = $wp_the_query->query_vars;
$tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
if ( ! empty( $args['taxonomy'] ) && ! empty( $args['term'] ) ) {
$tax_query[ $args['taxonomy'] ] = array(
'taxonomy' => $args['taxonomy'],
'terms' => array( $args['term'] ),
'field' => 'slug',
);
}
if ( ! empty( $args['product_cat'] ) ) {
$tax_query['product_cat'] = array(
'taxonomy' => 'product_cat',
'terms' => array( $args['product_cat'] ),
'field' => 'slug',
);
}
if ( ! empty( $args['product_tag'] ) ) {
$tax_query['product_tag'] = array(
'taxonomy' => 'product_tag',
'terms' => array( $args['product_tag'] ),
'field' => 'slug',
);
}
$tax_query = isset( $wp_the_query->tax_query, $wp_the_query->tax_query->queries ) ? $wp_the_query->tax_query->queries : array();
return $tax_query;
}

View File

@ -139,21 +139,11 @@ class WC_Tracker {
* @return array
*/
public static function get_theme_info() {
$wp_version = get_bloginfo( 'version' );
if ( version_compare( $wp_version, '3.4', '<' ) ) {
$theme_data = get_theme_data( get_stylesheet_directory() . '/style.css' );
$theme_name = $theme_data['Name'];
$theme_version = $theme_data['Version'];
} else {
$theme_data = wp_get_theme();
$theme_name = $theme_data->Name;
$theme_version = $theme_data->Version;
}
$theme_data = wp_get_theme();
$theme_child_theme = is_child_theme() ? 'Yes' : 'No';
$theme_wc_support = ( ! current_theme_supports( 'woocommerce' ) && ! in_array( $theme_data->template, wc_get_core_supported_themes() ) ) ? 'No' : 'Yes';
$theme_wc_support = ( ! current_theme_supports( 'woocommerce' ) && ! in_array( $theme_data->template, wc_get_core_supported_themes() ) ) ? 'No' : 'Yes';
return array( 'name' => $theme_name, 'version' => $theme_version, 'child_theme' => $theme_child_theme, 'wc_support' => $theme_wc_support );
return array( 'name' => $theme_data->Name, 'version' => $theme_data->Version, 'child_theme' => $theme_child_theme, 'wc_support' => $theme_wc_support );
}
/**

View File

@ -821,8 +821,8 @@ class WC_CLI_Product extends WC_CLI_Command {
'upsell_ids' => implode( ', ', $product->get_upsells() ),
'cross_sell_ids' => implode( ', ', $product->get_cross_sells() ),
'parent_id' => $product->post->post_parent,
'categories' => implode( ', ', wp_get_post_terms( $product->get_id(), 'product_cat', array( 'fields' => 'names' ) ) ),
'tags' => implode( ', ', wp_get_post_terms( $product->get_id(), 'product_tag', array( 'fields' => 'names' ) ) ),
'categories' => implode( ', ', wc_get_object_terms( $product->get_id(), 'product_cat', 'name' ) ),
'tags' => implode( ', ', wc_get_object_terms( $product->get_id(), 'product_tag', 'name' ) ),
'images' => $this->get_images( $product ),
'featured_src' => wp_get_attachment_url( get_post_thumbnail_id( $product->is_type( 'variation' ) ? $product->variation_id : $product->get_id() ) ),
'attributes' => $this->get_attributes( $product ),

View File

@ -19,18 +19,21 @@ class WC_Customer_Data_Store implements WC_Customer_Data_Store_Interface, WC_Obj
* @param WC_Customer
*/
public function create( &$customer ) {
$customer_id = wc_create_new_customer( $customer->get_email(), $customer->get_username(), $customer->get_password() );
$id = wc_create_new_customer( $customer->get_email(), $customer->get_username(), $customer->get_password() );
if ( ! is_wp_error( $customer_id ) ) {
$customer->set_id( $customer_id );
$this->update_user_meta( $customer );
wp_update_user( array( 'ID' => $customer->get_id(), 'role' => $customer->get_role() ) );
$wp_user = new WP_User( $customer->get_id() );
$customer->set_date_created( strtotime( $wp_user->user_registered ) );
$customer->set_date_modified( get_user_meta( $customer->get_id(), 'last_update', true ) );
$customer->save_meta_data();
$customer->apply_changes();
if ( is_wp_error( $id ) ) {
throw new WC_Data_Exception( $id->get_error_code(), $id->get_error_message() );
}
$customer->set_id( $id );
$this->update_user_meta( $customer );
wp_update_user( array( 'ID' => $customer->get_id(), 'role' => $customer->get_role() ) );
$wp_user = new WP_User( $customer->get_id() );
$customer->set_date_created( strtotime( $wp_user->user_registered ) );
$customer->set_date_modified( get_user_meta( $customer->get_id(), 'last_update', true ) );
$customer->save_meta_data();
$customer->apply_changes();
do_action( 'woocommerce_new_customer', $customer->get_id() );
}
/**
@ -64,6 +67,7 @@ class WC_Customer_Data_Store implements WC_Customer_Data_Store_Interface, WC_Obj
) );
$customer->read_meta_data();
$customer->set_object_read( true );
do_action( 'woocommerce_customer_loaded', $customer );
}
/**
@ -83,6 +87,7 @@ class WC_Customer_Data_Store implements WC_Customer_Data_Store_Interface, WC_Obj
$customer->set_date_modified( get_user_meta( $customer->get_id(), 'last_update', true ) );
$customer->save_meta_data();
$customer->apply_changes();
do_action( 'woocommerce_update_customer', $customer->get_id() );
}
/**
@ -99,7 +104,11 @@ class WC_Customer_Data_Store implements WC_Customer_Data_Store_Interface, WC_Obj
$args = wp_parse_args( $args, array(
'reassign' => 0,
) );
return wp_delete_user( $customer->get_id(), $args['reassign'] );
$id = $customer->get_id();
wp_delete_user( $id, $args['reassign'] );
do_action( 'woocommerce_delete_customer', $id );
}
/**

View File

@ -244,7 +244,7 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Object_D
if ( ! taxonomy_exists( $meta_value['name'] ) ) {
continue;
}
$options = wp_get_post_terms( $product->get_id(), $meta_value['name'], array( 'fields' => 'ids' ) );
$options = wc_get_object_terms( $product->get_id(), $meta_value['name'], 'term_id' );
} else {
$options = wc_get_text_attributes( $meta_value['value'] );
}
@ -505,7 +505,7 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Object_D
// Update counts for the post's terms.
foreach ( (array) get_object_taxonomies( $post_type ) as $taxonomy ) {
$tt_ids = wp_get_object_terms( $product->get_id(), $taxonomy, array( 'fields' => 'tt_ids' ) );
$tt_ids = wc_get_object_terms( $product->get_id(), $taxonomy, 'term_taxonomy_id' );
wp_update_term_count( $tt_ids, $taxonomy );
}
}
@ -864,4 +864,121 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Object_D
update_post_meta( $product->get_id(), '_wc_rating_count', $product->get_rating_counts( 'edit' ) );
}
/**
* Get shipping class ID by slug.
*
* @since 2.7.0
* @param $slug string
* @return int|false
*/
public function get_shipping_class_id_by_slug( $slug ) {
$shipping_class_term = get_term_by( 'slug', $slug, 'product_shipping_class' );
if ( $shipping_class_term ) {
return $shipping_class_term->term_id;
} else {
return false;
}
}
/**
* Returns an array of products.
*
* @param array $args @see wc_get_products
* @return array
*/
public function get_products( $args = array() ) {
/**
* Generate WP_Query args.
*/
$wp_query_args = array(
'post_type' => 'variation' === $args['type'] ? 'product_variation' : 'product',
'post_status' => $args['status'],
'posts_per_page' => $args['limit'],
'meta_query' => array(),
'orderby' => $args['orderby'],
'order' => $args['order'],
'tax_query' => array(),
);
// Do not load unneccessary post data if the user only wants IDs.
if ( 'ids' === $args['return'] ) {
$wp_query_args['fields'] = 'ids';
}
if ( 'variation' !== $args['type'] ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => $args['type'],
);
}
if ( ! empty( $args['sku'] ) ) {
$wp_query_args['meta_query'][] = array(
'key' => '_sku',
'value' => $args['sku'],
'compare' => 'LIKE',
);
}
if ( ! empty( $args['category'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $args['category'],
);
}
if ( ! empty( $args['tag'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_tag',
'field' => 'slug',
'terms' => $args['tag'],
);
}
if ( ! empty( $args['shipping_class'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_shipping_class',
'field' => 'slug',
'terms' => $args['shipping_class'],
);
}
if ( ! is_null( $args['parent'] ) ) {
$wp_query_args['post_parent'] = absint( $args['parent'] );
}
if ( ! is_null( $args['offset'] ) ) {
$wp_query_args['offset'] = absint( $args['offset'] );
} else {
$wp_query_args['paged'] = absint( $args['page'] );
}
if ( ! empty( $args['exclude'] ) ) {
$wp_query_args['post__not_in'] = array_map( 'absint', $args['exclude'] );
}
if ( ! $args['paginate'] ) {
$wp_query_args['no_found_rows'] = true;
}
// Get results.
$products = new WP_Query( $wp_query_args );
if ( 'objects' === $args['return'] ) {
$return = array_map( 'wc_get_product', $products->posts );
} else {
$return = $products->posts;
}
if ( $args['paginate'] ) {
return (object) array(
'products' => $return,
'total' => $products->found_posts,
'max_num_pages' => $products->max_num_pages,
);
} else {
return $return;
}
}
}

View File

@ -97,7 +97,7 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple
// Empty value indicates that all options for given attribute are available.
if ( in_array( '', $values ) || empty( $values ) ) {
$values = $attribute['is_taxonomy'] ? wp_get_post_terms( $product->get_id(), $attribute['name'], array( 'fields' => 'slugs' ) ) : wc_get_text_attributes( $attribute['value'] );
$values = $attribute['is_taxonomy'] ? wc_get_object_terms( $product->get_id(), $attribute['name'], 'slug' ) : wc_get_text_attributes( $attribute['value'] );
// Get custom attributes (non taxonomy) as defined.
} elseif ( ! $attribute['is_taxonomy'] ) {
$text_attributes = wc_get_text_attributes( $attribute['value'] );

View File

@ -93,4 +93,19 @@ interface WC_Product_Data_Store_Interface {
* @param string $operation set, increase and decrease.
*/
function update_product_stock( $product_id_with_stock, $stock_quantity = null, $operation = 'set' );
/**
* Get shipping class ID by slug.
* @param $slug string
* @return int|false
*/
public function get_shipping_class_id_by_slug( $slug );
/**
* Returns an array of products.
*
* @param array $args @see wc_get_products
* @return array
*/
public function get_products( $args = array() );
}

View File

@ -19,7 +19,7 @@ abstract class WC_Legacy_Shipping_Zone extends WC_Data {
* @deprecated 2.7
*/
public function get_zone_id() {
//wc_soft_deprecated_function( 'WC_Shipping_Zone::get_zone_id', '2.7', '2.8', 'WC_Shipping_Zone::get_id' );
// wc_soft_deprecated_function( 'WC_Shipping_Zone::get_zone_id', '2.7', '2.8', 'WC_Shipping_Zone::get_id' );
return $this->get_id();
}
@ -28,7 +28,7 @@ abstract class WC_Legacy_Shipping_Zone extends WC_Data {
* @deprecated 2.7.0 - Init a shipping zone with an ID.
*/
public function read( $zone_id ) {
//wc_soft_deprecated_function( 'WC_Shipping_Zone::read', '2.7', '2.8', 'Init a shipping zone with an ID.' );
// wc_soft_deprecated_function( 'WC_Shipping_Zone::read', '2.7', '2.8', 'Init a shipping zone with an ID.' );
$this->set_id( $zone_id );
$data_store = WC_Data_Store::load( 'shipping-zone' );
$data_store->read( $this );
@ -39,7 +39,7 @@ abstract class WC_Legacy_Shipping_Zone extends WC_Data {
* @deprecated 2.7.0 - Use ::save instead.
*/
public function update() {
//wc_soft_deprecated_function( 'WC_Shipping_Zone::update', '2.7', '2.8', 'Use ::save instead.' );
// wc_soft_deprecated_function( 'WC_Shipping_Zone::update', '2.7', '2.8', 'Use ::save instead.' );
$data_store = WC_Data_Store::load( 'shipping-zone' );
try {
$data_store->update( $this );
@ -53,7 +53,7 @@ abstract class WC_Legacy_Shipping_Zone extends WC_Data {
* @deprecated 2.7.0 - Use ::save instead.
*/
public function create() {
//wc_soft_deprecated_function( 'WC_Shipping_Zone::create', '2.7', '2.8', 'Use ::save instead.' );
// wc_soft_deprecated_function( 'WC_Shipping_Zone::create', '2.7', '2.8', 'Use ::save instead.' );
$data_store = WC_Data_Store::load( 'shipping-zone' );
try {
$data_store->create( $this );

View File

@ -24,9 +24,13 @@ if ( ! defined( 'ABSPATH' ) ) {
* status array|string List of statuses to find. Default: any. Options: any, draft, pending, private and publish.
* type array|string Product type, e.g. Default: all. Options: all, simple, external, variable, variation, grouped.
* parent int post/product parent
* skus array Limit result set to products with specific SKUs.
* categories array Limit result set to products assigned a specific category, e.g. 9,14.
* tags array Limit result set to products assigned a specific tag, e.g. 9,14.
* sku string Limit result set to products with specific SKU.
* category array Limit result set to products assigned to specific categories by slug
* e.g. array('hoodie', 'cap', 't-shirt').
* tag array Limit result set to products assigned to specific tags (by slug)
* e.g. array('funky', 'retro', 'designer')
* shipping_class array Limit results set to products in specific shipping classes (by slug)
* e.g. array('standard', 'next-day')
* limit int Maximum of products to retrieve.
* offset int Offset of products to retrieve.
* page int Page of products to retrieve. Ignored when using the 'offset' arg.
@ -80,99 +84,7 @@ function wc_get_products( $args ) {
}
}
/**
* Generate WP_Query args.
*/
$wp_query_args = array(
'post_type' => 'variation' === $args['type'] ? 'product_variation' : 'product',
'post_status' => $args['status'],
'posts_per_page' => $args['limit'],
'meta_query' => array(),
'orderby' => $args['orderby'],
'order' => $args['order'],
'tax_query' => array(),
);
// Do not load unneccessary post data if the user only wants IDs.
if ( 'ids' === $args['return'] ) {
$wp_query_args['fields'] = 'ids';
}
if ( 'variation' !== $args['type'] ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => $args['type'],
);
}
if ( ! empty( $args['sku'] ) ) {
$wp_query_args['meta_query'][] = array(
'key' => '_sku',
'value' => $args['sku'],
'compare' => 'LIKE',
);
}
if ( ! empty( $args['category'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $args['category'],
);
}
if ( ! empty( $args['tag'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_tag',
'field' => 'slug',
'terms' => $args['tag'],
);
}
if ( ! empty( $args['shipping_class'] ) ) {
$wp_query_args['tax_query'][] = array(
'taxonomy' => 'product_shipping_class',
'field' => 'slug',
'terms' => $args['shipping_class'],
);
}
if ( ! is_null( $args['parent'] ) ) {
$wp_query_args['post_parent'] = absint( $args['parent'] );
}
if ( ! is_null( $args['offset'] ) ) {
$wp_query_args['offset'] = absint( $args['offset'] );
} else {
$wp_query_args['paged'] = absint( $args['page'] );
}
if ( ! empty( $args['exclude'] ) ) {
$wp_query_args['post__not_in'] = array_map( 'absint', $args['exclude'] );
}
if ( ! $args['paginate'] ) {
$wp_query_args['no_found_rows'] = true;
}
// Get results.
$products = new WP_Query( $wp_query_args );
if ( 'objects' === $args['return'] ) {
$return = array_map( 'wc_get_product', $products->posts );
} else {
$return = $products->posts;
}
if ( $args['paginate'] ) {
return (object) array(
'products' => $return,
'total' => $products->found_posts,
'max_num_pages' => $products->max_num_pages,
);
} else {
return $return;
}
return WC_Data_Store::load( 'product' )->get_products( $args );
}
/**

View File

@ -2184,7 +2184,7 @@ 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_object_terms( $product->get_id(), $attribute );
foreach ( $terms as $term ) {
if ( in_array( $term->slug, $options ) ) {

View File

@ -14,15 +14,67 @@ if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Helper to get cached object terms and filter by field using wp_list_pluck().
* Works as a cached alternative for wp_get_post_terms() and wp_get_object_terms().
*
* @since 2.7.0
* @param int $object_id Object ID.
* @param string $taxonomy Taxonomy slug.
* @param string $field Field name.
* @param string $index_key Index key name.
* @return array
*/
function wc_get_object_terms( $object_id, $taxonomy, $field = null, $index_key = null ) {
// Test if terms exists.
// get_the_terms() return false when don't found terms.
if ( $terms = get_the_terms( $object_id, $taxonomy ) ) {
if ( ! is_null( $field ) ) {
$terms = wp_list_pluck( $terms, $field, $index_key );
}
} else {
$terms = array();
}
return $terms;
}
/**
* Cached version of wp_get_post_terms().
* This is a private function (internal use ONLY).
*
* @since 2.7.0
* @param int $product_id Product ID.
* @param string $taxonomy Taxonomy slug.
* @param array $args Query arguments.
* @return array
*/
function _wc_get_cached_product_terms( $product_id, $taxonomy, $args = array() ) {
$cache_key = 'wc_' . $taxonomy . md5( json_encode( $args ) );
$terms = wp_cache_get( $product_id, $cache_key );
if ( false !== $terms ) {
return $terms;
}
// @codingStandardsIgnoreStart
$terms = wp_get_post_terms( $product_id, $taxonomy, $args );
// @codingStandardsIgnoreEnd
wp_cache_add( $product_id, $terms, $cache_key );
return $terms;
}
/**
* Wrapper for wp_get_post_terms which supports ordering by parent.
*
* NOTE: At this point in time, ordering by menu_order for example isn't possible with this function. wp_get_post_terms has no.
* filters which we can utilise to modify it's query. https://core.trac.wordpress.org/ticket/19094.
*
* @param int $product_id
* @param string $taxonomy
* @param array $args
* @param int $product_id Product ID.
* @param string $taxonomy Taxonomy slug.
* @param array $args Query arguments.
* @return array
*/
function wc_get_product_terms( $product_id, $taxonomy, $args = array() ) {
@ -34,16 +86,16 @@ function wc_get_product_terms( $product_id, $taxonomy, $args = array() ) {
$args['orderby'] = wc_attribute_orderby( $taxonomy );
}
// Support ordering by parent
// Support ordering by parent.
if ( ! empty( $args['orderby'] ) && in_array( $args['orderby'], array( 'name_num', 'parent' ) ) ) {
$fields = isset( $args['fields'] ) ? $args['fields'] : 'all';
$orderby = $args['orderby'];
// Unset for wp_get_post_terms
// Unset for wp_get_post_terms.
unset( $args['orderby'] );
unset( $args['fields'] );
$terms = wp_get_post_terms( $product_id, $taxonomy, $args );
$terms = _wc_get_cached_product_terms( $product_id, $taxonomy, $args );
switch ( $orderby ) {
case 'name_num' :
@ -66,26 +118,26 @@ function wc_get_product_terms( $product_id, $taxonomy, $args = array() ) {
break;
}
} elseif ( ! empty( $args['orderby'] ) && 'menu_order' === $args['orderby'] ) {
// wp_get_post_terms doesn't let us use custom sort order
$args['include'] = wp_get_post_terms( $product_id, $taxonomy, array( 'fields' => 'ids' ) );
// wp_get_post_terms doesn't let us use custom sort order.
$args['include'] = wc_get_object_terms( $product_id, $taxonomy, 'id' );
if ( empty( $args['include'] ) ) {
$terms = array();
} else {
// This isn't needed for get_terms
// This isn't needed for get_terms.
unset( $args['orderby'] );
// Set args for get_terms
// Set args for get_terms.
$args['menu_order'] = isset( $args['order'] ) ? $args['order'] : 'ASC';
$args['hide_empty'] = isset( $args['hide_empty'] ) ? $args['hide_empty'] : 0;
$args['fields'] = isset( $args['fields'] ) ? $args['fields'] : 'names';
// Ensure slugs is valid for get_terms - slugs isn't supported
// Ensure slugs is valid for get_terms - slugs isn't supported.
$args['fields'] = ( 'slugs' === $args['fields'] ) ? 'id=>slug' : $args['fields'];
$terms = get_terms( $taxonomy, $args );
}
} else {
$terms = wp_get_post_terms( $product_id, $taxonomy, $args );
$terms = _wc_get_cached_product_terms( $product_id, $taxonomy, $args );
}
return apply_filters( 'woocommerce_get_product_terms' , $terms, $product_id, $taxonomy, $args );

View File

@ -34,11 +34,77 @@ class WC_Widget_Layered_Nav_Filters extends WC_Widget {
parent::__construct();
}
/**
* Get current page URL for layered nav items.
*
* @return string
*/
protected function get_page_base_url() {
if ( defined( 'SHOP_IS_ON_FRONT' ) ) {
$link = home_url();
} elseif ( is_post_type_archive( 'product' ) || is_page( wc_get_page_id( 'shop' ) ) ) {
$link = get_post_type_archive_link( 'product' );
} elseif ( is_product_category() ) {
$link = get_term_link( get_query_var( 'product_cat' ), 'product_cat' );
} elseif ( is_product_tag() ) {
$link = get_term_link( get_query_var( 'product_tag' ), 'product_tag' );
} else {
$queried_object = get_queried_object();
$link = get_term_link( $queried_object->slug, $queried_object->taxonomy );
}
// Min/Max
if ( isset( $_GET['min_price'] ) ) {
$link = add_query_arg( 'min_price', wc_clean( $_GET['min_price'] ), $link );
}
if ( isset( $_GET['max_price'] ) ) {
$link = add_query_arg( 'max_price', wc_clean( $_GET['max_price'] ), $link );
}
// Orderby
if ( isset( $_GET['orderby'] ) ) {
$link = add_query_arg( 'orderby', wc_clean( $_GET['orderby'] ), $link );
}
/**
* Search Arg.
* To support quote characters, first they are decoded from &quot; entities, then URL encoded.
*/
if ( get_search_query() ) {
$link = add_query_arg( 's', rawurlencode( htmlspecialchars_decode( get_search_query() ) ), $link );
}
// Post Type Arg
if ( isset( $_GET['post_type'] ) ) {
$link = add_query_arg( 'post_type', wc_clean( $_GET['post_type'] ), $link );
}
// Min Rating Arg
if ( isset( $_GET['min_rating'] ) ) {
$link = add_query_arg( 'min_rating', wc_clean( $_GET['min_rating'] ), $link );
}
// All current filters
if ( $_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes() ) {
foreach ( $_chosen_attributes as $name => $data ) {
$filter_name = sanitize_title( str_replace( 'pa_', '', $name ) );
if ( ! empty( $data['terms'] ) ) {
$link = add_query_arg( 'filter_' . $filter_name, implode( ',', $data['terms'] ), $link );
}
if ( 'or' == $data['query_type'] ) {
$link = add_query_arg( 'query_type_' . $filter_name, 'or', $link );
}
}
}
return $link;
}
/**
* Output widget.
*
* @see WP_Widget
*
* @param array $args
* @param array $instance
*/
@ -48,9 +114,10 @@ class WC_Widget_Layered_Nav_Filters extends WC_Widget {
}
$_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes();
$min_price = isset( $_GET['min_price'] ) ? wc_clean( $_GET['min_price'] ) : 0;
$max_price = isset( $_GET['max_price'] ) ? wc_clean( $_GET['max_price'] ) : 0;
$min_price = isset( $_GET['min_price'] ) ? wc_clean( $_GET['min_price'] ) : 0;
$max_price = isset( $_GET['max_price'] ) ? wc_clean( $_GET['max_price'] ) : 0;
$min_rating = isset( $_GET['min_rating'] ) ? absint( $_GET['min_rating'] ) : 0;
$base_link = $this->get_page_base_url();
if ( 0 < count( $_chosen_attributes ) || 0 < $min_price || 0 < $max_price || 0 < $min_rating ) {
@ -71,7 +138,7 @@ class WC_Widget_Layered_Nav_Filters extends WC_Widget {
$current_filter = array_map( 'sanitize_title', $current_filter );
$new_filter = array_diff( $current_filter, array( $term_slug ) );
$link = remove_query_arg( array( 'add-to-cart', $filter_name ) );
$link = remove_query_arg( array( 'add-to-cart', $filter_name ), $base_link );
if ( sizeof( $new_filter ) > 0 ) {
$link = add_query_arg( $filter_name, implode( ',', $new_filter ), $link );
@ -83,17 +150,17 @@ class WC_Widget_Layered_Nav_Filters extends WC_Widget {
}
if ( $min_price ) {
$link = remove_query_arg( 'min_price' );
$link = remove_query_arg( 'min_price', $base_link );
echo '<li class="chosen"><a aria-label="' . esc_attr__( 'Remove filter', 'woocommerce' ) . '" href="' . esc_url( $link ) . '">' . sprintf( __( 'Min %s', 'woocommerce' ), wc_price( $min_price ) ) . '</a></li>';
}
if ( $max_price ) {
$link = remove_query_arg( 'max_price' );
$link = remove_query_arg( 'max_price', $base_link );
echo '<li class="chosen"><a aria-label="' . esc_attr__( 'Remove filter', 'woocommerce' ) . '" href="' . esc_url( $link ) . '">' . sprintf( __( 'Max %s', 'woocommerce' ), wc_price( $max_price ) ) . '</a></li>';
}
if ( $min_rating ) {
$link = remove_query_arg( 'min_rating' );
$link = remove_query_arg( 'min_rating', $base_link );
echo '<li class="chosen"><a aria-label="' . esc_attr__( 'Remove filter', 'woocommerce' ) . '" href="' . esc_url( $link ) . '">' . sprintf( __( 'Rated %s and above', 'woocommerce' ), $min_rating ) . '</a></li>';
}

View File

@ -154,7 +154,7 @@
<exclude name="WordPress.VIP.RestrictedFunctions.urlencode" />
<exclude name="WordPress.VIP.RestrictedFunctions.url_to_postid" />
<exclude name="WordPress.VIP.RestrictedFunctions.user_meta" />
<exclude name="WordPress.VIP.RestrictedFunctions.wp_get_post_terms" />
<!-- <exclude name="WordPress.VIP.RestrictedFunctions.wp_get_post_terms" /> -->
<exclude name="WordPress.VIP.RestrictedFunctions.wp_redirect" />
<exclude name="WordPress.VIP.RestrictedFunctions.wp_remote_get" />
<exclude name="WordPress.VIP.RestrictedVariables.user_meta" />

View File

@ -49,7 +49,9 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php if ( $checkout->enable_guest_checkout ) : ?>
<p class="form-row form-row-wide create-account">
<input class="input-checkbox" id="createaccount" <?php checked( ( true === $checkout->get_value( 'createaccount' ) || ( true === apply_filters( 'woocommerce_create_account_default_checked', false ) ) ), true ) ?> type="checkbox" name="createaccount" value="1" /> <label for="createaccount" class="checkbox"><?php _e( 'Create an account?', 'woocommerce' ); ?></label>
<label class="woocommerce-form__label woocommerce-form__label--for-checkbox checkbox">
<input class="woocommerce-form__input woocommerce-form__input--checkbox input-checkbox" id="createaccount" <?php checked( ( true === $checkout->get_value( 'createaccount' ) || ( true === apply_filters( 'woocommerce_create_account_default_checked', false ) ) ), true ) ?> type="checkbox" name="createaccount" value="1" /> <span><?php _e( 'Create an account?', 'woocommerce' ); ?></span>
</label>
</p>
<?php endif; ?>

View File

@ -25,8 +25,9 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php if ( true === WC()->cart->needs_shipping_address() ) : ?>
<h3 id="ship-to-different-address">
<label for="ship-to-different-address-checkbox" class="checkbox"><?php _e( 'Ship to a different address?', 'woocommerce' ); ?></label>
<input id="ship-to-different-address-checkbox" class="input-checkbox" <?php checked( apply_filters( 'woocommerce_ship_to_different_address_checked', 'shipping' === get_option( 'woocommerce_ship_to_destination' ) ? 1 : 0 ), 1 ); ?> type="checkbox" name="ship_to_different_address" value="1" />
<label class="woocommerce-form__label woocommerce-form__label--for-checkbox checkbox">
<input id="ship-to-different-address-checkbox" class="woocommerce-form__input woocommerce-form__input--checkbox input-checkbox" <?php checked( apply_filters( 'woocommerce_ship_to_different_address_checked', 'shipping' === get_option( 'woocommerce_ship_to_destination' ) ? 1 : 0 ), 1 ); ?> type="checkbox" name="ship_to_different_address" value="1" /> <span><?php _e( 'Ship to a different address?', 'woocommerce' ); ?></span>
</label>
</h3>
<div class="shipping_address">

View File

@ -13,8 +13,9 @@ if ( ! defined( 'ABSPATH' ) ) {
if ( wc_get_page_id( 'terms' ) > 0 && apply_filters( 'woocommerce_checkout_show_terms', true ) ) : ?>
<?php do_action( 'woocommerce_checkout_before_terms_and_conditions' ); ?>
<p class="form-row terms wc-terms-and-conditions">
<input type="checkbox" class="input-checkbox" name="terms" <?php checked( apply_filters( 'woocommerce_terms_is_checked_default', isset( $_POST['terms'] ) ), true ); ?> id="terms" />
<label for="terms" class="checkbox"><?php printf( __( 'I&rsquo;ve read and accept the <a href="%s" target="_blank">terms &amp; conditions</a>', 'woocommerce' ), esc_url( wc_get_page_permalink( 'terms' ) ) ); ?> <span class="required">*</span></label>
<label class="woocommerce-form__label woocommerce-form__label--for-checkbox checkbox">
<input type="checkbox" class="woocommerce-form__input woocommerce-form__input--checkbox input-checkbox" name="terms" <?php checked( apply_filters( 'woocommerce_terms_is_checked_default', isset( $_POST['terms'] ) ), true ); ?> id="terms" /> <span><?php printf( __( 'I&rsquo;ve read and accept the <a href="%s" target="_blank">terms &amp; conditions</a>', 'woocommerce' ), esc_url( wc_get_page_permalink( 'terms' ) ) ); ?></span> <span class="required">*</span>
</label>
<input type="hidden" name="terms-field" value="1" />
</p>
<?php do_action( 'woocommerce_checkout_after_terms_and_conditions' ); ?>

View File

@ -25,7 +25,7 @@ if ( is_user_logged_in() ) {
}
?>
<form method="post" class="login" <?php if ( $hidden ) echo 'style="display:none;"'; ?>>
<form class="woocomerce-form woocommerce-form--login" method="post" class="login" <?php if ( $hidden ) echo 'style="display:none;"'; ?>>
<?php do_action( 'woocommerce_login_form_start' ); ?>
@ -47,8 +47,8 @@ if ( is_user_logged_in() ) {
<?php wp_nonce_field( 'woocommerce-login' ); ?>
<input type="submit" class="button" name="login" value="<?php esc_attr_e( 'Login', 'woocommerce' ); ?>" />
<input type="hidden" name="redirect" value="<?php echo esc_url( $redirect ) ?>" />
<label for="rememberme" class="inline">
<input name="rememberme" type="checkbox" id="rememberme" value="forever" /> <?php _e( 'Remember me', 'woocommerce' ); ?>
<label class="woocommerce-form__label woocommerce-form__label--for-checkbox inline">
<input class="woocommerce-form__input woocommerce-form__input--checkbox" name="rememberme" type="checkbox" id="rememberme" value="forever" /> <span><?php _e( 'Remember me', 'woocommerce' ); ?></span>
</label>
</p>
<p class="lost_password">

View File

@ -26,17 +26,17 @@ do_action( 'woocommerce_before_edit_account_form' ); ?>
<?php do_action( 'woocommerce_edit_account_form_start' ); ?>
<p class="woocommerce-FormRow woocommerce-FormRow--first form-row form-row-first">
<p class="woocommerce-form-row woocommerce-form-row--first form-row form-row-first">
<label for="account_first_name"><?php _e( 'First name', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="account_first_name" id="account_first_name" value="<?php echo esc_attr( $user->first_name ); ?>" />
</p>
<p class="woocommerce-FormRow woocommerce-FormRow--last form-row form-row-last">
<p class="woocommerce-form-row woocommerce-form-row--last form-row form-row-last">
<label for="account_last_name"><?php _e( 'Last name', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="account_last_name" id="account_last_name" value="<?php echo esc_attr( $user->last_name ); ?>" />
</p>
<div class="clear"></div>
<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="account_email"><?php _e( 'Email address', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="email" class="woocommerce-Input woocommerce-Input--email input-text" name="account_email" id="account_email" value="<?php echo esc_attr( $user->user_email ); ?>" />
</p>
@ -44,15 +44,15 @@ do_action( 'woocommerce_before_edit_account_form' ); ?>
<fieldset>
<legend><?php _e( 'Password change', 'woocommerce' ); ?></legend>
<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="password_current"><?php _e( 'Current password (leave blank to leave unchanged)', 'woocommerce' ); ?></label>
<input type="password" class="woocommerce-Input woocommerce-Input--password input-text" name="password_current" id="password_current" />
</p>
<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="password_1"><?php _e( 'New password (leave blank to leave unchanged)', 'woocommerce' ); ?></label>
<input type="password" class="woocommerce-Input woocommerce-Input--password input-text" name="password_1" id="password_1" />
</p>
<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="password_2"><?php _e( 'Confirm new password', 'woocommerce' ); ?></label>
<input type="password" class="woocommerce-Input woocommerce-Input--password input-text" name="password_2" id="password_2" />
</p>

View File

@ -36,15 +36,15 @@ if ( ! defined( 'ABSPATH' ) ) {
<h2><?php _e( 'Login', 'woocommerce' ); ?></h2>
<form method="post" class="login">
<form class="woocomerce-form woocommerce-form--login" method="post" class="login">
<?php do_action( 'woocommerce_login_form_start' ); ?>
<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="username"><?php _e( 'Username or email address', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="username" id="username" value="<?php if ( ! empty( $_POST['username'] ) ) echo esc_attr( $_POST['username'] ); ?>" />
</p>
<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="password"><?php _e( 'Password', 'woocommerce' ); ?> <span class="required">*</span></label>
<input class="woocommerce-Input woocommerce-Input--text input-text" type="password" name="password" id="password" />
</p>
@ -54,8 +54,8 @@ if ( ! defined( 'ABSPATH' ) ) {
<p class="form-row">
<?php wp_nonce_field( 'woocommerce-login', 'woocommerce-login-nonce' ); ?>
<input type="submit" class="woocommerce-Button button" name="login" value="<?php esc_attr_e( 'Login', 'woocommerce' ); ?>" />
<label for="rememberme" class="inline">
<input class="woocommerce-Input woocommerce-Input--checkbox" name="rememberme" type="checkbox" id="rememberme" value="forever" /> <?php _e( 'Remember me', 'woocommerce' ); ?>
<label class="woocommerce-form__label woocommerce-form__label--for-checkbox inline">
<input class="woocommerce-form__input woocommerce-form__input--checkbox" name="rememberme" type="checkbox" id="rememberme" value="forever" /> <span><?php _e( 'Remember me', 'woocommerce' ); ?></span>
</label>
</p>
<p class="woocommerce-LostPassword lost_password">
@ -80,21 +80,21 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php if ( 'no' === get_option( 'woocommerce_registration_generate_username' ) ) : ?>
<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="reg_username"><?php _e( 'Username', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="text" class="woocommerce-Input woocommerce-Input--text input-text" name="username" id="reg_username" value="<?php if ( ! empty( $_POST['username'] ) ) echo esc_attr( $_POST['username'] ); ?>" />
</p>
<?php endif; ?>
<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="reg_email"><?php _e( 'Email address', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="email" class="woocommerce-Input woocommerce-Input--text input-text" name="email" id="reg_email" value="<?php if ( ! empty( $_POST['email'] ) ) echo esc_attr( $_POST['email'] ); ?>" />
</p>
<?php if ( 'no' === get_option( 'woocommerce_registration_generate_password' ) ) : ?>
<p class="woocommerce-FormRow woocommerce-FormRow--wide form-row form-row-wide">
<p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
<label for="reg_password"><?php _e( 'Password', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="password" class="woocommerce-Input woocommerce-Input--text input-text" name="password" id="reg_password" />
</p>

View File

@ -26,7 +26,7 @@ wc_print_notices(); ?>
<p><?php echo apply_filters( 'woocommerce_lost_password_message', __( 'Lost your password? Please enter your username or email address. You will receive a link to create a new password via email.', 'woocommerce' ) ); ?></p>
<p class="woocommerce-FormRow woocommerce-FormRow--first form-row form-row-first">
<p class="woocommerce-form-row woocommerce-form-row--first form-row form-row-first">
<label for="user_login"><?php _e( 'Username or email', 'woocommerce' ); ?></label>
<input class="woocommerce-Input woocommerce-Input--text input-text" type="text" name="user_login" id="user_login" />
</p>
@ -35,7 +35,7 @@ wc_print_notices(); ?>
<?php do_action( 'woocommerce_lostpassword_form' ); ?>
<p class="woocommerce-FormRow form-row">
<p class="woocommerce-form-row form-row">
<input type="hidden" name="wc_reset_password" value="true" />
<input type="submit" class="woocommerce-Button button" value="<?php esc_attr_e( 'Reset password', 'woocommerce' ); ?>" />
</p>

View File

@ -26,11 +26,11 @@ wc_print_notices(); ?>
<p><?php echo apply_filters( 'woocommerce_reset_password_message', __( 'Enter a new password below.', 'woocommerce' ) ); ?></p>
<p class="woocommerce-FormRow woocommerce-FormRow--first form-row form-row-first">
<p class="woocommerce-form-row woocommerce-form-row--first form-row form-row-first">
<label for="password_1"><?php _e( 'New password', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="password" class="woocommerce-Input woocommerce-Input--text input-text" name="password_1" id="password_1" />
</p>
<p class="woocommerce-FormRow woocommerce-FormRow--last form-row form-row-last">
<p class="woocommerce-form-row woocommerce-form-row--last form-row form-row-last">
<label for="password_2"><?php _e( 'Re-enter new password', 'woocommerce' ); ?> <span class="required">*</span></label>
<input type="password" class="woocommerce-Input woocommerce-Input--text input-text" name="password_2" id="password_2" />
</p>
@ -42,7 +42,7 @@ wc_print_notices(); ?>
<?php do_action( 'woocommerce_resetpassword_form' ); ?>
<p class="woocommerce-FormRow form-row">
<p class="woocommerce-form-row form-row">
<input type="hidden" name="wc_reset_password" value="true" />
<input type="submit" class="woocommerce-Button button" value="<?php esc_attr_e( 'Save', 'woocommerce' ); ?>" />
</p>

View File

@ -41,7 +41,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<tr>
<th><?php echo wc_attribute_label( $attribute->get_name() ); ?></th>
<td><?php
$values = $attribute->is_taxonomy() ? wc_get_product_terms( $product->get_id(), $attribute->get_name(), array( 'fields' => 'names' ) ) : $attribute->get_options();
$values = $attribute->is_taxonomy() ? wc_get_object_terms( $product->get_id(), $attribute->get_name(), 'name' ) : $attribute->get_options();
echo apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values );
?></td>
</tr>

View File

@ -316,4 +316,36 @@ class WC_Tests_Product_Data_Store extends WC_Unit_Test_Case {
$product->delete();
}
function test_varation_save_attributes() {
// Create a variable product with a color attribute.
$product = new WC_Product_Variable;
$attribute = new WC_Product_Attribute();
$attribute->set_id( 0 );
$attribute->set_name( 'color' );
$attribute->set_options( explode( WC_DELIMITER, 'green | red' ) );
$attribute->set_visible( true );
$attribute->set_variation( true );
$product->set_attributes( array( $attribute ) );
$product->save();
// Create a new variation with the color 'green'.
$variation = new WC_Product_Variation;
$variation->set_parent_id( $product->get_id() );
$variation->set_attributes( array( 'color' => 'green' ) );
$variation->set_status( 'private' );
$variation->save();
// Now update some value unrelated to attributes.
$variation = wc_get_product( $variation->get_id() );
$variation->set_status( 'publish' );
$variation->save();
// Load up the updated variation and verify that the saved state is correct.
$loaded_variation = wc_get_product( $variation->get_id() );
$this->assertEquals( 'publish', $loaded_variation->get_status( 'edit' ) );
$this->assertEquals( 'green', $loaded_variation->get_attributes( 'edit' )[ 'attribute_color' ] );
}
}