Merge branch 'master' into pr/14896

# Conflicts:
#	assets/js/frontend/single-product.min.js
This commit is contained in:
Mike Jolley 2017-05-23 16:22:18 +01:00
commit a1a79e57b5
128 changed files with 3840 additions and 2555 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2051,6 +2051,31 @@ table.wp-list-table {
white-space: nowrap;
}
.column-handle {
width: 17px;
}
tbody {
td.column-handle {
cursor: move;
width: 17px;
text-align: center;
vertical-align: text-top;
&::before {
content: '\f333';
font-family: 'Dashicons';
text-align: center;
line-height: 1;
color: #999;
display: block;
width: 17px;
height: 100%;
margin: 4px 0 0 0;
}
}
}
.column-name {
width: 22%;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -404,18 +404,27 @@ table.variations {
.flex-control-thumbs li {
width: 33.3333%;
}
.flex-control-thumbs li:nth-child(3n+1) {
clear: left;
}
}
.woocommerce-product-gallery--columns-4 {
.flex-control-thumbs li {
width: 25%;
}
.flex-control-thumbs li:nth-child(4n+1) {
clear: left;
}
}
.woocommerce-product-gallery--columns-5 {
.flex-control-thumbs li {
width: 20%;
}
.flex-control-thumbs li:nth-child(5n+1) {
clear: left;
}
}
.woocommerce-product-gallery__trigger {
@ -985,12 +994,21 @@ button.pswp__button--zoom:hover {
}
}
.colors-dark.woocommerce-checkout {
.colors-dark {
.checkout-button {
border: 2px solid #555;
&:hover {
border-color: #fff;
}
}
.wc_payment_method {
.payment_box {
background: #333;
}
}
.select2-container--default {
.select2-results {
.select2-results__options {
@ -1000,6 +1018,7 @@ button.pswp__button--zoom:hover {
color: #333;
}
}
.select2-selection--single {
background-color: #333;
border: 1px solid #555;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -247,6 +247,24 @@ p.demo_store,
}
}
.woocommerce-product-gallery--columns-3 {
.flex-control-thumbs li:nth-child(3n+1) {
clear: left;
}
}
.woocommerce-product-gallery--columns-4 {
.flex-control-thumbs li:nth-child(4n+1) {
clear: left;
}
}
.woocommerce-product-gallery--columns-5 {
.flex-control-thumbs li:nth-child(5n+1) {
clear: left;
}
}
div.summary {
margin-bottom: 2em;
}

View File

@ -1 +1 @@
jQuery(function(a){var b={init:function(){a(document.body).on("click","a.help_tip, a.woocommerce-help-tip",this.preventTipTipClick).on("click","a.debug-report",this.generateReport).on("copy","#copy-for-support",this.copyReport).on("aftercopy","#copy-for-support",this.afterCopyReport)},preventTipTipClick:function(){return!1},generateReport:function(){var b="";a(".wc_status_table thead, .wc_status_table tbody").each(function(){if(a(this).is("thead")){var c=a(this).find("th:eq(0)").data("export-label")||a(this).text();b=b+"\n### "+a.trim(c)+" ###\n\n"}else a("tr",a(this)).each(function(){var c=a(this).find("td:eq(0)").data("export-label")||a(this).find("td:eq(0)").text(),d=a.trim(c).replace(/(<([^>]+)>)/gi,""),e=a(this).find("td:eq(2)").clone();e.find(".private").remove(),e.find(".dashicons-yes").replaceWith("&#10004;"),e.find(".dashicons-no-alt, .dashicons-warning").replaceWith("&#10060;");var f=a.trim(e.text()),g=f.split(", ");if(g.length>1){var h="";a.each(g,function(a,b){h=h+b+"\n"}),f=h}b=b+""+d+": "+f+"\n"})});try{return a("#debug-report").slideDown(),a("#debug-report").find("textarea").val("`"+b+"`").focus().select(),a(this).fadeOut(),!1}catch(a){console.log(a)}return!1},copyReport:function(b){b.clipboardData.clearData(),b.clipboardData.setData("text/plain",a("#debug-report").find("textarea").val()),b.preventDefault()},afterCopyReport:function(b){!0===b.success["text/plain"]?a("#copy-for-support").tipTip({attribute:"data-tip",activation:"focus",fadeIn:50,fadeOut:50,delay:0}).focus():(a(".copy-error").removeClass("hidden"),a("#debug-report").find("textarea").focus().select())}};b.init()});
jQuery(function(a){var b={init:function(){a(document.body).on("click","a.help_tip, a.woocommerce-help-tip",this.preventTipTipClick).on("click","a.debug-report",this.generateReport).on("copy","#copy-for-support",this.copyReport).on("aftercopy","#copy-for-support",this.afterCopyReport)},preventTipTipClick:function(){return!1},generateReport:function(){var b="";a(".wc_status_table thead, .wc_status_table tbody").each(function(){if(a(this).is("thead")){var c=a(this).find("th:eq(0)").data("export-label")||a(this).text();b=b+"\n### "+a.trim(c)+" ###\n\n"}else a("tr",a(this)).each(function(){var c=a(this).find("td:eq(0)").data("export-label")||a(this).find("td:eq(0)").text(),d=a.trim(c).replace(/(<([^>]+)>)/gi,""),e=a(this).find("td:eq(2)").clone();e.find(".private").remove(),e.find(".dashicons-yes").replaceWith("&#10004;"),e.find(".dashicons-no-alt, .dashicons-warning").replaceWith("&#10060;");var f=a.trim(e.text()),g=f.split(", ");if(g.length>1){var h="";a.each(g,function(a,b){h=h+b+"\n"}),f=h}b=b+""+d+": "+f+"\n"})});try{return a("#debug-report").slideDown(),a("#debug-report").find("textarea").val("`"+b+"`").focus().select(),a(this).fadeOut(),!1}catch(a){console.log(a)}return!1},copyReport:function(b){b.clipboardData.clearData(),b.clipboardData.setData("text/plain",a("#debug-report").find("textarea").val()),b.preventDefault()},afterCopyReport:function(b){!0===b.success["text/plain"]?a("#copy-for-support").tipTip({attribute:"data-tip",activation:"focus",fadeIn:50,fadeOut:50,delay:0}).focus():(a(".copy-error").removeClass("hidden"),a("#debug-report").find("textarea").focus().select())}};b.init(),a("#log-viewer-select").on("click","h2 a.page-title-action",function(a){return a.stopImmediatePropagation(),window.confirm(woocommerce_admin_system_status.delete_log_confirmation)})});

View File

@ -3,11 +3,14 @@
/* Modifided script from the simple-page-ordering plugin */
jQuery( function( $ ) {
$( 'table.widefat.wp-list-table tbody th, table.widefat tbody td' ).css( 'cursor', 'move' );
$( 'table.widefat.wp-list-table tr' ).append(
'<td class="column-handle"></td>'
);
$( 'table.widefat.wp-list-table' ).sortable({
items: 'tbody tr:not(.inline-edit-row)',
cursor: 'move',
handle: '.column-handle',
axis: 'y',
forcePlaceholderSize: true,
helper: 'clone',

View File

@ -1 +1 @@
jQuery(function(a){a("table.widefat.wp-list-table tbody th, table.widefat tbody td").css("cursor","move"),a("table.widefat.wp-list-table").sortable({items:"tbody tr:not(.inline-edit-row)",cursor:"move",axis:"y",forcePlaceholderSize:!0,helper:"clone",opacity:.65,placeholder:"product-cat-placeholder",scrollSensitivity:40,start:function(a,b){b.item.hasClass("alternate")||b.item.css("background-color","#ffffff"),b.item.children("td, th").css("border-bottom-width","0"),b.item.css("outline","1px solid #aaa")},stop:function(a,b){b.item.removeAttr("style"),b.item.children("td, th").css("border-bottom-width","1px")},update:function(b,c){var d,e,f=c.item.find(".check-column input").val(),g=c.item.find(".parent").html(),h=c.item.prev().find(".check-column input").val(),i=c.item.next().find(".check-column input").val();return void 0!==h&&(d=c.item.prev().find(".parent").html(),d!==g&&(h=void 0)),void 0!==i&&(e=c.item.next().find(".parent").html(),e!==g&&(i=void 0)),void 0===h&&void 0===i||void 0===i&&e===h||void 0!==i&&d===f?void a("table.widefat.wp-list-table").sortable("cancel"):(c.item.find(".check-column input").hide().after('<img alt="processing" src="images/wpspin_light.gif" class="waiting" style="margin-left: 6px;" />'),a.post(ajaxurl,{action:"woocommerce_term_ordering",id:f,nextid:i,thetaxonomy:woocommerce_term_ordering_params.taxonomy},function(a){"children"===a?window.location.reload():c.item.find(".check-column input").show().siblings("img").remove()}),void a("table.widefat tbody tr").each(function(){var a=jQuery("table.widefat tbody tr").index(this);a%2===0?jQuery(this).addClass("alternate"):jQuery(this).removeClass("alternate")}))}})});
jQuery(function(a){a("table.widefat.wp-list-table tr").append('<td class="column-handle"></td>'),a("table.widefat.wp-list-table").sortable({items:"tbody tr:not(.inline-edit-row)",cursor:"move",handle:".column-handle",axis:"y",forcePlaceholderSize:!0,helper:"clone",opacity:.65,placeholder:"product-cat-placeholder",scrollSensitivity:40,start:function(a,b){b.item.hasClass("alternate")||b.item.css("background-color","#ffffff"),b.item.children("td, th").css("border-bottom-width","0"),b.item.css("outline","1px solid #aaa")},stop:function(a,b){b.item.removeAttr("style"),b.item.children("td, th").css("border-bottom-width","1px")},update:function(b,c){var d,e,f=c.item.find(".check-column input").val(),g=c.item.find(".parent").html(),h=c.item.prev().find(".check-column input").val(),i=c.item.next().find(".check-column input").val();return void 0!==h&&(d=c.item.prev().find(".parent").html(),d!==g&&(h=void 0)),void 0!==i&&(e=c.item.next().find(".parent").html(),e!==g&&(i=void 0)),void 0===h&&void 0===i||void 0===i&&e===h||void 0!==i&&d===f?void a("table.widefat.wp-list-table").sortable("cancel"):(c.item.find(".check-column input").hide().after('<img alt="processing" src="images/wpspin_light.gif" class="waiting" style="margin-left: 6px;" />'),a.post(ajaxurl,{action:"woocommerce_term_ordering",id:f,nextid:i,thetaxonomy:woocommerce_term_ordering_params.taxonomy},function(a){"children"===a?window.location.reload():c.item.find(".check-column input").show().siblings("img").remove()}),void a("table.widefat tbody tr").each(function(){var a=jQuery("table.widefat tbody tr").index(this);a%2===0?jQuery(this).addClass("alternate"):jQuery(this).removeClass("alternate")}))}})});

View File

@ -15,6 +15,8 @@ jQuery( function ( $ ) {
$( '.js_field-country' ).select2().change( this.change_country );
$( '.js_field-country' ).trigger( 'change', [ true ] );
$( document.body ).on( 'change', 'select.js_field-state', this.change_state );
$( document.body ).on( 'click', 'button.js_copy-billing', this.copy_billing );
},
change_country: function( e, stickValue ) {
@ -75,6 +77,23 @@ jQuery( function ( $ ) {
country = $country.val();
$country.data( 'woocommerce.stickState-' + country, state );
},
copy_billing: function( event ) {
event.preventDefault();
$( '#fieldset-billing' ).find( 'input, select' ).each( function( i, el ) {
// The address keys match up, except for the prefix
var shipName = el.name.replace( /^billing_/, 'shipping_' );
// Swap prefix, then check if there are any elements
var shipEl = $( '[name="' + shipName + '"]' );
// No corresponding shipping field, skip this item
if ( ! shipEl.length ) {
return;
}
// Found a matching shipping element, update the value
shipEl.val( el.value ).trigger( 'change' );
} );
}
};

View File

@ -1 +1 @@
jQuery(function(a){var b={states:null,init:function(){"undefined"!=typeof wc_users_params.countries&&(this.states=a.parseJSON(wc_users_params.countries.replace(/&quot;/g,'"'))),a(".js_field-country").select2().change(this.change_country),a(".js_field-country").trigger("change",[!0]),a(document.body).on("change","select.js_field-state",this.change_state)},change_country:function(c,d){if("undefined"==typeof d&&(d=!1),null!==b.states){var e=a(this),f=e.val(),g=e.parents(".form-table").find(":input.js_field-state"),h=g.parent(),i=g.attr("name"),j=g.attr("id"),k=e.data("woocommerce.stickState-"+f)?e.data("woocommerce.stickState-"+f):g.val();if(d&&e.data("woocommerce.stickState-"+f,k),h.show().find(".select2-container").remove(),a.isEmptyObject(b.states[f]))g.replaceWith('<input type="text" class="js_field-state" name="'+i+'" id="'+j+'" value="'+k+'" />');else{var l=a('<select name="'+i+'" id="'+j+'" class="js_field-state" style="width: 25em;"></select>'),m=b.states[f];l.append(a('<option value="">'+wc_users_params.i18n_select_state_text+"</option>")),a.each(m,function(b){l.append(a('<option value="'+b+'">'+m[b]+"</option>"))}),l.val(k),g.replaceWith(l),l.show().select2().hide().change()}a(document.body).trigger("contry-change.woocommerce",[f,a(this).closest("div")]),a(document.body).trigger("country-change.woocommerce",[f,a(this).closest("div")])}},change_state:function(){var b=a(this),c=b.val(),d=b.parents(".form-table").find(":input.js_field-country"),e=d.val();d.data("woocommerce.stickState-"+e,c)}};b.init()});
jQuery(function(a){var b={states:null,init:function(){"undefined"!=typeof wc_users_params.countries&&(this.states=a.parseJSON(wc_users_params.countries.replace(/&quot;/g,'"'))),a(".js_field-country").select2().change(this.change_country),a(".js_field-country").trigger("change",[!0]),a(document.body).on("change","select.js_field-state",this.change_state),a(document.body).on("click","button.js_copy-billing",this.copy_billing)},change_country:function(c,d){if("undefined"==typeof d&&(d=!1),null!==b.states){var e=a(this),f=e.val(),g=e.parents(".form-table").find(":input.js_field-state"),h=g.parent(),i=g.attr("name"),j=g.attr("id"),k=e.data("woocommerce.stickState-"+f)?e.data("woocommerce.stickState-"+f):g.val();if(d&&e.data("woocommerce.stickState-"+f,k),h.show().find(".select2-container").remove(),a.isEmptyObject(b.states[f]))g.replaceWith('<input type="text" class="js_field-state" name="'+i+'" id="'+j+'" value="'+k+'" />');else{var l=a('<select name="'+i+'" id="'+j+'" class="js_field-state" style="width: 25em;"></select>'),m=b.states[f];l.append(a('<option value="">'+wc_users_params.i18n_select_state_text+"</option>")),a.each(m,function(b){l.append(a('<option value="'+b+'">'+m[b]+"</option>"))}),l.val(k),g.replaceWith(l),l.show().select2().hide().change()}a(document.body).trigger("contry-change.woocommerce",[f,a(this).closest("div")]),a(document.body).trigger("country-change.woocommerce",[f,a(this).closest("div")])}},change_state:function(){var b=a(this),c=b.val(),d=b.parents(".form-table").find(":input.js_field-country"),e=d.val();d.data("woocommerce.stickState-"+e,c)},copy_billing:function(b){b.preventDefault(),a("#fieldset-billing").find("input, select").each(function(b,c){var d=c.name.replace(/^billing_/,"shipping_"),e=a('[name="'+d+'"]');e.length&&e.val(c.value).trigger("change")})}};b.init()});

View File

@ -331,7 +331,7 @@ jQuery( function( $ ) {
$( '#terms' ).prop( 'checked', true );
}
// Fill in the payment details if possible
// Fill in the payment details if possible without overwriting data if set.
if ( ! $.isEmptyObject( paymentDetails ) ) {
$( '.payment_box input' ).each( function() {
var ID = $( this ).attr( 'id' );
@ -339,7 +339,7 @@ jQuery( function( $ ) {
if ( ID ) {
if ( $.inArray( $( this ).attr( 'type' ), [ 'checkbox', 'radio' ] ) !== -1 ) {
$( this ).prop( 'checked', paymentDetails[ ID ] ).change();
} else {
} else if ( 0 === $( this ).val().length ) {
$( this ).val( paymentDetails[ ID ] ).change();
}
}

File diff suppressed because one or more lines are too long

View File

@ -19,6 +19,8 @@ jQuery( function( $ ) {
$tabs.find( 'li.reviews_tab a' ).click();
} else if ( url.indexOf( 'comment-page-' ) > 0 || url.indexOf( 'cpage=' ) > 0 ) {
$tabs.find( 'li.reviews_tab a' ).click();
} else if ( hash === '#tab-additional_information' ) {
$tabs.find( 'li.additional_information_tab a' ).click();
} else {
$tabs.find( 'li:first a' ).click();
}
@ -212,10 +214,10 @@ jQuery( function( $ ) {
large_image_w = img.attr( 'data-large_image_width' ),
large_image_h = img.attr( 'data-large_image_height' ),
item = {
src: large_image_src,
w: large_image_w,
h: large_image_h,
title: img.attr( 'title' )
src : large_image_src,
w : large_image_w,
h : large_image_h,
title: img.attr( 'data-caption' ) ? img.attr( 'data-caption' ) : img.attr( 'title' )
};
items.push( item );
} );

File diff suppressed because one or more lines are too long

14
assets/js/jquery-payment/jquery.payment.js Normal file → Executable file
View File

@ -22,13 +22,6 @@ jQuery( function( $ ) {
$.payment.cards = cards = [
{
type: 'visaelectron',
patterns: [4026, 417500, 4405, 4508, 4844, 4913, 4917],
format: defaultFormat,
length: [16],
cvcLength: [3],
luhn: true
}, {
type: 'maestro',
patterns: [5018, 502, 503, 506, 56, 58, 639, 6220, 67],
format: defaultFormat,
@ -49,13 +42,6 @@ jQuery( function( $ ) {
length: [16],
cvcLength: [3],
luhn: true
}, {
type: 'elo',
patterns: [4011, 4312, 4389, 4514, 4573, 4576, 5041, 5066, 5067, 509, 6277, 6362, 6363, 650, 6516, 6550],
format: defaultFormat,
length: [16],
cvcLength: [3],
luhn: true
}, {
type: 'visa',
patterns: [4],

2
assets/js/jquery-payment/jquery.payment.min.js vendored Normal file → Executable file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,7 @@ global $states;
$states['NP'] = array(
'BAG' => __( 'Bagmati', 'woocommerce' ),
'BHE' => __( 'Bheri', 'woocommerce' ),
'DHA' => __( 'Dhawalagiri', 'woocommerce' ),
'DHA' => __( 'Dhaulagiri', 'woocommerce' ),
'GAN' => __( 'Gandaki', 'woocommerce' ),
'JAN' => __( 'Janakpur', 'woocommerce' ),
'KAR' => __( 'Karnali', 'woocommerce' ),

View File

@ -0,0 +1,85 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Abstract WC Object Query Class
*
* Extended by classes to provide a query abstraction layer for safe object searching.
*
* @version 3.1.0
* @package WooCommerce/Abstracts
* @category Abstract Class
* @author Automattic
*/
abstract class WC_Object_Query {
/**
* Stores query data.
* @var array
*/
protected $query_vars = array();
/**
* Create a new query.
* @param array $args Criteria to query on in a format similar to WP_Query.
*/
public function __construct( $args = array() ) {
$this->query_vars = wp_parse_args( $args, $this->get_default_query_vars() );
}
/**
* Get the current query vars.
* @return array
*/
public function get_query_vars() {
return $this->query_vars;
}
/**
* Get the value of a query variable.
* @param string $query_var Query variable to get value for.
* @param mixed $default Default value if query variable is not set.
* @return mixed Query variable value if set, otherwise default.
*/
public function get( $query_var, $default = '' ) {
if ( isset( $this->query_vars[ $query_var ] ) ) {
return $this->query_vars[ $query_var ];
}
return $default;
}
/**
* Set a query variable.
* @param string $query_var Query variable to set.
* @param mixed $value Value to set for query variable.
*/
public function set( $query_var, $value ) {
$this->query_vars[ $query_var ] = $value;
}
/**
* Get the default allowed query vars.
* @return array
*/
protected function get_default_query_vars() {
return array(
'name' => '',
'parent' => '',
'parent_exclude' => '',
'exclude' => '',
'limit' => get_option( 'posts_per_page' ),
'page' => 1,
'offset' => '',
'paginate' => false,
'order' => 'DESC',
'orderby' => 'date',
'return' => 'objects',
);
}
}

View File

@ -853,7 +853,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
if ( $item_id = $item->get_id() ) {
$this->items[ $items_key ][ $item_id ] = $item;
} else {
$this->items[ $items_key ][ 'new:' . sizeof( $this->items[ $items_key ] ) ] = $item;
$this->items[ $items_key ][ 'new:' . $items_key . sizeof( $this->items[ $items_key ] ) ] = $item;
}
}
@ -1024,7 +1024,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
$tax_class = $item->get_tax_class();
$tax_status = $item->get_tax_status();
if ( '0' !== $tax_class && 'taxable' === $tax_status ) {
if ( '0' !== $tax_class && 'taxable' === $tax_status && wc_tax_enabled() ) {
$tax_rates = WC_Tax::find_rates( array(
'country' => $args['country'],
'state' => $args['state'],
@ -1043,43 +1043,49 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
} else {
$item->set_taxes( array( 'total' => $taxes ) );
}
$item->save();
} else {
$item->set_taxes( false );
}
$item->save();
}
// Calc taxes for shipping
foreach ( $this->get_shipping_methods() as $item_id => $item ) {
$shipping_tax_class = get_option( 'woocommerce_shipping_tax_class' );
if ( wc_tax_enabled() ) {
$shipping_tax_class = get_option( 'woocommerce_shipping_tax_class' );
// Inherit tax class from items
if ( 'inherit' === $shipping_tax_class ) {
$tax_rates = array();
$tax_classes = array_merge( array( '' ), WC_Tax::get_tax_class_slugs() );
$found_tax_classes = $this->get_items_tax_classes();
// Inherit tax class from items
if ( 'inherit' === $shipping_tax_class ) {
$tax_rates = array();
$tax_classes = array_merge( array( '' ), WC_Tax::get_tax_class_slugs() );
$found_tax_classes = $this->get_items_tax_classes();
foreach ( $tax_classes as $tax_class ) {
if ( in_array( $tax_class, $found_tax_classes ) ) {
$tax_rates = WC_Tax::find_shipping_rates( array(
'country' => $args['country'],
'state' => $args['state'],
'postcode' => $args['postcode'],
'city' => $args['city'],
'tax_class' => $tax_class,
) );
break;
foreach ( $tax_classes as $tax_class ) {
if ( in_array( $tax_class, $found_tax_classes ) ) {
$tax_rates = WC_Tax::find_shipping_rates( array(
'country' => $args['country'],
'state' => $args['state'],
'postcode' => $args['postcode'],
'city' => $args['city'],
'tax_class' => $tax_class,
) );
break;
}
}
} else {
$tax_rates = WC_Tax::find_shipping_rates( array(
'country' => $args['country'],
'state' => $args['state'],
'postcode' => $args['postcode'],
'city' => $args['city'],
'tax_class' => $shipping_tax_class,
) );
}
} else {
$tax_rates = WC_Tax::find_shipping_rates( array(
'country' => $args['country'],
'state' => $args['state'],
'postcode' => $args['postcode'],
'city' => $args['city'],
'tax_class' => $shipping_tax_class,
) );
}
$item->set_taxes( array( 'total' => WC_Tax::calc_tax( $item->get_total(), $tax_rates, false ) ) );
$item->set_taxes( array( 'total' => WC_Tax::calc_tax( $item->get_total(), $tax_rates, false ) ) );
} else {
$item->set_taxes( false );
}
$item->save();
}
$this->update_taxes();
@ -1151,7 +1157,7 @@ abstract class WC_Abstract_Order extends WC_Abstract_Legacy_Order {
$cart_subtotal_tax = 0;
$cart_total_tax = 0;
if ( $and_taxes && wc_tax_enabled() ) {
if ( $and_taxes ) {
$this->calculate_taxes();
}

View File

@ -1332,7 +1332,7 @@ class WC_Product extends WC_Abstract_Legacy_Product {
*
* Backwards compat with downloadable/virtual.
*
* @param string $type Array or string of types
* @param string|array $type Array or string of types
* @return bool
*/
public function is_type( $type ) {

View File

@ -233,8 +233,7 @@ class WC_Admin_Assets {
$post_id = isset( $post->ID ) ? $post->ID : '';
$currency = '';
if ( $post_id && in_array( get_post_type( $post_id ), wc_get_order_types( 'order-meta-boxes' ) ) ) {
$order = wc_get_order( $post_id );
if ( $post_id && in_array( get_post_type( $post_id ), wc_get_order_types( 'order-meta-boxes' ) ) && ( $order = wc_get_order( $post_id ) ) ) {
$currency = $order->get_currency();
}

View File

@ -117,10 +117,6 @@ class WC_Admin_Help {
'title' => __( 'API Settings', 'woocommerce' ),
'url' => '//fast.wistia.net/embed/iframe/1q0ny74vvq.jsonp?',
),
'wc-settings-api' => array(
'title' => __( 'API Settings', 'woocommerce' ),
'url' => '//fast.wistia.net/embed/iframe/1q0ny74vvq.jsonp?',
),
'product' => array(
'title' => __( 'Creating Products', 'woocommerce' ),
'url' => '//fast.wistia.net/embed/iframe/fw0477t6wr.jsonp?',

View File

@ -311,7 +311,7 @@ class WC_Admin_Log_Table_List extends WP_List_Table {
$order = 'DESC';
}
return "ORDER BY {$by} {$order}";
return "ORDER BY {$by} {$order}, log_id {$order}";
}
/**

View File

@ -283,8 +283,6 @@ class WC_Admin_Notices {
*/
public static function no_shipping_methods_notice() {
if ( wc_shipping_enabled() && ( empty( $_GET['page'] ) || empty( $_GET['tab'] ) || 'wc-settings' !== $_GET['page'] || 'shipping' !== $_GET['tab'] ) ) {
global $wpdb;
$product_count = wp_count_posts( 'product' );
$method_count = wc_get_shipping_method_count();

View File

@ -93,6 +93,13 @@ class WC_Admin_Profile {
'shipping' => array(
'title' => __( 'Customer shipping address', 'woocommerce' ),
'fields' => array(
'copy_billing' => array(
'label' => __( 'Copy from billing address', 'woocommerce' ),
'description' => '',
'class' => 'js_copy-billing',
'type' => 'button',
'text' => __( 'Copy', 'woocommerce' ),
),
'shipping_first_name' => array(
'label' => __( 'First name', 'woocommerce' ),
'description' => '',
@ -151,10 +158,10 @@ class WC_Admin_Profile {
$show_fields = $this->get_customer_meta_fields();
foreach ( $show_fields as $fieldset ) :
foreach ( $show_fields as $fieldset_key => $fieldset ) :
?>
<h2><?php echo $fieldset['title']; ?></h2>
<table class="form-table">
<table class="form-table" id="<?php echo esc_attr( 'fieldset-' . $fieldset_key ); ?>">
<?php
foreach ( $fieldset['fields'] as $key => $field ) :
?>
@ -162,7 +169,7 @@ class WC_Admin_Profile {
<th><label for="<?php echo esc_attr( $key ); ?>"><?php echo esc_html( $field['label'] ); ?></label></th>
<td>
<?php if ( ! empty( $field['type'] ) && 'select' === $field['type'] ) : ?>
<select name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" class="<?php echo ( ! empty( $field['class'] ) ? $field['class'] : '' ); ?>" style="width: 25em;">
<select name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" class="<?php echo esc_attr( $field['class'] ); ?>" style="width: 25em;">
<?php
$selected = esc_attr( get_user_meta( $user->ID, $key, true ) );
foreach ( $field['options'] as $option_key => $option_value ) : ?>
@ -170,9 +177,11 @@ class WC_Admin_Profile {
<?php endforeach; ?>
</select>
<?php elseif ( ! empty( $field['type'] ) && 'checkbox' === $field['type'] ) : ?>
<input type="checkbox" name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" value="1" class="<?php echo ( ! empty( $field['class'] ) ? $field['class'] : '' ); ?>" <?php checked( (int) get_user_meta( $user->ID, $key, true ), 1, true ); ?> />
<input type="checkbox" name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" value="1" class="<?php echo esc_attr( $field['class'] ); ?>" <?php checked( (int) get_user_meta( $user->ID, $key, true ), 1, true ); ?> />
<?php elseif ( ! empty( $field['type'] ) && 'button' === $field['type'] ) : ?>
<button id="<?php echo esc_attr( $key ); ?>" class="button <?php echo esc_attr( $field['class'] ); ?>"><?php echo esc_html( $field['text'] ); ?></button>
<?php else : ?>
<input type="text" name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" value="<?php echo esc_attr( get_user_meta( $user->ID, $key, true ) ); ?>" class="<?php echo ( ! empty( $field['class'] ) ? $field['class'] : 'regular-text' ); ?>" />
<input type="text" name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" value="<?php echo esc_attr( $this->get_user_meta( $user->ID, $key ) ); ?>" class="<?php echo ( ! empty( $field['class'] ) ? esc_attr( $field['class'] ) : 'regular-text' ); ?>" />
<?php endif; ?>
<br/>
<span class="description"><?php echo wp_kses_post( $field['description'] ); ?></span>
@ -206,6 +215,27 @@ class WC_Admin_Profile {
}
}
}
/**
* Get user meta for a given key, with fallbacks to core user info for pre-existing fields.
*
* @since 3.1.0
* @param int $user_id User ID of the user being edited
* @param string $key Key for user meta field
* @return string
*/
protected function get_user_meta( $user_id, $key ) {
$value = get_user_meta( $user_id, $key, true );
$existing_fields = array( 'billing_first_name', 'billing_last_name' );
if ( ! $value && in_array( $key, $existing_fields ) ) {
$value = get_user_meta( $user_id, str_replace( 'billing_', '', $key ), true );
} elseif ( ! $value && ( 'billing_email' === $key ) ) {
$user = get_userdata( $user_id );
$value = $user->user_email;
}
return $value;
}
}
endif;

View File

@ -35,8 +35,6 @@ class WC_Admin_Status {
* Handles output of tools.
*/
public static function status_tools() {
global $wpdb;
$tools = self::get_tools();
if ( ! empty( $_GET['action'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'debug_action' ) ) {

View File

@ -428,9 +428,6 @@ class WC_Admin_Webhooks {
* Table list output.
*/
private static function table_list_output() {
global $wpdb;
echo '<h2>' . __( 'Webhooks', 'woocommerce' ) . ' <a href="' . esc_url( wp_nonce_url( admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks&create-webhook=1' ), 'create-webhook' ) ) . '" class="add-new-h2">' . __( 'Add webhook', 'woocommerce' ) . '</a></h2>';
// Get the webhooks count

View File

@ -310,8 +310,6 @@ class WC_Meta_Box_Coupon_Data {
* @param WP_Post $post
*/
public static function save( $post_id, $post ) {
global $wpdb;
// Check for dupe coupons
$coupon_code = wc_format_coupon_code( $post->post_title );
$id_from_code = wc_get_coupon_id_by_code( $coupon_code, $post_id );

View File

@ -31,8 +31,6 @@ class WC_Meta_Box_Order_Actions {
if ( ! is_object( $theorder ) ) {
$theorder = wc_get_order( $post->ID );
}
$order_type_object = get_post_type_object( $post->post_type );
?>
<ul class="order_actions submitbox">
@ -99,8 +97,6 @@ class WC_Meta_Box_Order_Actions {
* @param WP_Post $post
*/
public static function save( $post_id, $post ) {
global $wpdb;
// Order data saved, now get it so we can manipulate status
$order = wc_get_order( $post_id );

View File

@ -449,8 +449,6 @@ class WC_Meta_Box_Order_Data {
* @param int $order_id Order ID.
*/
public static function save( $order_id ) {
global $wpdb;
self::init_address_fields();
// Ensure gateways are loaded in case they need to insert data into the emails.

View File

@ -23,7 +23,6 @@ class WC_Meta_Box_Order_Downloads {
* @param WP_Post $post
*/
public static function output( $post ) {
global $post, $wpdb;
?>
<div class="order_download_permissions wc-metaboxes-wrapper">

View File

@ -25,7 +25,7 @@ class WC_Meta_Box_Product_Data {
* @param WP_Post $post
*/
public static function output( $post ) {
global $post, $thepostid, $product_object;
global $thepostid, $product_object;
$thepostid = $post->ID;
$product_object = $thepostid ? wc_get_product( $thepostid ) : new WC_Product;
@ -321,9 +321,9 @@ class WC_Meta_Box_Product_Data {
'date_on_sale_from' => wc_clean( $_POST['_sale_price_dates_from'] ),
'date_on_sale_to' => wc_clean( $_POST['_sale_price_dates_to'] ),
'manage_stock' => ! empty( $_POST['_manage_stock'] ),
'backorders' => wc_clean( $_POST['_backorders'] ),
'backorders' => isset( $_POST['_backorders'] ) ? wc_clean( $_POST['_backorders'] ) : null,
'stock_status' => wc_clean( $_POST['_stock_status'] ),
'stock_quantity' => wc_stock_amount( $_POST['_stock'] ),
'stock_quantity' => isset( $_POST['_stock'] ) ? wc_stock_amount( $_POST['_stock'] ) : null,
'download_limit' => '' === $_POST['_download_limit'] ? '' : absint( $_POST['_download_limit'] ),
'download_expiry' => '' === $_POST['_download_expiry'] ? '' : absint( $_POST['_download_expiry'] ),
'downloads' => self::prepare_downloads(
@ -398,8 +398,8 @@ class WC_Meta_Box_Product_Data {
isset( $_POST['_wc_variation_file_hashes'][ $variation_id ] ) ? $_POST['_wc_variation_file_hashes'][ $variation_id ] : array()
),
'manage_stock' => isset( $_POST['variable_manage_stock'][ $i ] ),
'stock_quantity' => wc_clean( $_POST['variable_stock'][ $i ] ),
'backorders' => wc_clean( $_POST['variable_backorders'][ $i ] ),
'stock_quantity' => isset( $_POST['variable_stock'][ $i ] ) ? wc_clean( $_POST['variable_stock'][ $i ] ) : null,
'backorders' => isset( $_POST['variable_backorders'][ $i ] ) ? wc_clean( $_POST['variable_backorders'][ $i ] ) : null,
'stock_status' => wc_clean( $_POST['variable_stock_status'][ $i ] ),
'image_id' => wc_clean( $_POST['upload_image_id'][ $i ] ),
'attributes' => self::prepare_set_attributes( $parent->get_attributes(), 'attribute_', $i ),

View File

@ -78,8 +78,6 @@ class WC_Report_Customer_List extends WP_List_Table {
* @return string
*/
public function column_default( $user, $column_name ) {
global $wpdb;
switch ( $column_name ) {
case 'customer_name' :
@ -245,8 +243,6 @@ class WC_Report_Customer_List extends WP_List_Table {
* Prepare customer list items.
*/
public function prepare_items() {
global $wpdb;
$current_page = absint( $this->get_pagenum() );
$per_page = 20;

View File

@ -259,8 +259,6 @@ class WC_Settings_Shipping extends WC_Settings_Page {
* Show zones
*/
protected function zones_screen() {
global $wpdb;
$allowed_countries = WC()->countries->get_allowed_countries();
$continents = WC()->countries->get_continents();
$method_count = wc_get_shipping_method_count();

View File

@ -96,8 +96,6 @@ class WC_Settings_Tax extends WC_Settings_Page {
* Save settings.
*/
public function save() {
global $current_section, $wpdb;
if ( ! $current_section ) {
$settings = $this->get_settings();
WC_Admin_Settings::save_fields( $settings );
@ -113,7 +111,7 @@ class WC_Settings_Tax extends WC_Settings_Page {
* Output tax rate tables.
*/
public function output_tax_rates() {
global $wpdb, $current_section;
global $current_section;
$current_class = $this->get_current_tax_class();

View File

@ -44,6 +44,12 @@ function wc_get_screen_ids() {
$screen_ids[] = 'edit-' . $type;
}
if ( $attributes = wc_get_attribute_taxonomies() ) {
foreach ( $attributes as $attribute ) {
$screen_ids[] = 'edit-' . wc_attribute_taxonomy_name( $attribute->attribute_name );
}
}
return apply_filters( 'woocommerce_screen_ids', $screen_ids );
}

View File

@ -453,7 +453,6 @@ class WC_REST_Product_Variations_Controller extends WC_REST_Products_Controller
* @return WP_Error|boolean
*/
public function delete_item( $request ) {
$id = absint( is_array( $request['id'] ) ? $request['id']['id'] : $request['id'] );
$force = (bool) $request['force'];
$object = $this->get_object( (int) $request['id'] );
$result = false;

View File

@ -178,6 +178,9 @@ class WC_REST_Setting_Options_Controller extends WC_REST_Controller {
if ( 'multi_select_countries' === $setting['type'] ) {
$setting['options'] = WC()->countries->get_countries();
$setting['type'] = 'multiselect';
} elseif ( 'single_select_country' === $setting['type'] ) {
$setting['type'] = 'select';
$setting['options'] = $this->get_countries_and_states();
}
$filtered_settings[] = $setting;
@ -186,6 +189,33 @@ class WC_REST_Setting_Options_Controller extends WC_REST_Controller {
return $filtered_settings;
}
/**
* Returns a list of countries and states for use in the base location setting.
*
* @since 3.0.7
* @return array Array of states and countries.
*/
private function get_countries_and_states() {
$countries = WC()->countries->get_countries();
if ( ! $countries ) {
return array();
}
$output = array();
foreach ( $countries as $key => $value ) {
if ( $states = WC()->countries->get_states( $key ) ) {
foreach ( $states as $state_key => $state_value ) {
$output[ $key . ':' . $state_key ] = $value . ' - ' . $state_value;
}
} else {
$output[ $key ] = $value;
}
}
return $output;
}
/**
* Get setting data.
*

View File

@ -86,6 +86,10 @@ class WC_REST_Shipping_Zone_Locations_Controller extends WC_REST_Shipping_Zones_
return $zone;
}
if ( 0 === $zone->get_id() ) {
return new WP_Error( "woocommerce_rest_shipping_zone_locations_invalid_zone", __( 'The "rest of the world" zone cannot be updated.', 'woocommerce' ), array( 'status' => 403 ) );
}
$raw_locations = $request->get_json_params();
$locations = array();

View File

@ -155,8 +155,6 @@ class WC_REST_Shipping_Zone_Methods_Controller extends WC_REST_Shipping_Zones_Co
* @return WP_REST_Request|WP_Error
*/
public function create_item( $request ) {
global $wpdb;
$method_id = $request['method_id'];
$zone = $this->get_zone( $request['zone_id'] );
if ( is_wp_error( $zone ) ) {
@ -193,8 +191,6 @@ class WC_REST_Shipping_Zone_Methods_Controller extends WC_REST_Shipping_Zones_Co
* @return WP_Error|boolean
*/
public function delete_item( $request ) {
global $wpdb;
$zone = $this->get_zone( $request['zone_id'] );
if ( is_wp_error( $zone ) ) {
return $zone;
@ -251,8 +247,6 @@ class WC_REST_Shipping_Zone_Methods_Controller extends WC_REST_Shipping_Zones_Co
* @return WP_REST_Response|WP_Error
*/
public function update_item( $request ) {
global $wpdb;
$zone = $this->get_zone( $request['zone_id'] );
if ( is_wp_error( $zone ) ) {
return $zone;

View File

@ -166,6 +166,10 @@ class WC_REST_Shipping_Zones_Controller extends WC_REST_Shipping_Zones_Controlle
return $zone;
}
if ( 0 === $zone->get_id() ) {
return new WP_Error( "woocommerce_rest_shipping_zone_invalid_zone", __( 'The "rest of the world" zone cannot be updated.', 'woocommerce' ), array( 'status' => 403 ) );
}
$zone_changed = false;
if ( ! is_null( $request->get_param( 'name' ) ) ) {

View File

@ -677,6 +677,11 @@ class WC_REST_System_Status_Controller extends WC_REST_Controller {
*/
public function get_active_plugins() {
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
require_once( ABSPATH . 'wp-admin/includes/update.php' );
if ( ! function_exists( 'get_plugin_updates' ) ) {
return array();
}
// Get both site plugins and network plugins
$active_plugins = (array) get_option( 'active_plugins', array() );
@ -887,7 +892,6 @@ class WC_REST_System_Status_Controller extends WC_REST_Controller {
$pages_output = array();
foreach ( $check_pages as $page_name => $values ) {
$errors = array();
$page_id = get_option( $values['option'] );
$page_set = $page_exists = $page_visible = false;
$shortcode_present = $shortcode_required = false;

View File

@ -101,13 +101,6 @@ class WC_REST_Webhook_Deliveries_Controller extends WC_REST_Webhook_Deliveries_V
'context' => array( 'view' ),
'readonly' => true,
),
'request_headers' => array(
'description' => __( 'The URL where the webhook was delivered.', 'woocommerce' ),
'type' => 'string',
'format' => 'uri',
'context' => array( 'view' ),
'readonly' => true,
),
'request_headers' => array(
'description' => __( 'Request headers.', 'woocommerce' ),
'type' => 'array',

View File

@ -939,10 +939,15 @@ class WC_API_Orders extends WC_API_Resource {
$line_item->set_variation( $item['variations'] );
}
$item_id = $line_item->save();
// Save or add to order.
if ( $creating ) {
$order->add_item( $line_item );
} else {
$item_id = $line_item->save();
if ( ! $item_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_line_item', __( 'Cannot create line item, try again.', 'woocommerce' ), 500 );
if ( ! $item_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_line_item', __( 'Cannot create line item, try again.', 'woocommerce' ), 500 );
}
}
}
@ -1023,11 +1028,7 @@ class WC_API_Orders extends WC_API_Resource {
$item = new WC_Order_Item_Shipping();
$item->set_order_id( $order->get_id() );
$item->set_shipping_rate( $rate );
$shipping_id = $item->save();
if ( ! $shipping_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_shipping', __( 'Cannot create shipping method, try again.', 'woocommerce' ), 500 );
}
$order->add_item( $item );
} else {
$item = new WC_Order_Item_Shipping( $shipping['id'] );
@ -1094,11 +1095,7 @@ class WC_API_Orders extends WC_API_Resource {
}
}
$fee_id = $item->save();
if ( ! $fee_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_fee', __( 'Cannot create fee, try again.', 'woocommerce' ), 500 );
}
$order->add_item( $item );
} else {
$item = new WC_Order_Item_Fee( $fee['id'] );
@ -1157,11 +1154,7 @@ class WC_API_Orders extends WC_API_Resource {
'discount_tax' => 0,
'order_id' => $order->get_id(),
) );
$coupon_id = $item->save();
if ( ! $coupon_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_order_coupon', __( 'Cannot create coupon, try again.', 'woocommerce' ), 500 );
}
$order->add_item( $item );
} else {
$item = new WC_Order_Item_Coupon( $coupon['id'] );

View File

@ -243,8 +243,8 @@ class WC_API_Orders extends WC_API_Resource {
'meta' => array_values( $item_meta ),
);
if ( in_array( 'products', $expand ) ) {
$_product_data = WC()->api->WC_API_Products->get_product( $product_id );
if ( in_array( 'products', $expand ) && is_object( $product ) ) {
$_product_data = WC()->api->WC_API_Products->get_product( $product->get_id() );
if ( isset( $_product_data['product'] ) ) {
$line_item['product_data'] = $_product_data['product'];
@ -988,10 +988,15 @@ class WC_API_Orders extends WC_API_Resource {
$line_item->set_variation( $item['variations'] );
}
$item_id = $line_item->save();
// Save or add to order.
if ( $creating ) {
$order->add_item( $line_item );
} else {
$item_id = $line_item->save();
if ( ! $item_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_line_item', __( 'Cannot create line item, try again.', 'woocommerce' ), 500 );
if ( ! $item_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_line_item', __( 'Cannot create line item, try again.', 'woocommerce' ), 500 );
}
}
}
@ -1073,11 +1078,7 @@ class WC_API_Orders extends WC_API_Resource {
$item = new WC_Order_Item_Shipping();
$item->set_order_id( $order->get_id() );
$item->set_shipping_rate( $rate );
$shipping_id = $item->save();
if ( ! $shipping_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_shipping', __( 'Cannot create shipping method, try again.', 'woocommerce' ), 500 );
}
$order->add_item( $item );
} else {
$item = new WC_Order_Item_Shipping( $shipping['id'] );
@ -1144,11 +1145,7 @@ class WC_API_Orders extends WC_API_Resource {
}
}
$fee_id = $item->save();
if ( ! $fee_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_fee', __( 'Cannot create fee, try again.', 'woocommerce' ), 500 );
}
$order->add_item( $item );
} else {
$item = new WC_Order_Item_Fee( $fee['id'] );
@ -1207,11 +1204,7 @@ class WC_API_Orders extends WC_API_Resource {
'discount_tax' => 0,
'order_id' => $order->get_id(),
) );
$coupon_id = $item->save();
if ( ! $coupon_id ) {
throw new WC_API_Exception( 'woocommerce_cannot_create_order_coupon', __( 'Cannot create coupon, try again.', 'woocommerce' ), 500 );
}
$order->add_item( $item );
} else {
$item = new WC_Order_Item_Coupon( $coupon['id'] );

View File

@ -125,8 +125,6 @@ class WC_REST_Orders_V1_Controller extends WC_REST_Posts_Controller {
* @return WP_REST_Response $data
*/
public function prepare_item_for_response( $post, $request ) {
global $wpdb;
$order = wc_get_order( $post );
$dp = $request['dp'];

View File

@ -307,8 +307,6 @@ class WC_REST_Product_Attributes_V1_Controller extends WC_REST_Controller {
* @return WP_REST_Request|WP_Error
*/
public function get_item( $request ) {
global $wpdb;
$attribute = $this->get_attribute( (int) $request['id'] );
if ( is_wp_error( $attribute ) ) {

View File

@ -255,13 +255,6 @@ class WC_REST_Webhook_Deliveries_V1_Controller extends WC_REST_Controller {
'context' => array( 'view' ),
'readonly' => true,
),
'request_headers' => array(
'description' => __( 'The URL where the webhook was delivered.', 'woocommerce' ),
'type' => 'string',
'format' => 'uri',
'context' => array( 'view' ),
'readonly' => true,
),
'request_headers' => array(
'description' => __( 'Request headers.', 'woocommerce' ),
'type' => 'array',

View File

@ -364,8 +364,6 @@ class WC_REST_Webhooks_V1_Controller extends WC_REST_Posts_Controller {
* @return WP_Error|stdClass $data Post object.
*/
protected function prepare_item_for_database( $request ) {
global $wpdb;
$data = new stdClass;
// Post ID.

View File

@ -1222,16 +1222,12 @@ class WC_AJAX {
$term = wc_clean( stripslashes( $_GET['term'] ) );
$exclude = array();
$limit = '';
if ( empty( $term ) ) {
wp_die();
}
// Stop if it is not numeric and smaller than 3 characters.
if ( ! is_numeric( $term ) && 2 >= strlen( $term ) ) {
wp_die();
}
// Search by ID.
if ( is_numeric( $term ) ) {
$customer = new WC_Customer( intval( $term ) );
@ -1244,7 +1240,13 @@ class WC_AJAX {
$ids = array( $customer->get_id() );
} else {
$data_store = WC_Data_Store::load( 'customer' );
$ids = $data_store->search_customers( $term );
// If search is smaller than 3 characters, limit result set to avoid
// too many rows being returned.
if ( 3 > strlen( $term ) ) {
$limit = 20;
}
$ids = $data_store->search_customers( $term, $limit );
}
$found_customers = array();
@ -1326,7 +1328,7 @@ class WC_AJAX {
$index ++;
$menu_orders[ $id ] = $index;
$wpdb->update( $wpdb->posts, array( 'menu_order' => $index ), array( 'ID' => $id ) );
/**
* When a single product has gotten it's ordering updated.
* $id The product ID

View File

@ -709,6 +709,24 @@ class WC_Checkout {
do_action( 'woocommerce_after_checkout_validation', $data, $errors );
}
/**
* Set address field for customer.
*
* @since 3.0.7
* @param $field string to update
* @param $key
* @param $data array of data to get the value from
*/
protected function set_customer_address_fields( $field, $key, $data ) {
if ( isset( $data[ "billing_{$field}" ] ) ) {
WC()->customer->{"set_billing_{$field}"}( $data[ "billing_{$field}" ] );
WC()->customer->{"set_shipping_{$field}"}( $data[ "billing_{$field}" ] );
}
if ( isset( $data[ "shipping_{$field}" ] ) ) {
WC()->customer->{"set_shipping_{$field}"}( $data[ "shipping_{$field}" ] );
}
}
/**
* Update customer and session data from the posted checkout data.
*
@ -716,27 +734,17 @@ class WC_Checkout {
* @param array $data
*/
protected function update_session( $data ) {
if ( isset( $data['billing_country'] ) ) {
WC()->customer->set_billing_country( $data['billing_country'] );
WC()->customer->set_shipping_country( $data['billing_country'] );
}
if ( isset( $data['billing_state'] ) ) {
WC()->customer->set_billing_state( $data['billing_state'] );
WC()->customer->set_shipping_state( $data['billing_state'] );
}
if ( isset( $data['billing_postcode'] ) ) {
WC()->customer->set_billing_postcode( $data['billing_postcode'] );
WC()->customer->set_shipping_postcode( $data['billing_postcode'] );
}
if ( isset( $data['shipping_country'] ) ) {
WC()->customer->set_shipping_country( $data['shipping_country'] );
}
if ( isset( $data['shipping_state'] ) ) {
WC()->customer->set_shipping_state( $data['shipping_state'] );
}
if ( isset( $data['shipping_postcode'] ) ) {
WC()->customer->set_shipping_postcode( $data['shipping_postcode'] );
}
// Update both shipping and billing to the passed billing address first if set.
$address_fields = array(
'address_1',
'address_2',
'city',
'postcode',
'state',
'country',
);
array_walk( $address_fields, array( $this, 'set_customer_address_fields' ), $data );
WC()->customer->save();
// Update customer shipping and payment method to posted method

View File

@ -347,7 +347,7 @@ class WC_Countries {
* @return string
*/
public function tax_or_vat() {
$return = in_array( $this->get_base_country(), $this->get_european_union_countries( 'eu_vat' ) ) ? __( 'VAT', 'woocommerce' ) : __( 'Tax', 'woocommerce' );
$return = in_array( $this->get_base_country(), array_merge( $this->get_european_union_countries( 'eu_vat' ), array( 'NO' ) ) ) ? __( 'VAT', 'woocommerce' ) : __( 'Tax', 'woocommerce' );
return apply_filters( 'woocommerce_countries_tax_or_vat', $return );
}
@ -357,7 +357,7 @@ class WC_Countries {
* @return string
*/
public function inc_tax_or_vat() {
$return = in_array( $this->get_base_country(), $this->get_european_union_countries( 'eu_vat' ) ) ? __( '(incl. VAT)', 'woocommerce' ) : __( '(incl. tax)', 'woocommerce' );
$return = in_array( $this->get_base_country(), array_merge( $this->get_european_union_countries( 'eu_vat' ), array( 'NO' ) ) ) ? __( '(incl. VAT)', 'woocommerce' ) : __( '(incl. tax)', 'woocommerce' );
return apply_filters( 'woocommerce_countries_inc_tax_or_vat', $return );
}
@ -367,7 +367,7 @@ class WC_Countries {
* @return string
*/
public function ex_tax_or_vat() {
$return = in_array( $this->get_base_country(), $this->get_european_union_countries( 'eu_vat' ) ) ? __( '(ex. VAT)', 'woocommerce' ) : __( '(ex. tax)', 'woocommerce' );
$return = in_array( $this->get_base_country(), array_merge( $this->get_european_union_countries( 'eu_vat' ), array( 'NO' ) ) ) ? __( '(ex. VAT)', 'woocommerce' ) : __( '(ex. tax)', 'woocommerce' );
return apply_filters( 'woocommerce_countries_ex_tax_or_vat', $return );
}
@ -1107,7 +1107,6 @@ class WC_Countries {
$address_fields = array();
foreach ( $fields as $key => $value ) {
$keys = array_keys( $fields );
$address_fields[ $type . $key ] = $value;
}

View File

@ -789,7 +789,6 @@ class WC_Coupon extends WC_Legacy_Coupon {
$user_id = get_current_user_id();
}
if ( $this->get_usage_limit_per_user() > 0 && is_user_logged_in() && $this->get_id() && $this->data_store ) {
global $wpdb;
$usage_count = $this->data_store->get_usage_by_user_id( $this, $user_id );
if ( $usage_count >= $this->get_usage_limit_per_user() ) {
throw new Exception( self::E_WC_COUPON_USAGE_LIMIT_REACHED );

View File

@ -127,7 +127,7 @@ class WC_Embed {
<?php
/* translators: %s: average rating */
printf(
esc_html_( 'Rated %s out of 5', 'woocommerce' ),
esc_html__( 'Rated %s out of 5', 'woocommerce' ),
esc_html( $_product->get_average_rating() )
);
?>

View File

@ -588,7 +588,8 @@ class WC_Form_Handler {
foreach ( $item->get_meta_data() as $meta ) {
if ( taxonomy_is_product_attribute( $meta->key ) ) {
$variations[ $meta->key ] = $meta->value;
$term = get_term_by( 'slug', $meta->value, $meta->key );
$variations[ $meta->key ] = $term ? $term->name : $meta->value;
} elseif ( meta_is_product_attribute( $meta->key, $meta->value, $product_id ) ) {
$variations[ $meta->key ] = $meta->value;
}

View File

@ -201,7 +201,7 @@ class WC_Frontend_Scripts {
'jquery-payment' => array(
'src' => self::get_asset_url( 'assets/js/jquery-payment/jquery.payment' . $suffix . '.js' ),
'deps' => array( 'jquery' ),
'version' => '1.4.1',
'version' => '3.0.0',
),
'photoswipe' => array(
'src' => self::get_asset_url( 'assets/js/photoswipe/photoswipe' . $suffix . '.js' ),
@ -474,16 +474,16 @@ class WC_Frontend_Scripts {
'animationSpeed' => 500,
'animationLoop' => false, // Breaks photoswipe pagination if true.
) ),
'zoom_enabled' => get_theme_support( 'wc-product-gallery-zoom' ),
'photoswipe_enabled' => get_theme_support( 'wc-product-gallery-lightbox' ),
'photoswipe_options' => apply_filters( 'woocommerce_single_product_photoswipe_options', array(
'zoom_enabled' => apply_filters( 'woocommerce_single_product_zoom_enabled', get_theme_support( 'wc-product-gallery-zoom' ) ),
'photoswipe_enabled' => apply_filters( 'woocommerce_single_product_photoswipe_enabled', get_theme_support( 'wc-product-gallery-lightbox' ) ),
'photoswipe_options' => apply_filters( 'woocommerce_single_product_photoswipe_options', array(
'shareEl' => false,
'closeOnScroll' => false,
'history' => false,
'hideAnimationDuration' => 0,
'showAnimationDuration' => 0
) ),
'flexslider_enabled' => get_theme_support( 'wc-product-gallery-slider' ),
'flexslider_enabled' => apply_filters( 'woocommerce_single_product_flexslider_enabled', get_theme_support( 'wc-product-gallery-slider' ) ),
);
break;
case 'wc-checkout' :

View File

@ -66,6 +66,33 @@ class WC_Geolocation {
return $new_value;
}
/**
* Check if is a valid IP address.
*
* @since 3.0.6
* @param string $ip_address IP address.
* @return string|bool The valid IP address, otherwise false.
*/
private static function is_ip_address( $ip_address ) {
// WP 4.7+ only.
if ( function_exists( 'rest_is_ip_address' ) ) {
return rest_is_ip_address( $ip_address );
}
// Support for WordPress 4.4 to 4.6.
if ( ! class_exists( 'Requests_IPv6', false ) ) {
include_once( dirname( __FILE__ ) . '/vendor/class-requests-ipv6.php' );
}
$ipv4_pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/';
if ( ! preg_match( $ipv4_pattern, $ip_address ) && ! Requests_IPv6::check_ipv6( $ip_address ) ) {
return false;
}
return $ip_address;
}
/**
* Get current user IP Address.
* @return string
@ -76,7 +103,7 @@ class WC_Geolocation {
} elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
// Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2
// Make sure we always only send through the first IP in the list which should always be the client IP.
return trim( current( explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) );
return (string) self::is_ip_address( trim( current( explode( ',', $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) );
} elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
return $_SERVER['REMOTE_ADDR'];
}
@ -90,8 +117,12 @@ class WC_Geolocation {
* @return string
*/
public static function get_external_ip_address() {
$transient_name = 'external_ip_address_' . self::get_ip_address();
$external_ip_address = get_transient( $transient_name );
$external_ip_address = '0.0.0.0';
if ( '' !== self::get_ip_address() ) {
$transient_name = 'external_ip_address_' . self::get_ip_address();
$external_ip_address = get_transient( $transient_name );
}
if ( false === $external_ip_address ) {
$external_ip_address = '0.0.0.0';

View File

@ -25,7 +25,7 @@ abstract class WC_Log_Levels {
* 'error': Error conditions.
* 'warning': Warning conditions.
* 'notice': Normal but significant condition.
* 'informational': Informational messages.
* 'info': Informational messages.
* 'debug': Debug-level messages.
*
* @see @link {https://tools.ietf.org/html/rfc5424}

View File

@ -115,7 +115,7 @@ class WC_Logger implements WC_Logger_Interface {
* 'error': Error conditions.
* 'warning': Warning conditions.
* 'notice': Normal but significant condition.
* 'informational': Informational messages.
* 'info': Informational messages.
* 'debug': Debug-level messages.
* @param string $message Log message.
* @param array $context Optional. Additional information for log handlers.

View File

@ -56,8 +56,6 @@ class WC_Order_Factory {
* @return WC_Order_Item|false if not found
*/
public static function get_order_item( $item_id = 0 ) {
global $wpdb;
if ( is_numeric( $item_id ) ) {
$item_type = WC_Data_Store::load( 'order-item' )->get_order_item_type( $item_id );
$id = $item_id;
@ -68,7 +66,6 @@ class WC_Order_Factory {
$id = $item_id->order_item_id;
$item_type = $item_id->order_item_type;
} else {
$item_data = false;
$item_type = false;
$id = false;
}

View File

@ -109,7 +109,7 @@ class WC_Order_Item_Product extends WC_Order_Item {
$this->set_prop( 'total', floatval( wc_format_decimal( $value ) ) );
// Subtotal cannot be less than total
if ( ! $this->get_subtotal() || $this->get_subtotal() < $this->get_total() ) {
if ( '' === $this->get_subtotal() || $this->get_subtotal() < $this->get_total() ) {
$this->set_subtotal( $value );
}
}

View File

@ -97,7 +97,7 @@ class WC_Order_Item_Shipping extends WC_Order_Item {
$tax_data = array(
'total' => array(),
);
if ( ! empty( $raw_tax_data['total'] ) ) {
if ( isset( $raw_tax_data['total'] ) ) {
$tax_data['total'] = array_map( 'wc_format_decimal', $raw_tax_data['total'] );
} elseif ( ! empty( $raw_tax_data ) && is_array( $raw_tax_data ) ) {
// Older versions just used an array.

View File

@ -181,7 +181,7 @@ class WC_Order_Item extends WC_Data implements ArrayAccess {
$order_item_name = $this->get_name();
foreach ( $meta_data as $meta ) {
if ( empty( $meta->id ) || '' === $meta->value || is_array( $meta->value ) || ( $hideprefix_length && substr( $meta->key, 0, $hideprefix_length ) === $hideprefix ) ) {
if ( empty( $meta->id ) || '' === $meta->value || ! is_scalar( $meta->value ) || ( $hideprefix_length && substr( $meta->key, 0, $hideprefix_length ) === $hideprefix ) ) {
continue;
}

View File

@ -0,0 +1,83 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class for parameter-based Order querying.
*
* @version 3.1.0
* @since 3.1.0
* @package WooCommerce/Classes
* @category Class
*/
class WC_Order_Query extends WC_Object_Query {
/**
* Valid query vars for orders.
* @return array
*/
protected function get_default_query_vars() {
return array_merge(
parent::get_default_query_vars(),
array(
'status' => array_keys( wc_get_order_statuses() ),
'type' => wc_get_order_types( 'view-orders' ),
'currency' => '',
'version' => '',
'prices_include_tax' => '',
'date_created' => '',
'date_modified' => '',
'date_completed' => '',
'date_paid' => '',
'discount_total' => '',
'discount_tax' => '',
'shipping_total' => '',
'shipping_tax' => '',
'cart_tax' => '',
'total' => '',
'total_tax' => '',
'customer' => '',
'customer_id' => '',
'order_key' => '',
'billing_first_name' => '',
'billing_last_name' => '',
'billing_company' => '',
'billing_address_1' => '',
'billing_address_2' => '',
'billing_city' => '',
'billing_state' => '',
'billing_postcode' => '',
'billing_country' => '',
'billing_email' => '',
'billing_phone' => '',
'shipping_first_name' => '',
'shipping_last_name' => '',
'shipping_company' => '',
'shipping_address_1' => '',
'shipping_address_2' => '',
'shipping_city' => '',
'shipping_state' => '',
'shipping_postcode' => '',
'shipping_country' => '',
'payment_method' => '',
'payment_method_title' => '',
'transaction_id' => '',
'customer_ip_address' => '',
'customer_user_agent' => '',
'created_via' => '',
'customer_note' => '',
)
);
}
/**
* Get orders matching the current query vars.
* @return array of WC_Order objects
*/
public function get_orders() {
$args = apply_filters( 'woocommerce_order_query_args', $this->get_query_vars() );
$results = WC_Data_Store::load( 'order' )->query( $this->get_query_vars() );
return apply_filters( 'woocommerce_order_query', $results, $args );
}
}

View File

@ -397,8 +397,6 @@ class WC_Post_Data {
* Remove downloadable permissions on permanent order deletion.
*/
public static function delete_order_downloadable_permissions( $postid ) {
global $wpdb;
if ( in_array( get_post_type( $postid ), wc_get_order_types() ) ) {
do_action( 'woocommerce_delete_order_downloadable_permissions', $postid );

View File

@ -208,7 +208,6 @@ class WC_Post_types {
'show_ui' => true,
'show_in_quick_edit' => false,
'show_in_menu' => false,
'show_in_nav_menus' => false,
'meta_box_cb' => false,
'query_var' => 1 === $tax->attribute_public,
'rewrite' => false,
@ -291,7 +290,7 @@ class WC_Post_types {
'rewrite' => $permalinks['product_rewrite_slug'] ? array( 'slug' => $permalinks['product_rewrite_slug'], 'with_front' => false, 'feeds' => true ) : false,
'query_var' => true,
'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'comments', 'custom-fields', 'publicize', 'wpcom-markdown' ),
'has_archive' => ( $shop_page_id = wc_get_page_id( 'shop' ) ) && get_post( $shop_page_id ) ? get_page_uri( $shop_page_id ) : 'shop',
'has_archive' => ( $shop_page_id = wc_get_page_id( 'shop' ) ) && get_post( $shop_page_id ) ? urldecode( get_page_uri( $shop_page_id ) ) : 'shop',
'show_in_nav_menus' => true,
'show_in_rest' => true,
)

View File

@ -352,6 +352,10 @@ class WC_Product_Variable extends WC_Product {
$this->set_backorders( 'no' );
$this->set_stock_status( $this->child_is_in_stock() ? 'instock' : 'outofstock' );
// If backorders are enabled, always in stock.
} elseif ( 'no' !== $this->get_backorders() ) {
$this->set_stock_status( 'instock' );
// If we are stock managing and we don't have stock, force out of stock status.
} elseif ( $this->get_stock_quantity() <= get_option( 'woocommerce_notify_no_stock_amount' ) ) {
$this->set_stock_status( 'outofstock' );

View File

@ -39,6 +39,7 @@ class WC_Product_Variation extends WC_Product_Simple {
'tax_class' => '',
'shipping_class_id' => '',
'image_id' => '',
'purchase_note' => '',
);
/**
@ -319,6 +320,23 @@ class WC_Product_Variation extends WC_Product_Simple {
return $image_id;
}
/**
* Get purchase note.
*
* @since 3.0.0
* @param string $context
* @return string
*/
public function get_purchase_note( $context = 'view' ) {
$value = $this->get_prop( 'purchase_note', $context );
// Inherit value from parent.
if ( 'view' === $context && empty( $value ) ) {
$value = apply_filters( $this->get_hook_prefix() . 'purchase_note', $this->parent_data['purchase_note'], $this );
}
return $value;
}
/**
* Get shipping class ID.
*
@ -391,6 +409,18 @@ class WC_Product_Variation extends WC_Product_Simple {
return $this->get_prop( 'attributes', $context );
}
/**
* Returns whether or not the product has any visible attributes.
*
* Variations are mapped to specific attributes unlike products, and the return
* value of ->get_attributes differs. Therefore this returns false.
*
* @return boolean
*/
public function has_attributes() {
return false;
}
/*
|--------------------------------------------------------------------------
| Conditionals

View File

@ -229,7 +229,9 @@ class WC_Shipping_Zone extends WC_Legacy_Shipping_Zone {
* @param array
*/
public function set_zone_locations( $locations ) {
$this->set_prop( 'zone_locations', $locations );
if ( 0 !== $this->get_id() ) {
$this->set_prop( 'zone_locations', $locations );
}
}
/*
@ -332,7 +334,7 @@ class WC_Shipping_Zone extends WC_Legacy_Shipping_Zone {
* @param string $type state or postcode
*/
public function add_location( $code, $type ) {
if ( $this->is_valid_location_type( $type ) ) {
if ( 0 !== $this->get_id() && $this->is_valid_location_type( $type ) ) {
if ( 'postcode' === $type ) {
$code = trim( strtoupper( str_replace( chr( 226 ) . chr( 128 ) . chr( 166 ), '...', $code ) ) ); // No normalization - postcodes are matched against both normal and formatted versions to support wildcards.
}

View File

@ -117,7 +117,6 @@ class WC_Shipping_Zones {
public static function get_zone_matching_package( $package ) {
$country = strtoupper( wc_clean( $package['destination']['country'] ) );
$state = strtoupper( wc_clean( $package['destination']['state'] ) );
$continent = strtoupper( wc_clean( WC()->countries->get_continent_code_for_country( $country ) ) );
$postcode = wc_normalize_postcode( wc_clean( $package['destination']['postcode'] ) );
$cache_key = WC_Cache_Helper::get_cache_prefix( 'shipping_zones' ) . 'wc_shipping_zone_' . md5( sprintf( '%s+%s+%s', $country, $state, $postcode ) );
$matching_zone_id = wp_cache_get( $cache_key, 'shipping_zones' );

View File

@ -429,7 +429,7 @@ class WC_Shortcodes {
* @return string
*/
public static function product_add_to_cart( $atts ) {
global $wpdb, $post;
global $post;
if ( empty( $atts ) ) {
return '';
@ -486,8 +486,6 @@ class WC_Shortcodes {
* @return string
*/
public static function product_add_to_cart_url( $atts ) {
global $wpdb;
if ( empty( $atts ) ) {
return '';
}

View File

@ -200,34 +200,38 @@ class WC_Structured_Data {
return;
}
$markup_offer = array(
'@type' => 'Offer',
'priceCurrency' => $currency,
'availability' => 'https://schema.org/' . $stock = ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
'sku' => $product->get_sku(),
'image' => wp_get_attachment_url( $product->get_image_id() ),
'description' => $product->get_description(),
'seller' => array(
'@type' => 'Organization',
'name' => $shop_name,
'url' => $shop_url,
),
);
if ( $product->is_type( 'variable' ) ) {
$prices = $product->get_variation_prices();
$markup_offer['priceSpecification'] = array(
'price' => wc_format_decimal( $product->get_price(), wc_get_price_decimals() ),
'minPrice' => wc_format_decimal( current( $prices['price'] ), wc_get_price_decimals() ),
'maxPrice' => wc_format_decimal( end( $prices['price'] ), wc_get_price_decimals() ),
if ( '' !== $product->get_price() ) {
$markup_offer = array(
'@type' => 'Offer',
'priceCurrency' => $currency,
'availability' => 'https://schema.org/' . $stock = ( $product->is_in_stock() ? 'InStock' : 'OutOfStock' ),
'sku' => $product->get_sku(),
'image' => wp_get_attachment_url( $product->get_image_id() ),
'description' => $product->get_description(),
'seller' => array(
'@type' => 'Organization',
'name' => $shop_name,
'url' => $shop_url,
),
);
} else {
$markup_offer['price'] = wc_format_decimal( $product->get_price(), wc_get_price_decimals() );
}
$markup['offers'] = array( apply_filters( 'woocommerce_structured_data_product_offer', $markup_offer, $product ) );
if ( $product->is_type( 'variable' ) ) {
$prices = $product->get_variation_prices();
if ( current( $prices['price'] ) === end( $prices['price'] ) ) {
$markup_offer['price'] = wc_format_decimal( $product->get_price(), wc_get_price_decimals() );
} else {
$markup_offer['priceSpecification'] = array(
'price' => wc_format_decimal( $product->get_price(), wc_get_price_decimals() ),
'minPrice' => wc_format_decimal( current( $prices['price'] ), wc_get_price_decimals() ),
'maxPrice' => wc_format_decimal( end( $prices['price'] ), wc_get_price_decimals() ),
'priceCurrency' => $currency,
);
}
} else {
$markup_offer['price'] = wc_format_decimal( $product->get_price(), wc_get_price_decimals() );
}
}
if ( $product->get_rating_count() ) {
$markup['aggregateRating'] = array(
@ -398,7 +402,7 @@ class WC_Structured_Data {
$markup = array();
$markup['@type'] = 'Order';
$markup['url'] = $order_url;
$markup['orderStatus'] = isset( $order_status[ $order->get_status() ] ) ? $order_status[ $order->get_status() ] : '';
$markup['orderStatus'] = isset( $order_statuses[ $order->get_status() ] ) ? $order_statuses[ $order->get_status() ] : '';
$markup['orderNumber'] = $order->get_order_number();
$markup['orderDate'] = $order->get_date_created()->format( 'c' );
$markup['acceptedOffer'] = $markup_offers;

View File

@ -65,6 +65,7 @@ class WC_Validation {
$valid = (bool) preg_match( '/^([0]{1}[1-9]{1}|[1-9]{1}[0-9]{1})[0-9]{3}$/', $postcode );
break;
case 'ES' :
case 'FR' :
$valid = (bool) preg_match( '/^([0-9]{5})$/i', $postcode );
break;
case 'GB' :

View File

@ -335,7 +335,7 @@ class WC_Webhook {
* @param mixed $resource_id first hook argument, typically the resource ID
* @return mixed payload data
*/
private function build_payload( $resource_id ) {
public function build_payload( $resource_id ) {
// build the payload with the same user context as the user who created
// the webhook -- this avoids permission errors as background processing
// runs with no user context

View File

@ -63,7 +63,8 @@ class WC_CLI_REST_Command {
*/
public function __construct( $name, $route, $schema ) {
$this->name = $name;
$parsed_args = preg_match_all( '#\([^\)]+\)#', $route, $matches );
preg_match_all( '#\([^\)]+\)#', $route, $matches );
$first_match = $matches[0];
$resource_id = ! empty( $matches[0] ) ? array_pop( $matches[0] ) : null;
$this->route = rtrim( $route );

View File

@ -108,15 +108,10 @@ class WC_CLI_Runner {
// Get a list of supported commands for each route.
foreach ( $route_data['endpoints'] as $endpoint ) {
$parsed_args = preg_match_all( '#\([^\)]+\)#', $route, $matches );
$first_match = $matches[0];
preg_match_all( '#\([^\)]+\)#', $route, $matches );
$resource_id = ! empty( $matches[0] ) ? array_pop( $matches[0] ) : null;
$trimmed_route = rtrim( $route );
$is_singular = substr( $trimmed_route, - strlen( $resource_id ) ) === $resource_id;
if ( ! $is_singular ) {
$resource_id = $first_match;
}
$command = '';
// List a collection
if ( array( 'GET' ) == $endpoint['methods'] && ! $is_singular ) {

View File

@ -86,7 +86,6 @@ abstract class Abstract_WC_Order_Data_Store_CPT extends WC_Data_Store_WP impleme
throw new Exception( __( 'Invalid order.', 'woocommerce' ) );
}
$id = $order->get_id();
$order->set_props( array(
'parent_id' => $post_object->post_parent,
'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,

View File

@ -127,8 +127,6 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
* @throws Exception
*/
public function read( &$customer ) {
global $wpdb;
// User object is required.
if ( ! $customer->get_id() || ! ( $user_object = get_user_by( 'id', $customer->get_id() ) ) || empty( $user_object->ID ) ) {
throw new Exception( __( 'Invalid customer.', 'woocommerce' ) );
@ -367,17 +365,20 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
* Search customers and return customer IDs.
*
* @param string $term
* @oaram int|string $limit @since 3.0.7
* @return array
*/
public function search_customers( $term ) {
public function search_customers( $term, $limit = '' ) {
$query = new WP_User_Query( array(
'search' => '*' . esc_attr( $term ) . '*',
'search_columns' => array( 'user_login', 'user_url', 'user_email', 'user_nicename', 'display_name' ),
'fields' => 'ID',
'number' => $limit,
) );
$query2 = new WP_User_Query( array(
'fields' => 'ID',
'number' => $limit,
'meta_query' => array(
'relation' => 'OR',
array(
@ -392,6 +393,13 @@ class WC_Customer_Data_Store extends WC_Data_Store_WP implements WC_Customer_Dat
),
),
) );
return wp_parse_id_list( array_merge( $query->get_results(), $query2->get_results() ) );
$results = wp_parse_id_list( array_merge( $query->get_results(), $query2->get_results() ) );
if ( $limit && count( $results ) > $limit ) {
$results = array_slice( $results, 0, $limit );
}
return $results;
}
}

View File

@ -194,4 +194,224 @@ class WC_Data_Store_WP {
return $props_to_update;
}
/**
* Get valid WP_Query args from a WC_Object_Query's query variables.
*
* @since 3.1.0
* @param array $query_vars query vars from a WC_Object_Query
* @return array
*/
protected function get_wp_query_args( $query_vars ) {
$skipped_values = array( '', array(), null );
$wp_query_args = array(
'meta_query' => array(),
);
foreach ( $query_vars as $key => $value ) {
if ( in_array( $value, $skipped_values, true ) || 'meta_query' === $key ) {
continue;
}
// Build meta queries out of vars that are stored in internal meta keys.
if ( in_array( '_' . $key, $this->internal_meta_keys ) ) {
$wp_query_args['meta_query'][] = array(
'key' => '_' . $key,
'value' => $value,
'compare' => '=',
);
// Other vars get mapped to wp_query args or just left alone.
} else {
$key_mapping = array(
'parent' => 'post_parent',
'parent_exclude' => 'post_parent__not_in',
'exclude' => 'post__not_in',
'limit' => 'posts_per_page',
'type' => 'post_type',
'return' => 'fields',
);
if ( isset( $key_mapping[ $key ] ) ) {
$wp_query_args[ $key_mapping[ $key ] ] = $value;
} else {
$wp_query_args[ $key ] = $value;
}
}
}
return apply_filters( 'woocommerce_get_wp_query_args', $wp_query_args, $query_vars );
}
/**
* Map a valid date query var to WP_Query arguments.
* Valid date formats: YYYY-MM-DD or timestamp, possibly combined with an operator from $valid_operators.
* Also accepts a WC_DateTime object.
* @param mixed $query_var A valid date format
* @param string $key meta or db column key
* @param array $wp_query_args WP_Query args
* @return array Modified $wp_query_args
*/
protected function parse_date_for_wp_query( $query_var, $key, $wp_query_args = array() ) {
$query_parse_regex = '/([^.<>]*)(>=|<=|>|<|\.\.\.)([^.<>]+)/';
$valid_operators = array( '>', '>=', '=', '<=', '<', '...' );
// YYYY-MM-DD queries have 'day' precision. Timestamp/WC_DateTime queries have 'second' precision.
$precision = 'second';
$dates = array();
$operator = '=';
try {
// Specific time query with a WC_DateTime.
if ( is_a( $query_var, 'WC_DateTime' ) ) {
$dates[] = $query_var;
// Specific time query with a timestamp.
} elseif ( is_numeric( $query_var ) ) {
$dates[] = new WC_DateTime( "@{$query_var}", new DateTimeZone( 'UTC' ) );
// Query with operators and possible range of dates.
} elseif ( preg_match( $query_parse_regex, $query_var, $sections ) ) {
if ( ! empty( $sections[1] ) ) {
$dates[] = is_numeric( $sections[1] ) ? new WC_DateTime( "@{$sections[1]}", new DateTimeZone( 'UTC' ) ) : wc_string_to_datetime( $sections[1] );
}
$operator = in_array( $sections[2], $valid_operators ) ? $sections[2] : '';
$dates[] = is_numeric( $sections[3] ) ? new WC_DateTime( "@{$sections[3]}", new DateTimeZone( 'UTC' ) ) : wc_string_to_datetime( $sections[3] );
if ( ! is_numeric( $sections[1] ) && ! is_numeric( $sections[3] ) ) {
$precision = 'day';
}
// Specific time query with a string.
} else {
$dates[] = wc_string_to_datetime( $query_var );
$precision = 'day';
}
} catch ( Exception $e ) {
return $wp_query_args;
}
// Check for valid inputs.
if ( ! $operator || empty( $dates ) || ( '...' === $operator && count( $dates ) < 2 ) ) {
return $wp_query_args;
}
// Build date query for 'post_date' or 'post_modified' keys.
if ( 'post_date' === $key || 'post_modified' === $key ) {
if ( ! isset( $wp_query_args['date_query'] ) ) {
$wp_query_args['date_query'] = array();
}
$query_arg = array(
'column' => 'day' === $precision ? $key : $key . '_gmt',
'inclusive' => '>' !== $operator && '<' !== $operator,
);
// Add 'before'/'after' query args.
$comparisons = array();
if ( '>' === $operator || '>=' === $operator || '...' === $operator ) {
$comparisons[] = 'after';
}
if ( '<' === $operator || '<=' === $operator || '...' === $operator ) {
$comparisons[] = 'before';
}
foreach ( $comparisons as $index => $comparison ) {
/**
* WordPress doesn't generate the correct SQL for inclusive day queries with both a 'before' and
* 'after' string query, so we have to use the array format in 'day' precision.
* @see https://core.trac.wordpress.org/ticket/29908
*/
if ( 'day' === $precision ) {
$query_arg[ $comparison ]['year'] = $dates[ $index ]->date( 'Y' );
$query_arg[ $comparison ]['month'] = $dates[ $index ]->date( 'n' );
$query_arg[ $comparison ]['day'] = $dates[ $index ]->date( 'j' );
/**
* WordPress doesn't support 'hour'/'second'/'minute' in array format 'before'/'after' queries,
* so we have to use a string query.
*/
} else {
$query_arg[ $comparison ] = gmdate( 'm/d/Y H:i:s', $dates[ $index ]->getTimestamp() );
}
}
if ( empty( $comparisons ) ) {
$query_arg['year'] = $dates[0]->date( 'Y' );
$query_arg['month'] = $dates[0]->date( 'n' );
$query_arg['day'] = $dates[0]->date( 'j' );
if ( 'second' === $precision ) {
$query_arg['hour'] = $dates[0]->date( 'H' );
$query_arg['minute'] = $dates[0]->date( 'i' );
$query_arg['second'] = $dates[0]->date( 's' );
}
}
$wp_query_args['date_query'][] = $query_arg;
return $wp_query_args;
}
// Build meta query for unrecognized keys.
if ( ! isset( $wp_query_args['meta_query'] ) ) {
$wp_query_args['meta_query'] = array();
}
// Meta dates are stored as timestamps in the db.
// Check against begining/end-of-day timestamps when using 'day' precision.
if ( 'day' === $precision ) {
$start_timestamp = strtotime( gmdate( 'm/d/Y 00:00:00', $dates[0]->getTimestamp() ) );
$end_timestamp = '...' !== $operator ? ( $start_timestamp + DAY_IN_SECONDS ) : strtotime( gmdate( 'm/d/Y 00:00:00', $dates[1]->getTimestamp() ) );
switch ( $operator ) {
case '>':
case '<=':
$wp_query_args['meta_query'][] = array(
'key' => $key,
'value' => $end_timestamp,
'compare' => $operator,
);
break;
case '<':
case '>=':
$wp_query_args['meta_query'][] = array(
'key' => $key,
'value' => $start_timestamp,
'compare' => $operator,
);
break;
default:
$wp_query_args['meta_query'][] = array(
'key' => $key,
'value' => $start_timestamp,
'compare' => '>=',
);
$wp_query_args['meta_query'][] = array(
'key' => $key,
'value' => $end_timestamp,
'compare' => '<=',
);
}
} else {
if ( '...' !== $operator ) {
$wp_query_args['meta_query'][] = array(
'key' => $key,
'value' => $dates[0]->getTimestamp(),
'compare' => $operator,
);
} else {
$wp_query_args['meta_query'][] = array(
'key' => $key,
'value' => $dates[0]->getTimestamp(),
'compare' => '>=',
);
$wp_query_args['meta_query'][] = array(
'key' => $key,
'value' => $dates[1]->getTimestamp(),
'compare' => '<=',
);
}
}
return $wp_query_args;
}
}

View File

@ -354,74 +354,14 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
/**
* Get all orders matching the passed in args.
*
* @deprecated 3.1.0 - Use wc_get_orders instead.
* @see wc_get_orders()
* @param array $args
* @return array of orders
*/
public function get_orders( $args = array() ) {
/**
* Generate WP_Query args. This logic will change if orders are moved to
* custom tables in the future.
*/
$wp_query_args = array(
'post_type' => $args['type'] ? $args['type'] : 'shop_order',
'post_status' => $args['status'],
'posts_per_page' => $args['limit'],
'meta_query' => array(),
'fields' => 'ids',
'orderby' => $args['orderby'],
'order' => $args['order'],
);
if ( ! is_null( $args['parent'] ) ) {
$wp_query_args['post_parent'] = absint( $args['parent'] );
}
if ( ! is_null( $args['offset'] ) ) {
$wp_query_args['offset'] = absint( $args['offset'] );
} else {
$wp_query_args['paged'] = absint( $args['page'] );
}
if ( isset( $args['customer'] ) && '' !== $args['customer'] ) {
$values = is_array( $args['customer'] ) ? $args['customer'] : array( $args['customer'] );
$wp_query_args['meta_query'][] = $this->get_orders_generate_customer_meta_query( $values );
}
if ( ! empty( $args['exclude'] ) ) {
$wp_query_args['post__not_in'] = array_map( 'absint', $args['exclude'] );
}
if ( ! $args['paginate'] ) {
$wp_query_args['no_found_rows'] = true;
}
if ( ! empty( $args['date_before'] ) ) {
$wp_query_args['date_query']['before'] = $args['date_before'];
}
if ( ! empty( $args['date_after'] ) ) {
$wp_query_args['date_query']['after'] = $args['date_after'];
}
// Get results.
$orders = new WP_Query( apply_filters( 'woocommerce_order_data_store_cpt_get_orders_query', $wp_query_args, $args, $this ) );
if ( 'objects' === $args['return'] ) {
$return = array_map( 'wc_get_order', $orders->posts );
} else {
$return = $orders->posts;
}
if ( $args['paginate'] ) {
return (object) array(
'orders' => $return,
'total' => $orders->found_posts,
'max_num_pages' => $orders->max_num_pages,
);
} else {
return $return;
}
wc_deprecated_function( 'WC_Order_Data_Store_CPT::get_orders', '3.1.0', 'Use wc_get_orders instead.' );
return wc_get_orders( $args );
}
/**
@ -634,4 +574,93 @@ class WC_Order_Data_Store_CPT extends Abstract_WC_Order_Data_Store_CPT implement
public function get_order_type( $order_id ) {
return get_post_type( $order_id );
}
/**
* Get valid WP_Query args from a WC_Order_Query's query variables.
*
* @since 3.1.0
* @param array $query_vars query vars from a WC_Order_Query
* @return array
*/
protected function get_wp_query_args( $query_vars ) {
$key_mapping = array(
'customer_id' => 'customer_user',
'status' => 'post_status',
);
foreach ( $key_mapping as $query_key => $db_key ) {
if ( isset( $query_vars[ $query_key ] ) ) {
$query_vars[ $db_key ] = $query_vars[ $query_key ];
unset( $query_vars[ $query_key ] );
}
}
$wp_query_args = parent::get_wp_query_args( $query_vars );
if ( ! isset( $wp_query_args['date_query'] ) ) {
$wp_query_args['date_query'] = array();
}
if ( ! isset( $wp_query_args['meta_query'] ) ) {
$wp_query_args['meta_query'] = array();
}
$date_queries = array(
'date_created' => 'post_date',
'date_modified' => 'post_modified',
'date_completed' => '_date_completed',
'date_paid' => '_date_paid',
);
foreach ( $date_queries as $query_var_key => $db_key ) {
if ( isset( $query_vars[ $query_var_key ] ) && '' !== $query_vars[ $query_var_key ] ) {
// Remove any existing meta queries for the same keys to prevent conflicts.
$existing_queries = wp_list_pluck( $wp_query_args['meta_query'], 'key', true );
foreach ( $existing_queries as $query_index => $query_contents ) {
unset( $wp_query_args['meta_query'][ $query_index ] );
}
$wp_query_args = $this->parse_date_for_wp_query( $query_vars[ $query_var_key ], $db_key, $wp_query_args );
}
}
if ( isset( $query_vars['customer'] ) && '' !== $query_vars['customer'] && array() !== $query_vars['customer'] ) {
$values = is_array( $query_vars['customer'] ) ? $query_vars['customer'] : array( $query_vars['customer'] );
$wp_query_args['meta_query'][] = $this->get_orders_generate_customer_meta_query( $values );
}
if ( ! isset( $query_vars['paginate'] ) || ! $query_vars['paginate'] ) {
$wp_query_args['no_found_rows'] = true;
}
return apply_filters( 'woocommerce_order_data_store_cpt_get_orders_query', $wp_query_args, $query_vars, $this );
}
/**
* Query for Orders matching specific criteria.
*
* @since 3.1.0
* @param array $query_vars query vars from a WC_Order_Query
* @return array of WC_Order objects or ids
*/
public function query( $query_vars ) {
$args = $this->get_wp_query_args( $query_vars );
$query = new WP_Query( $args );
if ( isset( $query_vars['return'] ) && 'ids' === $query_vars['return'] ) {
return $query->posts;
}
$orders = array_filter( array_map( 'wc_get_order', $query->posts ) );
if ( isset( $query_vars['paginate'] ) && $query_vars['paginate'] ) {
return (object) array(
'orders' => $orders,
'total' => $query->found_posts,
'max_num_pages' => $query->max_num_pages,
);
}
return $orders;
}
}

View File

@ -606,8 +606,11 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
$terms[] = 'outofstock';
}
$rating = max( array( 5, min( array( 1, round( $product->get_average_rating(), 0 ) ) ) ) );
$terms[] = 'rated-' . $rating;
$rating = min( 5, round( $product->get_average_rating(), 0 ) );
if ( $rating > 0 ) {
$terms[] = 'rated-' . $rating;
}
switch ( $product->get_catalog_visibility() ) {
case 'hidden' :
@ -997,50 +1000,46 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
public function get_related_products_query( $cats_array, $tags_array, $exclude_ids, $limit ) {
global $wpdb;
// Arrays to string.
$exclude_ids = implode( ',', array_map( 'absint', $exclude_ids ) );
$cats_array = implode( ',', array_map( 'absint', $cats_array ) );
$tags_array = implode( ',', array_map( 'absint', $tags_array ) );
$limit = absint( $limit );
$query = array();
$query['fields'] = "SELECT DISTINCT ID FROM {$wpdb->posts} p";
$query['join'] = " INNER JOIN {$wpdb->term_relationships} tr ON (p.ID = tr.object_id)";
$query['join'] .= " INNER JOIN {$wpdb->term_taxonomy} tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)";
$query['join'] .= " INNER JOIN {$wpdb->terms} t ON (t.term_id = tt.term_id)";
$query['where'] = ' WHERE 1=1';
$query['where'] .= " AND p.post_status = 'publish'";
$query['where'] .= " AND p.post_type = 'product'";
$query['where'] .= " AND p.ID NOT IN ( {$exclude_ids} )";
$include_term_ids = array_merge( $cats_array, $tags_array );
$exclude_term_ids = array();
$product_visibility_term_ids = wc_get_product_visibility_term_ids();
if ( $product_visibility_term_ids['exclude-from-catalog'] ) {
$query['where'] .= " AND t.term_id !=" . $product_visibility_term_ids['exclude-from-catalog'];
$exclude_term_ids[] = $product_visibility_term_ids['exclude-from-catalog'];
}
if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) && $product_visibility_term_ids['outofstock'] ) {
$query['where'] .= " AND t.term_id !=" . $product_visibility_term_ids['outofstock'];
$exclude_term_ids[] = $product_visibility_term_ids['outofstock'];
}
if ( $cats_array || $tags_array ) {
$query['where'] .= ' AND (';
$query = array(
'fields' => "
SELECT DISTINCT ID FROM {$wpdb->posts} p
",
'join' => '',
'where' => "
WHERE 1=1
AND p.post_status = 'publish'
AND p.post_type = 'product'
if ( $cats_array ) {
$query['where'] .= " ( tt.taxonomy = 'product_cat' AND t.term_id IN ( {$cats_array} ) ) ";
if ( $tags_array ) {
$query['where'] .= ' OR ';
}
}
",
'limits' => "
LIMIT " . absint( $limit ) . "
",
);
if ( $tags_array ) {
$query['where'] .= " ( tt.taxonomy = 'product_tag' AND t.term_id IN ( {$tags_array} ) ) ";
}
$query['where'] .= ')';
if ( count( $exclude_term_ids ) ) {
$query['join'] .= " LEFT JOIN ( SELECT object_id FROM {$wpdb->term_relationships} WHERE term_taxonomy_id IN ( " . implode( ',', array_map( 'absint', $exclude_term_ids ) ) . " ) ) AS exclude_join ON exclude_join.object_id = p.ID";
$query['where'] .= " AND exclude_join.object_id IS NULL";
}
$query['limits'] = " LIMIT {$limit} ";
if ( count( $include_term_ids ) ) {
$query['join'] .= " INNER JOIN ( SELECT object_id FROM {$wpdb->term_relationships} INNER JOIN {$wpdb->term_taxonomy} using( term_taxonomy_id ) WHERE term_id IN ( " . implode( ',', array_map( 'absint', $include_term_ids ) ) . " ) ) AS include_join ON include_join.object_id = p.ID";
}
if ( count( $exclude_ids ) ) {
$query['where'] .= " AND p.ID NOT IN ( " . implode( ',', array_map( 'absint', $exclude_ids ) ) . " )";
}
return $query;
}

View File

@ -41,7 +41,6 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
return;
}
$id = $product->get_id();
$product->set_parent_id( $post_object->post_parent );
$parent_id = $product->get_parent_id();
@ -73,9 +72,10 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
/**
* If a variation title is not in sync with the parent e.g. saved prior to 3.0, or if the parent title has changed, detect here and update.
*/
if ( version_compare( get_post_meta( $product->get_id(), '_product_version', true ), '3.0', '<' ) && 0 !== strpos( $post_object->post_title, get_post_field( 'post_title', $product->get_parent_id() ) ) ) {
global $wpdb;
$parent_title = get_post_field( 'post_title', $product->get_parent_id() );
if ( 0 !== strpos( $post_object->post_title, $parent_title ) ) {
global $wpdb;
$new_title = $this->generate_product_title( $product );
$product->set_name( $new_title );
$wpdb->update( $wpdb->posts, array( 'post_title' => $new_title ), array( 'ID' => $product->get_id() ) );
@ -203,11 +203,12 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
protected function generate_product_title( $product ) {
$attributes = (array) $product->get_attributes();
// Don't include attributes if the product has 3+ attributes.
// Do not include attributes if the product has 3+ attributes.
$should_include_attributes = count( $attributes ) < 3;
// Don't include attributes if an attribute name has 2+ words.
if ( $should_include_attributes ) {
// Do not include attributes if an attribute name has 2+ words and the
// product has multiple attributes.
if ( $should_include_attributes && 1 < count( $attributes ) ) {
foreach ( $attributes as $name => $value ) {
if ( false !== strpos( $name, '-' ) ) {
$should_include_attributes = false;
@ -287,6 +288,7 @@ class WC_Product_Variation_Data_Store_CPT extends WC_Product_Data_Store_CPT impl
'tax_class' => get_post_meta( $product->get_parent_id(), '_tax_class', true ),
'shipping_class_id' => absint( current( $this->get_term_ids( $product->get_parent_id(), 'product_shipping_class' ) ) ),
'image_id' => get_post_thumbnail_id( $product->get_parent_id() ),
'purchase_note' => get_post_meta( $product->get_parent_id(), '_purchase_note', true ),
) );
// Pull data from the parent when there is no user-facing way to set props.

View File

@ -269,7 +269,6 @@ class WC_Shipping_Zone_Data_Store extends WC_Data_Store_WP implements WC_Shippin
* @param WC_Shipping_Zone
*/
private function save_locations( &$zone ) {
$updated_props = array();
$changed_props = array_keys( $zone->get_changes() );
if ( ! in_array( 'zone_locations', $changed_props ) ) {
return false;

View File

@ -32,7 +32,7 @@ class WC_Email_Cancelled_Order extends WC_Email {
$this->template_plain = 'emails/plain/admin-cancelled-order.php';
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_processing_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_on-hold_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 );
// Call parent constructor

View File

@ -26,15 +26,15 @@ class WC_Email_Customer_Completed_Order extends WC_Email {
$this->id = 'customer_completed_order';
$this->customer_email = true;
$this->title = __( 'Completed order', 'woocommerce' );
$this->description = __( 'Order complete emails are sent to customers when their orders are marked completed and usually indicate that their orders have been shipped.', 'woocommerce' );
$this->heading = __( 'Your order is complete', 'woocommerce' );
$this->subject = __( 'Your {site_title} order from {order_date} is complete', 'woocommerce' );
$this->template_html = 'emails/customer-completed-order.php';
$this->template_plain = 'emails/plain/customer-completed-order.php';
$this->set_email_strings();
// Triggers for this email
add_action( 'woocommerce_order_status_completed_notification', array( $this, 'trigger' ), 10, 2 );
@ -46,6 +46,16 @@ class WC_Email_Customer_Completed_Order extends WC_Email {
parent::__construct();
}
/**
* Set email strings.
*/
public function set_email_strings() {
$this->setup_locale();
$this->heading = __( 'Your order is complete', 'woocommerce' );
$this->subject = __( 'Your {site_title} order from {order_date} is complete', 'woocommerce' );
$this->restore_locale();
}
/**
* Trigger the sending of this email.
*

View File

@ -39,27 +39,35 @@ class WC_Email_Customer_Invoice extends WC_Email {
public function __construct() {
$this->id = 'customer_invoice';
$this->customer_email = true;
$this->title = __( 'Customer invoice', 'woocommerce' );
$this->description = __( 'Customer invoice emails can be sent to customers containing their order information and payment links.', 'woocommerce' );
$this->template_html = 'emails/customer-invoice.php';
$this->template_plain = 'emails/plain/customer-invoice.php';
$this->subject = __( 'Invoice for order {order_number} from {order_date}', 'woocommerce' );
$this->heading = __( 'Invoice for order {order_number}', 'woocommerce' );
$this->subject_paid = __( 'Your {site_title} order from {order_date}', 'woocommerce' );
$this->heading_paid = __( 'Order {order_number} details', 'woocommerce' );
$this->set_email_strings();
// Call parent constructor
parent::__construct();
$this->customer_email = true;
$this->manual = true;
$this->heading_paid = $this->get_option( 'heading_paid', $this->heading_paid );
$this->subject_paid = $this->get_option( 'subject_paid', $this->subject_paid );
}
/**
* Set email strings.
*/
public function set_email_strings() {
$this->setup_locale();
$this->subject = __( 'Invoice for order {order_number} from {order_date}', 'woocommerce' );
$this->heading = __( 'Invoice for order {order_number}', 'woocommerce' );
$this->subject_paid = __( 'Your {site_title} order from {order_date}', 'woocommerce' );
$this->heading_paid = __( 'Order {order_number} details', 'woocommerce' );
$this->restore_locale();
}
/**
* Trigger the sending of this email.
*

View File

@ -54,19 +54,29 @@ class WC_Email_Customer_New_Account extends WC_Email {
$this->id = 'customer_new_account';
$this->customer_email = true;
$this->title = __( 'New account', 'woocommerce' );
$this->description = __( 'Customer "new account" emails are sent to the customer when a customer signs up via checkout or account pages.', 'woocommerce' );
$this->template_html = 'emails/customer-new-account.php';
$this->template_plain = 'emails/plain/customer-new-account.php';
$this->subject = __( 'Your account on {site_title}', 'woocommerce' );
$this->heading = __( 'Welcome to {site_title}', 'woocommerce' );
$this->set_email_strings();
// Call parent constructor
parent::__construct();
}
/**
* Set email strings.
*/
public function set_email_strings() {
$this->setup_locale();
$this->subject = __( 'Your account on {site_title}', 'woocommerce' );
$this->heading = __( 'Welcome to {site_title}', 'woocommerce' );
$this->restore_locale();
}
/**
* Trigger.
*

View File

@ -33,14 +33,14 @@ class WC_Email_Customer_Note extends WC_Email {
$this->id = 'customer_note';
$this->customer_email = true;
$this->title = __( 'Customer note', 'woocommerce' );
$this->description = __( 'Customer note emails are sent when you add a note to an order.', 'woocommerce' );
$this->template_html = 'emails/customer-note.php';
$this->template_plain = 'emails/plain/customer-note.php';
$this->subject = __( 'Note added to your {site_title} order from {order_date}', 'woocommerce' );
$this->heading = __( 'A note has been added to your order', 'woocommerce' );
$this->set_email_strings();
// Triggers
add_action( 'woocommerce_new_customer_note_notification', array( $this, 'trigger' ) );
@ -49,6 +49,16 @@ class WC_Email_Customer_Note extends WC_Email {
parent::__construct();
}
/**
* Set email strings.
*/
public function set_email_strings() {
$this->setup_locale();
$this->subject = __( 'Note added to your {site_title} order from {order_date}', 'woocommerce' );
$this->heading = __( 'A note has been added to your order', 'woocommerce' );
$this->restore_locale();
}
/**
* Trigger.
*

View File

@ -25,13 +25,14 @@ class WC_Email_Customer_On_Hold_Order extends WC_Email {
public function __construct() {
$this->id = 'customer_on_hold_order';
$this->customer_email = true;
$this->title = __( 'Order on-hold', 'woocommerce' );
$this->description = __( 'This is an order notification sent to customers containing order details after an order is placed on-hold.', 'woocommerce' );
$this->heading = __( 'Thank you for your order', 'woocommerce' );
$this->subject = __( 'Your {site_title} order receipt from {order_date}', 'woocommerce' );
$this->template_html = 'emails/customer-on-hold-order.php';
$this->template_plain = 'emails/plain/customer-on-hold-order.php';
$this->set_email_strings();
// Triggers for this email
add_action( 'woocommerce_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_failed_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 );
@ -40,6 +41,16 @@ class WC_Email_Customer_On_Hold_Order extends WC_Email {
parent::__construct();
}
/**
* Set email strings.
*/
public function set_email_strings() {
$this->setup_locale();
$this->heading = __( 'Thank you for your order', 'woocommerce' );
$this->subject = __( 'Your {site_title} order receipt from {order_date}', 'woocommerce' );
$this->restore_locale();
}
/**
* Trigger the sending of this email.
*

View File

@ -25,13 +25,14 @@ class WC_Email_Customer_Processing_Order extends WC_Email {
public function __construct() {
$this->id = 'customer_processing_order';
$this->customer_email = true;
$this->title = __( 'Processing order', 'woocommerce' );
$this->description = __( 'This is an order notification sent to customers containing order details after payment.', 'woocommerce' );
$this->heading = __( 'Thank you for your order', 'woocommerce' );
$this->subject = __( 'Your {site_title} order receipt from {order_date}', 'woocommerce' );
$this->template_html = 'emails/customer-processing-order.php';
$this->template_plain = 'emails/plain/customer-processing-order.php';
$this->set_email_strings();
// Triggers for this email
add_action( 'woocommerce_order_status_on-hold_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
add_action( 'woocommerce_order_status_pending_to_processing_notification', array( $this, 'trigger' ), 10, 2 );
@ -40,6 +41,16 @@ class WC_Email_Customer_Processing_Order extends WC_Email {
parent::__construct();
}
/**
* Set email strings.
*/
public function set_email_strings() {
$this->setup_locale();
$this->heading = __( 'Thank you for your order', 'woocommerce' );
$this->subject = __( 'Your {site_title} order receipt from {order_date}', 'woocommerce' );
$this->restore_locale();
}
/**
* Trigger the sending of this email.
*

View File

@ -37,9 +37,10 @@ class WC_Email_Customer_Refunded_Order extends WC_Email {
* Constructor.
*/
public function __construct() {
$this->set_email_strings();
$this->customer_email = true;
$this->set_email_strings();
// Triggers for this email
add_action( 'woocommerce_order_fully_refunded_notification', array( $this, 'trigger_full' ), 10, 2 );
add_action( 'woocommerce_order_partially_refunded_notification', array( $this, 'trigger_partial' ), 10, 2 );
@ -54,11 +55,13 @@ class WC_Email_Customer_Refunded_Order extends WC_Email {
* @param bool $partial_refund
*/
public function set_email_strings( $partial_refund = false ) {
$this->setup_locale();
$this->subject_partial = $this->get_option( 'subject_partial', __( 'Your {site_title} order from {order_date} has been partially refunded', 'woocommerce' ) );
$this->subject_full = $this->get_option( 'subject_full', __( 'Your {site_title} order from {order_date} has been refunded', 'woocommerce' ) );
$this->heading_full = $this->get_option( 'heading_full', __( 'Your order has been fully refunded', 'woocommerce' ) );
$this->heading_partial = $this->get_option( 'heading_partial', __( 'Your order has been partially refunded', 'woocommerce' ) );
$this->restore_locale();
$this->template_html = 'emails/customer-refunded-order.php';
$this->template_plain = 'emails/plain/customer-refunded-order.php';

View File

@ -46,15 +46,15 @@ class WC_Email_Customer_Reset_Password extends WC_Email {
public function __construct() {
$this->id = 'customer_reset_password';
$this->customer_email = true;
$this->title = __( 'Reset password', 'woocommerce' );
$this->description = __( 'Customer "reset password" emails are sent when customers reset their passwords.', 'woocommerce' );
$this->customer_email = true;
$this->template_html = 'emails/customer-reset-password.php';
$this->template_plain = 'emails/plain/customer-reset-password.php';
$this->subject = __( 'Password reset for {site_title}', 'woocommerce' );
$this->heading = __( 'Password reset instructions', 'woocommerce' );
$this->set_email_strings();
// Trigger
add_action( 'woocommerce_reset_password_notification', array( $this, 'trigger' ), 10, 2 );
@ -63,6 +63,16 @@ class WC_Email_Customer_Reset_Password extends WC_Email {
parent::__construct();
}
/**
* Set email strings.
*/
public function set_email_strings() {
$this->setup_locale();
$this->subject = __( 'Password reset for {site_title}', 'woocommerce' );
$this->heading = __( 'Password reset instructions', 'woocommerce' );
$this->restore_locale();
}
/**
* Trigger.
*

View File

@ -243,6 +243,24 @@ class WC_Email extends WC_Settings_API {
return str_replace( apply_filters( 'woocommerce_email_format_string_find', $this->find, $this ), apply_filters( 'woocommerce_email_format_string_replace', $this->replace, $this ), $string );
}
/**
* Set the locale to the store locale for customer emails to make sure emails are in the store language.
*/
public function setup_locale() {
if ( function_exists( 'switch_to_locale' ) && $this->is_customer_email() ) {
switch_to_locale( get_locale() );
}
}
/**
* Restore the locale to the default locale. Use after finished with setup_locale.
*/
public function restore_locale() {
if ( function_exists( 'restore_previous_locale' ) && $this->is_customer_email() ) {
restore_previous_locale();
}
}
/**
* Get email subject.
*
@ -280,7 +298,7 @@ class WC_Email extends WC_Settings_API {
public function get_headers() {
$header = "Content-Type: " . $this->get_content_type() . "\r\n";
if ( 'new_order' === $this->id ) {
if ( 'new_order' === $this->id && $this->object && $this->object->get_billing_email() && ( $this->object->get_billing_first_name() || $this->object->get_billing_last_name() ) ) {
$header .= 'Reply-to: ' . $this->object->get_billing_first_name() . ' ' . $this->object->get_billing_last_name() . ' <' . $this->object->get_billing_email() . ">\r\n";
}
@ -388,6 +406,7 @@ class WC_Email extends WC_Settings_API {
* @return string
*/
public function get_content() {
$this->setup_locale();
$this->sending = true;
if ( 'plain' === $this->get_email_type() ) {
@ -395,6 +414,7 @@ class WC_Email extends WC_Settings_API {
} else {
$email_content = $this->get_content_html();
}
$this->restore_locale();
return wordwrap( $email_content, 70 );
}

View File

@ -36,7 +36,7 @@ interface WC_Logger_Interface {
* 'error': Error conditions.
* 'warning': Warning conditions.
* 'notice': Normal but significant condition.
* 'informational': Informational messages.
* 'info': Informational messages.
* 'debug': Debug-level messages.
* @param string $message Log message.
* @param array $context Optional. Additional information for log handlers.

View File

@ -1089,7 +1089,6 @@ class Emogrifier
$mediaTypesExpression = '|' . implode('|', array_keys($this->allowedMediaTypes));
}
$media = '';
$cssForAllowedMediaTypes = preg_replace_callback(
'#@media\\s+(?:only\\s)?(?:[\\s{\\(]' . $mediaTypesExpression . ')\\s?[^{]+{.*}\\s*}\\s*#misU',
array( $this, '_media_concat' ),

Some files were not shown because too many files have changed in this diff Show More