Conflicts from master
This commit is contained in:
commit
c18f6efeb4
|
@ -1,5 +1,77 @@
|
|||
== Changelog ==
|
||||
|
||||
= 2.6.8 - 10/11/16 =
|
||||
* Fix - REQUEST_URI was missing a trailing slash when being compared in the cache prevention functions.
|
||||
* Fix - Prevent issues when sending empty prices to PayPal.
|
||||
* Fix - Invalid email check.
|
||||
* Tweak - New extensions screen.
|
||||
|
||||
= 2.6.7 - 26/10/16 =
|
||||
* Fix - Use FLOOR and CEIL to get price filter values. Fixes the issue where max price is capped at 99.
|
||||
* Fix - Hide "Sales this month" information from Dashboard widget for users that don't have `view_woocommerce_reports` capability.
|
||||
* Fix - Remove notices only once on cart so subsequent notices do not remove older notices.
|
||||
* Tweak - Improve credit card fields for better mobile experience.
|
||||
|
||||
= 2.6.6 - 20/10/16 =
|
||||
* Fix - Conflict with Local Pickup Plus extension due to 2.7.x code in has_shipping_method().
|
||||
* Fix - Shipping method display order on frontend.
|
||||
|
||||
= 2.6.5 - 19/10/16 =
|
||||
* Fix - Shipping classes URL in admin.
|
||||
* Fix - Notice in reports when using custom date ranges.
|
||||
* Fix - When checking needs_shipping, ignore anything after : in the method ID.
|
||||
* Fix - Allow has_shipping_method to work with instances.
|
||||
* Fix - Potential notice in wc_add_to_cart_message().
|
||||
* Fix - Prevent notice in wpdb_table_fix if termmeta table is not used.
|
||||
* Fix - Payment method box fixes e.g. maintain previously selected payment method after update.
|
||||
* Fix - Prevent multiple password validation methods at once on my account page.
|
||||
* Fix - Ship to specific counties option had no effect.
|
||||
* Fix - Broken Webhook delivery due to use of post_date_gmt which does not exist for drafts.
|
||||
* Fix - Use method title in admin shipping dropdown.
|
||||
* Fix - Fixed downloadable variable product URL.
|
||||
* Fix - Handle object when generate_cart_id is used to prevent notices.
|
||||
* Fix - Set header link color in emails.
|
||||
* Fix - Rest of the world ID 0 zone handling when using CRUD classes.
|
||||
* Fix - Cast prices as decimal when querying prices in price filter widget.
|
||||
* Fix - API - Fix coupon description field.
|
||||
* Fix - API - ID needs to be capitalized to allow correct sorting.
|
||||
* Fix - API - Fixed undefined order ID.
|
||||
* Fix - API - Allow API to save refund reason.
|
||||
* Fix - API - Resolved encoding issues with attribute and variation slugs.
|
||||
* Fix - API - get_attributes should return term name, not slug.
|
||||
* Fix - API - Product "filter" and "sku" paramaters.
|
||||
* Fix - Handle info notices in cart, not just error messages.
|
||||
* Fix - Don't remove hyphens in attribute labels.
|
||||
* Fix - Start sales on variations after they are saved, if applicable.
|
||||
* Fix - Made the text showing max variations you can link match the actual filtered value.
|
||||
* Fix - Add missing tables to wpmu_drop_tables function.
|
||||
* Fix - When syncing variation stock, ensure post is a variation.
|
||||
* Fix - Resolved some sales by date sum issues.
|
||||
* Fix - Fix cart update in IE when enter key is pressed.
|
||||
* Fix - Variation is_on_backorder when parent manages stock.
|
||||
* Fix - Fix variation script malfunctioning when show_option_none arg is set to false.
|
||||
* Fix - Fire tokenisation event on load for pay page.
|
||||
* Fix - Populate attribute dropdown when empty.
|
||||
* Fix - Fix email check on my account page.
|
||||
* Fix - Send processing email on on-hold to processing transition.
|
||||
* Fix - Incompatibility with SQLite databases.
|
||||
* Fix - KGS and ISK currency symbols.
|
||||
* Tweak - Password reset now uses WP functions.
|
||||
* Tweak - Format US 9-digit postcodes.
|
||||
|
||||
= 2.6.4 - 26/07/16 =
|
||||
* Fix - Security - Only allow image MIME type upload via REST APIs.
|
||||
* Fix - Shipping method title display in COD settings.
|
||||
* Fix - Order date input in Edge browser.
|
||||
* Fix - Ensure value is not null in variations to support empty show_option_none setting.
|
||||
* Fix - get_the_title does not need escape in grouped template file.
|
||||
* Fix - Ensure WC_ROUNDING_PRECISION is defined and use it as a low precision boundary in wc_get_rounding_precision().
|
||||
* Fix - Response body should be a string in webhook class.
|
||||
* Fix - Use h2 instead of h3 headings in profile screen.
|
||||
* Dev - API - Allow Allow meta_key/value filters for products.
|
||||
* Dev - CLI - Explode tags and category IDs to allow multiple comma separated values.
|
||||
* Dev - add $order arg to woocommerce_admin_order_item_class and woocommerce_admin_html_order_item_class filters.
|
||||
|
||||
= 2.6.3 - 19/07/16 =
|
||||
* Fix - Security - Escape captions in product-thumbnail and product-image templates (template versions have been bumped).
|
||||
* Fix - Fixed how we calculate shipping tax rates when using more than one tax class.
|
||||
|
|
|
@ -64,13 +64,15 @@ jQuery( function( $ ) {
|
|||
*/
|
||||
var update_wc_div = function( html_str ) {
|
||||
var $html = $.parseHTML( html_str );
|
||||
var $new_form = $( '.shop_table.cart', $html ).closest( 'form' );
|
||||
var $new_form = $( '.woocommerce-cart-form', $html );
|
||||
var $new_totals = $( '.cart_totals', $html );
|
||||
var $notices = $( '.woocommerce-error, .woocommerce-message, .woocommerce-info', $html );
|
||||
|
||||
// Error message collection
|
||||
var $error = $( '.woocommerce-error', $html );
|
||||
var $message = $( '.woocommerce-message', $html );
|
||||
var $info = $( '.woocommerce-info', $html );
|
||||
// No form, cannot do this.
|
||||
if ( $( '.woocommerce-cart-form' ).length === 0 ) {
|
||||
window.location.href = window.location.href;
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove errors
|
||||
$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
|
||||
|
@ -78,23 +80,17 @@ jQuery( function( $ ) {
|
|||
if ( $new_form.length === 0 ) {
|
||||
// If the checkout is also displayed on this page, trigger reload instead.
|
||||
if ( $( '.woocommerce-checkout' ).length ) {
|
||||
window.location.reload();
|
||||
window.location.href = window.location.href;
|
||||
return;
|
||||
}
|
||||
|
||||
// No items to display now! Replace all cart content.
|
||||
var $cart_html = $( '.cart-empty', $html ).closest( '.woocommerce' );
|
||||
$( '.shop_table.cart' ).closest( '.woocommerce' ).replaceWith( $cart_html );
|
||||
$( '.woocommerce-cart-form__contents' ).closest( '.woocommerce' ).replaceWith( $cart_html );
|
||||
|
||||
// Display errors
|
||||
if ( $error.length > 0 ) {
|
||||
show_notice( $error, $( '.cart-empty' ).closest( '.woocommerce' ) );
|
||||
}
|
||||
if ( $message.length > 0 ) {
|
||||
show_notice( $message, $( '.cart-empty' ).closest( '.woocommerce' ) );
|
||||
}
|
||||
if ( $info.length > 0 ) {
|
||||
show_notice( $info, $( '.cart-empty' ).closest( '.woocommerce' ) );
|
||||
if ( $notices.length > 0 ) {
|
||||
show_notice( $notices, $( '.cart-empty' ).closest( '.woocommerce' ) );
|
||||
}
|
||||
} else {
|
||||
// If the checkout is also displayed on this page, trigger update event.
|
||||
|
@ -102,17 +98,11 @@ jQuery( function( $ ) {
|
|||
$( document.body ).trigger( 'update_checkout' );
|
||||
}
|
||||
|
||||
$( '.shop_table.cart' ).closest( 'form' ).replaceWith( $new_form );
|
||||
$( '.shop_table.cart' ).closest( 'form' ).find( 'input[name="update_cart"]' ).prop( 'disabled', true );
|
||||
$( '.woocommerce-cart-form' ).replaceWith( $new_form );
|
||||
$( '.woocommerce-cart-form' ).find( 'input[name="update_cart"]' ).prop( 'disabled', true );
|
||||
|
||||
if ( $error.length > 0 ) {
|
||||
show_notice( $error );
|
||||
}
|
||||
if ( $message.length > 0 ) {
|
||||
show_notice( $message );
|
||||
}
|
||||
if ( $info.length > 0 ) {
|
||||
show_notice( $info );
|
||||
if ( $notices.length > 0 ) {
|
||||
show_notice( $notices );
|
||||
}
|
||||
|
||||
update_cart_totals_div( $new_totals );
|
||||
|
@ -138,7 +128,7 @@ jQuery( function( $ ) {
|
|||
*/
|
||||
var show_notice = function( html_element, $target ) {
|
||||
if ( ! $target ) {
|
||||
$target = $( '.shop_table.cart' ).closest( 'form' );
|
||||
$target = $( '.woocommerce-cart-form' );
|
||||
}
|
||||
$target.before( html_element );
|
||||
};
|
||||
|
@ -280,15 +270,15 @@ jQuery( function( $ ) {
|
|||
this.update_cart );
|
||||
$( document ).on(
|
||||
'click',
|
||||
'div.woocommerce > form input[type=submit]',
|
||||
'.woocommerce-cart-form input[type=submit]',
|
||||
this.submit_click );
|
||||
$( document ).on(
|
||||
'keypress',
|
||||
'div.woocommerce > form input[type=number]',
|
||||
'.woocommerce-cart-form input[type=number]',
|
||||
this.input_keypress );
|
||||
$( document ).on(
|
||||
'submit',
|
||||
'div.woocommerce:not(.widget_product_search) > form',
|
||||
'.woocommerce-cart-form',
|
||||
this.cart_submit );
|
||||
$( document ).on(
|
||||
'click',
|
||||
|
@ -296,28 +286,28 @@ jQuery( function( $ ) {
|
|||
this.remove_coupon_clicked );
|
||||
$( document ).on(
|
||||
'click',
|
||||
'td.product-remove > a',
|
||||
'.woocommerce-cart-form .product-remove > a',
|
||||
this.item_remove_clicked );
|
||||
$( document ).on(
|
||||
'change input',
|
||||
'div.woocommerce > form .cart_item :input',
|
||||
'.woocommerce-cart-form .cart_item :input',
|
||||
this.input_changed );
|
||||
|
||||
$( 'div.woocommerce > form input[name="update_cart"]' ).prop( 'disabled', true );
|
||||
$( '.woocommerce-cart-form input[name="update_cart"]' ).prop( 'disabled', true );
|
||||
},
|
||||
|
||||
/**
|
||||
* After an input is changed, enable the update cart button.
|
||||
*/
|
||||
input_changed: function() {
|
||||
$( 'div.woocommerce > form input[name="update_cart"]' ).prop( 'disabled', false );
|
||||
$( '.woocommerce-cart-form input[name="update_cart"]' ).prop( 'disabled', false );
|
||||
},
|
||||
|
||||
/**
|
||||
* Update entire cart via ajax.
|
||||
*/
|
||||
update_cart: function() {
|
||||
var $form = $( '.shop_table.cart' ).closest( 'form' );
|
||||
var $form = $( '.woocommerce-cart-form' );
|
||||
|
||||
block( $form );
|
||||
block( $( 'div.cart_totals' ) );
|
||||
|
@ -391,7 +381,7 @@ jQuery( function( $ ) {
|
|||
$form = $( evt.currentTarget ).parents( 'form' );
|
||||
}
|
||||
|
||||
if ( 0 === $form.find( '.shop_table.cart' ).length ) {
|
||||
if ( 0 === $form.find( '.woocommerce-cart-form__contents' ).length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -399,11 +389,11 @@ jQuery( function( $ ) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if ( $clicked.is( '[name="update_cart"]' ) || $submit.is( 'input.qty' ) ) {
|
||||
if ( $clicked.is( 'input[name="update_cart"]' ) || $submit.is( 'input.qty' ) ) {
|
||||
evt.preventDefault();
|
||||
this.quantity_update( $form );
|
||||
|
||||
} else if ( $clicked.is( '[name="apply_coupon"]' ) || $submit.is( '#coupon_code' ) ) {
|
||||
} else if ( $clicked.is( 'input[name="apply_coupon"]' ) || $submit.is( '#coupon_code' ) ) {
|
||||
evt.preventDefault();
|
||||
this.apply_coupon( $form );
|
||||
}
|
||||
|
@ -463,10 +453,10 @@ jQuery( function( $ ) {
|
|||
evt.preventDefault();
|
||||
|
||||
var cart = this;
|
||||
var $tr = $( evt.currentTarget ).parents( 'tr' );
|
||||
var $wrapper = $( evt.currentTarget ).closest( '.cart_totals' );
|
||||
var coupon = $( evt.currentTarget ).attr( 'data-coupon' );
|
||||
|
||||
block( $tr.parents( 'table' ) );
|
||||
block( $wrapper );
|
||||
|
||||
var data = {
|
||||
security: wc_cart_params.remove_coupon_nonce,
|
||||
|
@ -482,7 +472,7 @@ jQuery( function( $ ) {
|
|||
$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
|
||||
show_notice( response );
|
||||
$( document.body ).trigger( 'removed_coupon' );
|
||||
unblock( $tr.parents( 'table' ) );
|
||||
unblock( $wrapper );
|
||||
},
|
||||
complete: function() {
|
||||
cart.update_cart_totals();
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -132,10 +132,12 @@ jQuery( function( $ ) {
|
|||
* Init zoom.
|
||||
*/
|
||||
init_zoom: function() {
|
||||
// But only zoom if the img is larger than its container and the visitor is not on a touch device.
|
||||
if ( ( $( '.woocommerce-product-gallery__image img' ).attr( 'width' ) > $( '.woocommerce-product-gallery' ).width() ) && ( ! wc_product_gallery.is_touch_device() ) ) {
|
||||
// But only zoom if the img is larger than its container.
|
||||
if ( ( $( '.woocommerce-product-gallery__image img' ).attr( 'width' ) > $( '.woocommerce-product-gallery' ).width() ) ) {
|
||||
$( '.woocommerce-product-gallery__image' ).trigger( 'zoom.destroy' );
|
||||
$( '.woocommerce-product-gallery__image' ).zoom();
|
||||
$( '.woocommerce-product-gallery__image' ).zoom({
|
||||
touch: false
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
jQuery(function(a){if("undefined"==typeof wc_single_product_params)return!1;a("body").on("init",".wc-tabs-wrapper, .woocommerce-tabs",function(){a(".wc-tab, .woocommerce-tabs .panel:not(.panel .panel)").hide();var b=window.location.hash,c=window.location.href,d=a(this).find(".wc-tabs, ul.tabs").first();b.toLowerCase().indexOf("comment-")>=0||"#reviews"===b||"#tab-reviews"===b?d.find("li.reviews_tab a").click():c.indexOf("comment-page-")>0||c.indexOf("cpage=")>0?d.find("li.reviews_tab a").click():d.find("li:first a").click()}).on("click",".wc-tabs li a, ul.tabs li a",function(b){b.preventDefault();var c=a(this),d=c.closest(".wc-tabs-wrapper, .woocommerce-tabs"),e=d.find(".wc-tabs, ul.tabs");e.find("li").removeClass("active"),d.find(".wc-tab, .panel:not(.panel .panel)").hide(),c.closest("li").addClass("active"),d.find(c.attr("href")).show()}).on("click","a.woocommerce-review-link",function(){return a(".reviews_tab a").click(),!0}).on("init","#rating",function(){a("#rating").hide().before('<p class="stars"><span><a class="star-1" href="#">1</a><a class="star-2" href="#">2</a><a class="star-3" href="#">3</a><a class="star-4" href="#">4</a><a class="star-5" href="#">5</a></span></p>')}).on("click","#respond p.stars a",function(){var b=a(this),c=a(this).closest("#respond").find("#rating"),d=a(this).closest(".stars");return c.val(b.text()),b.siblings("a").removeClass("active"),b.addClass("active"),d.addClass("selected"),!1}).on("click","#respond #submit",function(){var b=a(this).closest("#respond").find("#rating"),c=b.val();if(b.length>0&&!c&&"yes"===wc_single_product_params.review_rating_required)return window.alert(wc_single_product_params.i18n_required_rating_text),!1}).on("woocommerce_init_gallery",function(){a.isFunction(a.fn.zoom)&&b.init_zoom()}),a(".wc-tabs-wrapper, .woocommerce-tabs, #rating").trigger("init");var b={init:function(){a.isFunction(a.fn.flexslider)&&this.init_flexslider(),a.isFunction(a.fn.zoom)&&this.init_zoom(),"undefined"!=typeof PhotoSwipe&&(this.init_photoswipe(),a(document).on("click",".woocommerce-product-gallery__trigger",this.trigger_photoswipe))},is_touch_device:function(){return"ontouchstart"in window||navigator.maxTouchPoints},init_flexslider:function(){a(".woocommerce-product-gallery").flexslider({selector:".woocommerce-product-gallery__wrapper > .woocommerce-product-gallery__image",animation:flexslider_options.animation,smoothHeight:flexslider_options.smoothHeight,directionNav:flexslider_options.directionNav,controlNav:flexslider_options.controlNav,slideshow:flexslider_options.slideshow,animationSpeed:flexslider_options.animationSpeed,animationLoop:!1})},init_zoom:function(){a(".woocommerce-product-gallery__image img").attr("width")>a(".woocommerce-product-gallery").width()&&!b.is_touch_device()&&(a(".woocommerce-product-gallery__image").trigger("zoom.destroy"),a(".woocommerce-product-gallery__image").zoom())},get_gallery_items:function(){var b=a(".woocommerce-product-gallery__wrapper").children(),c=[],d=b.filter(".flex-active-slide").index();return b.length>0&&b.each(function(b,d){var e=a(d).find("img"),f=e.attr("data-large-image"),g=e.attr("data-large-image-width"),h=e.attr("data-large-image-height"),i={src:f,w:g,h:h,title:e.attr("title")};c.push(i)}),{index:d,items:c}},init_photoswipe:function(){a(".woocommerce-product-gallery").prepend('<a href="#" class="woocommerce-product-gallery__trigger">🔍</a>')},trigger_photoswipe:function(c){c.preventDefault();var d=a(".pswp")[0],e=b.get_gallery_items(),f={index:e.index,shareEl:!1,closeOnScroll:!1,history:!1,hideAnimationDuration:0,showAnimationDuration:0},g=new PhotoSwipe(d,PhotoSwipeUI_Default,e.items,f);g.init()}};b.init()});
|
||||
jQuery(function(a){if("undefined"==typeof wc_single_product_params)return!1;a("body").on("init",".wc-tabs-wrapper, .woocommerce-tabs",function(){a(".wc-tab, .woocommerce-tabs .panel:not(.panel .panel)").hide();var b=window.location.hash,c=window.location.href,d=a(this).find(".wc-tabs, ul.tabs").first();b.toLowerCase().indexOf("comment-")>=0||"#reviews"===b||"#tab-reviews"===b?d.find("li.reviews_tab a").click():c.indexOf("comment-page-")>0||c.indexOf("cpage=")>0?d.find("li.reviews_tab a").click():d.find("li:first a").click()}).on("click",".wc-tabs li a, ul.tabs li a",function(b){b.preventDefault();var c=a(this),d=c.closest(".wc-tabs-wrapper, .woocommerce-tabs"),e=d.find(".wc-tabs, ul.tabs");e.find("li").removeClass("active"),d.find(".wc-tab, .panel:not(.panel .panel)").hide(),c.closest("li").addClass("active"),d.find(c.attr("href")).show()}).on("click","a.woocommerce-review-link",function(){return a(".reviews_tab a").click(),!0}).on("init","#rating",function(){a("#rating").hide().before('<p class="stars"><span><a class="star-1" href="#">1</a><a class="star-2" href="#">2</a><a class="star-3" href="#">3</a><a class="star-4" href="#">4</a><a class="star-5" href="#">5</a></span></p>')}).on("click","#respond p.stars a",function(){var b=a(this),c=a(this).closest("#respond").find("#rating"),d=a(this).closest(".stars");return c.val(b.text()),b.siblings("a").removeClass("active"),b.addClass("active"),d.addClass("selected"),!1}).on("click","#respond #submit",function(){var b=a(this).closest("#respond").find("#rating"),c=b.val();if(b.length>0&&!c&&"yes"===wc_single_product_params.review_rating_required)return window.alert(wc_single_product_params.i18n_required_rating_text),!1}).on("woocommerce_init_gallery",function(){a.isFunction(a.fn.zoom)&&b.init_zoom()}),a(".wc-tabs-wrapper, .woocommerce-tabs, #rating").trigger("init");var b={init:function(){a.isFunction(a.fn.flexslider)&&this.init_flexslider(),a.isFunction(a.fn.zoom)&&this.init_zoom(),"undefined"!=typeof PhotoSwipe&&(this.init_photoswipe(),a(document).on("click",".woocommerce-product-gallery__trigger",this.trigger_photoswipe))},is_touch_device:function(){return"ontouchstart"in window||navigator.maxTouchPoints},init_flexslider:function(){a(".woocommerce-product-gallery").flexslider({selector:".woocommerce-product-gallery__wrapper > .woocommerce-product-gallery__image",animation:flexslider_options.animation,smoothHeight:flexslider_options.smoothHeight,directionNav:flexslider_options.directionNav,controlNav:flexslider_options.controlNav,slideshow:flexslider_options.slideshow,animationSpeed:flexslider_options.animationSpeed,animationLoop:!1})},init_zoom:function(){a(".woocommerce-product-gallery__image img").attr("width")>a(".woocommerce-product-gallery").width()&&(a(".woocommerce-product-gallery__image").trigger("zoom.destroy"),a(".woocommerce-product-gallery__image").zoom({touch:!1}))},get_gallery_items:function(){var b=a(".woocommerce-product-gallery__wrapper").children(),c=[],d=b.filter(".flex-active-slide").index();return b.length>0&&b.each(function(b,d){var e=a(d).find("img"),f=e.attr("data-large-image"),g=e.attr("data-large-image-width"),h=e.attr("data-large-image-height"),i={src:f,w:g,h:h,title:e.attr("title")};c.push(i)}),{index:d,items:c}},init_photoswipe:function(){a(".woocommerce-product-gallery").prepend('<a href="#" class="woocommerce-product-gallery__trigger">🔍</a>')},trigger_photoswipe:function(c){c.preventDefault();var d=a(".pswp")[0],e=b.get_gallery_items(),f={index:e.index,shareEl:!1,closeOnScroll:!1,history:!1,hideAnimationDuration:0,showAnimationDuration:0},g=new PhotoSwipe(d,PhotoSwipeUI_Default,e.items,f);g.init()}};b.init()});
|
|
@ -212,9 +212,10 @@ abstract class WC_Data {
|
|||
* @since 2.6.0
|
||||
* @param string $key
|
||||
* @param bool $single return first found meta with key, or all with $key
|
||||
* @param string $context What the value is for. Valid values are view and edit.
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_meta( $key = '', $single = true ) {
|
||||
public function get_meta( $key = '', $single = true, $context = 'view' ) {
|
||||
$array_keys = array_keys( wp_list_pluck( $this->get_meta_data(), 'key' ), $key );
|
||||
$value = '';
|
||||
|
||||
|
@ -224,6 +225,10 @@ abstract class WC_Data {
|
|||
} else {
|
||||
$value = array_intersect_key( $this->meta_data, array_flip( $array_keys ) );
|
||||
}
|
||||
|
||||
if ( 'view' === $context ) {
|
||||
$value = apply_filters( $this->get_hook_prefix() . $key, $value, $this );
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
|
|
@ -571,7 +571,7 @@ abstract class WC_Abstract_Legacy_Order extends WC_Data {
|
|||
* @return array
|
||||
*/
|
||||
public function expand_item_meta( $item ) {
|
||||
_deprecated_function( 'expand_item_meta', '2.7', '' );
|
||||
_deprecated_function( 'expand_item_meta', '2.7' );
|
||||
return $item;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy Payment Tokens.
|
||||
* Payment Tokens were introduced in 2.6.0 with create and update as methods.
|
||||
* Major CRUD changes occurred in 2.7, so these were deprecated (save and delete still work).
|
||||
* This legacy class is for backwards compatibility in case any code called ->read, ->update or ->create
|
||||
* directly on the object.
|
||||
*
|
||||
* @version 2.7.0
|
||||
* @package WooCommerce/Classes
|
||||
* @category Class
|
||||
* @author WooCommerce
|
||||
*/
|
||||
abstract class WC_Legacy_Payment_Token extends WC_Data {
|
||||
|
||||
/**
|
||||
* Read a token by ID.
|
||||
* @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.' );
|
||||
$this->set_id( $token_id );
|
||||
$data_store = WC_Data_Store::load( 'payment-token' );
|
||||
$data_store->read( $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a token.
|
||||
* @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.' );
|
||||
$data_store = WC_Data_Store::load( 'payment-token' );
|
||||
try {
|
||||
$data_store->update( $this );
|
||||
} catch ( Exception $e ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a token.
|
||||
* @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.' );
|
||||
$data_store = WC_Data_Store::load( 'payment-token' );
|
||||
try {
|
||||
$data_store->create( $this );
|
||||
} catch ( Exception $e ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
include_once( 'abstract-wc-legacy-payment-token.php' );
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,12 +12,13 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* examples: Credit Card, eCheck.
|
||||
*
|
||||
* @class WC_Payment_Token
|
||||
* @version 2.7.0
|
||||
* @since 2.6.0
|
||||
* @package WooCommerce/Abstracts
|
||||
* @category Abstract Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
abstract class WC_Payment_Token extends WC_Data {
|
||||
abstract class WC_Payment_Token extends WC_Legacy_Payment_Token {
|
||||
|
||||
/**
|
||||
* Token Data (stored in the payment_tokens table).
|
||||
|
@ -24,8 +27,9 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
protected $data = array(
|
||||
'gateway_id' => '',
|
||||
'token' => '',
|
||||
'is_default' => 0,
|
||||
'is_default' => false,
|
||||
'user_id' => 0,
|
||||
'type' => '',
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -47,98 +51,145 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @param mixed $token
|
||||
*/
|
||||
public function __construct( $token = '' ) {
|
||||
// Set token type (cc, echeck)
|
||||
if ( ! empty( $this->type ) ) {
|
||||
$this->set_type( $this->type );
|
||||
}
|
||||
|
||||
if ( is_numeric( $token ) ) {
|
||||
$this->read( $token );
|
||||
$this->set_id( $token );
|
||||
} elseif ( is_object( $token ) ) {
|
||||
$token_id = $token->get_id();
|
||||
if ( ! empty( $token_id ) ) {
|
||||
$this->read( $token->get_id() );
|
||||
}
|
||||
}
|
||||
// Set token type (cc, echeck)
|
||||
if ( ! empty( $this->type ) ) {
|
||||
$this->data['type'] = $this->type;
|
||||
$this->set_id( $token->get_id() );
|
||||
}
|
||||
} else {
|
||||
$this->set_object_read( true );
|
||||
}
|
||||
|
||||
$this->data_store = WC_Data_Store::load( 'payment-token' );
|
||||
if ( $this->get_id() > 0 ) {
|
||||
$this->data_store->read( $this );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Getters
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the raw payment token.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string Raw token
|
||||
*/
|
||||
public function get_token() {
|
||||
return $this->data['token'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the raw payment token.
|
||||
* @since 2.6.0
|
||||
* @param string $token
|
||||
*/
|
||||
public function set_token( $token ) {
|
||||
$this->data['token'] = $token;
|
||||
public function get_token( $context = 'view' ) {
|
||||
return $this->get_prop( 'token', $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this payment token (CC, eCheck, or something else).
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string Payment Token Type (CC, eCheck)
|
||||
*/
|
||||
public function get_type() {
|
||||
return isset( $this->data['type'] ) ? $this->data['type'] : '';
|
||||
public function get_type( $context = 'view' ) {
|
||||
return $this->get_prop( 'type', $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type to display to user.
|
||||
* Get's overwritten by child classes.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string
|
||||
*/
|
||||
public function get_display_name() {
|
||||
return $this->get_type();
|
||||
public function get_display_name( $context = 'view' ) {
|
||||
return $this->get_type( $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the user ID associated with the token or false if this token is not associated.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return int User ID if this token is associated with a user or 0 if no user is associated
|
||||
*/
|
||||
public function get_user_id() {
|
||||
return ( isset( $this->data['user_id'] ) && $this->data['user_id'] > 0 ) ? absint( $this->data['user_id'] ) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user ID for the user associated with this order.
|
||||
* @since 2.6.0
|
||||
* @param int $user_id
|
||||
*/
|
||||
public function set_user_id( $user_id ) {
|
||||
$this->data['user_id'] = absint( $user_id );
|
||||
public function get_user_id( $context = 'view' ) {
|
||||
return $this->get_prop( 'user_id', $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the gateway associated with this payment token.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string Gateway ID
|
||||
*/
|
||||
public function get_gateway_id() {
|
||||
return $this->data['gateway_id'];
|
||||
public function get_gateway_id( $context = 'view' ) {
|
||||
return $this->get_prop( 'gateway_id', $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ID of the gateway associated with this payment token.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string Gateway ID
|
||||
*/
|
||||
public function get_is_default( $context = 'view' ) {
|
||||
return $this->get_prop( 'is_default', $context );
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Setters
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Set the raw payment token.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $token
|
||||
*/
|
||||
public function set_token( $token ) {
|
||||
$this->set_prop( 'token', $token );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of this payment token (CC, eCheck, or something else).
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param string Payment Token Type (CC, eCheck)
|
||||
*/
|
||||
public function set_type( $type ) {
|
||||
return $this->set_prop( 'type', $type );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user ID for the user associated with this order.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param int $user_id
|
||||
*/
|
||||
public function set_user_id( $user_id ) {
|
||||
$this->set_prop( 'user_id', absint( $user_id ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the gateway ID.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $gateway_id
|
||||
*/
|
||||
public function set_gateway_id( $gateway_id ) {
|
||||
$this->data['gateway_id'] = $gateway_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the token is marked as default.
|
||||
* @since 2.6.0
|
||||
* @return boolean True if the token is default
|
||||
*/
|
||||
public function is_default() {
|
||||
return ! empty( $this->data['is_default'] );
|
||||
$this->set_prop( 'gateway_id', $gateway_id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,7 +198,23 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @param boolean $is_default True or false
|
||||
*/
|
||||
public function set_default( $is_default ) {
|
||||
$this->data['is_default'] = (bool) $is_default;
|
||||
$this->set_prop( 'is_default', (bool) $is_default );
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Other Methods
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns if the token is marked as default.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @return boolean True if the token is default
|
||||
*/
|
||||
public function is_default() {
|
||||
return (bool) $this->get_prop( 'is_default', 'view' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,132 +223,17 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* @return boolean True if the passed data is valid
|
||||
*/
|
||||
public function validate() {
|
||||
if ( empty( $this->data['token'] ) ) {
|
||||
$token = $this->get_prop( 'token', 'edit' );
|
||||
if ( empty( $token ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( empty( $this->data['type'] ) ) {
|
||||
$type = $this->get_prop( 'type', 'edit' );
|
||||
if ( empty( $type ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a token from the database.
|
||||
* @since 2.6.0
|
||||
* @param int $token_id Token ID
|
||||
*/
|
||||
public function read( $token_id ) {
|
||||
global $wpdb;
|
||||
if ( $token = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d LIMIT 1;", $token_id ) ) ) {
|
||||
$token_id = $token->token_id;
|
||||
$token = (array) $token;
|
||||
unset( $token['token_id'] );
|
||||
$this->data = $token;
|
||||
$this->set_id( $token_id );
|
||||
$this->read_meta_data();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a payment token.
|
||||
* @since 2.6.0
|
||||
* @return boolean on success, false if validation failed and a payment token could not be updated
|
||||
*/
|
||||
public function update() {
|
||||
if ( false === $this->validate() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$payment_token_data = array(
|
||||
'gateway_id' => $this->get_gateway_id(),
|
||||
'token' => $this->get_token(),
|
||||
'user_id' => $this->get_user_id(),
|
||||
'type' => $this->get_type(),
|
||||
);
|
||||
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'woocommerce_payment_tokens',
|
||||
$payment_token_data,
|
||||
array( 'token_id' => $this->get_id() )
|
||||
);
|
||||
|
||||
$this->save_meta_data();
|
||||
|
||||
// Make sure all other tokens are not set to default
|
||||
if ( $this->is_default() && $this->get_user_id() > 0 ) {
|
||||
WC_Payment_Tokens::set_users_default( $this->get_user_id(), $this->get_id() );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_payment_token_updated', $this->get_id() );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new payment token in the database.
|
||||
* @since 2.6.0
|
||||
* @return boolean on success, false if validation failed and a payment token could not be created
|
||||
*/
|
||||
public function create() {
|
||||
if ( false === $this->validate() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
// Are there any other tokens? If not, set this token as default
|
||||
if ( ! $this->is_default() && $this->get_user_id() > 0 ) {
|
||||
$default_token = WC_Payment_Tokens::get_customer_default_token( $this->get_user_id() );
|
||||
if ( is_null( $default_token ) ) {
|
||||
$this->set_default( true );
|
||||
}
|
||||
}
|
||||
|
||||
$payment_token_data = array(
|
||||
'gateway_id' => $this->get_gateway_id(),
|
||||
'token' => $this->get_token(),
|
||||
'user_id' => $this->get_user_id(),
|
||||
'type' => $this->get_type(),
|
||||
);
|
||||
|
||||
$wpdb->insert( $wpdb->prefix . 'woocommerce_payment_tokens', $payment_token_data );
|
||||
$token_id = $wpdb->insert_id;
|
||||
$this->set_id( $token_id );
|
||||
$this->save_meta_data();
|
||||
|
||||
// Make sure all other tokens are not set to default
|
||||
if ( $this->is_default() && $this->get_user_id() > 0 ) {
|
||||
WC_Payment_Tokens::set_users_default( $this->get_user_id(), $token_id );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_payment_token_created', $token_id );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a payment token to the database - does not require you to know if this is a new token or an update token.
|
||||
* @since 2.6.0
|
||||
* @return boolean on success, false if validation failed and a payment token could not be saved
|
||||
*/
|
||||
public function save() {
|
||||
if ( $this->get_id() > 0 ) {
|
||||
return $this->update();
|
||||
} else {
|
||||
return $this->create();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a payment token from the database.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public function delete( $force_delete = false ) {
|
||||
global $wpdb;
|
||||
$this->read( $this->get_id() ); // Make sure we have a token to return after deletion
|
||||
$wpdb->delete( $wpdb->prefix . 'woocommerce_payment_tokens', array( 'token_id' => $this->get_id() ), array( '%d' ) );
|
||||
$wpdb->delete( $wpdb->prefix . 'woocommerce_payment_tokenmeta', array( 'payment_token_id' => $this->get_id() ), array( '%d' ) );
|
||||
do_action( 'woocommerce_payment_token_deleted', $this->get_id(), $this );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ class WC_Admin_Attributes {
|
|||
* @return bool|WP_error result
|
||||
*/
|
||||
private static function valid_attribute_name( $attribute_name ) {
|
||||
if ( strlen( $attribute_name ) >= 28 ) {
|
||||
if ( strlen( $attribute_name ) > 28 ) {
|
||||
/* translators: %s: attribute name */
|
||||
return new WP_Error( 'error', sprintf( __( 'Slug "%s" is too long (28 characters max). Shorten it, please.', 'woocommerce' ), sanitize_title( $attribute_name ) ) );
|
||||
} elseif ( wc_check_if_attribute_name_is_reserved( $attribute_name ) ) {
|
||||
|
@ -290,7 +290,7 @@ class WC_Admin_Attributes {
|
|||
</th>
|
||||
<td>
|
||||
<input name="attribute_name" id="attribute_name" type="text" value="<?php echo esc_attr( $att_name ); ?>" maxlength="28" />
|
||||
<p class="description"><?php _e( 'Unique slug/reference for the attribute; must be shorter than 28 characters.', 'woocommerce' ); ?></p>
|
||||
<p class="description"><?php _e( 'Unique slug/reference for the attribute; must be no more than 28 characters.', 'woocommerce' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="form-field form-required">
|
||||
|
@ -455,7 +455,7 @@ class WC_Admin_Attributes {
|
|||
<div class="form-field">
|
||||
<label for="attribute_name"><?php _e( 'Slug', 'woocommerce' ); ?></label>
|
||||
<input name="attribute_name" id="attribute_name" type="text" value="" maxlength="28" />
|
||||
<p class="description"><?php _e( 'Unique slug/reference for the attribute; must be shorter than 28 characters.', 'woocommerce' ); ?></p>
|
||||
<p class="description"><?php _e( 'Unique slug/reference for the attribute; must be no more than 28 characters.', 'woocommerce' ); ?></p>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
|
|
|
@ -13,6 +13,7 @@ $environment = $system_status->get_environment_info();
|
|||
$database = $system_status->get_database_info();
|
||||
$active_plugins = $system_status->get_active_plugins();
|
||||
$theme = $system_status->get_theme_info();
|
||||
$security = $system_status->get_security_info();
|
||||
$settings = $system_status->get_settings();
|
||||
$pages = $system_status->get_pages();
|
||||
?>
|
||||
|
@ -327,6 +328,37 @@ $pages = $system_status->get_pages();
|
|||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="wc_status_table widefat" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th colspan="3" data-export-label="Security"><h2><?php _e( 'Security', 'woocommerce' ); ?></h2></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td data-export-label="Secure connection (HTTPS)"><?php _e( 'Secure connection (HTTPS)', 'woocommerce' ); ?>:</td>
|
||||
<td class="help"><?php echo wc_help_tip( __( 'Is the connection to your store secure?', 'woocommerce' ) ); ?></td>
|
||||
<td>
|
||||
<?php if ( $security['secure_connection'] ) : ?>
|
||||
<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>
|
||||
<?php else : ?>
|
||||
<mark class="error"><span class="dashicons dashicons-warning"></span><?php printf( __( 'Your store is not using HTTPS. <a href="%s" target="_blank">Learn more about HTTPS and SSL Certificates</a>.', 'woocommerce' ), 'https://docs.woocommerce.com/document/ssl-and-https/' ); ?></mark>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td data-export-label="Hide errors from visitors"><?php _e( 'Hide errors from visitors', 'woocommerce' ); ?></td>
|
||||
<td class="help"><?php echo wc_help_tip( __( 'Error messages can contain sensitive information about your store environment. These should be hidden from untrusted visitors.', 'woocommerce' ) ); ?></td>
|
||||
<td>
|
||||
<?php if ( $security['hide_errors'] ) : ?>
|
||||
<mark class="yes"><span class="dashicons dashicons-yes"></span></mark>
|
||||
<?php else : ?>
|
||||
<mark class="error"><span class="dashicons dashicons-warning"></span><?php _e( 'Error messages should not be shown to visitors.', 'woocommerce' ); ?></mark>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table class="wc_status_table widefat" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
|
@ -414,6 +414,23 @@ class WC_REST_System_Status_Controller extends WC_REST_Controller {
|
|||
),
|
||||
),
|
||||
),
|
||||
'security' => array(
|
||||
'description' => __( 'Security', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
'properties' => array(
|
||||
'secure_connection' => array(
|
||||
'description' => __( 'Is the connection to your store secure?', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
'hide_errors' => array(
|
||||
'description' => __( 'Hide errors from visitors?', 'woocommerce' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array( 'view', 'edit' ),
|
||||
),
|
||||
),
|
||||
),
|
||||
'pages' => array(
|
||||
'description' => __( 'WooCommerce pages', 'woocommerce' ),
|
||||
'type' => 'array',
|
||||
|
@ -437,6 +454,7 @@ class WC_REST_System_Status_Controller extends WC_REST_Controller {
|
|||
'active_plugins' => $this->get_active_plugins(),
|
||||
'theme' => $this->get_theme_info(),
|
||||
'settings' => $this->get_settings(),
|
||||
'security' => $this->get_security_info(),
|
||||
'pages' => $this->get_pages(),
|
||||
);
|
||||
}
|
||||
|
@ -737,6 +755,18 @@ class WC_REST_System_Status_Controller extends WC_REST_Controller {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns security tips.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_security_info() {
|
||||
return array(
|
||||
'secure_connection' => 'https' === substr( get_permalink( wc_get_page_id( 'shop' ) ), 0, 5 ),
|
||||
'hide_errors' => ! ( defined( 'WP_DEBUG' ) && defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG && WP_DEBUG_DISPLAY ) || 0 === intval( ini_get( 'display_errors' ) ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a mini-report on WC pages and if they are configured correctly:
|
||||
* Present, visible, and including the correct shortcode.
|
||||
|
|
|
@ -1983,7 +1983,7 @@ class WC_AJAX {
|
|||
foreach ( $variations as $variation_id ) {
|
||||
$_downloadable = get_post_meta( $variation_id, '_downloadable', true );
|
||||
$is_downloadable = 'no' === $_downloadable ? 'yes' : 'no';
|
||||
update_post_meta( $variation_id, '_downloadable', wc_clean( $is_downloadable ) );
|
||||
update_post_meta( $variation_id, '_downloadable', $is_downloadable );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1998,7 +1998,7 @@ class WC_AJAX {
|
|||
foreach ( $variations as $variation_id ) {
|
||||
$_virtual = get_post_meta( $variation_id, '_virtual', true );
|
||||
$is_virtual = 'no' === $_virtual ? 'yes' : 'no';
|
||||
update_post_meta( $variation_id, '_virtual', wc_clean( $is_virtual ) );
|
||||
update_post_meta( $variation_id, '_virtual', $is_virtual );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,8 +81,6 @@ class WC_Autoloader {
|
|||
$path = $this->include_path . 'admin/meta-boxes/';
|
||||
} elseif ( strpos( $class, 'wc_admin' ) === 0 ) {
|
||||
$path = $this->include_path . 'admin/';
|
||||
} elseif ( strpos( $class, 'wc_cli_' ) === 0 ) {
|
||||
$path = $this->include_path . 'cli/';
|
||||
} elseif ( strpos( $class, 'wc_payment_token_' ) === 0 ) {
|
||||
$path = $this->include_path . 'payment-tokens/';
|
||||
}
|
||||
|
|
|
@ -1,23 +1,6 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Manage WooCommerce from CLI.
|
||||
* Deprecated. No longer needed.
|
||||
*
|
||||
* @class WC_CLI
|
||||
* @version 2.5.0
|
||||
* @package WooCommerce/CLI
|
||||
* @category CLI
|
||||
* @author WooThemes
|
||||
* @package WooCommerce
|
||||
*/
|
||||
class WC_CLI extends WP_CLI_Command {
|
||||
}
|
||||
|
||||
WP_CLI::add_command( 'wc', 'WC_CLI' );
|
||||
WP_CLI::add_command( 'wc coupon', 'WC_CLI_Coupon' );
|
||||
WP_CLI::add_command( 'wc customer', 'WC_CLI_Customer' );
|
||||
WP_CLI::add_command( 'wc order', 'WC_CLI_Order' );
|
||||
WP_CLI::add_command( 'wc product', 'WC_CLI_Product' );
|
||||
WP_CLI::add_command( 'wc product category', 'WC_CLI_Product_Category' );
|
||||
WP_CLI::add_command( 'wc report', 'WC_CLI_Report' );
|
||||
WP_CLI::add_command( 'wc tax', 'WC_CLI_Tax' );
|
||||
WP_CLI::add_command( 'wc tool', 'WC_CLI_Tool' );
|
||||
|
|
|
@ -28,11 +28,16 @@ class WC_Data_Store {
|
|||
* Ran through `woocommerce_data_stores`.
|
||||
*/
|
||||
private $stores = array(
|
||||
<<<<<<< HEAD
|
||||
'coupon' => 'WC_Coupon_Data_Store_CPT',
|
||||
'product' => 'WC_Product_Data_Store_CPT',
|
||||
'product_grouped' => 'WC_Product_Grouped_Data_Store_CPT',
|
||||
'product_variable' => 'WC_Product_Variable_Data_Store_CPT',
|
||||
'product_variation' => 'WC_Product_Variation_Data_Store_CPT',
|
||||
=======
|
||||
'coupon' => 'WC_Coupon_Data_Store_CPT',
|
||||
'payment-token' => 'WC_Payment_Token_Data_Store_Table',
|
||||
>>>>>>> master
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* An API for storing and managing tokens for gateways and customers.
|
||||
*
|
||||
* @class WC_Payment_Tokens
|
||||
* @version 2.7.0
|
||||
* @since 2.6.0
|
||||
* @package WooCommerce/Classes
|
||||
* @category Class
|
||||
|
@ -18,12 +19,12 @@ class WC_Payment_Tokens {
|
|||
|
||||
/**
|
||||
* Gets valid tokens from the database based on user defined criteria.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param array $args
|
||||
* @return array
|
||||
*/
|
||||
public static function get_tokens( $args ) {
|
||||
global $wpdb;
|
||||
|
||||
$args = wp_parse_args( $args, array(
|
||||
'token_id' => '',
|
||||
'user_id' => '',
|
||||
|
@ -31,33 +32,8 @@ class WC_Payment_Tokens {
|
|||
'type' => '',
|
||||
) );
|
||||
|
||||
$sql = "SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens";
|
||||
$where = array( '1=1' );
|
||||
|
||||
if ( $args['token_id'] ) {
|
||||
$token_ids = array_map( 'absint', is_array( $args['token_id'] ) ? $args['token_id'] : array( $args['token_id'] ) );
|
||||
$where[] = "token_id IN ('" . implode( "','", array_map( 'esc_sql', $token_ids ) ) . "')";
|
||||
}
|
||||
|
||||
if ( $args['user_id'] ) {
|
||||
$where[] = 'user_id = ' . absint( $args['user_id'] );
|
||||
}
|
||||
|
||||
if ( $args['gateway_id'] ) {
|
||||
$gateway_ids = array( $args['gateway_id'] );
|
||||
} else {
|
||||
$gateways = WC_Payment_Gateways::instance();
|
||||
$gateway_ids = $gateways->get_payment_gateway_ids();
|
||||
}
|
||||
|
||||
$gateway_ids[] = '';
|
||||
$where[] = "gateway_id IN ('" . implode( "','", array_map( 'esc_sql', $gateway_ids ) ) . "')";
|
||||
|
||||
if ( $args['type'] ) {
|
||||
$where[] = 'type = ' . esc_sql( $args['type'] );
|
||||
}
|
||||
|
||||
$token_results = $wpdb->get_results( $sql . ' WHERE ' . implode( ' AND ', $where ) );
|
||||
$data_store = WC_Data_Store::load( 'payment-token' );
|
||||
$token_results = $data_store->get_tokens( $args );
|
||||
$tokens = array();
|
||||
|
||||
if ( ! empty( $token_results ) ) {
|
||||
|
@ -74,6 +50,7 @@ class WC_Payment_Tokens {
|
|||
|
||||
/**
|
||||
* Returns an array of payment token objects associated with the passed customer ID.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param int $customer_id Customer ID
|
||||
* @param string $gateway_id Optional Gateway ID for getting tokens for a specific gateway
|
||||
|
@ -94,6 +71,7 @@ class WC_Payment_Tokens {
|
|||
|
||||
/**
|
||||
* Returns a customers default token or NULL if there is no default token.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param int $customer_id
|
||||
* @return WC_Payment_Token|null
|
||||
|
@ -103,12 +81,8 @@ class WC_Payment_Tokens {
|
|||
return null;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$token = $wpdb->get_row( $wpdb->prepare(
|
||||
"SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE user_id = %d AND is_default = 1",
|
||||
$customer_id
|
||||
) );
|
||||
$data_store = WC_Data_Store::load( 'payment-token' );
|
||||
$token = $data_store->get_users_default_token( $customer_id );
|
||||
|
||||
if ( $token ) {
|
||||
return self::get( $token->token_id, $token );
|
||||
|
@ -119,6 +93,7 @@ class WC_Payment_Tokens {
|
|||
|
||||
/**
|
||||
* Returns an array of payment token objects associated with the passed order ID.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param int $order_id Order ID
|
||||
* @return array Array of token objects
|
||||
|
@ -130,6 +105,7 @@ class WC_Payment_Tokens {
|
|||
return array();
|
||||
}
|
||||
|
||||
// @todo Order Data Store should handle this one.
|
||||
$token_ids = get_post_meta( $order_id, '_payment_tokens', true );
|
||||
if ( empty( $token_ids ) ) {
|
||||
return array();
|
||||
|
@ -144,19 +120,16 @@ class WC_Payment_Tokens {
|
|||
|
||||
/**
|
||||
* Get a token object by ID.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param int $token_id Token ID
|
||||
* @return WC_Payment_Token|null Returns a valid payment token or null if no token can be found
|
||||
*/
|
||||
public static function get( $token_id, $token_result = null ) {
|
||||
global $wpdb;
|
||||
$data_store = WC_Data_Store::load( 'payment-token' );
|
||||
|
||||
if ( is_null( $token_result ) ) {
|
||||
$token_result = $wpdb->get_row( $wpdb->prepare(
|
||||
"SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d",
|
||||
$token_id
|
||||
) );
|
||||
|
||||
$token_result = $data_store->get_token_by_id( $token_id );
|
||||
// Still empty? Token doesn't exist? Don't continue
|
||||
if ( empty( $token_result ) ) {
|
||||
return null;
|
||||
|
@ -166,7 +139,7 @@ class WC_Payment_Tokens {
|
|||
$token_class = 'WC_Payment_Token_' . $token_result->type;
|
||||
|
||||
if ( class_exists( $token_class ) ) {
|
||||
$meta = get_metadata( 'payment_token', $token_id );
|
||||
$meta = $data_store->get_metadata( $token_id );
|
||||
$passed_meta = array();
|
||||
if ( ! empty( $meta ) ) {
|
||||
foreach ( $meta as $meta_key => $meta_value ) {
|
||||
|
@ -195,50 +168,33 @@ class WC_Payment_Tokens {
|
|||
|
||||
/**
|
||||
* Loops through all of a users payment tokens and sets is_default to false for all but a specific token.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param int $user_id User to set a default for
|
||||
* @param int $token_id The ID of the token that should be default
|
||||
*/
|
||||
public static function set_users_default( $user_id, $token_id ) {
|
||||
global $wpdb; // DB queries so we avoid an infinite loop (update & create use this function)
|
||||
$data_store = WC_Data_Store::load( 'payment-token' );
|
||||
$users_tokens = self::get_customer_tokens( $user_id );
|
||||
foreach ( $users_tokens as $token ) {
|
||||
if ( $token_id === $token->get_id() ) {
|
||||
$token->set_default( true );
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'woocommerce_payment_tokens',
|
||||
array( 'is_default' => 1 ),
|
||||
array(
|
||||
'token_id' => $token->get_id(),
|
||||
)
|
||||
);
|
||||
|
||||
$data_store->set_default_status( $token->get_id(), true );
|
||||
do_action( 'woocommerce_payment_token_set_default', $token_id, $token );
|
||||
} else {
|
||||
$token->set_default( false );
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'woocommerce_payment_tokens',
|
||||
array( 'is_default' => 0 ),
|
||||
array(
|
||||
'token_id' => $token->get_id(),
|
||||
)
|
||||
);
|
||||
$data_store->set_default_status( $token->get_id(), false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns what type (credit card, echeck, etc) of token a token is by ID.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param int $token_id Token ID
|
||||
* @return string Type
|
||||
*/
|
||||
public static function get_token_type_by_id( $token_id ) {
|
||||
global $wpdb;
|
||||
$type = $wpdb->get_var( $wpdb->prepare(
|
||||
"SELECT type FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d",
|
||||
$token_id
|
||||
) );
|
||||
return $type;
|
||||
$data_store = WC_Data_Store::load( 'payment-token' );
|
||||
return $data_store->get_token_type_by_id( $token_id );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -508,7 +508,7 @@ class WC_Query {
|
|||
public function order_by_rating_post_clauses( $args ) {
|
||||
global $wpdb;
|
||||
|
||||
_deprecated_function( 'order_by_rating_post_clauses', '2.7', '' );
|
||||
_deprecated_function( 'order_by_rating_post_clauses', '2.7' );
|
||||
|
||||
$args['fields'] .= ", AVG( $wpdb->commentmeta.meta_value ) as average_rating ";
|
||||
$args['where'] .= " AND ( $wpdb->commentmeta.meta_key = 'rating' OR $wpdb->commentmeta.meta_key IS null ) ";
|
||||
|
@ -738,7 +738,7 @@ class WC_Query {
|
|||
* @deprecated 2.6.0
|
||||
*/
|
||||
public function layered_nav_init() {
|
||||
_deprecated_function( 'layered_nav_init', '2.6', '' );
|
||||
_deprecated_function( 'layered_nav_init', '2.6' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -746,7 +746,7 @@ class WC_Query {
|
|||
* @deprecated 2.6.0 due to performance concerns
|
||||
*/
|
||||
public function get_products_in_view() {
|
||||
_deprecated_function( 'get_products_in_view', '2.6', '' );
|
||||
_deprecated_function( 'get_products_in_view', '2.6' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -754,6 +754,6 @@ class WC_Query {
|
|||
* @deprecated 2.6.0 due to performance concerns
|
||||
*/
|
||||
public function layered_nav_query( $filtered_posts ) {
|
||||
_deprecated_function( 'layered_nav_query', '2.6', '' );
|
||||
_deprecated_function( 'layered_nav_query', '2.6' );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -402,7 +402,7 @@ class WC_Shipping {
|
|||
* @deprecated 2.6.0 Was previously used to determine sort order of methods, but this is now controlled by zones and thus unused.
|
||||
*/
|
||||
public function sort_shipping_methods() {
|
||||
_deprecated_function( 'sort_shipping_methods', '2.6', '' );
|
||||
_deprecated_function( 'sort_shipping_methods', '2.6' );
|
||||
return $this->shipping_methods;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -548,7 +548,7 @@ class WC_Tax {
|
|||
// This will be per order shipping - loop through the order and find the highest tax class rate
|
||||
$cart_tax_classes = WC()->cart->get_cart_item_tax_classes();
|
||||
|
||||
// If multiple classes are found, use the first one. Don't bother with standard rate, we can get that later.
|
||||
// If multiple classes are found, use the first one found unless a standard rate item is found. This will be the first listed in the 'additonal tax class' section.
|
||||
if ( sizeof( $cart_tax_classes ) > 1 && ! in_array( '', $cart_tax_classes ) ) {
|
||||
$tax_classes = self::get_tax_classes();
|
||||
|
||||
|
|
|
@ -1,407 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* WooCommerce CLI Command.
|
||||
*
|
||||
* Base class that must be extended by any WooCommerce sub commands.
|
||||
*
|
||||
* @class WC_CLI_Command
|
||||
* @version 2.5.0
|
||||
* @package WooCommerce/CLI
|
||||
* @category CLI
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_CLI_Command extends WP_CLI_Command {
|
||||
|
||||
/**
|
||||
* Add common cli arguments to argument list before WP_Query is run.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $base_args Required arguments for the query (e.g. `post_type`, etc)
|
||||
* @param array $assoc_args Arguments provided in when invoking the command
|
||||
* @return array
|
||||
*/
|
||||
protected function merge_wp_query_args( $base_args, $assoc_args ) {
|
||||
$args = array();
|
||||
|
||||
// date
|
||||
if ( ! empty( $assoc_args['created_at_min'] ) || ! empty( $assoc_args['created_at_max'] ) || ! empty( $assoc_args['updated_at_min'] ) || ! empty( $assoc_args['updated_at_max'] ) ) {
|
||||
|
||||
$args['date_query'] = array();
|
||||
|
||||
// resources created after specified date
|
||||
if ( ! empty( $assoc_args['created_at_min'] ) ) {
|
||||
$args['date_query'][] = array( 'column' => 'post_date_gmt', 'after' => $this->parse_datetime( $assoc_args['created_at_min'] ), 'inclusive' => true );
|
||||
}
|
||||
|
||||
// resources created before specified date
|
||||
if ( ! empty( $assoc_args['created_at_max'] ) ) {
|
||||
$args['date_query'][] = array( 'column' => 'post_date_gmt', 'before' => $this->parse_datetime( $assoc_args['created_at_max'] ), 'inclusive' => true );
|
||||
}
|
||||
|
||||
// resources updated after specified date
|
||||
if ( ! empty( $assoc_args['updated_at_min'] ) ) {
|
||||
$args['date_query'][] = array( 'column' => 'post_modified_gmt', 'after' => $this->parse_datetime( $assoc_args['updated_at_min'] ), 'inclusive' => true );
|
||||
}
|
||||
|
||||
// resources updated before specified date
|
||||
if ( ! empty( $assoc_args['updated_at_max'] ) ) {
|
||||
$args['date_query'][] = array( 'column' => 'post_modified_gmt', 'before' => $this->parse_datetime( $assoc_args['updated_at_max'] ), 'inclusive' => true );
|
||||
}
|
||||
}
|
||||
|
||||
// Search.
|
||||
if ( ! empty( $assoc_args['q'] ) ) {
|
||||
$args['s'] = $assoc_args['q'];
|
||||
}
|
||||
|
||||
// Number of post to show per page.
|
||||
if ( ! empty( $assoc_args['limit'] ) ) {
|
||||
$args['posts_per_page'] = $assoc_args['limit'];
|
||||
}
|
||||
|
||||
// Number of post to displace or pass over.
|
||||
if ( ! empty( $assoc_args['offset'] ) ) {
|
||||
$args['offset'] = $assoc_args['offset'];
|
||||
}
|
||||
|
||||
// order (ASC or DESC, DESC by default).
|
||||
if ( ! empty( $assoc_args['order'] ) ) {
|
||||
$args['order'] = $assoc_args['order'];
|
||||
}
|
||||
|
||||
// orderby.
|
||||
if ( ! empty( $assoc_args['orderby'] ) ) {
|
||||
$args['orderby'] = $assoc_args['orderby'];
|
||||
|
||||
// allow sorting by meta value
|
||||
if ( ! empty( $assoc_args['orderby_meta_key'] ) ) {
|
||||
$args['meta_key'] = $assoc_args['orderby_meta_key'];
|
||||
}
|
||||
}
|
||||
|
||||
// allow post status change
|
||||
if ( ! empty( $assoc_args['post_status'] ) ) {
|
||||
$args['post_status'] = $assoc_args['post_status'];
|
||||
unset( $assoc_args['post_status'] );
|
||||
}
|
||||
|
||||
// filter by a list of post ids
|
||||
if ( ! empty( $assoc_args['in'] ) ) {
|
||||
$args['post__in'] = explode( ',', $assoc_args['in'] );
|
||||
unset( $assoc_args['in'] );
|
||||
}
|
||||
|
||||
// exclude by a list of post ids
|
||||
if ( ! empty( $assoc_args['not_in'] ) ) {
|
||||
$args['post__not_in'] = explode( ',', $assoc_args['not_in'] );
|
||||
unset( $assoc_args['not_in'] );
|
||||
}
|
||||
|
||||
// posts page.
|
||||
$args['paged'] = ( isset( $assoc_args['page'] ) ) ? absint( $assoc_args['page'] ) : 1;
|
||||
|
||||
$args = apply_filters( 'woocommerce_cli_query_args', $args, $assoc_args );
|
||||
|
||||
return array_merge( $base_args, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add common cli arguments to argument list before WP_User_Query is run.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $base_args required arguments for the query (e.g. `post_type`, etc)
|
||||
* @param array $assoc_args arguments provided in when invoking the command
|
||||
* @return array
|
||||
*/
|
||||
protected function merge_wp_user_query_args( $base_args, $assoc_args ) {
|
||||
$args = array();
|
||||
|
||||
// Custom Role
|
||||
if ( ! empty( $assoc_args['role'] ) ) {
|
||||
$args['role'] = $assoc_args['role'];
|
||||
}
|
||||
|
||||
// Search
|
||||
if ( ! empty( $assoc_args['q'] ) ) {
|
||||
$args['search'] = $assoc_args['q'];
|
||||
}
|
||||
|
||||
// Limit number of users returned.
|
||||
if ( ! empty( $assoc_args['limit'] ) ) {
|
||||
$args['number'] = absint( $assoc_args['limit'] );
|
||||
}
|
||||
|
||||
// Offset
|
||||
if ( ! empty( $assoc_args['offset'] ) ) {
|
||||
$args['offset'] = absint( $assoc_args['offset'] );
|
||||
}
|
||||
|
||||
// date
|
||||
if ( ! empty( $assoc_args['created_at_min'] ) || ! empty( $assoc_args['created_at_max'] ) ) {
|
||||
|
||||
$args['date_query'] = array();
|
||||
|
||||
// resources created after specified date
|
||||
if ( ! empty( $assoc_args['created_at_min'] ) ) {
|
||||
$args['date_query'][] = array( 'after' => $this->parse_datetime( $assoc_args['created_at_min'] ), 'inclusive' => true );
|
||||
}
|
||||
|
||||
// resources created before specified date
|
||||
if ( ! empty( $assoc_args['created_at_max'] ) ) {
|
||||
$args['date_query'][] = array( 'before' => $this->parse_datetime( $assoc_args['created_at_max'] ), 'inclusive' => true );
|
||||
}
|
||||
}
|
||||
|
||||
// Order (ASC or DESC, ASC by default).
|
||||
if ( ! empty( $assoc_args['order'] ) ) {
|
||||
$args['order'] = $assoc_args['order'];
|
||||
}
|
||||
|
||||
// Orderby.
|
||||
if ( ! empty( $assoc_args['orderby'] ) ) {
|
||||
$args['orderby'] = $assoc_args['orderby'];
|
||||
}
|
||||
|
||||
$args = apply_filters( 'woocommerce_cli_user_query_args', $args, $assoc_args );
|
||||
|
||||
return array_merge( $base_args, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an RFC3339 datetime into a MySQl datetime.
|
||||
*
|
||||
* Invalid dates default to unix epoch.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param string $datetime RFC3339 datetime
|
||||
* @return string MySQl datetime (YYYY-MM-DD HH:MM:SS)
|
||||
*/
|
||||
protected function parse_datetime( $datetime ) {
|
||||
// Strip millisecond precision (a full stop followed by one or more digits)
|
||||
if ( strpos( $datetime, '.' ) !== false ) {
|
||||
$datetime = preg_replace( '/\.\d+/', '', $datetime );
|
||||
}
|
||||
|
||||
// default timezone to UTC
|
||||
$datetime = preg_replace( '/[+-]\d+:+\d+$/', '+00:00', $datetime );
|
||||
|
||||
try {
|
||||
|
||||
$datetime = new DateTime( $datetime, new DateTimeZone( 'UTC' ) );
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
|
||||
$datetime = new DateTime( '@0' );
|
||||
|
||||
}
|
||||
|
||||
return $datetime->format( 'Y-m-d H:i:s' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a unix timestamp or MySQL datetime into an RFC3339 datetime.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param int|string $timestamp unix timestamp or MySQL datetime
|
||||
* @param bool $convert_to_utc
|
||||
* @return string RFC3339 datetime
|
||||
*/
|
||||
protected function format_datetime( $timestamp, $convert_to_utc = false ) {
|
||||
if ( $convert_to_utc ) {
|
||||
$timezone = new DateTimeZone( wc_timezone_string() );
|
||||
} else {
|
||||
$timezone = new DateTimeZone( 'UTC' );
|
||||
}
|
||||
|
||||
try {
|
||||
if ( is_numeric( $timestamp ) ) {
|
||||
$date = new DateTime( "@{$timestamp}" );
|
||||
} else {
|
||||
$date = new DateTime( $timestamp, $timezone );
|
||||
}
|
||||
|
||||
// convert to UTC by adjusting the time based on the offset of the site's timezone
|
||||
if ( $convert_to_utc ) {
|
||||
$date->modify( -1 * $date->getOffset() . ' seconds' );
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
$date = new DateTime( '@0' );
|
||||
}
|
||||
|
||||
return $date->format( 'Y-m-d\TH:i:s\Z' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get formatter object based on supplied arguments.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $assoc_args Associative args from CLI to determine formatting
|
||||
* @return \WP_CLI\Formatter
|
||||
*/
|
||||
protected function get_formatter( $assoc_args ) {
|
||||
$args = $this->get_format_args( $assoc_args );
|
||||
return new \WP_CLI\Formatter( $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default fields for formatter.
|
||||
*
|
||||
* Class that extends WC_CLI_Command should override this method.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return null|string|array
|
||||
*/
|
||||
protected function get_default_format_fields() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get format args that will be passed into CLI Formatter.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $assoc_args Associative args from CLI
|
||||
* @return array Formatter args
|
||||
*/
|
||||
protected function get_format_args( $assoc_args ) {
|
||||
$format_args = array(
|
||||
'fields' => $this->get_default_format_fields(),
|
||||
'field' => null,
|
||||
'format' => 'table',
|
||||
);
|
||||
|
||||
if ( isset( $assoc_args['fields'] ) ) {
|
||||
$format_args['fields'] = $assoc_args['fields'];
|
||||
}
|
||||
|
||||
if ( isset( $assoc_args['field'] ) ) {
|
||||
$format_args['field'] = $assoc_args['field'];
|
||||
}
|
||||
|
||||
if ( ! empty( $assoc_args['format'] ) && in_array( $assoc_args['format'], array( 'count', 'ids', 'table', 'csv', 'json' ) ) ) {
|
||||
$format_args['format'] = $assoc_args['format'];
|
||||
}
|
||||
|
||||
return $format_args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten multidimensional array in which nested array will be prefixed with
|
||||
* parent keys separated with dot char, e.g. given an array:
|
||||
*
|
||||
* array(
|
||||
* 'a' => array(
|
||||
* 'b' => array(
|
||||
* 'c' => ...
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* a flatten array would contain key 'a.b.c' => ...
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $arr Array that may contains nested array
|
||||
* @param string $prefix Prefix
|
||||
*
|
||||
* @return array Flattened array
|
||||
*/
|
||||
protected function flatten_array( $arr, $prefix = '' ) {
|
||||
$flattened = array();
|
||||
foreach ( $arr as $key => $value ) {
|
||||
if ( is_array( $value ) ) {
|
||||
if ( sizeof( $value ) > 0 ) {
|
||||
|
||||
// Full access to whole elements if indices are numerical.
|
||||
$flattened[ $prefix . $key ] = $value;
|
||||
|
||||
// This is naive assumption that if element with index zero
|
||||
// exists then array indices are numberical.
|
||||
if ( ! empty( $value[0] ) ) {
|
||||
|
||||
// Allow size of array to be accessed, i.e., a.b.arr.size
|
||||
$flattened[ $prefix . $key . '.size' ] = sizeof( $value );
|
||||
}
|
||||
|
||||
$flattened = array_merge( $flattened, $this->flatten_array( $value, $prefix . $key . '.' ) );
|
||||
} else {
|
||||
$flattened[ $prefix . $key ] = '';
|
||||
|
||||
// Tells user that size of this array is zero.
|
||||
$flattened[ $prefix . $key . '.size' ] = 0;
|
||||
}
|
||||
} else {
|
||||
$flattened[ $prefix . $key ] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $flattened;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unflatten array will make key 'a.b.c' becomes nested array:
|
||||
*
|
||||
* array(
|
||||
* 'a' => array(
|
||||
* 'b' => array(
|
||||
* 'c' => ...
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $arr Flattened array
|
||||
* @return array
|
||||
*/
|
||||
protected function unflatten_array( $arr ) {
|
||||
$unflatten = array();
|
||||
|
||||
foreach ( $arr as $key => $value ) {
|
||||
$key_list = explode( '.', $key );
|
||||
$first_key = array_shift( $key_list );
|
||||
$first_key = $this->get_normalized_array_key( $first_key );
|
||||
if ( sizeof( $key_list ) > 0 ) {
|
||||
$remaining_keys = implode( '.', $key_list );
|
||||
$subarray = $this->unflatten_array( array( $remaining_keys => $value ) );
|
||||
|
||||
foreach ( $subarray as $sub_key => $sub_value ) {
|
||||
$sub_key = $this->get_normalized_array_key( $sub_key );
|
||||
if ( ! empty( $unflatten[ $first_key ][ $sub_key ] ) ) {
|
||||
$unflatten[ $first_key ][ $sub_key ] = array_merge_recursive( $unflatten[ $first_key ][ $sub_key ], $sub_value );
|
||||
} else {
|
||||
$unflatten[ $first_key ][ $sub_key ] = $sub_value;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$unflatten[ $first_key ] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $unflatten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get normalized array key. If key is a numeric one it will be converted
|
||||
* as absolute integer.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param string $key Array key
|
||||
* @return string|int
|
||||
*/
|
||||
protected function get_normalized_array_key( $key ) {
|
||||
if ( is_numeric( $key ) ) {
|
||||
$key = absint( $key );
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the value is equal to 'yes', 'true' or '1'
|
||||
*
|
||||
* @since 2.5.4
|
||||
* @param string $value
|
||||
* @return boolean
|
||||
*/
|
||||
protected function is_true( $value ) {
|
||||
return ( 'yes' === $value || 'true' === $value || '1' === $value ) ? true : false;
|
||||
}
|
||||
}
|
|
@ -1,672 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Manage Coupons.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @package WooCommerce/CLI
|
||||
* @category CLI
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_CLI_Coupon extends WC_CLI_Command {
|
||||
|
||||
/**
|
||||
* Create a coupon.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : Associative args for the new coupon.
|
||||
*
|
||||
* [--porcelain]
|
||||
* : Outputs just the new coupon id.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields are available for create command:
|
||||
*
|
||||
* * code
|
||||
* * type
|
||||
* * amount
|
||||
* * description
|
||||
* * expiry_date
|
||||
* * individual_use
|
||||
* * product_ids
|
||||
* * exclude_product_ids
|
||||
* * usage_limit
|
||||
* * usage_limit_per_user
|
||||
* * limit_usage_to_x_items
|
||||
* * usage_count
|
||||
* * enable_free_shipping
|
||||
* * product_category_ids
|
||||
* * exclude_product_category_ids
|
||||
* * minimum_amount
|
||||
* * maximum_amount
|
||||
* * customer_emails
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc coupon create --code=new-coupon --type=percent
|
||||
*
|
||||
*/
|
||||
public function create( $__, $assoc_args ) {
|
||||
global $wpdb;
|
||||
|
||||
try {
|
||||
$porcelain = isset( $assoc_args['porcelain'] );
|
||||
unset( $assoc_args['porcelain'] );
|
||||
|
||||
$assoc_args = apply_filters( 'woocommerce_cli_create_coupon_data', $assoc_args );
|
||||
|
||||
// Check if coupon code is specified.
|
||||
if ( ! isset( $assoc_args['code'] ) ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_missing_coupon_code', sprintf( __( 'Missing parameter %s', 'woocommerce' ), 'code' ) );
|
||||
}
|
||||
|
||||
$coupon_code = apply_filters( 'woocommerce_coupon_code', $assoc_args['code'] );
|
||||
|
||||
// Check for duplicate coupon codes.
|
||||
$coupon_found = $wpdb->get_var( $wpdb->prepare( "
|
||||
SELECT $wpdb->posts.ID
|
||||
FROM $wpdb->posts
|
||||
WHERE $wpdb->posts.post_type = 'shop_coupon'
|
||||
AND $wpdb->posts.post_status = 'publish'
|
||||
AND $wpdb->posts.post_title = '%s'
|
||||
", $coupon_code ) );
|
||||
|
||||
if ( $coupon_found ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
$defaults = array(
|
||||
'type' => 'fixed_cart',
|
||||
'amount' => 0,
|
||||
'individual_use' => false,
|
||||
'product_ids' => array(),
|
||||
'exclude_product_ids' => array(),
|
||||
'usage_limit' => '',
|
||||
'usage_limit_per_user' => '',
|
||||
'limit_usage_to_x_items' => '',
|
||||
'usage_count' => '',
|
||||
'expiry_date' => '',
|
||||
'enable_free_shipping' => false,
|
||||
'product_category_ids' => array(),
|
||||
'exclude_product_category_ids' => array(),
|
||||
'exclude_sale_items' => false,
|
||||
'minimum_amount' => '',
|
||||
'maximum_amount' => '',
|
||||
'customer_emails' => array(),
|
||||
'description' => '',
|
||||
);
|
||||
|
||||
$coupon_data = wp_parse_args( $assoc_args, $defaults );
|
||||
|
||||
// Validate coupon types
|
||||
if ( ! in_array( wc_clean( $coupon_data['type'] ), array_keys( wc_get_coupon_types() ) ) ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_invalid_coupon_type', sprintf( __( 'Invalid coupon type - the coupon type must be any of these: %s', 'woocommerce' ), implode( ', ', array_keys( wc_get_coupon_types() ) ) ) );
|
||||
}
|
||||
|
||||
$new_coupon = array(
|
||||
'post_title' => $coupon_code,
|
||||
'post_content' => '',
|
||||
'post_status' => 'publish',
|
||||
'post_author' => get_current_user_id(),
|
||||
'post_type' => 'shop_coupon',
|
||||
'post_excerpt' => $coupon_data['description'],
|
||||
);
|
||||
|
||||
$id = wp_insert_post( $new_coupon, $wp_error = false );
|
||||
|
||||
if ( is_wp_error( $id ) ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_cannot_create_coupon', $id->get_error_message() );
|
||||
}
|
||||
|
||||
// Set coupon meta
|
||||
update_post_meta( $id, 'discount_type', $coupon_data['type'] );
|
||||
update_post_meta( $id, 'coupon_amount', wc_format_decimal( $coupon_data['amount'] ) );
|
||||
update_post_meta( $id, 'individual_use', ( $this->is_true( $coupon_data['individual_use'] ) ) ? 'yes' : 'no' );
|
||||
update_post_meta( $id, 'product_ids', implode( ',', array_filter( array_map( 'intval', $coupon_data['product_ids'] ) ) ) );
|
||||
update_post_meta( $id, 'exclude_product_ids', implode( ',', array_filter( array_map( 'intval', $coupon_data['exclude_product_ids'] ) ) ) );
|
||||
update_post_meta( $id, 'usage_limit', absint( $coupon_data['usage_limit'] ) );
|
||||
update_post_meta( $id, 'usage_limit_per_user', absint( $coupon_data['usage_limit_per_user'] ) );
|
||||
update_post_meta( $id, 'limit_usage_to_x_items', absint( $coupon_data['limit_usage_to_x_items'] ) );
|
||||
update_post_meta( $id, 'usage_count', absint( $coupon_data['usage_count'] ) );
|
||||
update_post_meta( $id, 'expiry_date', $this->get_coupon_expiry_date( wc_clean( $coupon_data['expiry_date'] ) ) );
|
||||
update_post_meta( $id, 'free_shipping', ( $this->is_true( $coupon_data['enable_free_shipping'] ) ) ? 'yes' : 'no' );
|
||||
update_post_meta( $id, 'product_categories', array_filter( array_map( 'intval', $coupon_data['product_category_ids'] ) ) );
|
||||
update_post_meta( $id, 'exclude_product_categories', array_filter( array_map( 'intval', $coupon_data['exclude_product_category_ids'] ) ) );
|
||||
update_post_meta( $id, 'exclude_sale_items', ( $this->is_true( $coupon_data['exclude_sale_items'] ) ) ? 'yes' : 'no' );
|
||||
update_post_meta( $id, 'minimum_amount', wc_format_decimal( $coupon_data['minimum_amount'] ) );
|
||||
update_post_meta( $id, 'maximum_amount', wc_format_decimal( $coupon_data['maximum_amount'] ) );
|
||||
update_post_meta( $id, 'customer_email', array_filter( array_map( 'sanitize_email', $coupon_data['customer_emails'] ) ) );
|
||||
|
||||
do_action( 'woocommerce_cli_create_coupon', $id, $coupon_data );
|
||||
|
||||
if ( $porcelain ) {
|
||||
WP_CLI::line( $id );
|
||||
} else {
|
||||
WP_CLI::success( "Created coupon $id." );
|
||||
}
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete one or more coupons.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <id>...
|
||||
* : The coupon ID to delete.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc coupon delete 123
|
||||
*
|
||||
* wp wc coupon delete $(wp wc coupon list --format=ids)
|
||||
*
|
||||
*/
|
||||
public function delete( $args, $assoc_args ) {
|
||||
$exit_code = 0;
|
||||
foreach ( $this->get_many_coupons_from_ids_or_codes( $args, true ) as $coupon ) {
|
||||
do_action( 'woocommerce_cli_delete_coupon', $coupon->get_id() );
|
||||
$r = wp_delete_post( $coupon->get_id(), true );
|
||||
|
||||
if ( $r ) {
|
||||
WP_CLI::success( "Deleted coupon " . $coupon->get_id() );
|
||||
} else {
|
||||
$exit_code += 1;
|
||||
WP_CLI::warning( "Failed deleting coupon " . $coupon->get_id() );
|
||||
}
|
||||
}
|
||||
exit( $exit_code ? 1 : 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a coupon.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <coupon>
|
||||
* : Coupon ID or code
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Instead of returning the whole coupon fields, returns the value of a single fields.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Get a specific subset of the coupon's fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Accepted values: table, json, csv. Default: table.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields are available for get command:
|
||||
*
|
||||
* * id
|
||||
* * code
|
||||
* * type
|
||||
* * amount
|
||||
* * description
|
||||
* * expiry_date
|
||||
* * individual_use
|
||||
* * product_ids
|
||||
* * exclude_product_ids
|
||||
* * usage_limit
|
||||
* * usage_limit_per_user
|
||||
* * limit_usage_to_x_items
|
||||
* * usage_count
|
||||
* * enable_free_shipping
|
||||
* * product_category_ids
|
||||
* * exclude_product_category_ids
|
||||
* * minimum_amount
|
||||
* * maximum_amount
|
||||
* * customer_emails
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc coupon get 123 --field=discount_type
|
||||
*
|
||||
* wp wc coupon get disc50 --format=json > disc50.json
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function get( $args, $assoc_args ) {
|
||||
global $wpdb;
|
||||
|
||||
try {
|
||||
$coupon = $this->get_coupon_from_id_or_code( $args[0] );
|
||||
if ( ! $coupon ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_invalid_coupon', sprintf( __( 'Invalid coupon ID or code: %s', 'woocommerce' ), $args[0] ) );
|
||||
}
|
||||
|
||||
$coupon_post = get_post( $coupon->get_id() );
|
||||
$coupon_usage_limit = $coupon->get_usage_limit();
|
||||
$coupon_usage_limit_per_user = $coupon->get_usage_limit_per_user();
|
||||
$coupon_date_expires = $coupon->get_date_expires();
|
||||
$coupon_data = array(
|
||||
'id' => $coupon->get_id(),
|
||||
'code' => $coupon->get_code(),
|
||||
'type' => $coupon->get_discount_type(),
|
||||
'created_at' => $this->format_datetime( $coupon_post->post_date_gmt ),
|
||||
'updated_at' => $this->format_datetime( $coupon_post->post_modified_gmt ),
|
||||
'amount' => wc_format_decimal( $coupon->get_amount(), 2 ),
|
||||
'individual_use' => $coupon->get_individual_use(),
|
||||
'product_ids' => implode( ', ', $coupon->get_product_ids() ),
|
||||
'exclude_product_ids' => implode( ', ', $coupon->get_excluded_product_ids() ),
|
||||
'usage_limit' => ( ! empty( $coupon_usage_limit ) ) ? $coupon_usage_limit : null,
|
||||
'usage_limit_per_user' => ( ! empty( $coupon_usage_limit_per_user ) ) ? $coupon_usage_limit_per_user : null,
|
||||
'limit_usage_to_x_items' => (int) $coupon->get_limit_usage_to_x_items(),
|
||||
'usage_count' => (int) $coupon->get_usage_count(),
|
||||
'expiry_date' => ( ! empty( $coupon_date_expires ) ) ? $this->format_datetime( $coupon_date_expires ) : null,
|
||||
'enable_free_shipping' => $coupon->get_free_shipping(),
|
||||
'product_category_ids' => implode( ', ', $coupon->get_product_categories() ),
|
||||
'exclude_product_category_ids' => implode( ', ', $coupon->get_excluded_product_categories() ),
|
||||
'exclude_sale_items' => $coupon->get_exclude_sale_items(),
|
||||
'minimum_amount' => wc_format_decimal( $coupon->get_minimum_amount(), 2 ),
|
||||
'maximum_amount' => wc_format_decimal( $coupon->get_maximum_amount(), 2 ),
|
||||
'customer_emails' => implode( ', ', $coupon->get_email_restrictions() ),
|
||||
'description' => $coupon_post->post_excerpt,
|
||||
);
|
||||
|
||||
$coupon_data = apply_filters( 'woocommerce_cli_get_coupon', $coupon_data );
|
||||
|
||||
if ( empty( $assoc_args['fields'] ) ) {
|
||||
$assoc_args['fields'] = array_keys( $coupon_data );
|
||||
}
|
||||
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
$formatter->display_item( $coupon_data );
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List coupons.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : Filter coupon based on coupon property.
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Prints the value of a single field for each coupon.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Limit the output to specific coupon fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Acceptec values: table, csv, json, count, ids. Default: table.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields will be displayed by default for each coupon:
|
||||
*
|
||||
* * id
|
||||
* * code
|
||||
* * type
|
||||
* * amount
|
||||
* * description
|
||||
* * expiry_date
|
||||
*
|
||||
* These fields are optionally available:
|
||||
*
|
||||
* * individual_use
|
||||
* * product_ids
|
||||
* * exclude_product_ids
|
||||
* * usage_limit
|
||||
* * usage_limit_per_user
|
||||
* * limit_usage_to_x_items
|
||||
* * usage_count
|
||||
* * free_shipping
|
||||
* * product_category_ids
|
||||
* * exclude_product_category_ids
|
||||
* * exclude_sale_items
|
||||
* * minimum_amount
|
||||
* * maximum_amount
|
||||
* * customer_emails
|
||||
*
|
||||
* Fields for filtering query result also available:
|
||||
*
|
||||
* * q Filter coupons with search query.
|
||||
* * in Specify coupon IDs to retrieve.
|
||||
* * not_in Specify coupon IDs NOT to retrieve.
|
||||
* * created_at_min Filter coupons created after this date.
|
||||
* * created_at_max Filter coupons created before this date.
|
||||
* * updated_at_min Filter coupons updated after this date.
|
||||
* * updated_at_max Filter coupons updated before this date.
|
||||
* * page Page number.
|
||||
* * offset Number of coupon to displace or pass over.
|
||||
* * order Accepted values: ASC and DESC. Default: DESC.
|
||||
* * orderby Sort retrieved coupons by parameter. One or more options can be passed.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc coupon list
|
||||
*
|
||||
* wp wc coupon list --field=id
|
||||
*
|
||||
* wp wc coupon list --fields=id,code,type --format=json
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @subcommand list
|
||||
*/
|
||||
public function list_( $__, $assoc_args ) {
|
||||
$query_args = $this->merge_wp_query_args( $this->get_list_query_args(), $assoc_args );
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
|
||||
if ( 'ids' === $formatter->format ) {
|
||||
$query_args['fields'] = 'ids';
|
||||
$query = new WP_Query( $query_args );
|
||||
echo implode( ' ', $query->posts );
|
||||
} else {
|
||||
$query = new WP_Query( $query_args );
|
||||
$items = $this->format_posts_to_items( $query->posts );
|
||||
$formatter->display_items( $items );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get coupon types.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc coupon types
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function types( $__, $___ ) {
|
||||
$coupon_types = wc_get_coupon_types();
|
||||
foreach ( $coupon_types as $type => $label ) {
|
||||
WP_CLI::line( sprintf( '%s: %s', $label, $type ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update one or more coupons.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <coupon>
|
||||
* : The ID or code of the coupon to update.
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : One or more fields to update.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields are available for update command:
|
||||
*
|
||||
* * code
|
||||
* * type
|
||||
* * amount
|
||||
* * description
|
||||
* * expiry_date
|
||||
* * individual_use
|
||||
* * product_ids
|
||||
* * exclude_product_ids
|
||||
* * usage_limit
|
||||
* * usage_limit_per_user
|
||||
* * limit_usage_to_x_items
|
||||
* * usage_count
|
||||
* * enable_free_shipping
|
||||
* * product_category_ids
|
||||
* * exclude_product_categories
|
||||
* * exclude_product_category_ids
|
||||
* * minimum_amount
|
||||
* * maximum_amount
|
||||
* * customer_emails
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc coupon update 123 --amount=5
|
||||
*
|
||||
* wp wc coupon update coupon-code --code=new-coupon-code
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function update( $args, $assoc_args ) {
|
||||
try {
|
||||
$coupon = $this->get_coupon_from_id_or_code( $args[0] );
|
||||
if ( ! $coupon ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_invalid_coupon', sprintf( __( 'Invalid coupon ID or code: %s', 'woocommerce' ), $args[0] ) );
|
||||
}
|
||||
|
||||
$id = $coupon->get_id();
|
||||
$coupon_code = $coupon->get_code();
|
||||
$data = apply_filters( 'woocommerce_cli_update_coupon_data', $assoc_args, $id );
|
||||
if ( isset( $data['code'] ) ) {
|
||||
global $wpdb;
|
||||
|
||||
$coupon_code = apply_filters( 'woocommerce_coupon_code', $data['code'] );
|
||||
|
||||
// Check for duplicate coupon codes
|
||||
$coupon_found = $wpdb->get_var( $wpdb->prepare( "
|
||||
SELECT $wpdb->posts.ID
|
||||
FROM $wpdb->posts
|
||||
WHERE $wpdb->posts.post_type = 'shop_coupon'
|
||||
AND $wpdb->posts.post_status = 'publish'
|
||||
AND $wpdb->posts.post_title = '%s'
|
||||
AND $wpdb->posts.ID != %s
|
||||
", $coupon_code, $id ) );
|
||||
|
||||
if ( $coupon_found ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ) );
|
||||
}
|
||||
}
|
||||
|
||||
$id = wp_update_post( array( 'ID' => intval( $id ), 'post_title' => $coupon_code, 'post_excerpt' => isset( $data['description'] ) ? $data['description'] : '' ) );
|
||||
if ( 0 === $id ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_cannot_update_coupon', __( 'Failed to update coupon', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['type'] ) ) {
|
||||
// Validate coupon types.
|
||||
if ( ! in_array( wc_clean( $data['type'] ), array_keys( wc_get_coupon_types() ) ) ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_invalid_coupon_type', sprintf( __( 'Invalid coupon type - the coupon type must be any of these: %s', 'woocommerce' ), implode( ', ', array_keys( wc_get_coupon_types() ) ) ) );
|
||||
}
|
||||
update_post_meta( $id, 'discount_type', $data['type'] );
|
||||
}
|
||||
|
||||
if ( isset( $data['amount'] ) ) {
|
||||
update_post_meta( $id, 'coupon_amount', wc_format_decimal( $data['amount'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['individual_use'] ) ) {
|
||||
update_post_meta( $id, 'individual_use', ( $this->is_true( $data['individual_use'] ) ) ? 'yes' : 'no' );
|
||||
}
|
||||
|
||||
if ( isset( $data['product_ids'] ) ) {
|
||||
update_post_meta( $id, 'product_ids', implode( ',', array_filter( array_map( 'intval', $data['product_ids'] ) ) ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['exclude_product_ids'] ) ) {
|
||||
update_post_meta( $id, 'exclude_product_ids', implode( ',', array_filter( array_map( 'intval', $data['exclude_product_ids'] ) ) ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['usage_limit'] ) ) {
|
||||
update_post_meta( $id, 'usage_limit', absint( $data['usage_limit'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['usage_limit_per_user'] ) ) {
|
||||
update_post_meta( $id, 'usage_limit_per_user', absint( $data['usage_limit_per_user'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['limit_usage_to_x_items'] ) ) {
|
||||
update_post_meta( $id, 'limit_usage_to_x_items', absint( $data['limit_usage_to_x_items'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['usage_count'] ) ) {
|
||||
update_post_meta( $id, 'usage_count', absint( $data['usage_count'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['expiry_date'] ) ) {
|
||||
update_post_meta( $id, 'expiry_date', $this->get_coupon_expiry_date( wc_clean( $data['expiry_date'] ) ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['enable_free_shipping'] ) ) {
|
||||
update_post_meta( $id, 'free_shipping', ( $this->is_true( $data['enable_free_shipping'] ) ) ? 'yes' : 'no' );
|
||||
}
|
||||
|
||||
if ( isset( $data['product_category_ids'] ) ) {
|
||||
update_post_meta( $id, 'product_categories', array_filter( array_map( 'intval', $data['product_category_ids'] ) ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['exclude_product_category_ids'] ) ) {
|
||||
update_post_meta( $id, 'exclude_product_categories', array_filter( array_map( 'intval', $data['exclude_product_category_ids'] ) ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['exclude_sale_items'] ) ) {
|
||||
update_post_meta( $id, 'exclude_sale_items', ( $this->is_true( $data['exclude_sale_items'] ) ) ? 'yes' : 'no' );
|
||||
}
|
||||
|
||||
if ( isset( $data['minimum_amount'] ) ) {
|
||||
update_post_meta( $id, 'minimum_amount', wc_format_decimal( $data['minimum_amount'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['maximum_amount'] ) ) {
|
||||
update_post_meta( $id, 'maximum_amount', wc_format_decimal( $data['maximum_amount'] ) );
|
||||
}
|
||||
|
||||
if ( isset( $data['customer_emails'] ) ) {
|
||||
update_post_meta( $id, 'customer_email', array_filter( array_map( 'sanitize_email', $data['customer_emails'] ) ) );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_cli_update_coupon', $id, $data );
|
||||
|
||||
WP_CLI::success( "Updated coupon $id." );
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get query args for list subcommand.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return array
|
||||
*/
|
||||
protected function get_list_query_args() {
|
||||
return array(
|
||||
'post_type' => 'shop_coupon',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => -1,
|
||||
'order' => 'DESC',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default format fields that will be used in `list` and `get` subcommands.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return string
|
||||
*/
|
||||
protected function get_default_format_fields() {
|
||||
return 'id,code,type,amount,description,expiry_date';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format posts from WP_Query result to items in which each item contain
|
||||
* common properties of item, for instance `post_title` will be `code`.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $posts Array of post
|
||||
* @return array Items
|
||||
*/
|
||||
protected function format_posts_to_items( $posts ) {
|
||||
$items = array();
|
||||
foreach ( $posts as $post ) {
|
||||
$coupon = new WC_Coupon;
|
||||
$coupon->read( $post->ID );
|
||||
$coupon_usage_limit = $coupon->get_usage_limit();
|
||||
$coupon_usage_limit_per_user = $coupon->get_usage_limit_per_user();
|
||||
$coupon_date_expires = $coupon->get_date_expires();
|
||||
$items[] = array(
|
||||
'id' => $post->ID,
|
||||
'code' => $post->post_title,
|
||||
'type' => $coupon->get_discount_type(),
|
||||
'created_at' => $this->format_datetime( $post->post_date_gmt ),
|
||||
'updated_at' => $this->format_datetime( $post->post_modified_gmt ),
|
||||
'amount' => wc_format_decimal( $coupon->get_amount(), 2 ),
|
||||
'individual_use' => $coupon->get_individual_use(),
|
||||
'product_ids' => implode( ', ', is_array( $coupon->get_product_ids() ) ? $coupon->get_product_ids() : array() ),
|
||||
'exclude_product_ids' => implode( ', ', is_array( $coupon->get_excluded_product_ids() ) ? $coupon->get_excluded_product_ids() : array() ),
|
||||
'usage_limit' => ( ! empty( $coupon_usage_limit ) ) ? $coupon_usage_limit : null,
|
||||
'usage_limit_per_user' => ( ! empty( $coupon_usage_limit_per_user ) ) ? $coupon_usage_limit_per_user : null,
|
||||
'limit_usage_to_x_items' => (int) $coupon->get_limit_usage_to_x_items(),
|
||||
'usage_count' => (int) $coupon->get_usage_count(),
|
||||
'expiry_date' => ( ! empty( $coupon_date_expires ) ) ? $this->format_datetime( $coupon_date_expires ) : null,
|
||||
'free_shipping' => $coupon->get_free_shipping(),
|
||||
'product_category_ids' => implode( ', ', is_array( $coupon->get_product_categories() ) ? $coupon->get_product_categories() : array() ),
|
||||
'exclude_product_category_ids' => implode( ', ', is_array( $coupon->get_excluded_product_categories() ) ? $coupon->get_excluded_product_categories() : array() ),
|
||||
'exclude_sale_items' => $coupon->get_exclude_sale_items(),
|
||||
'minimum_amount' => wc_format_decimal( $coupon->get_minimum_amount(), 2 ),
|
||||
'maximum_amount' => wc_format_decimal( $coupon->get_maximum_amount(), 2 ),
|
||||
'customer_emails' => implode( ', ', is_array( $coupon->get_email_restrictions() ) ? $coupon->get_email_restrictions() : array() ),
|
||||
'description' => $post->post_excerpt,
|
||||
);
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get expiry_date format before saved into DB.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param string $expiry_date
|
||||
* @return string
|
||||
*/
|
||||
protected function get_coupon_expiry_date( $expiry_date ) {
|
||||
if ( '' !== $expiry_date ) {
|
||||
return date( 'Y-m-d', strtotime( $expiry_date ) );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get coupon from coupon's ID or code.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param int|string $coupon_id_or_code Coupon's ID or code
|
||||
* @param bool $display_warning Display warning if ID or code is invalid. Default false.
|
||||
* @return WC_Coupon
|
||||
*/
|
||||
protected function get_coupon_from_id_or_code( $coupon_id_or_code, $display_warning = false ) {
|
||||
global $wpdb;
|
||||
|
||||
$code = $wpdb->get_var( $wpdb->prepare( "SELECT post_title FROM $wpdb->posts WHERE (id = %s OR post_title = %s) AND post_type = 'shop_coupon' AND post_status = 'publish' LIMIT 1", $coupon_id_or_code, $coupon_id_or_code ) );
|
||||
if ( ! $code ) {
|
||||
if ( $display_warning ) {
|
||||
WP_CLI::warning( "Invalid coupon ID or code $coupon_id_or_code" );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return new WC_Coupon( $code );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get coupon from coupon's ID or code.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $args Coupon's IDs or codes
|
||||
* @param bool $display_warning Display warning if ID or code is invalid. Default false.
|
||||
* @return WC_Coupon
|
||||
*/
|
||||
protected function get_many_coupons_from_ids_or_codes( $args, $display_warning = false ) {
|
||||
$coupons = array();
|
||||
|
||||
foreach ( $args as $arg ) {
|
||||
$code = $this->get_coupon_from_id_or_code( $arg, $display_warning );
|
||||
if ( $code ) {
|
||||
$coupons[] = $code;
|
||||
}
|
||||
}
|
||||
|
||||
return $coupons;
|
||||
}
|
||||
}
|
|
@ -1,742 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Manage Customers.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @package WooCommerce/CLI
|
||||
* @category CLI
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_CLI_Customer extends WC_CLI_Command {
|
||||
|
||||
/**
|
||||
* Create a customer.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <email>
|
||||
* : The email address of the customer to create.
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : Associative args for the new customer.
|
||||
*
|
||||
* [--porcelain]
|
||||
* : Outputs just the new customer id.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields are optionally available for create command:
|
||||
*
|
||||
* * username
|
||||
* * password
|
||||
* * first_name
|
||||
* * last_name
|
||||
*
|
||||
* Billing address fields:
|
||||
*
|
||||
* * billing_address.first_name
|
||||
* * billing_address.last_name
|
||||
* * billing_address.company
|
||||
* * billing_address.address_1
|
||||
* * billing_address.address_2
|
||||
* * billing_address.city
|
||||
* * billing_address.state
|
||||
* * billing_address.postcode
|
||||
* * billing_address.country
|
||||
* * billing_address.email
|
||||
* * billing_address.phone
|
||||
*
|
||||
* Shipping address fields:
|
||||
*
|
||||
* * shipping_address.first_name
|
||||
* * shipping_address.last_name
|
||||
* * shipping_address.company
|
||||
* * shipping_address.address_1
|
||||
* * shipping_address.address_2
|
||||
* * shipping_address.city
|
||||
* * shipping_address.state
|
||||
* * shipping_address.postcode
|
||||
* * shipping_address.country
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc customer create new-customer@example.com --first_name=Akeda
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function create( $args, $assoc_args ) {
|
||||
global $wpdb;
|
||||
|
||||
try {
|
||||
$porcelain = isset( $assoc_args['porcelain'] );
|
||||
unset( $assoc_args['porcelain'] );
|
||||
|
||||
$assoc_args['email'] = $args[0];
|
||||
$data = apply_filters( 'woocommerce_cli_create_customer_data', $this->unflatten_array( $assoc_args ) );
|
||||
|
||||
// Sets the username.
|
||||
$data['username'] = ! empty( $data['username'] ) ? $data['username'] : '';
|
||||
|
||||
// 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_CLI_Exception( $id->get_error_code(), $id->get_error_message() );
|
||||
}
|
||||
|
||||
// Added customer data.
|
||||
$this->update_customer_data( $id, $data );
|
||||
|
||||
do_action( 'woocommerce_cli_create_customer', $id, $data );
|
||||
|
||||
if ( $porcelain ) {
|
||||
WP_CLI::line( $id );
|
||||
} else {
|
||||
WP_CLI::success( "Created customer $id." );
|
||||
}
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete one or more customers.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <customer>...
|
||||
* : The customer ID, email, or username to delete.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc customer delete 123
|
||||
*
|
||||
* wp wc customer delete $(wp wc customer list --format=ids)
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function delete( $args, $assoc_args ) {
|
||||
$exit_code = 0;
|
||||
foreach ( $args as $arg ) {
|
||||
try {
|
||||
$customer = $this->get_user( $arg );
|
||||
do_action( 'woocommerce_cli_delete_customer', $customer['id'] );
|
||||
$r = wp_delete_user( $customer['id'] );
|
||||
|
||||
if ( $r ) {
|
||||
WP_CLI::success( "Deleted customer {$customer['id']}." );
|
||||
} else {
|
||||
$exit_code += 1;
|
||||
WP_CLI::warning( "Failed deleting customer {$customer['id']}." );
|
||||
}
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::warning( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
exit( $exit_code ? 1 : 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* View customer downloads.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <customer>
|
||||
* : The customer ID, email or username.
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Instead of returning the whole customer fields, returns the value of a single fields.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Get a specific subset of the customer's fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Accepted values: table, json, csv. Default: table.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* * download_id
|
||||
* * download_name
|
||||
* * access_expires
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc customer downloads 123
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function downloads( $args, $assoc_args ) {
|
||||
try {
|
||||
$user = $this->get_user( $args[0] );
|
||||
$downloads = array();
|
||||
foreach ( wc_get_customer_available_downloads( $user['id'] ) as $key => $download ) {
|
||||
$downloads[ $key ] = $download;
|
||||
$downloads[ $key ]['access_expires'] = $this->format_datetime( $download['access_expires'] );
|
||||
}
|
||||
$downloads = apply_filters( 'woocommerce_cli_customer_downloads', $downloads, $user, $assoc_args );
|
||||
|
||||
if ( empty( $assoc_args['fields'] ) ) {
|
||||
$assoc_args['fields'] = $this->get_customer_download_fields();
|
||||
}
|
||||
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
$formatter->display_items( $downloads );
|
||||
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a customer.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <customer>
|
||||
* : Customer ID, email, or username.
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Instead of returning the whole customer fields, returns the value of a single fields.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Get a specific subset of the customer's fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Accepted values: table, json, csv. Default: table.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* * id
|
||||
* * email
|
||||
* * first_name
|
||||
* * last_name
|
||||
* * created_at
|
||||
* * username
|
||||
* * last_order_id
|
||||
* * last_order_date
|
||||
* * orders_count
|
||||
* * total_spent
|
||||
* * avatar_url
|
||||
*
|
||||
* Billing address fields:
|
||||
*
|
||||
* * billing_address.first_name
|
||||
* * billing_address.last_name
|
||||
* * billing_address.company
|
||||
* * billing_address.address_1
|
||||
* * billing_address.address_2
|
||||
* * billing_address.city
|
||||
* * billing_address.state
|
||||
* * billing_address.postcode
|
||||
* * billing_address.country
|
||||
* * billing_address.email
|
||||
* * billing_address.phone
|
||||
*
|
||||
* Shipping address fields:
|
||||
*
|
||||
* * shipping_address.first_name
|
||||
* * shipping_address.last_name
|
||||
* * shipping_address.company
|
||||
* * shipping_address.address_1
|
||||
* * shipping_address.address_2
|
||||
* * shipping_address.city
|
||||
* * shipping_address.state
|
||||
* * shipping_address.postcode
|
||||
* * shipping_address.country
|
||||
*
|
||||
* Fields for filtering query result also available:
|
||||
*
|
||||
* * role Filter customers associated with certain role.
|
||||
* * q Filter customers with search query.
|
||||
* * created_at_min Filter customers whose registered after this date.
|
||||
* * created_at_max Filter customers whose registered before this date.
|
||||
* * limit The maximum returned number of results.
|
||||
* * offset Offset the returned results.
|
||||
* * order Accepted values: ASC and DESC. Default: DESC.
|
||||
* * orderby Sort retrieved customers by parameter. One or more options can be passed.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc customer get 123 --field=email
|
||||
*
|
||||
* wp wc customer get customer-login --format=json
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function get( $args, $assoc_args ) {
|
||||
try {
|
||||
$user = $this->get_user( $args[0] );
|
||||
|
||||
if ( empty( $assoc_args['fields'] ) ) {
|
||||
$assoc_args['fields'] = array_keys( $user );
|
||||
}
|
||||
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
$formatter->display_item( $user );
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List customers.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : Filter customer based on customer property.
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Prints the value of a single field for each customer.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Limit the output to specific customer fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Acceptec values: table, csv, json, count, ids. Default: table.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields will be displayed by default for each customer:
|
||||
*
|
||||
* * id
|
||||
* * email
|
||||
* * first_name
|
||||
* * last_name
|
||||
* * created_at
|
||||
*
|
||||
* These fields are optionally available:
|
||||
*
|
||||
* * username
|
||||
* * last_order_id
|
||||
* * last_order_date
|
||||
* * orders_count
|
||||
* * total_spent
|
||||
* * avatar_url
|
||||
*
|
||||
* Billing address fields:
|
||||
*
|
||||
* * billing_address.first_name
|
||||
* * billing_address.last_name
|
||||
* * billing_address.company
|
||||
* * billing_address.address_1
|
||||
* * billing_address.address_2
|
||||
* * billing_address.city
|
||||
* * billing_address.state
|
||||
* * billing_address.postcode
|
||||
* * billing_address.country
|
||||
* * billing_address.email
|
||||
* * billing_address.phone
|
||||
*
|
||||
* Shipping address fields:
|
||||
*
|
||||
* * shipping_address.first_name
|
||||
* * shipping_address.last_name
|
||||
* * shipping_address.company
|
||||
* * shipping_address.address_1
|
||||
* * shipping_address.address_2
|
||||
* * shipping_address.city
|
||||
* * shipping_address.state
|
||||
* * shipping_address.postcode
|
||||
* * shipping_address.country
|
||||
*
|
||||
* Fields for filtering query result also available:
|
||||
*
|
||||
* * role Filter customers associated with certain role.
|
||||
* * q Filter customers with search query.
|
||||
* * created_at_min Filter customers whose registered after this date.
|
||||
* * created_at_max Filter customers whose registered before this date.
|
||||
* * limit The maximum returned number of results.
|
||||
* * offset Offset the returned results.
|
||||
* * order Accepted values: ASC and DESC. Default: DESC.
|
||||
* * orderby Sort retrieved customers by parameter. One or more options can be passed.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc customer list
|
||||
*
|
||||
* wp wc customer list --field=id
|
||||
*
|
||||
* wp wc customer list --fields=id,email,first_name --format=json
|
||||
*
|
||||
* @subcommand list
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function list_( $__, $assoc_args ) {
|
||||
$query_args = $this->merge_wp_user_query_args( $this->get_list_query_args(), $assoc_args );
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
|
||||
if ( 'ids' === $formatter->format ) {
|
||||
$query_args['fields'] = 'ids';
|
||||
$query = new WP_User_Query( $query_args );
|
||||
echo implode( ' ', $query->results );
|
||||
} else {
|
||||
$query = new WP_User_Query( $query_args );
|
||||
$items = $this->format_users_to_items( $query->results );
|
||||
$formatter->display_items( $items );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View customer orders.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <customer>
|
||||
* : The customer ID, email or username.
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Instead of returning the whole customer fields, returns the value of a single fields.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Get a specific subset of the customer's fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Accepted values: table, json, csv. Default: table.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* For more fields, see: wp wc order list --help
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc customer orders 123
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function orders( $args, $assoc_args ) {
|
||||
try {
|
||||
WP_CLI::run_command( array( 'wc', 'order', 'list' ), array( 'customer_id' => $args[0] ) );
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update one or more customers.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <customer>
|
||||
* : Customer ID, email, or username.
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : One or more fields to update.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields are available for update command:
|
||||
*
|
||||
* * email
|
||||
* * password
|
||||
* * first_name
|
||||
* * last_name
|
||||
*
|
||||
* Billing address fields:
|
||||
*
|
||||
* * billing_address.first_name
|
||||
* * billing_address.last_name
|
||||
* * billing_address.company
|
||||
* * billing_address.address_1
|
||||
* * billing_address.address_2
|
||||
* * billing_address.city
|
||||
* * billing_address.state
|
||||
* * billing_address.postcode
|
||||
* * billing_address.country
|
||||
* * billing_address.email
|
||||
* * billing_address.phone
|
||||
*
|
||||
* Shipping address fields:
|
||||
*
|
||||
* * shipping_address.first_name
|
||||
* * shipping_address.last_name
|
||||
* * shipping_address.company
|
||||
* * shipping_address.address_1
|
||||
* * shipping_address.address_2
|
||||
* * shipping_address.city
|
||||
* * shipping_address.state
|
||||
* * shipping_address.postcode
|
||||
* * shipping_address.country
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc customer update customer-login --first_name=akeda --last_name=bagus
|
||||
*
|
||||
* wp wc customer update customer@example.com --password=new-password
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function update( $args, $assoc_args ) {
|
||||
try {
|
||||
$user = $this->get_user( $args[0] );
|
||||
$data = $this->unflatten_array( $assoc_args );
|
||||
$data = apply_filters( 'woocommerce_cli_update_customer_data', $data );
|
||||
|
||||
// Customer email.
|
||||
if ( isset( $data['email'] ) ) {
|
||||
wp_update_user( array( 'ID' => $user['id'], 'user_email' => sanitize_email( $data['email'] ) ) );
|
||||
}
|
||||
|
||||
// Customer password.
|
||||
if ( isset( $data['password'] ) ) {
|
||||
wp_update_user( array( 'ID' => $user['id'], 'user_pass' => wc_clean( $data['password'] ) ) );
|
||||
}
|
||||
|
||||
// Update customer data.
|
||||
$this->update_customer_data( $user['id'], $data );
|
||||
|
||||
do_action( 'woocommerce_cli_update_customer', $user['id'], $data );
|
||||
|
||||
WP_CLI::success( "Updated customer {$user['id']}." );
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get query args for list subcommand.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return array
|
||||
*/
|
||||
protected function get_list_query_args() {
|
||||
return array(
|
||||
'role' => 'customer',
|
||||
'orderby' => 'registered',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default format fields that will be used in `list` and `get` subcommands.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return string
|
||||
*/
|
||||
protected function get_default_format_fields() {
|
||||
return 'id,email,first_name,last_name,created_at';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format users from WP_User_Query result to items in which each item contain
|
||||
* common properties of item.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $users Array of user
|
||||
* @return array Items
|
||||
*/
|
||||
protected function format_users_to_items( $users ) {
|
||||
$items = array();
|
||||
foreach ( $users as $user ) {
|
||||
try {
|
||||
$items[] = $this->get_user( $user->ID );
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::warning( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user from given user ID, email, or login
|
||||
*
|
||||
* @throws WC_CLI_Exception
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param mixed $id_email_or_login
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
protected function get_user( $id_email_or_login ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( is_numeric( $id_email_or_login ) ) {
|
||||
$user = get_user_by( 'id', $id_email_or_login );
|
||||
} elseif ( is_email( $id_email_or_login ) ) {
|
||||
$user = get_user_by( 'email', $id_email_or_login );
|
||||
} else {
|
||||
$user = get_user_by( 'login', $id_email_or_login );
|
||||
}
|
||||
|
||||
if ( ! $user ) {
|
||||
/* translators: %s: id email or login */
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_invalid_customer', sprintf( __( 'Invalid customer "%s"', 'woocommerce' ), $id_email_or_login ) );
|
||||
}
|
||||
|
||||
// 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 = {$user->ID}
|
||||
AND posts.post_type = 'shop_order'
|
||||
AND posts.post_status IN ( '" . implode( "','", array_keys( wc_get_order_statuses() ) ) . "' )
|
||||
ORDER BY posts.ID DESC
|
||||
" );
|
||||
|
||||
$customer = array(
|
||||
'id' => $user->ID,
|
||||
'created_at' => $this->format_datetime( $user->user_registered ),
|
||||
'email' => $user->user_email,
|
||||
'first_name' => $user->first_name,
|
||||
'last_name' => $user->last_name,
|
||||
'username' => $user->user_login,
|
||||
'role' => $user->roles[0],
|
||||
'last_order_id' => is_object( $last_order ) ? $last_order->get_id() : null,
|
||||
'last_order_date' => is_object( $last_order ) ? $this->format_datetime( $last_order->post_date_gmt ) : null,
|
||||
'orders_count' => wc_get_customer_order_count( $user->ID ),
|
||||
'total_spent' => wc_format_decimal( wc_get_customer_total_spent( $user->ID ), 2 ),
|
||||
'avatar_url' => $this->get_avatar_url( $user->customer_email ),
|
||||
'billing_address' => array(
|
||||
'first_name' => $user->billing_first_name,
|
||||
'last_name' => $user->billing_last_name,
|
||||
'company' => $user->billing_company,
|
||||
'address_1' => $user->billing_address_1,
|
||||
'address_2' => $user->billing_address_2,
|
||||
'city' => $user->billing_city,
|
||||
'state' => $user->billing_state,
|
||||
'postcode' => $user->billing_postcode,
|
||||
'country' => $user->billing_country,
|
||||
'email' => $user->billing_email,
|
||||
'phone' => $user->billing_phone,
|
||||
),
|
||||
'shipping_address' => array(
|
||||
'first_name' => $user->shipping_first_name,
|
||||
'last_name' => $user->shipping_last_name,
|
||||
'company' => $user->shipping_company,
|
||||
'address_1' => $user->shipping_address_1,
|
||||
'address_2' => $user->shipping_address_2,
|
||||
'city' => $user->shipping_city,
|
||||
'state' => $user->shipping_state,
|
||||
'postcode' => $user->shipping_postcode,
|
||||
'country' => $user->shipping_country,
|
||||
),
|
||||
);
|
||||
|
||||
// Allow dot notation for nested array so that user can specifies field
|
||||
// like 'billing_address.first_name'.
|
||||
return $this->flatten_array( $customer );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.5.0
|
||||
* @param string $email the customer's email
|
||||
* @return string the URL to the customer's avatar
|
||||
*/
|
||||
protected 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/Update customer data.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param int $id The customer ID
|
||||
* @param array $data
|
||||
*/
|
||||
protected function update_customer_data( $id, $data ) {
|
||||
// Customer first name.
|
||||
if ( isset( $data['first_name'] ) ) {
|
||||
update_user_meta( $id, '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 billing address.
|
||||
if ( isset( $data['billing_address'] ) ) {
|
||||
foreach ( $this->get_customer_billing_address_fields() as $address ) {
|
||||
if ( isset( $data['billing_address'][ $address ] ) ) {
|
||||
update_user_meta( $id, 'billing_' . $address, wc_clean( $data['billing_address'][ $address ] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Customer shipping address.
|
||||
if ( isset( $data['shipping_address'] ) ) {
|
||||
foreach ( $this->get_customer_shipping_address_fields() as $address ) {
|
||||
if ( isset( $data['shipping_address'][ $address ] ) ) {
|
||||
update_user_meta( $id, 'shipping_' . $address, wc_clean( $data['shipping_address'][ $address ] ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_cli_update_customer_data', $id, $data );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get customer billing address fields.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return array
|
||||
*/
|
||||
protected function get_customer_billing_address_fields() {
|
||||
return apply_filters( 'woocommerce_cli_customer_billing_address_fields', array(
|
||||
'first_name',
|
||||
'last_name',
|
||||
'company',
|
||||
'address_1',
|
||||
'address_2',
|
||||
'city',
|
||||
'state',
|
||||
'postcode',
|
||||
'country',
|
||||
'email',
|
||||
'phone',
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get customer shipping address fields.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return array
|
||||
*/
|
||||
protected function get_customer_shipping_address_fields() {
|
||||
return apply_filters( 'woocommerce_cli_customer_shipping_address_fields', array(
|
||||
'first_name',
|
||||
'last_name',
|
||||
'company',
|
||||
'address_1',
|
||||
'address_2',
|
||||
'city',
|
||||
'state',
|
||||
'postcode',
|
||||
'country',
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get customer download fields.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return array
|
||||
*/
|
||||
protected function get_customer_download_fields() {
|
||||
return apply_filters( 'woocommerce_cli_customer_download_fields', array(
|
||||
'download_id',
|
||||
'download_name',
|
||||
'access_expires',
|
||||
) );
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* WooCommerce CLI Exception Class.
|
||||
*
|
||||
* Extends Exception to provide additional data.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @package WooCommerce/CLI
|
||||
* @category CLI
|
||||
* @author WooThemes
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
class WC_CLI_Exception extends Exception {
|
||||
|
||||
/** @var string sanitized error code */
|
||||
protected $error_code;
|
||||
|
||||
/**
|
||||
* Setup exception, requires 3 params:
|
||||
*
|
||||
* error code - machine-readable, e.g. `woocommerce_invalid_product_id`
|
||||
* error message - friendly message, e.g. 'Product ID is invalid'
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param string $error_code
|
||||
* @param string $error_message user-friendly translated error message
|
||||
*/
|
||||
public function __construct( $error_code, $error_message ) {
|
||||
$this->error_code = $error_code;
|
||||
parent::__construct( $error_message );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error code
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return string
|
||||
*/
|
||||
public function getErrorCode() {
|
||||
return $this->error_code;
|
||||
}
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Manage Product Categories.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @package WooCommerce/CLI
|
||||
* @category CLI
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_CLI_Product_Category extends WC_CLI_Command {
|
||||
|
||||
/**
|
||||
* Get product category.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <id>
|
||||
* : Product category ID.
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Instead of returning the whole product category fields, returns the value of a single fields.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Get a specific subset of the product category's fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Accepted values: table, json, csv. Default: table.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* * id
|
||||
* * name
|
||||
* * slug
|
||||
* * parent
|
||||
* * description
|
||||
* * display
|
||||
* * image
|
||||
* * count
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc product category get 123
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function get( $args, $assoc_args ) {
|
||||
try {
|
||||
$product_category = $this->get_product_category( $args[0] );
|
||||
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
$formatter->display_item( $product_category );
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List of product categories.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : Filter products based on product property.
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Prints the value of a single field for each product.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Limit the output to specific product fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Acceptec values: table, csv, json, count, ids. Default: table.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* * id
|
||||
* * name
|
||||
* * slug
|
||||
* * parent
|
||||
* * description
|
||||
* * display
|
||||
* * image
|
||||
* * count
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc product category list
|
||||
*
|
||||
* wp wc product category list --fields=id,name --format=json
|
||||
*
|
||||
* @subcommand list
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function list_( $__, $assoc_args ) {
|
||||
try {
|
||||
$product_categories = array();
|
||||
$terms = get_terms( 'product_cat', array( 'hide_empty' => false, 'fields' => 'ids' ) );
|
||||
|
||||
foreach ( $terms as $term_id ) {
|
||||
$product_categories[] = $this->get_product_category( $term_id );
|
||||
}
|
||||
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
$formatter->display_items( $product_categories );
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get product category properties from given term ID.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param int $term_id Category term ID
|
||||
* @return array
|
||||
* @throws WC_CLI_Exception
|
||||
*/
|
||||
protected function get_product_category( $term_id ) {
|
||||
$term_id = absint( $term_id );
|
||||
$term = get_term( $term_id, 'product_cat' );
|
||||
|
||||
if ( is_wp_error( $term ) || is_null( $term ) ) {
|
||||
/* translators: %s: product category ID */
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_invalid_product_category_id', sprintf( __( 'Invalid product category ID "%s"', 'woocommerce' ), $term_id ) );
|
||||
}
|
||||
|
||||
$term_id = intval( $term->term_id );
|
||||
|
||||
// Get category display type.
|
||||
$display_type = get_woocommerce_term_meta( $term_id, 'display_type' );
|
||||
|
||||
// Get category image.
|
||||
$image = '';
|
||||
if ( $image_id = get_woocommerce_term_meta( $term_id, 'thumbnail_id' ) ) {
|
||||
$image = wp_get_attachment_url( $image_id );
|
||||
}
|
||||
|
||||
return array(
|
||||
'id' => $term_id,
|
||||
'name' => $term->name,
|
||||
'slug' => $term->slug,
|
||||
'parent' => $term->parent,
|
||||
'description' => $term->description,
|
||||
'display' => $display_type ? $display_type : 'default',
|
||||
'image' => $image ? esc_url( $image ) : '',
|
||||
'count' => intval( $term->count ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default format fields that will be used in `list` and `get` subcommands.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return string
|
||||
*/
|
||||
protected function get_default_format_fields() {
|
||||
return 'id,name,slug,parent,description,display,image,count';
|
||||
}
|
||||
}
|
|
@ -1,371 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Show Reports.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @package WooCommerce/CLI
|
||||
* @category CLI
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_CLI_Report extends WC_CLI_Command {
|
||||
|
||||
/**
|
||||
* List reports.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Acceptec values: table, csv, json, count, ids. Default: table.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc report list
|
||||
*
|
||||
* @subcommand list
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function list_( $__, $assoc_args ) {
|
||||
$reports = array( 'sales', 'sales/top_sellers' );
|
||||
$formatter = $this->get_formatter(
|
||||
array_merge(
|
||||
array( 'fields' => array_keys( $reports ) ),
|
||||
$assoc_args
|
||||
)
|
||||
);
|
||||
|
||||
if ( 'ids' === $formatter->format ) {
|
||||
echo implode( ' ', $reports );
|
||||
} else {
|
||||
$formatter->display_item( $reports );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* View sales report.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Instead of returning the whole report fields, returns the value of a single fields.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Get a specific subset of the report's fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Accepted values: table, json, csv. Default: table.
|
||||
*
|
||||
* [--period=<period>]
|
||||
* : The supported periods are: week, month, last_month, and year. If invalid
|
||||
* period is supplied, week is used. If period is not specified, the current
|
||||
* day is used.
|
||||
*
|
||||
* [--date_min]
|
||||
* : Return sales for a specific start date. The date need to be in the YYYY-MM-AA format.
|
||||
*
|
||||
* [--date_max]
|
||||
* : Return sales for a specific end date. The dates need to be in the YYYY-MM-AA format.
|
||||
*
|
||||
* [--limit]
|
||||
* : Limit report result. Default: 12.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields are available for get command:
|
||||
*
|
||||
* * total_sales
|
||||
* * average_sales
|
||||
* * total_orders
|
||||
* * total_items
|
||||
* * total_tax
|
||||
* * total_shipping
|
||||
* * total_discount
|
||||
* * totals_grouped_by
|
||||
* * totals
|
||||
* * total_customers
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc report sales
|
||||
*
|
||||
* wp wc report sales --period=last_month
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function sales( $__, $assoc_args ) {
|
||||
$reporter = $this->get_reporter( $assoc_args );
|
||||
|
||||
// new customers
|
||||
$users_query = new WP_User_Query(
|
||||
array(
|
||||
'fields' => array( 'user_registered' ),
|
||||
'role' => 'customer',
|
||||
)
|
||||
);
|
||||
|
||||
$customers = $users_query->get_results();
|
||||
|
||||
foreach ( $customers as $key => $customer ) {
|
||||
if ( strtotime( $customer->user_registered ) < $reporter->start_date || strtotime( $customer->user_registered ) > $reporter->end_date ) {
|
||||
unset( $customers[ $key ] );
|
||||
}
|
||||
}
|
||||
|
||||
$total_customers = count( $customers );
|
||||
$report_data = $reporter->get_report_data();
|
||||
$period_totals = array();
|
||||
|
||||
// setup period totals by ensuring each period in the interval has data
|
||||
for ( $i = 0; $i <= $reporter->chart_interval; $i ++ ) {
|
||||
|
||||
switch ( $reporter->chart_groupby ) {
|
||||
case 'day' :
|
||||
$time = date( 'Y-m-d', strtotime( "+{$i} DAY", $reporter->start_date ) );
|
||||
break;
|
||||
default :
|
||||
$time = date( 'Y-m', strtotime( "+{$i} MONTH", $reporter->start_date ) );
|
||||
break;
|
||||
}
|
||||
|
||||
// set the customer signups for each period
|
||||
$customer_count = 0;
|
||||
foreach ( $customers as $customer ) {
|
||||
if ( date( ( 'day' == $reporter->chart_groupby ) ? 'Y-m-d' : 'Y-m', strtotime( $customer->user_registered ) ) == $time ) {
|
||||
$customer_count++;
|
||||
}
|
||||
}
|
||||
|
||||
$period_totals[ $time ] = array(
|
||||
'sales' => wc_format_decimal( 0.00, 2 ),
|
||||
'orders' => 0,
|
||||
'items' => 0,
|
||||
'tax' => wc_format_decimal( 0.00, 2 ),
|
||||
'shipping' => wc_format_decimal( 0.00, 2 ),
|
||||
'discount' => wc_format_decimal( 0.00, 2 ),
|
||||
'customers' => $customer_count,
|
||||
);
|
||||
}
|
||||
|
||||
// add total sales, total order count, total tax and total shipping for each period
|
||||
foreach ( $report_data->orders as $order ) {
|
||||
$time = ( 'day' === $reporter->chart_groupby ) ? date( 'Y-m-d', strtotime( $order->post_date ) ) : date( 'Y-m', strtotime( $order->post_date ) );
|
||||
|
||||
if ( ! isset( $period_totals[ $time ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$period_totals[ $time ]['sales'] = wc_format_decimal( $order->total_sales, 2 );
|
||||
$period_totals[ $time ]['tax'] = wc_format_decimal( $order->total_tax + $order->total_shipping_tax, 2 );
|
||||
$period_totals[ $time ]['shipping'] = wc_format_decimal( $order->total_shipping, 2 );
|
||||
}
|
||||
|
||||
foreach ( $report_data->order_counts as $order ) {
|
||||
$time = ( 'day' === $reporter->chart_groupby ) ? date( 'Y-m-d', strtotime( $order->post_date ) ) : date( 'Y-m', strtotime( $order->post_date ) );
|
||||
|
||||
if ( ! isset( $period_totals[ $time ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$period_totals[ $time ]['orders'] = (int) $order->count;
|
||||
}
|
||||
|
||||
// add total order items for each period
|
||||
foreach ( $report_data->order_items as $order_item ) {
|
||||
$time = ( 'day' === $reporter->chart_groupby ) ? date( 'Y-m-d', strtotime( $order_item->post_date ) ) : date( 'Y-m', strtotime( $order_item->post_date ) );
|
||||
|
||||
if ( ! isset( $period_totals[ $time ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$period_totals[ $time ]['items'] = (int) $order_item->order_item_count;
|
||||
}
|
||||
|
||||
// add total discount for each period
|
||||
foreach ( $report_data->coupons as $discount ) {
|
||||
$time = ( 'day' === $reporter->chart_groupby ) ? date( 'Y-m-d', strtotime( $discount->post_date ) ) : date( 'Y-m', strtotime( $discount->post_date ) );
|
||||
|
||||
if ( ! isset( $period_totals[ $time ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$period_totals[ $time ]['discount'] = wc_format_decimal( $discount->discount_amount, 2 );
|
||||
}
|
||||
|
||||
$sales_data = array(
|
||||
'total_sales' => $report_data->total_sales,
|
||||
'net_sales' => $report_data->net_sales,
|
||||
'average_sales' => $report_data->average_sales,
|
||||
'total_orders' => $report_data->total_orders,
|
||||
'total_items' => $report_data->total_items,
|
||||
'total_tax' => wc_format_decimal( $report_data->total_tax + $report_data->total_shipping_tax, 2 ),
|
||||
'total_shipping' => $report_data->total_shipping,
|
||||
'total_refunds' => $report_data->total_refunds,
|
||||
'total_discount' => $report_data->total_coupons,
|
||||
'totals_grouped_by' => $reporter->chart_groupby,
|
||||
'totals' => $period_totals,
|
||||
'total_customers' => $total_customers,
|
||||
);
|
||||
|
||||
$sales_data = apply_filters( 'woocommerce_cli_sales_report', $sales_data );
|
||||
|
||||
if ( empty( $assoc_args['fields'] ) ) {
|
||||
$assoc_args['fields'] = array_keys( $sales_data );
|
||||
}
|
||||
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
$formatter->display_item( $sales_data );
|
||||
}
|
||||
|
||||
/**
|
||||
* View report of top sellers.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : Filter report based on report property.
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Prints the value of a single field for each seller.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Limit the output to specific report fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Acceptec values: table, csv, json, count, ids. Default: table.
|
||||
*
|
||||
* [--period=<period>]
|
||||
* : The supported periods are: week, month, last_month, and year. If invalid
|
||||
* period is supplied, week is used. If period is not specified, the current
|
||||
* day is used.
|
||||
*
|
||||
* [--date_min]
|
||||
* : Return sales for a specific start date. The date need to be in the YYYY-MM-AA format.
|
||||
*
|
||||
* [--date_max]
|
||||
* : Return sales for a specific end date. The dates need to be in the YYYY-MM-AA format.
|
||||
*
|
||||
* [--limit]
|
||||
* : Limit report result. Default: 12.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields will be displayed by default for each row:
|
||||
*
|
||||
* * title
|
||||
* * product_id
|
||||
* * quantity
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc report top_sellers
|
||||
*
|
||||
* wp wc report top_sellers --period=last_month
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function top_sellers( $__, $assoc_args ) {
|
||||
$reporter = $this->get_reporter( $assoc_args );
|
||||
$top_sellers = $reporter->get_order_report_data( array(
|
||||
'data' => array(
|
||||
'_product_id' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => 'line_item',
|
||||
'function' => '',
|
||||
'name' => 'product_id',
|
||||
),
|
||||
'_qty' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => 'line_item',
|
||||
'function' => 'SUM',
|
||||
'name' => 'order_item_qty',
|
||||
),
|
||||
),
|
||||
'order_by' => 'order_item_qty DESC',
|
||||
'group_by' => 'product_id',
|
||||
'limit' => isset( $assoc_args['limit'] ) ? absint( $assoc_args['limit'] ) : 12,
|
||||
'query_type' => 'get_results',
|
||||
'filter_range' => true,
|
||||
) );
|
||||
|
||||
$top_sellers_data = array();
|
||||
foreach ( $top_sellers as $top_seller ) {
|
||||
$product = wc_get_product( $top_seller->product_id );
|
||||
|
||||
if ( $product ) {
|
||||
$top_sellers_data[] = array(
|
||||
'title' => $product->get_title(),
|
||||
'product_id' => $top_seller->product_id,
|
||||
'quantity' => $top_seller->order_item_qty,
|
||||
);
|
||||
}
|
||||
}
|
||||
$top_sellers_data = apply_filters( 'woocommerce_cli_top_sellers_report', $top_sellers_data );
|
||||
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
if ( 'ids' === $formatter->format ) {
|
||||
$query_args['fields'] = 'ids';
|
||||
echo implode( ' ', wp_list_pluck( $top_sellers_data, 'product_id' ) );
|
||||
} else {
|
||||
$formatter->display_items( $top_sellers_data );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the report object and parse any date filtering
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $assoc_args Arguments provided in when invoking the command
|
||||
* @return WC_Report_Sales_By_Date
|
||||
*/
|
||||
private function get_reporter( $assoc_args ) {
|
||||
|
||||
include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-admin-report.php' );
|
||||
include_once( WC()->plugin_path() . '/includes/admin/reports/class-wc-report-sales-by-date.php' );
|
||||
|
||||
$report = new WC_Report_Sales_By_Date();
|
||||
|
||||
if ( empty( $assoc_args['period'] ) ) {
|
||||
|
||||
// custom date range
|
||||
$assoc_args['period'] = 'custom';
|
||||
|
||||
if ( ! empty( $assoc_args['date_min'] ) || ! empty( $assoc_args['date_max'] ) ) {
|
||||
|
||||
// overwrite _GET to make use of WC_Admin_Report::calculate_current_range() for custom date ranges
|
||||
$_GET['start_date'] = $this->parse_datetime( $assoc_args['date_min'] );
|
||||
$_GET['end_date'] = isset( $assoc_args['date_max'] ) ? $this->parse_datetime( $assoc_args['date_max'] ) : null;
|
||||
|
||||
} else {
|
||||
|
||||
// default custom range to today
|
||||
$_GET['start_date'] = $_GET['end_date'] = date( 'Y-m-d', current_time( 'timestamp' ) );
|
||||
}
|
||||
} else {
|
||||
|
||||
// ensure period is valid
|
||||
if ( ! in_array( $assoc_args['period'], array( 'week', 'month', 'last_month', 'year' ) ) ) {
|
||||
$assoc_args['period'] = 'week';
|
||||
}
|
||||
|
||||
// TODO: change WC_Admin_Report class to use "week" instead, as it's more consistent with other periods
|
||||
// allow "week" for period instead of "7day"
|
||||
if ( 'week' === $assoc_args['period'] ) {
|
||||
$assoc_args['period'] = '7day';
|
||||
}
|
||||
}
|
||||
|
||||
$report->calculate_current_range( $assoc_args['period'] );
|
||||
|
||||
return $report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default format fields that will be used in `list` and `get` subcommands.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return string
|
||||
*/
|
||||
protected function get_default_format_fields() {
|
||||
return 'title,product_id,quantity';
|
||||
}
|
||||
}
|
|
@ -1,685 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Manage Taxes.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @package WooCommerce/CLI
|
||||
* @category CLI
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_CLI_Tax extends WC_CLI_Command {
|
||||
|
||||
/**
|
||||
* Create a tax rate.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : Associative args for the new tax rate.
|
||||
*
|
||||
* [--porcelain]
|
||||
* : Outputs just the new tax rate id.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields are available for create command:
|
||||
*
|
||||
* * country
|
||||
* * state
|
||||
* * postcode
|
||||
* * city
|
||||
* * rate
|
||||
* * name
|
||||
* * priority
|
||||
* * compound
|
||||
* * shipping
|
||||
* * class
|
||||
* * order
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc tax create --country=US --rate=5 --class=standard --type=percent
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function create( $__, $assoc_args ) {
|
||||
$porcelain = isset( $assoc_args['porcelain'] );
|
||||
unset( $assoc_args['porcelain'] );
|
||||
|
||||
$assoc_args = apply_filters( 'woocommerce_cli_create_tax_rate_data', $assoc_args );
|
||||
|
||||
$tax_data = array(
|
||||
'tax_rate_country' => '',
|
||||
'tax_rate_state' => '',
|
||||
'tax_rate' => '',
|
||||
'tax_rate_name' => '',
|
||||
'tax_rate_priority' => 1,
|
||||
'tax_rate_compound' => 0,
|
||||
'tax_rate_shipping' => 1,
|
||||
'tax_rate_order' => 0,
|
||||
'tax_rate_class' => '',
|
||||
);
|
||||
|
||||
foreach ( $tax_data as $key => $value ) {
|
||||
$new_key = str_replace( 'tax_rate_', '', $key );
|
||||
$new_key = 'tax_rate' === $new_key ? 'rate' : $new_key;
|
||||
|
||||
if ( isset( $assoc_args[ $new_key ] ) ) {
|
||||
if ( in_array( $new_key, array( 'compound', 'shipping' ) ) ) {
|
||||
$tax_data[ $key ] = $assoc_args[ $new_key ] ? 1 : 0;
|
||||
} else {
|
||||
$tax_data[ $key ] = $assoc_args[ $new_key ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create tax rate.
|
||||
$id = WC_Tax::_insert_tax_rate( $tax_data );
|
||||
|
||||
// Add locales.
|
||||
if ( ! empty( $assoc_args['postcode'] ) ) {
|
||||
WC_Tax::_update_tax_rate_postcodes( $id, wc_clean( $assoc_args['postcode'] ) );
|
||||
}
|
||||
|
||||
if ( ! empty( $assoc_args['city'] ) ) {
|
||||
WC_Tax::_update_tax_rate_cities( $id, wc_clean( $assoc_args['city'] ) );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_cli_create_tax_rate', $id, $tax_data );
|
||||
|
||||
if ( $porcelain ) {
|
||||
WP_CLI::line( $id );
|
||||
} else {
|
||||
WP_CLI::success( "Created tax rate $id." );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a tax class.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : Associative args for the new tax class.
|
||||
*
|
||||
* [--porcelain]
|
||||
* : Outputs just the new tax class slug.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields are available for create command:
|
||||
*
|
||||
* * name
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc tax create_class --name="Reduced Rate"
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function create_class( $__, $assoc_args ) {
|
||||
try {
|
||||
$porcelain = isset( $assoc_args['porcelain'] );
|
||||
unset( $assoc_args['porcelain'] );
|
||||
|
||||
$assoc_args = apply_filters( 'woocommerce_cli_create_tax_class_data', $assoc_args );
|
||||
|
||||
// Check if name is specified.
|
||||
if ( ! isset( $assoc_args['name'] ) ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_missing_name', sprintf( __( 'Missing parameter %s', 'woocommerce' ), 'name' ) );
|
||||
}
|
||||
|
||||
$name = sanitize_text_field( $assoc_args['name'] );
|
||||
$slug = sanitize_title( $name );
|
||||
$classes = WC_Tax::get_tax_classes();
|
||||
$exists = false;
|
||||
|
||||
// Check if class exists.
|
||||
foreach ( $classes as $key => $class ) {
|
||||
if ( sanitize_title( $class ) === $slug ) {
|
||||
$exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return error if tax class already exists.
|
||||
if ( $exists ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_cannot_create_tax_class', __( 'Tax class already exists', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
// Add the new class
|
||||
$classes[] = $name;
|
||||
|
||||
update_option( 'woocommerce_tax_classes', implode( "\n", $classes ) );
|
||||
|
||||
do_action( 'woocommerce_cli_create_tax_class', $slug, array( 'name' => $name ) );
|
||||
|
||||
if ( $porcelain ) {
|
||||
WP_CLI::line( $slug );
|
||||
} else {
|
||||
WP_CLI::success( "Created tax class $slug." );
|
||||
}
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete one or more tax rates.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <id>...
|
||||
* : The tax rate ID to delete.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc tax delete 123
|
||||
*
|
||||
* wp wc tax delete $(wp wc tax list --format=ids)
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function delete( $args, $assoc_args ) {
|
||||
$exit_code = 0;
|
||||
|
||||
foreach ( $args as $tax_id ) {
|
||||
$tax_id = absint( $tax_id );
|
||||
$tax = WC_Tax::_get_tax_rate( $tax_id );
|
||||
|
||||
if ( is_null( $tax ) ) {
|
||||
$exit_code += 1;
|
||||
WP_CLI::warning( "Failed deleting tax rate {$tax_id}." );
|
||||
continue;
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_cli_delete_tax_rate', $tax_id );
|
||||
|
||||
WC_Tax::_delete_tax_rate( $tax_id );
|
||||
WP_CLI::success( "Deleted tax rate {$tax_id}." );
|
||||
}
|
||||
exit( $exit_code ? 1 : 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete one or more tax classes.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <slug>...
|
||||
* : The tax class slug to delete.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc tax delete_class reduced-rate
|
||||
*
|
||||
* wp wc tax delete_class $(wp wc tax list_class --format=ids)
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function delete_class( $args, $assoc_args ) {
|
||||
$classes = WC_Tax::get_tax_classes();
|
||||
$exit_code = 0;
|
||||
|
||||
foreach ( $args as $slug ) {
|
||||
$slug = sanitize_title( $slug );
|
||||
$deleted = false;
|
||||
|
||||
foreach ( $classes as $key => $class ) {
|
||||
if ( sanitize_title( $class ) === $slug ) {
|
||||
unset( $classes[ $key ] );
|
||||
$deleted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $deleted ) {
|
||||
WP_CLI::success( "Deleted tax class {$slug}." );
|
||||
} else {
|
||||
$exit_code += 1;
|
||||
WP_CLI::warning( "Failed deleting tax class {$slug}." );
|
||||
}
|
||||
}
|
||||
|
||||
update_option( 'woocommerce_tax_classes', implode( "\n", $classes ) );
|
||||
|
||||
exit( $exit_code ? 1 : 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a tax rate.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <id>
|
||||
* : Tax rate ID
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Instead of returning the whole tax rate fields, returns the value of a single fields.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Get a specific subset of the tax rates fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Accepted values: table, json, csv. Default: table.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields are available for get command:
|
||||
*
|
||||
* * id
|
||||
* * country
|
||||
* * state
|
||||
* * postcode
|
||||
* * city
|
||||
* * rate
|
||||
* * name
|
||||
* * priority
|
||||
* * compound
|
||||
* * shipping
|
||||
* * order
|
||||
* * class
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc tax get 123 --field=rate
|
||||
*
|
||||
* wp wc tax get 321 --format=json > rate321.json
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function get( $args, $assoc_args ) {
|
||||
global $wpdb;
|
||||
|
||||
try {
|
||||
|
||||
$tax_data = $this->format_taxes_to_items( array( $args[0] ) );
|
||||
|
||||
if ( empty( $tax_data ) ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_invalid_tax_rate', sprintf( __( 'Invalid tax rate ID: %s', 'woocommerce' ), $args[0] ) );
|
||||
}
|
||||
|
||||
$tax_data = apply_filters( 'woocommerce_cli_get_tax_rate', $tax_data[0] );
|
||||
|
||||
if ( empty( $assoc_args['fields'] ) ) {
|
||||
$assoc_args['fields'] = array_keys( $tax_data );
|
||||
}
|
||||
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
$formatter->display_item( $tax_data );
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List taxes.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : Filter tax based on tax property.
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Prints the value of a single field for each tax.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Limit the output to specific tax fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Acceptec values: table, csv, json, count, ids. Default: table.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields will be displayed by default for each tax:
|
||||
*
|
||||
* * id
|
||||
* * country
|
||||
* * state
|
||||
* * postcode
|
||||
* * city
|
||||
* * rate
|
||||
* * name
|
||||
* * priority
|
||||
* * compound
|
||||
* * shipping
|
||||
* * class
|
||||
*
|
||||
* These fields are optionally available:
|
||||
*
|
||||
* * order
|
||||
*
|
||||
* Fields for filtering query result also available:
|
||||
*
|
||||
* * class Sort by tax class.
|
||||
* * page Page number.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc tax list
|
||||
*
|
||||
* wp wc tax list --field=id
|
||||
*
|
||||
* wp wc tax list --fields=id,rate,class --format=json
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @subcommand list
|
||||
*/
|
||||
public function list_( $__, $assoc_args ) {
|
||||
$query_args = $this->merge_tax_query_args( array(), $assoc_args );
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
|
||||
$taxes = $this->query_tax_rates( $query_args );
|
||||
|
||||
if ( 'ids' === $formatter->format ) {
|
||||
$_taxes = array();
|
||||
foreach ( $taxes as $tax ) {
|
||||
$_taxes[] = $tax->tax_rate_id;
|
||||
}
|
||||
echo implode( ' ', $_taxes );
|
||||
} else {
|
||||
$items = $this->format_taxes_to_items( $taxes );
|
||||
$formatter->display_items( $items );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List tax classes.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : Filter tax class based on tax class property.
|
||||
*
|
||||
* [--field=<field>]
|
||||
* : Prints the value of a single field for each tax class.
|
||||
*
|
||||
* [--fields=<fields>]
|
||||
* : Limit the output to specific tax class fields.
|
||||
*
|
||||
* [--format=<format>]
|
||||
* : Acceptec values: table, csv, json, count, ids. Default: table.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields will be displayed by default for each tax class:
|
||||
*
|
||||
* * slug
|
||||
* * name
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc tax list_class
|
||||
*
|
||||
* wp wc tax list_class --field=slug
|
||||
*
|
||||
* wp wc tax list_class --format=json
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @subcommand list_class
|
||||
*/
|
||||
public function list_class( $__, $assoc_args ) {
|
||||
// Set default fields for tax classes
|
||||
if ( empty( $assoc_args['fields'] ) ) {
|
||||
$assoc_args['fields'] = 'slug,name';
|
||||
}
|
||||
|
||||
$formatter = $this->get_formatter( $assoc_args );
|
||||
$items = array();
|
||||
|
||||
// Add standard class
|
||||
$items[] = array(
|
||||
'slug' => 'standard',
|
||||
'name' => __( 'Standard rate', 'woocommerce' ),
|
||||
);
|
||||
|
||||
$classes = WC_Tax::get_tax_classes();
|
||||
|
||||
foreach ( $classes as $class ) {
|
||||
$items[] = apply_filters( 'woocommerce_cli_tax_class_response', array(
|
||||
'slug' => sanitize_title( $class ),
|
||||
'name' => $class,
|
||||
), $class, $assoc_args, $this );
|
||||
}
|
||||
|
||||
if ( 'ids' === $formatter->format ) {
|
||||
$_slugs = array();
|
||||
foreach ( $items as $item ) {
|
||||
$_slugs[] = $item['slug'];
|
||||
}
|
||||
echo implode( ' ', $_slugs );
|
||||
} else {
|
||||
$formatter->display_items( $items );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a tax rate.
|
||||
*
|
||||
* ## OPTIONS
|
||||
*
|
||||
* <id>
|
||||
* : The ID of the tax rate to update.
|
||||
*
|
||||
* [--<field>=<value>]
|
||||
* : One or more fields to update.
|
||||
*
|
||||
* ## AVAILABLE FIELDS
|
||||
*
|
||||
* These fields are available for update command:
|
||||
*
|
||||
* * country
|
||||
* * state
|
||||
* * postcode
|
||||
* * city
|
||||
* * rate
|
||||
* * name
|
||||
* * priority
|
||||
* * compound
|
||||
* * shipping
|
||||
* * class
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc tax update 123 --rate=5
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function update( $args, $assoc_args ) {
|
||||
try {
|
||||
// Get current tax rate data
|
||||
$tax_data = $this->format_taxes_to_items( array( $args[0] ) );
|
||||
|
||||
if ( empty( $tax_data ) ) {
|
||||
throw new WC_CLI_Exception( 'woocommerce_cli_invalid_tax_rate', sprintf( __( 'Invalid tax rate ID: %s', 'woocommerce' ), $args[0] ) );
|
||||
}
|
||||
|
||||
$current_data = $tax_data[0];
|
||||
$id = $current_data['id'];
|
||||
$data = apply_filters( 'woocommerce_cli_update_tax_rate_data', $assoc_args, $id );
|
||||
$new_data = array();
|
||||
$default_fields = array(
|
||||
'tax_rate_country',
|
||||
'tax_rate_state',
|
||||
'tax_rate',
|
||||
'tax_rate_name',
|
||||
'tax_rate_priority',
|
||||
'tax_rate_compound',
|
||||
'tax_rate_shipping',
|
||||
'tax_rate_order',
|
||||
'tax_rate_class',
|
||||
);
|
||||
|
||||
foreach ( $data as $key => $value ) {
|
||||
$new_key = 'rate' === $key ? 'tax_rate' : 'tax_rate_' . $key;
|
||||
|
||||
// Check if the key is valid
|
||||
if ( ! in_array( $new_key, $default_fields ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Test new data against current data
|
||||
if ( $value === $current_data[ $key ] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Fix compund and shipping values
|
||||
if ( in_array( $key, array( 'compound', 'shipping' ) ) ) {
|
||||
$value = $value ? 1 : 0;
|
||||
}
|
||||
|
||||
$new_data[ $new_key ] = $value;
|
||||
}
|
||||
|
||||
// Update tax rate
|
||||
WC_Tax::_update_tax_rate( $id, $new_data );
|
||||
|
||||
// Update locales
|
||||
if ( ! empty( $data['postcode'] ) && $current_data['postcode'] != $data['postcode'] ) {
|
||||
WC_Tax::_update_tax_rate_postcodes( $id, wc_clean( $data['postcode'] ) );
|
||||
}
|
||||
|
||||
if ( ! empty( $data['city'] ) && $current_data['city'] != $data['city'] ) {
|
||||
WC_Tax::_update_tax_rate_cities( $id, wc_clean( $data['city'] ) );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_cli_update_tax_rate', $id, $data );
|
||||
|
||||
WP_CLI::success( "Updated tax rate $id." );
|
||||
} catch ( WC_CLI_Exception $e ) {
|
||||
WP_CLI::error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add common cli arguments to argument list before $wpdb->get_results() is run.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $base_args Required arguments for the query (e.g. `limit`, etc)
|
||||
* @param array $assoc_args Arguments provided in when invoking the command
|
||||
* @return array
|
||||
*/
|
||||
protected function merge_tax_query_args( $base_args, $assoc_args ) {
|
||||
$args = array();
|
||||
|
||||
if ( ! empty( $assoc_args['class'] ) ) {
|
||||
$args['class'] = $assoc_args['class'];
|
||||
}
|
||||
|
||||
// Number of post to show per page.
|
||||
if ( ! empty( $assoc_args['limit'] ) ) {
|
||||
$args['posts_per_page'] = $assoc_args['limit'];
|
||||
}
|
||||
|
||||
// posts page.
|
||||
$args['paged'] = ( isset( $assoc_args['page'] ) ) ? absint( $assoc_args['page'] ) : 1;
|
||||
|
||||
$args = apply_filters( 'woocommerce_cli_tax_query_args', $args, $assoc_args );
|
||||
|
||||
return array_merge( $base_args, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get tax rates objects
|
||||
*
|
||||
* @since 2.5.0
|
||||
*
|
||||
* @param array $args
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function query_tax_rates( $args ) {
|
||||
global $wpdb;
|
||||
|
||||
$query = "
|
||||
SELECT tax_rate_id
|
||||
FROM {$wpdb->prefix}woocommerce_tax_rates
|
||||
WHERE 1 = 1
|
||||
";
|
||||
|
||||
// Filter by tax class
|
||||
if ( ! empty( $args['class'] ) ) {
|
||||
$class = 'standard' !== $args['class'] ? sanitize_title( $args['class'] ) : '';
|
||||
$query .= " AND tax_rate_class = '$class'";
|
||||
}
|
||||
|
||||
// Order tax rates
|
||||
$order_by = ' ORDER BY tax_rate_order';
|
||||
|
||||
// Pagination
|
||||
$per_page = isset( $args['posts_per_page'] ) ? $args['posts_per_page'] : get_option( 'posts_per_page' );
|
||||
$offset = 1 < $args['paged'] ? ( $args['paged'] - 1 ) * $per_page : 0;
|
||||
$pagination = sprintf( ' LIMIT %d, %d', $offset, $per_page );
|
||||
|
||||
return $wpdb->get_results( $query . $order_by . $pagination );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default format fields that will be used in `list` and `get` subcommands.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @return string
|
||||
*/
|
||||
protected function get_default_format_fields() {
|
||||
return 'id,country,state,postcode,city,rate,name,priority,compound,shipping,class';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format taxes from query result to items in which each item contain
|
||||
* common properties of item, for instance `tax_rate_id` will be `id`.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @param array $taxes Array of tax rate.
|
||||
* @return array Items
|
||||
*/
|
||||
protected function format_taxes_to_items( $taxes ) {
|
||||
global $wpdb;
|
||||
|
||||
$items = array();
|
||||
|
||||
foreach ( $taxes as $tax_id ) {
|
||||
$id = is_object( $tax_id ) ? $tax_id->tax_rate_id : $tax_id;
|
||||
$id = absint( $id );
|
||||
|
||||
// Get tax rate details
|
||||
$tax = WC_Tax::_get_tax_rate( $id );
|
||||
|
||||
if ( is_wp_error( $tax ) || empty( $tax ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tax_data = array(
|
||||
'id' => $tax['tax_rate_id'],
|
||||
'country' => $tax['tax_rate_country'],
|
||||
'state' => $tax['tax_rate_state'],
|
||||
'postcode' => '',
|
||||
'city' => '',
|
||||
'rate' => $tax['tax_rate'],
|
||||
'name' => $tax['tax_rate_name'],
|
||||
'priority' => (int) $tax['tax_rate_priority'],
|
||||
'compound' => (bool) $tax['tax_rate_compound'],
|
||||
'shipping' => (bool) $tax['tax_rate_shipping'],
|
||||
'order' => (int) $tax['tax_rate_order'],
|
||||
'class' => $tax['tax_rate_class'] ? $tax['tax_rate_class'] : 'standard',
|
||||
);
|
||||
|
||||
// Get locales from a tax rate
|
||||
$locales = $wpdb->get_results( $wpdb->prepare( "
|
||||
SELECT location_code, location_type
|
||||
FROM {$wpdb->prefix}woocommerce_tax_rate_locations
|
||||
WHERE tax_rate_id = %d
|
||||
", $id ) );
|
||||
|
||||
if ( ! is_wp_error( $tax ) && ! is_null( $tax ) ) {
|
||||
foreach ( $locales as $locale ) {
|
||||
$tax_data[ $locale->location_type ] = $locale->location_code;
|
||||
}
|
||||
}
|
||||
|
||||
$items[] = $tax_data;
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Tools for WooCommerce.
|
||||
*
|
||||
* @since 2.5.0
|
||||
* @package WooCommerce/CLI
|
||||
* @category CLI
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_CLI_Tool extends WC_CLI_Command {
|
||||
|
||||
/**
|
||||
* Clear the product/shop transients cache.
|
||||
*
|
||||
* ## EXAMPLES
|
||||
*
|
||||
* wp wc tool clear_transients
|
||||
*
|
||||
* @since 2.5.0
|
||||
*/
|
||||
public function clear_transients( $args, $assoc_args ) {
|
||||
wc_delete_product_transients();
|
||||
wc_delete_shop_order_transients();
|
||||
WC_Cache_Helper::get_transient_version( 'shipping', true );
|
||||
|
||||
WP_CLI::success( 'Product transients and shop order transients were cleared.' );
|
||||
}
|
||||
}
|
|
@ -14,6 +14,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Coupon_Da
|
|||
|
||||
/**
|
||||
* Method to create a new coupon in the database.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Coupon
|
||||
*/
|
||||
public function create( &$coupon ) {
|
||||
|
@ -40,6 +42,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Coupon_Da
|
|||
|
||||
/**
|
||||
* Method to read a coupon.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Coupon
|
||||
*/
|
||||
public function read( &$coupon ) {
|
||||
|
@ -47,7 +51,6 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Coupon_Da
|
|||
|
||||
if ( ! $coupon->get_id() || ! ( $post_object = get_post( $coupon->get_id() ) ) ) {
|
||||
throw new Exception( __( 'Invalid coupon.', 'woocommerce' ) );
|
||||
return;
|
||||
}
|
||||
|
||||
$coupon_id = $coupon->get_id();
|
||||
|
@ -82,6 +85,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Coupon_Da
|
|||
|
||||
/**
|
||||
* Updates a coupon in the database.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Coupon
|
||||
*/
|
||||
public function update( &$coupon ) {
|
||||
|
@ -98,6 +103,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Coupon_Da
|
|||
|
||||
/**
|
||||
* Deletes a coupon from the database.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Coupon
|
||||
* @param bool $force_delete True to permently delete, false to trash.
|
||||
*/
|
||||
|
@ -114,6 +121,7 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Coupon_Da
|
|||
|
||||
/**
|
||||
* Helper method that updates all the post meta for a coupon based on it's settings in the WC_Coupon class.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
private function update_post_meta( $coupon ) {
|
||||
|
@ -172,6 +180,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Coupon_Da
|
|||
|
||||
/**
|
||||
* Increase usage count for current coupon.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Coupon
|
||||
* @param string $used_by Either user ID or billing email
|
||||
*/
|
||||
|
@ -185,6 +195,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Coupon_Da
|
|||
|
||||
/**
|
||||
* Decrease usage count for current coupon.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Coupon
|
||||
* @param string $used_by Either user ID or billing email
|
||||
*/
|
||||
|
@ -206,6 +218,8 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Coupon_Da
|
|||
|
||||
/**
|
||||
* Get the number of uses for a coupon by user ID.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Coupon
|
||||
* @param id $user_id
|
||||
* @return int
|
||||
|
@ -215,4 +229,34 @@ class WC_Coupon_Data_Store_CPT extends WC_Data_Store_CPT implements WC_Coupon_Da
|
|||
return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( meta_id ) FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = '_used_by' AND meta_value = %d;", $coupon->get_id(), $user_id ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a coupon code for a specific ID.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param int $id
|
||||
* @return string Coupon Code
|
||||
*/
|
||||
public function get_code_by_id( $id ) {
|
||||
global $wpdb;
|
||||
return $wpdb->get_var( $wpdb->prepare( "
|
||||
SELECT post_title
|
||||
FROM $wpdb->posts
|
||||
WHERE ID = %d
|
||||
AND post_type = 'shop_coupon'
|
||||
AND post_status = 'publish';
|
||||
", $id ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of IDs for for a specific coupon code.
|
||||
* Can return multiple to check for existence.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param string $code
|
||||
* @return array Array of IDs.
|
||||
*/
|
||||
public function get_ids_by_code( $code ) {
|
||||
global $wpdb;
|
||||
return $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC;", $code ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,256 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC Payment Token Data Store: Custom Table.
|
||||
*
|
||||
* @version 2.7.0
|
||||
* @category Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Payment_Token_Data_Store_Table implements WC_Payment_Token_Data_Store_Interface, WC_Object_Data_Store {
|
||||
|
||||
/**
|
||||
* Create a new payment token in the database.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Payment_Token $token
|
||||
*/
|
||||
public function create( &$token ) {
|
||||
if ( false === $token->validate() ) {
|
||||
throw new Exception( __( 'Invalid or missing payment token fields.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
if ( ! $token->is_default() && $token->get_user_id() > 0 ) {
|
||||
$default_token = WC_Payment_Tokens::get_customer_default_token( $token->get_user_id() );
|
||||
if ( is_null( $default_token ) ) {
|
||||
$token->set_default( true );
|
||||
}
|
||||
}
|
||||
|
||||
$payment_token_data = array(
|
||||
'gateway_id' => $token->get_gateway_id( 'edit' ),
|
||||
'token' => $token->get_token( 'edit' ),
|
||||
'user_id' => $token->get_user_id( 'edit' ),
|
||||
'type' => $token->get_type( 'edit' ),
|
||||
);
|
||||
|
||||
$wpdb->insert( $wpdb->prefix . 'woocommerce_payment_tokens', $payment_token_data );
|
||||
$token_id = $wpdb->insert_id;
|
||||
$token->set_id( $token_id );
|
||||
$token->save_meta_data();
|
||||
$token->apply_changes();
|
||||
|
||||
// Make sure all other tokens are not set to default
|
||||
if ( $token->is_default() && $token->get_user_id() > 0 ) {
|
||||
WC_Payment_Tokens::set_users_default( $token->get_user_id(), $token_id );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_payment_token_created', $token_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a payment token.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Payment_Token $token
|
||||
*/
|
||||
public function update( &$token ) {
|
||||
if ( false === $token->validate() ) {
|
||||
throw new Exception( __( 'Invalid or missing payment token fields.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$payment_token_data = array(
|
||||
'gateway_id' => $token->get_gateway_id( 'edit' ),
|
||||
'token' => $token->get_token( 'edit' ),
|
||||
'user_id' => $token->get_user_id( 'edit' ),
|
||||
'type' => $token->get_type( 'edit' ),
|
||||
);
|
||||
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'woocommerce_payment_tokens',
|
||||
$payment_token_data,
|
||||
array( 'token_id' => $token->get_id( 'edit' ) )
|
||||
);
|
||||
|
||||
$token->save_meta_data();
|
||||
$token->apply_changes();
|
||||
|
||||
// Make sure all other tokens are not set to default
|
||||
if ( $token->is_default() && $token->get_user_id() > 0 ) {
|
||||
WC_Payment_Tokens::set_users_default( $token->get_user_id(), $token->get_id() );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_payment_token_updated', $token->get_id() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a payment token from the database.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Payment_Token $token
|
||||
* @param bool $force_delete
|
||||
*/
|
||||
public function delete( &$token, $force_delete = false ) {
|
||||
global $wpdb;
|
||||
$wpdb->delete( $wpdb->prefix . 'woocommerce_payment_tokens', array( 'token_id' => $token->get_id() ), array( '%d' ) );
|
||||
$wpdb->delete( $wpdb->prefix . 'woocommerce_payment_tokenmeta', array( 'payment_token_id' => $token->get_id() ), array( '%d' ) );
|
||||
do_action( 'woocommerce_payment_token_deleted', $token->get_id(), $token );
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a token from the database.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param WC_Payment_Token $token
|
||||
*/
|
||||
public function read( &$token ) {
|
||||
global $wpdb;
|
||||
if ( $data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d LIMIT 1;", $token->get_id() ) ) ) {
|
||||
$token->set_props( array(
|
||||
'token' => $data->token,
|
||||
'user_id' => $data->user_id,
|
||||
'gateway_id' => $data->gateway_id,
|
||||
'default' => $data->is_default,
|
||||
) );
|
||||
$token->read_meta_data();
|
||||
$token->set_object_read( true );
|
||||
do_action( 'woocommerce_payment_token_loaded', $token );
|
||||
} else {
|
||||
throw new Exception( __( 'Invalid payment token.', 'woocommerce' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of objects (stdObject) matching specific token critera.
|
||||
* Accepts token_id, user_id, gateway_id, and type.
|
||||
* Each object should contain the fields token_id, gateway_id, token, user_id, type, is_default.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param array $args
|
||||
* @return array
|
||||
*/
|
||||
public function get_tokens( $args ) {
|
||||
global $wpdb;
|
||||
$args = wp_parse_args( $args, array(
|
||||
'token_id' => '',
|
||||
'user_id' => '',
|
||||
'gateway_id' => '',
|
||||
'type' => '',
|
||||
) );
|
||||
|
||||
$sql = "SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens";
|
||||
$where = array( '1=1' );
|
||||
|
||||
if ( $args['token_id'] ) {
|
||||
$token_ids = array_map( 'absint', is_array( $args['token_id'] ) ? $args['token_id'] : array( $args['token_id'] ) );
|
||||
$where[] = "token_id IN ('" . implode( "','", array_map( 'esc_sql', $token_ids ) ) . "')";
|
||||
}
|
||||
|
||||
if ( $args['user_id'] ) {
|
||||
$where[] = 'user_id = ' . absint( $args['user_id'] );
|
||||
}
|
||||
|
||||
if ( $args['gateway_id'] ) {
|
||||
$gateway_ids = array( $args['gateway_id'] );
|
||||
} else {
|
||||
$gateways = WC_Payment_Gateways::instance();
|
||||
$gateway_ids = $gateways->get_payment_gateway_ids();
|
||||
}
|
||||
|
||||
$gateway_ids[] = '';
|
||||
$where[] = "gateway_id IN ('" . implode( "','", array_map( 'esc_sql', $gateway_ids ) ) . "')";
|
||||
|
||||
if ( $args['type'] ) {
|
||||
$where[] = 'type = ' . esc_sql( $args['type'] );
|
||||
}
|
||||
|
||||
$token_results = $wpdb->get_results( $sql . ' WHERE ' . implode( ' AND ', $where ) );
|
||||
|
||||
return $token_results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an stdObject of a token for a user's default token.
|
||||
* Should contain the fields token_id, gateway_id, token, user_id, type, is_default.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param id $user_id
|
||||
* @return object
|
||||
*/
|
||||
public function get_users_default_token( $user_id ) {
|
||||
global $wpdb;
|
||||
return $wpdb->get_row( $wpdb->prepare(
|
||||
"SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE user_id = %d AND is_default = 1",
|
||||
$user_id
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an stdObject of a token.
|
||||
* Should contain the fields token_id, gateway_id, token, user_id, type, is_default.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param id $token_id
|
||||
* @return object
|
||||
*/
|
||||
public function get_token_by_id( $token_id ) {
|
||||
global $wpdb;
|
||||
return $wpdb->get_row( $wpdb->prepare(
|
||||
"SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d",
|
||||
$token_id
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns metadata for a specific payment token.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param id $token_id
|
||||
* @return array
|
||||
*/
|
||||
public function get_metadata( $token_id ) {
|
||||
return get_metadata( 'payment_token', $token_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a token's type by ID.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param id $token_id
|
||||
* @return string
|
||||
*/
|
||||
public function get_token_type_by_id( $token_id ) {
|
||||
global $wpdb;
|
||||
return $wpdb->get_var( $wpdb->prepare(
|
||||
"SELECT type FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d",
|
||||
$token_id
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update's a tokens default status in the database. Used for quickly
|
||||
* looping through tokens and setting their statuses instead of creating a bunch
|
||||
* of objects.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param id $token_id
|
||||
* @return string
|
||||
*/
|
||||
public function set_default_status( $token_id, $status = true ) {
|
||||
global $wpdb;
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'woocommerce_payment_tokens',
|
||||
array( 'is_default' => $status ),
|
||||
array(
|
||||
'token_id' => $token_id,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC Payment Token Data Store Interface
|
||||
*
|
||||
* Functions that must be defined by payment token store classes.
|
||||
*
|
||||
* @version 2.7.0
|
||||
* @category Interface
|
||||
* @author WooThemes
|
||||
*/
|
||||
interface WC_Payment_Token_Data_Store_Interface {
|
||||
/**
|
||||
* Returns an array of objects (stdObject) matching specific token critera.
|
||||
* Accepts token_id, user_id, gateway_id, and type.
|
||||
* Each object should contain the fields token_id, gateway_id, token, user_id, type, is_default.
|
||||
* @param array $args
|
||||
* @return array
|
||||
*/
|
||||
public function get_tokens( $args );
|
||||
|
||||
/**
|
||||
* Returns an stdObject of a token for a user's default token.
|
||||
* Should contain the fields token_id, gateway_id, token, user_id, type, is_default.
|
||||
* @param id $user_id
|
||||
* @return object
|
||||
*/
|
||||
public function get_users_default_token( $user_id );
|
||||
|
||||
/**
|
||||
* Returns an stdObject of a token.
|
||||
* Should contain the fields token_id, gateway_id, token, user_id, type, is_default.
|
||||
* @param id $token_id
|
||||
* @return object
|
||||
*/
|
||||
public function get_token_by_id( $token_id );
|
||||
|
||||
/**
|
||||
* Returns metadata for a specific payment token.
|
||||
* @param id $token_id
|
||||
* @return array
|
||||
*/
|
||||
public function get_metadata( $token_id );
|
||||
|
||||
/**
|
||||
* Get a token's type by ID.
|
||||
*
|
||||
* @since 2.7.0
|
||||
* @param id $token_id
|
||||
* @return string
|
||||
*/
|
||||
public function get_token_type_by_id( $token_id );
|
||||
|
||||
/**
|
||||
* Update's a tokens default status in the database. Used for quickly
|
||||
* looping through tokens and setting their statuses instead of creating a bunch
|
||||
* of objects.
|
||||
* @param id $token_id
|
||||
* @return string
|
||||
*/
|
||||
public function set_default_status( $token_id, $status = true );
|
||||
}
|
|
@ -34,4 +34,19 @@ interface WC_Coupon_Data_Store {
|
|||
* @return int
|
||||
*/
|
||||
public function get_usage_by_user_id( &$coupon, $user_id );
|
||||
|
||||
/**
|
||||
* Return a coupon code for a specific ID.
|
||||
* @param int $id
|
||||
* @return string Coupon Code
|
||||
*/
|
||||
public function get_code_by_id( $id );
|
||||
|
||||
/**
|
||||
* Return an array of IDs for for a specific coupon code.
|
||||
* Can return multiple to check for existence.
|
||||
* @param string $code
|
||||
* @return array Array of IDs.
|
||||
*/
|
||||
public function get_ids_by_code( $code );
|
||||
}
|
||||
|
|
|
@ -314,7 +314,7 @@ class WC_Gateway_Paypal_Request {
|
|||
* Add PayPal Line Item.
|
||||
* @param string $item_name
|
||||
* @param int $quantity
|
||||
* @param int $amount
|
||||
* @param float $amount
|
||||
* @param string $item_number
|
||||
* @return bool successfully added or not
|
||||
*/
|
||||
|
@ -326,8 +326,8 @@ class WC_Gateway_Paypal_Request {
|
|||
}
|
||||
|
||||
$this->line_items[ 'item_name_' . $index ] = html_entity_decode( wc_trim_string( $item_name ? $item_name : __( 'Item', 'woocommerce' ), 127 ), ENT_NOQUOTES, 'UTF-8' );
|
||||
$this->line_items[ 'quantity_' . $index ] = $quantity;
|
||||
$this->line_items[ 'amount_' . $index ] = $amount;
|
||||
$this->line_items[ 'quantity_' . $index ] = (int) $quantity;
|
||||
$this->line_items[ 'amount_' . $index ] = (float) $amount;
|
||||
$this->line_items[ 'item_number_' . $index ] = $item_number;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -140,7 +140,7 @@ abstract class WC_Legacy_Coupon extends WC_Data {
|
|||
* @return array
|
||||
*/
|
||||
public function format_array( $array ) {
|
||||
_deprecated_function( 'format_array', '2.7', '' );
|
||||
_deprecated_function( 'format_array', '2.7' );
|
||||
if ( ! is_array( $array ) ) {
|
||||
if ( is_serialized( $array ) ) {
|
||||
$array = maybe_unserialize( $array );
|
||||
|
@ -158,7 +158,7 @@ abstract class WC_Legacy_Coupon extends WC_Data {
|
|||
* @return bool
|
||||
*/
|
||||
public function apply_before_tax() {
|
||||
_deprecated_function( 'apply_before_tax', '2.7', '' );
|
||||
_deprecated_function( 'apply_before_tax', '2.7' );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -150,7 +150,7 @@ abstract class WC_Legacy_Customer extends WC_Data {
|
|||
* Set default data for a customer.
|
||||
*/
|
||||
public function set_default_data() {
|
||||
_deprecated_function( 'WC_Customer::set_default_data', '2.7', '' );
|
||||
_deprecated_function( 'WC_Customer::set_default_data', '2.7' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,6 +9,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* Representation of a payment token for credit cards.
|
||||
*
|
||||
* @class WC_Payment_Token_CC
|
||||
* @version 2.7.0
|
||||
* @since 2.6.0
|
||||
* @category PaymentTokens
|
||||
* @package WooCommerce/PaymentTokens
|
||||
|
@ -19,6 +20,15 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
|
|||
/** @protected string Token Type String. */
|
||||
protected $type = 'CC';
|
||||
|
||||
/**
|
||||
* Hook prefix
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
protected function get_hook_prefix() {
|
||||
return 'woocommerce_payment_token_cc_get_';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate credit card payment tokens.
|
||||
*
|
||||
|
@ -36,27 +46,27 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
|
|||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->get_last4() ) {
|
||||
if ( ! $this->get_last4( 'edit' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->get_expiry_year() ) {
|
||||
if ( ! $this->get_expiry_year( 'edit' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->get_expiry_month() ) {
|
||||
if ( ! $this->get_expiry_month( 'edit' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->get_card_type() ) {
|
||||
if ( ! $this->get_card_type( 'edit' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( 4 !== strlen( $this->get_expiry_year() ) ) {
|
||||
if ( 4 !== strlen( $this->get_expiry_year( 'edit' ) ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( 2 !== strlen( $this->get_expiry_month() ) ) {
|
||||
if ( 2 !== strlen( $this->get_expiry_month( 'edit' ) ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -65,27 +75,32 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
|
|||
|
||||
/**
|
||||
* Get type to display to user.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string
|
||||
*/
|
||||
public function get_display_name() {
|
||||
public function get_display_name( $context = 'view' ) {
|
||||
/* translators: 1: credit card type 2: last 4 digits 3: expiry month 4: expiry year */
|
||||
$display = sprintf(
|
||||
__( '%1$s ending in %2$s (expires %3$s/%4$s)', 'woocommerce' ),
|
||||
wc_get_credit_card_type_label( $this->get_card_type() ),
|
||||
$this->get_last4(),
|
||||
$this->get_expiry_month(),
|
||||
substr( $this->get_expiry_year(), 2 )
|
||||
wc_get_credit_card_type_label( $this->get_card_type( $context ) ),
|
||||
$this->get_last4( $context ),
|
||||
$this->get_expiry_month( $context ),
|
||||
substr( $this->get_expiry_year( $context ), 2 )
|
||||
);
|
||||
return $display;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the card type (mastercard, visa, ...).
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string Card type
|
||||
*/
|
||||
public function get_card_type() {
|
||||
return $this->get_meta( 'card_type' );
|
||||
public function get_card_type( $context = 'view' ) {
|
||||
return $this->get_meta( 'card_type', true, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,11 +114,13 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
|
|||
|
||||
/**
|
||||
* Returns the card expiration year (YYYY).
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string Expiration year
|
||||
*/
|
||||
public function get_expiry_year() {
|
||||
return $this->get_meta( 'expiry_year' );
|
||||
public function get_expiry_year( $context = 'view' ) {
|
||||
return $this->get_meta( 'expiry_year', true, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -117,11 +134,13 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
|
|||
|
||||
/**
|
||||
* Returns the card expiration month (MM).
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string Expiration month
|
||||
*/
|
||||
public function get_expiry_month() {
|
||||
return $this->get_meta( 'expiry_month' );
|
||||
public function get_expiry_month( $context = 'view' ) {
|
||||
return $this->get_meta( 'expiry_month', true, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,11 +154,13 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
|
|||
|
||||
/**
|
||||
* Returns the last four digits.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string Last 4 digits
|
||||
*/
|
||||
public function get_last4() {
|
||||
return $this->get_meta( 'last4' );
|
||||
public function get_last4( $context = 'view' ) {
|
||||
return $this->get_meta( 'last4', true, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* Representation of a payment token for eChecks.
|
||||
*
|
||||
* @class WC_Payment_Token_eCheck
|
||||
* @version 2.7.0
|
||||
* @since 2.6.0
|
||||
* @category PaymentTokens
|
||||
* @package WooCommerce/PaymentTokens
|
||||
|
@ -20,6 +21,15 @@ class WC_Payment_Token_eCheck extends WC_Payment_Token {
|
|||
/** @protected string Token Type String */
|
||||
protected $type = 'eCheck';
|
||||
|
||||
/**
|
||||
* Hook prefix
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
protected function get_hook_prefix() {
|
||||
return 'woocommerce_payment_token_echeck_get_';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate eCheck payment tokens.
|
||||
*
|
||||
|
@ -34,7 +44,7 @@ class WC_Payment_Token_eCheck extends WC_Payment_Token {
|
|||
return false;
|
||||
}
|
||||
|
||||
if ( ! $this->get_last4() ) {
|
||||
if ( ! $this->get_last4( 'edit' ) ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -42,19 +52,24 @@ class WC_Payment_Token_eCheck extends WC_Payment_Token {
|
|||
|
||||
/**
|
||||
* Get type to display to user.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string
|
||||
*/
|
||||
public function get_display_name() {
|
||||
public function get_display_name( $context = 'view' ) {
|
||||
return __( 'eCheck', 'woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last four digits.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $context
|
||||
* @return string Last 4 digits
|
||||
*/
|
||||
public function get_last4() {
|
||||
return $this->get_meta( 'last4' );
|
||||
public function get_last4( $context = 'view' ) {
|
||||
return $this->get_meta( 'last4', true, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WooCommerce Coupons Functions
|
||||
*
|
||||
|
@ -7,13 +11,9 @@
|
|||
* @author WooThemes
|
||||
* @category Core
|
||||
* @package WooCommerce/Functions
|
||||
* @version 2.1.0
|
||||
* @version 2.7.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Get coupon types.
|
||||
*
|
||||
|
@ -79,17 +79,8 @@ function wc_coupons_enabled() {
|
|||
* @return string
|
||||
*/
|
||||
function wc_get_coupon_code_by_id( $id ) {
|
||||
global $wpdb;
|
||||
|
||||
$code = $wpdb->get_var( $wpdb->prepare( "
|
||||
SELECT post_title
|
||||
FROM $wpdb->posts
|
||||
WHERE ID = %d
|
||||
AND post_type = 'shop_coupon'
|
||||
AND post_status = 'publish';
|
||||
", $id ) );
|
||||
|
||||
return (string) $code;
|
||||
$data_store = WC_Data_Store::load( 'coupon' );
|
||||
return (string) $data_store->get_code_by_id( $id );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,14 +92,11 @@ function wc_get_coupon_code_by_id( $id ) {
|
|||
* @return int
|
||||
*/
|
||||
function wc_get_coupon_id_by_code( $code, $exclude = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$data_store = WC_Data_Store::load( 'coupon' );
|
||||
$ids = wp_cache_get( WC_Cache_Helper::get_cache_prefix( 'coupons' ) . 'coupon_id_from_code_' . $code, 'coupons' );
|
||||
|
||||
if ( false === $ids ) {
|
||||
$sql = $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' ORDER BY post_date DESC;", $code );
|
||||
$ids = $wpdb->get_col( $sql );
|
||||
|
||||
$ids = $data_store->get_ids_by_code( $code );
|
||||
if ( $ids ) {
|
||||
wp_cache_set( WC_Cache_Helper::get_cache_prefix( 'coupons' ) . 'coupon_id_from_code_' . $code, $ids, 'coupons' );
|
||||
}
|
||||
|
|
|
@ -73,25 +73,25 @@ function woocommerce_show_messages() {
|
|||
* @deprecated
|
||||
*/
|
||||
function woocommerce_weekend_area_js() {
|
||||
_deprecated_function( 'woocommerce_weekend_area_js', '2.1', '' );
|
||||
_deprecated_function( 'woocommerce_weekend_area_js', '2.1' );
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
function woocommerce_tooltip_js() {
|
||||
_deprecated_function( 'woocommerce_tooltip_js', '2.1', '' );
|
||||
_deprecated_function( 'woocommerce_tooltip_js', '2.1' );
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
function woocommerce_datepicker_js() {
|
||||
_deprecated_function( 'woocommerce_datepicker_js', '2.1', '' );
|
||||
_deprecated_function( 'woocommerce_datepicker_js', '2.1' );
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
function woocommerce_admin_scripts() {
|
||||
_deprecated_function( 'woocommerce_admin_scripts', '2.1', '' );
|
||||
_deprecated_function( 'woocommerce_admin_scripts', '2.1' );
|
||||
}
|
||||
/**
|
||||
* @deprecated
|
||||
|
|
|
@ -1108,7 +1108,7 @@ if ( ! function_exists( 'woocommerce_product_reviews_tab' ) ) {
|
|||
* @subpackage Product/Tabs
|
||||
*/
|
||||
function woocommerce_product_reviews_tab() {
|
||||
_deprecated_function( 'woocommerce_product_reviews_tab', '2.4', '' );
|
||||
_deprecated_function( 'woocommerce_product_reviews_tab', '2.4' );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -515,8 +515,6 @@ function _wc_term_recount( $terms, $taxonomy, $callback = true, $terms_are_term_
|
|||
LEFT JOIN {$wpdb->postmeta} AS meta_visibility ON posts.ID = meta_visibility.post_id
|
||||
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
|
||||
LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
|
||||
LEFT JOIN {$wpdb->terms} AS term USING( term_id )
|
||||
LEFT JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id
|
||||
$stock_join
|
||||
WHERE post_status = 'publish'
|
||||
AND post_type = 'product'
|
||||
|
|
|
@ -13,22 +13,21 @@
|
|||
* @see https://docs.woocommerce.com/document/template-structure/
|
||||
* @author WooThemes
|
||||
* @package WooCommerce/Templates
|
||||
* @version 2.3.8
|
||||
* @version 2.7.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
wc_print_notices();
|
||||
|
||||
do_action( 'woocommerce_before_cart' ); ?>
|
||||
|
||||
<form action="<?php echo esc_url( wc_get_cart_url() ); ?>" method="post">
|
||||
|
||||
<form class="woocommerce-cart-form" action="<?php echo esc_url( wc_get_cart_url() ); ?>" method="post">
|
||||
<?php do_action( 'woocommerce_before_cart_table' ); ?>
|
||||
|
||||
<table class="shop_table shop_table_responsive cart" cellspacing="0">
|
||||
<table class="shop_table shop_table_responsive cart woocommerce-cart-form__contents" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="product-remove"> </th>
|
||||
|
@ -50,7 +49,7 @@ do_action( 'woocommerce_before_cart' ); ?>
|
|||
if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
|
||||
$product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
|
||||
?>
|
||||
<tr class="<?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
|
||||
<tr class="woocommerce-cart-form__cart-item <?php echo esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) ); ?>">
|
||||
|
||||
<td class="product-remove">
|
||||
<?php
|
||||
|
@ -126,17 +125,16 @@ do_action( 'woocommerce_before_cart' ); ?>
|
|||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_cart_contents' );
|
||||
?>
|
||||
|
||||
<?php do_action( 'woocommerce_cart_contents' ); ?>
|
||||
|
||||
<tr>
|
||||
<td colspan="6" class="actions">
|
||||
|
||||
<?php if ( wc_coupons_enabled() ) { ?>
|
||||
<div class="coupon">
|
||||
|
||||
<label for="coupon_code"><?php _e( 'Coupon:', 'woocommerce' ); ?></label> <input type="text" name="coupon_code" class="input-text" id="coupon_code" value="" placeholder="<?php esc_attr_e( 'Coupon code', 'woocommerce' ); ?>" /> <input type="submit" class="button" name="apply_coupon" value="<?php esc_attr_e( 'Apply coupon', 'woocommerce' ); ?>" />
|
||||
|
||||
<?php do_action( 'woocommerce_cart_coupon' ); ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
@ -152,15 +150,11 @@ do_action( 'woocommerce_before_cart' ); ?>
|
|||
<?php do_action( 'woocommerce_after_cart_contents' ); ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php do_action( 'woocommerce_after_cart_table' ); ?>
|
||||
|
||||
</form>
|
||||
|
||||
<div class="cart-collaterals">
|
||||
|
||||
<?php do_action( 'woocommerce_cart_collaterals' ); ?>
|
||||
|
||||
</div>
|
||||
|
||||
<?php do_action( 'woocommerce_after_cart' ); ?>
|
||||
|
|
|
@ -54,6 +54,7 @@ class WC_Tests_REST_System_Status extends WC_REST_Unit_Test_Case {
|
|||
$this->assertArrayHasKey( 'active_plugins', $data );
|
||||
$this->assertArrayHasKey( 'theme', $data );
|
||||
$this->assertArrayHasKey( 'settings', $data );
|
||||
$this->assertArrayHasKey( 'security', $data );
|
||||
$this->assertArrayHasKey( 'pages', $data );
|
||||
}
|
||||
|
||||
|
@ -156,6 +157,23 @@ class WC_Tests_REST_System_Status extends WC_REST_Unit_Test_Case {
|
|||
$this->assertEquals( $term_response, $settings['taxonomies'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to make sure security response is correct.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_get_system_status_info_security() {
|
||||
wp_set_current_user( $this->user );
|
||||
|
||||
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/system_status' ) );
|
||||
$data = $response->get_data();
|
||||
$settings = $data['security'];
|
||||
|
||||
$this->assertEquals( 2, count( $settings ) );
|
||||
$this->assertEquals( 'https' === substr( get_permalink( wc_get_page_id( 'shop' ) ), 0, 5 ), $settings['secure_connection'] );
|
||||
$this->assertEquals( ! ( defined( 'WP_DEBUG' ) && defined( 'WP_DEBUG_DISPLAY' ) && WP_DEBUG && WP_DEBUG_DISPLAY ) || 0 === intval( ini_get( 'display_errors' ) ), $settings['hide_errors'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to make sure pages response is correct.
|
||||
*
|
||||
|
@ -179,12 +197,13 @@ class WC_Tests_REST_System_Status extends WC_REST_Unit_Test_Case {
|
|||
$response = $this->server->dispatch( $request );
|
||||
$data = $response->get_data();
|
||||
$properties = $data['schema']['properties'];
|
||||
$this->assertEquals( 6, count( $properties ) );
|
||||
$this->assertEquals( 7, count( $properties ) );
|
||||
$this->assertArrayHasKey( 'environment', $properties );
|
||||
$this->assertArrayHasKey( 'database', $properties );
|
||||
$this->assertArrayHasKey( 'active_plugins', $properties );
|
||||
$this->assertArrayHasKey( 'theme', $properties );
|
||||
$this->assertArrayHasKey( 'settings', $properties );
|
||||
$this->assertArrayHasKey( 'security', $properties );
|
||||
$this->assertArrayHasKey( 'pages', $properties );
|
||||
}
|
||||
|
||||
|
|
|
@ -61,4 +61,22 @@ class WC_Tests_Functions extends WC_Unit_Test_Case {
|
|||
|
||||
$this->assertEmpty( wc_get_coupon_code_by_id( 0 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test wc_get_coupon_id_by_code().
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_wc_get_coupon_id_by_code() {
|
||||
// Create coupon.
|
||||
$code = 'testcoupon';
|
||||
$coupon = WC_Helper_Coupon::create_coupon( $code );
|
||||
|
||||
$this->assertEquals( $coupon->get_id(), wc_get_coupon_id_by_code( $coupon->get_code() ) );
|
||||
|
||||
// Delete coupon.
|
||||
WC_Helper_Coupon::delete_coupon( $coupon->get_id() );
|
||||
|
||||
$this->assertEmpty( wc_get_coupon_id_by_code( 0 ) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,8 +92,7 @@ class WC_Tests_Payment_Token_CC extends WC_Unit_Test_Case {
|
|||
public function test_wc_payment_token_cc_read_pulls_meta() {
|
||||
$token = WC_Helper_Payment_Token::create_cc_token();
|
||||
$token_id = $token->get_id();
|
||||
$token_read = new WC_Payment_Token_CC();
|
||||
$token_read->read( $token_id );
|
||||
$token_read = new WC_Payment_Token_CC( $token_id );
|
||||
$this->assertEquals( '1234', $token_read->get_last4() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,9 +36,7 @@ class WC_Tests_Payment_Token_eCheck extends WC_Unit_Test_Case {
|
|||
$token = WC_Helper_Payment_Token::create_eCheck_token();
|
||||
$token_id = $token->get_id();
|
||||
|
||||
$token_read = new WC_Payment_Token_eCheck();
|
||||
$token_read->read( $token_id );
|
||||
|
||||
$token_read = new WC_Payment_Token_eCheck( $token_id );
|
||||
$this->assertEquals( '1234', $token_read->get_last4() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class Payment_Token
|
||||
* @package WooCommerce\Tests\Payment_Tokens
|
||||
|
@ -60,7 +59,7 @@ class WC_Tests_Payment_Token extends WC_Unit_Test_Case {
|
|||
* @since 2.6.0
|
||||
*/
|
||||
public function test_wc_payment_token_is_default() {
|
||||
$token = new WC_Payment_Token_Stub( 1 );
|
||||
$token = new WC_Payment_Token_Stub();
|
||||
$token->set_default( true );
|
||||
$this->assertTrue( $token->is_default() );
|
||||
$token->set_default( false );
|
||||
|
@ -79,11 +78,11 @@ class WC_Tests_Payment_Token extends WC_Unit_Test_Case {
|
|||
$token->set_gateway_id( 'paypal' );
|
||||
$token->set_extra( 'woocommerce' );
|
||||
|
||||
$data = $token->get_data();
|
||||
$this->assertEquals( $raw_token, $token->get_token() );
|
||||
$this->assertEquals( 'paypal', $token->get_gateway_id() );
|
||||
$this->assertEquals( 'stub', $token->get_type() );
|
||||
|
||||
$this->assertEquals( $raw_token, $data['token'] );
|
||||
$this->assertEquals( 'paypal', $data['gateway_id'] );
|
||||
$this->assertEquals( 'stub', $data['type'] );
|
||||
$data = $token->get_data();
|
||||
$this->assertEquals( 'extra', $data['meta_data'][0]->key );
|
||||
$this->assertEquals( 'woocommerce', $data['meta_data'][0]->value );
|
||||
}
|
||||
|
@ -109,8 +108,7 @@ class WC_Tests_Payment_Token extends WC_Unit_Test_Case {
|
|||
$token = WC_Helper_Payment_Token::create_stub_token( __FUNCTION__ );
|
||||
$token_id = $token->get_id();
|
||||
|
||||
$token_read = new WC_Payment_Token_Stub();
|
||||
$token_read->read( $token_id );
|
||||
$token_read = new WC_Payment_Token_Stub( $token_id );
|
||||
|
||||
$this->assertEquals( $token->get_token(), $token_read->get_token() );
|
||||
$this->assertEquals( $token->get_extra(), $token_read->get_extra() );
|
||||
|
@ -124,7 +122,9 @@ class WC_Tests_Payment_Token extends WC_Unit_Test_Case {
|
|||
$token = WC_Helper_Payment_Token::create_stub_token( __FUNCTION__ );
|
||||
$this->assertEquals( __FUNCTION__, $token->get_extra() );
|
||||
$token->set_extra( ':)' );
|
||||
$token->update();
|
||||
$token->save();
|
||||
|
||||
$token = new WC_Payment_Token_Stub( $token->get_id() );
|
||||
$this->assertEquals( ':)', $token->get_extra() );
|
||||
}
|
||||
|
||||
|
@ -136,9 +136,10 @@ class WC_Tests_Payment_Token extends WC_Unit_Test_Case {
|
|||
$token = new WC_Payment_Token_Stub();
|
||||
$token->set_extra( __FUNCTION__ );
|
||||
$token->set_token( time() );
|
||||
$token->create();
|
||||
|
||||
$token->save();
|
||||
$this->assertNotEmpty( $token->get_id() );
|
||||
|
||||
$token = new WC_Payment_Token_Stub( $token->get_id() );
|
||||
$this->assertEquals( __FUNCTION__, $token->get_extra() );
|
||||
}
|
||||
|
||||
|
@ -162,4 +163,30 @@ class WC_Tests_Payment_Token extends WC_Unit_Test_Case {
|
|||
$token = new WC_Payment_Token_Stub();
|
||||
$this->assertFalse( is_callable( $token, 'get_last4' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test legacy token functions.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_wc_payment_token_legacy() {
|
||||
$token = WC_Helper_Payment_Token::create_stub_token( __FUNCTION__ );
|
||||
$token_id = $token->get_id();
|
||||
|
||||
$token_read = new WC_Payment_Token_Stub();
|
||||
$token_read->read( $token_id );
|
||||
$this->assertEquals( $token_id, $token_read->get_id() );
|
||||
|
||||
$token = new WC_Payment_Token_Stub();
|
||||
$token->set_token( 'blah' );
|
||||
$token->create();
|
||||
|
||||
$this->assertEquals( 'blah', $token->get_token() );
|
||||
$this->assertNotEmpty( $token->get_id() );
|
||||
|
||||
$token->set_token( 'blah2' );
|
||||
$token->update();
|
||||
|
||||
$this->assertEquals( 'blah2', $token->get_token() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -166,14 +166,14 @@ class WC_Tests_Payment_Tokens extends WC_Unit_Test_Case {
|
|||
$this->assertFalse( $token2->is_default() );
|
||||
|
||||
WC_Payment_Tokens::set_users_default( $this->user_id, $token_id_2 );
|
||||
$token->read( $token_id );
|
||||
$token2->read( $token_id_2 );
|
||||
$token = new WC_Payment_Token_CC( $token_id );
|
||||
$token2 = new WC_Payment_Token_CC( $token_id_2 );
|
||||
$this->assertFalse( $token->is_default() );
|
||||
$this->assertTrue( $token2->is_default() );
|
||||
|
||||
WC_Payment_Tokens::set_users_default( $this->user_id, $token_id );
|
||||
$token->read( $token_id );
|
||||
$token2->read( $token_id_2 );
|
||||
$token = new WC_Payment_Token_CC( $token_id );
|
||||
$token2 = new WC_Payment_Token_CC( $token_id_2 );
|
||||
$this->assertTrue( $token->is_default() );
|
||||
$this->assertFalse( $token2->is_default() );
|
||||
}
|
||||
|
|
|
@ -289,17 +289,15 @@ final class WooCommerce {
|
|||
include_once( WC_ABSPATH . 'includes/data-stores/interfaces/interface-wc-coupon-data-store.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/interfaces/interface-wc-product-data-store.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/interfaces/interface-wc-product-variable-data-store.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/interfaces/class-wc-payment-token-data-store-interface.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/class-wc-data-store-cpt.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/class-wc-coupon-data-store-cpt.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/class-wc-payment-token-data-store-table.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/class-wc-product-data-store-cpt.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/class-wc-product-grouped-data-store-cpt.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/class-wc-product-variable-data-store-cpt.php' );
|
||||
include_once( WC_ABSPATH . 'includes/data-stores/class-wc-product-variation-data-store-cpt.php' );
|
||||
|
||||
if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-cli.php' );
|
||||
}
|
||||
|
||||
$this->query = new WC_Query();
|
||||
$this->api = new WC_API();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue