Merge remote-tracking branch 'woothemes/master'

This commit is contained in:
Job 2016-06-03 15:41:51 +02:00
commit 85598eb76f
41 changed files with 1250 additions and 895 deletions

View File

@ -1 +1 @@
div.woocommerce-message{overflow:hidden;position:relative;border-left-color:#cc99c2!important}div.woocommerce-message p{max-width:700px}.woocommerce-message a.button-primary,p.woocommerce-actions a.button-primary{background:#cc99c2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15);border-color:#b366a4;box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15);color:#fff;text-shadow:0 -1px 1px #8a4f7f,1px 0 1px #8a4f7f,0 1px 1px #8a4f7f,-1px 0 1px #8a4f7f}.woocommerce-message a.button-primary:hover,p.woocommerce-actions a.button-primary:hover{background:#bb77ae;border-color:#aa559a;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15)}.woocommerce-message a.button-primary:active,p.woocommerce-actions a.button-primary:active{background:#aa559a;border-color:#aa559a}.woocommerce-message a.woocommerce-message-close,p.woocommerce-actions a.woocommerce-message-close{position:absolute;top:0;right:0;padding:10px 15px 10px 21px;font-size:13px;line-height:1.23076923;text-decoration:none}.woocommerce-message a.woocommerce-message-close:before,p.woocommerce-actions a.woocommerce-message-close:before{position:absolute;top:8px;left:0;-webkit-transition:all .1s ease-in-out;transition:all .1s ease-in-out}.woocommerce-message a.button-primary,.woocommerce-message a.button-secondary,p.woocommerce-actions a.button-primary,p.woocommerce-actions a.button-secondary{text-decoration:none!important}.woocommerce-message .twitter-share-button,p.woocommerce-actions .twitter-share-button{margin-top:-3px;margin-left:3px;vertical-align:middle}.woocommerce-about-text,p.woocommerce-actions{margin-bottom:1em!important}div.woocommerce-legacy-shipping-notice,div.woocommerce-no-shipping-methods-notice{overflow:hidden;padding:1px 12px}div.woocommerce-legacy-shipping-notice p,div.woocommerce-no-shipping-methods-notice p{position:relative;z-index:1;max-width:700px;line-height:1.5em;margin:12px 0}div.woocommerce-legacy-shipping-notice p.main,div.woocommerce-no-shipping-methods-notice p.main{font-size:1.1em}div.woocommerce-legacy-shipping-notice:before,div.woocommerce-no-shipping-methods-notice:before{content:"\e01b";font-family:WooCommerce;text-align:center;line-height:1;color:#F7F1F6;display:block;width:1em;font-size:20em;top:36px;right:12px;position:absolute}
div.woocommerce-message{overflow:hidden;position:relative;border-left-color:#cc99c2!important}div.woocommerce-message p{max-width:700px}.woocommerce-message a.button-primary,p.woocommerce-actions a.button-primary{background:#bb77ae;border-color:#A36597;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 #A36597;box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 #A36597;color:#fff;text-shadow:0 -1px 1px #A36597,1px 0 1px #A36597,0 1px 1px #A36597,-1px 0 1px #A36597}.woocommerce-message a.button-primary:active,.woocommerce-message a.button-primary:focus,.woocommerce-message a.button-primary:hover,p.woocommerce-actions a.button-primary:active,p.woocommerce-actions a.button-primary:focus,p.woocommerce-actions a.button-primary:hover{background:#A36597;border-color:#A36597;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 #A36597;box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 #A36597}.woocommerce-message a.woocommerce-message-close,p.woocommerce-actions a.woocommerce-message-close{position:absolute;top:0;right:0;padding:10px 15px 10px 21px;font-size:13px;line-height:1.23076923;text-decoration:none}.woocommerce-message a.woocommerce-message-close:before,p.woocommerce-actions a.woocommerce-message-close:before{position:absolute;top:8px;left:0;-webkit-transition:all .1s ease-in-out;transition:all .1s ease-in-out}.woocommerce-message a.button-primary,.woocommerce-message a.button-secondary,p.woocommerce-actions a.button-primary,p.woocommerce-actions a.button-secondary{text-decoration:none!important}.woocommerce-message .twitter-share-button,p.woocommerce-actions .twitter-share-button{margin-top:-3px;margin-left:3px;vertical-align:middle}.woocommerce-about-text,p.woocommerce-actions{margin-bottom:1em!important}div.woocommerce-legacy-shipping-notice,div.woocommerce-no-shipping-methods-notice{overflow:hidden;padding:1px 12px}div.woocommerce-legacy-shipping-notice p,div.woocommerce-no-shipping-methods-notice p{position:relative;z-index:1;max-width:700px;line-height:1.5em;margin:12px 0}div.woocommerce-legacy-shipping-notice p.main,div.woocommerce-no-shipping-methods-notice p.main{font-size:1.1em}div.woocommerce-legacy-shipping-notice:before,div.woocommerce-no-shipping-methods-notice:before{content:"\e01b";font-family:WooCommerce;text-align:center;line-height:1;color:#F7F1F6;display:block;width:1em;font-size:20em;top:36px;right:12px;position:absolute}

View File

@ -23,23 +23,18 @@ div.woocommerce-message {
p.woocommerce-actions,
.woocommerce-message {
a.button-primary {
background: #cc99c2;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15);
border-color: #b366a4;
box-shadow: inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15);
background: #bb77ae;
border-color: #A36597;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
color: #fff;
text-shadow: 0px -1px 1px #8a4f7f, 1px 0px 1px #8a4f7f, 0px 1px 1px #8a4f7f, -1px 0px 1px #8a4f7f;
text-shadow: 0px -1px 1px #A36597, 1px 0px 1px #A36597, 0px 1px 1px #A36597, -1px 0px 1px #A36597;
&:hover {
background: #bb77ae;
border-color: #aa559a;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15);
box-shadow: inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15);
}
&:active {
background: #aa559a;
border-color: #aa559a;
&:hover, &:focus, &:active {
background: #A36597;
border-color: #A36597;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
}
}

File diff suppressed because one or more lines are too long

View File

@ -114,32 +114,17 @@
a.button-primary,
button.button-primary {
background: #bb77ae;
border-color: #aa559a;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15);
box-shadow: inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15);
border-color: #A36597;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
color: #fff;
text-decoration: none !important;
text-shadow: 0px -1px 1px #8a4f7f, 1px 0px 1px #8a4f7f, 0px 1px 1px #8a4f7f, -1px 0px 1px #8a4f7f;
text-shadow: 0px -1px 1px #A36597, 1px 0px 1px #A36597, 0px 1px 1px #A36597, -1px 0px 1px #A36597;
&:hover {
background: #c480b7;
border-color: #aa559a;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15);
box-shadow: inset 0 1px 0 rgba(255,255,255,.25),0 1px 0 rgba(0,0,0,.15);
}
&:active {
background: #aa559a;
border-color: #873A79;
-webkit-box-shadow: inset 0px 2px 0px #873A79;
box-shadow: inset 0px 2px 0px #873A79;
}
&:focus {
background: #bb77ae;
border-color: #aa559a;
-webkit-box-shadow: 0px 1px 0px #bb77ae, 0px 0px 2px 1px #aa559a;
box-shadow: 0px 1px 0px #bb77ae, 0px 0px 2px 1px #aa559a;
&:hover, &:focus, &:active {
background: #A36597;
border-color: #A36597;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
}
}
@ -2325,8 +2310,8 @@ table.wc-shipping-zones, table.wc-shipping-zone-methods, table.wc-shipping-class
position: absolute;
}
.button-primary {
background-color: #a16696;
border-color: #a16696;
background-color: #804877;
border-color: #804877;
-webkit-box-shadow: inset 0 1px 0 rgba( 255, 255, 255, 0.2 ), 0 1px 0 rgba( 0, 0, 0, 0.15 );
box-shadow: inset 0 1px 0 rgba( 255, 255, 255, 0.2 ), 0 1px 0 rgba( 0, 0, 0, 0.15 );
margin: 0;

File diff suppressed because one or more lines are too long

View File

@ -238,10 +238,11 @@ body {
}
.setup-product {
a {
background-color: #a16696;
border-color: #a16696;
-webkit-box-shadow: inset 0 1px 0 rgba( 255, 255, 255, 0.2 ), 0 1px 0 rgba( 0, 0, 0, 0.15 );
box-shadow: inset 0 1px 0 rgba( 255, 255, 255, 0.2 ), 0 1px 0 rgba( 0, 0, 0, 0.15 );
background-color: #bb77ae;
border-color: #A36597;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
text-shadow: 0px -1px 1px #A36597, 1px 0px 1px #A36597, 0px 1px 1px #A36597, -1px 0px 1px #A36597;
font-size: 1em;
height: auto;
line-height: 1.75em;
@ -249,7 +250,13 @@ body {
opacity: 1;
padding: 1em;
text-align: center;
text-shadow: 0px -1px 1px #8a4f7f, 1px 0px 1px #8a4f7f, 0px 1px 1px #8a4f7f, -1px 0px 1px #8a4f7f;
&:hover, &:focus, &:active {
background: #A36597;
border-color: #A36597;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
}
}
}
li a:before {
@ -347,17 +354,26 @@ body {
padding: .5em 1em;
line-height: 1em;
margin-right: .5em;
margin-bottom: 2px;
height: auto;
border-radius: 4px;
}
.button-primary {
background-color: #a16696;
border-color: #a16696;
-webkit-box-shadow: inset 0 1px 0 rgba( 255, 255, 255, 0.2 ), 0 1px 0 rgba( 0, 0, 0, 0.15 );
box-shadow: inset 0 1px 0 rgba( 255, 255, 255, 0.2 ), 0 1px 0 rgba( 0, 0, 0, 0.15 );
background-color: #bb77ae;
border-color: #A36597;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
text-shadow: 0px -1px 1px #A36597, 1px 0px 1px #A36597, 0px 1px 1px #A36597, -1px 0px 1px #A36597;
float: right;
margin: 0;
opacity: 1;
text-shadow: 0px -1px 1px #8a4f7f, 1px 0px 1px #8a4f7f, 0px 1px 1px #8a4f7f, -1px 0px 1px #8a4f7f;
&:hover, &:focus, &:active {
background: #A36597;
border-color: #A36597;
-webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
box-shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 0 #A36597;
}
}
}
.wc-return-to-dashboard {

View File

@ -98,7 +98,7 @@ jQuery( function( $ ) {
}
}
if ( 'postcode' === key || 'city' === key ) {
if ( 'postcode' === key || 'city' === key || 'state' === key ) {
if ( locale['default'][ key ].label ) {
field.find( 'label' ).html( locale['default'][ key ].label );
}

View File

@ -1 +1 @@
jQuery(function(a){function b(a,b){b?(a.find("label").append(' <abbr class="required" title="'+wc_address_i18n_params.i18n_required_text+'">*</abbr>'),a.addClass("validate-required")):(a.find("label abbr").remove(),a.removeClass("validate-required"))}if("undefined"==typeof wc_address_i18n_params)return!1;var c=wc_address_i18n_params.locale.replace(/&quot;/g,'"'),d=a.parseJSON(c);a(document.body).bind("country_to_state_changing",function(c,e,f){var g,h=f;g="undefined"!=typeof d[e]?d[e]:d["default"];var i=h.find("#billing_postcode_field, #shipping_postcode_field"),j=h.find("#billing_city_field, #shipping_city_field"),k=h.find("#billing_state_field, #shipping_state_field");i.attr("data-o_class")||(i.attr("data-o_class",i.attr("class")),j.attr("data-o_class",j.attr("class")),k.attr("data-o_class",k.attr("class"))),g.postcode_before_city?(i.add(j).add(k).removeClass("form-row-first form-row-last").addClass("form-row-first"),j.removeClass("form-row-wide form-row-first").addClass("form-row-last"),i.insertBefore(j)):(i.attr("class",i.attr("data-o_class")),j.attr("class",j.attr("data-o_class")),k.attr("class",k.attr("data-o_class")),i.insertAfter(k));var l=a.parseJSON(wc_address_i18n_params.locale_fields);a.each(l,function(a,c){var e=h.find(c);g[a]?(g[a].label&&e.find("label").html(g[a].label),g[a].placeholder&&e.find("input").attr("placeholder",g[a].placeholder),b(e,!1),"undefined"==typeof g[a].required&&d["default"][a].required===!0?b(e,!0):g[a].required===!0&&b(e,!0),"state"!==a&&(g[a].hidden===!0?e.hide().find("input").val(""):e.show())):d["default"][a]&&("state"!==a&&("undefined"==typeof d["default"][a].hidden||d["default"][a].hidden===!1?e.show():d["default"][a].hidden===!0&&e.hide().find("input").val("")),"postcode"!==a&&"city"!==a||(d["default"][a].label&&e.find("label").html(d["default"][a].label),d["default"][a].placeholder&&e.find("input").attr("placeholder",d["default"][a].placeholder)),d["default"][a].required===!0&&0===e.find("label abbr").length&&b(e,!0))})})});
jQuery(function(a){function b(a,b){b?(a.find("label").append(' <abbr class="required" title="'+wc_address_i18n_params.i18n_required_text+'">*</abbr>'),a.addClass("validate-required")):(a.find("label abbr").remove(),a.removeClass("validate-required"))}if("undefined"==typeof wc_address_i18n_params)return!1;var c=wc_address_i18n_params.locale.replace(/&quot;/g,'"'),d=a.parseJSON(c);a(document.body).bind("country_to_state_changing",function(c,e,f){var g,h=f;g="undefined"!=typeof d[e]?d[e]:d["default"];var i=h.find("#billing_postcode_field, #shipping_postcode_field"),j=h.find("#billing_city_field, #shipping_city_field"),k=h.find("#billing_state_field, #shipping_state_field");i.attr("data-o_class")||(i.attr("data-o_class",i.attr("class")),j.attr("data-o_class",j.attr("class")),k.attr("data-o_class",k.attr("class"))),g.postcode_before_city?(i.add(j).add(k).removeClass("form-row-first form-row-last").addClass("form-row-first"),j.removeClass("form-row-wide form-row-first").addClass("form-row-last"),i.insertBefore(j)):(i.attr("class",i.attr("data-o_class")),j.attr("class",j.attr("data-o_class")),k.attr("class",k.attr("data-o_class")),i.insertAfter(k));var l=a.parseJSON(wc_address_i18n_params.locale_fields);a.each(l,function(a,c){var e=h.find(c);g[a]?(g[a].label&&e.find("label").html(g[a].label),g[a].placeholder&&e.find("input").attr("placeholder",g[a].placeholder),b(e,!1),"undefined"==typeof g[a].required&&d["default"][a].required===!0?b(e,!0):g[a].required===!0&&b(e,!0),"state"!==a&&(g[a].hidden===!0?e.hide().find("input").val(""):e.show())):d["default"][a]&&("state"!==a&&("undefined"==typeof d["default"][a].hidden||d["default"][a].hidden===!1?e.show():d["default"][a].hidden===!0&&e.hide().find("input").val("")),"postcode"!==a&&"city"!==a&&"state"!==a||(d["default"][a].label&&e.find("label").html(d["default"][a].label),d["default"][a].placeholder&&e.find("input").attr("placeholder",d["default"][a].placeholder)),d["default"][a].required===!0&&0===e.find("label abbr").length&&b(e,!0))})})});

View File

@ -61,8 +61,9 @@ jQuery( function( $ ) {
* @param {String} html_str The HTML string with which to replace the div.
*/
var update_wc_div = function( html_str ) {
var $html = $.parseHTML( html_str );
var $new_form = $( 'table.shop_table.cart', $html ).closest( 'form' );
var $html = $.parseHTML( html_str );
var $new_form = $( 'table.shop_table.cart', $html ).closest( 'form' );
var $new_totals = $( '.cart_totals', $html );
// Error message collection
var $error = $( '.woocommerce-error', $html );
@ -84,6 +85,7 @@ jQuery( function( $ ) {
} else {
$( 'table.shop_table.cart' ).closest( 'form' ).replaceWith( $new_form );
$( 'table.shop_table.cart' ).closest( 'form' ).find( 'input[name="update_cart"]' ).prop( 'disabled', true );
$( '.cart_totals' ).replaceWith( $new_totals );
if ( $error.length > 0 ) {
show_notice( $error );
@ -91,6 +93,8 @@ jQuery( function( $ ) {
show_notice( $message );
}
}
$( document.body ).trigger( 'updated_wc_div' );
};
/**
@ -183,10 +187,10 @@ jQuery( function( $ ) {
shipping_calculator_submit: function( evt ) {
evt.preventDefault();
var cart = this.cart;
var $form = $( evt.target );
block( $form );
block( $( 'div.cart_totals' ) );
// Provide the submit button value because wc-form-handler expects it.
$( '<input />' ).attr( 'type', 'hidden' )
@ -201,11 +205,11 @@ jQuery( function( $ ) {
data: $form.serialize(),
dataType: 'html',
success: function( response ) {
update_wc_div(response );
update_wc_div( response );
},
complete: function() {
unblock( $form );
cart.update_cart_totals();
unblock( $( 'div.cart_totals' ) );
}
} );
}
@ -219,14 +223,18 @@ jQuery( function( $ ) {
* Initialize cart UI events.
*/
init: function() {
this.update_cart_totals = this.update_cart_totals.bind( this );
this.cart_submit = this.cart_submit.bind( this );
this.submit_click = this.submit_click.bind( this );
this.apply_coupon = this.apply_coupon.bind( this );
this.update_cart_totals = this.update_cart_totals.bind( this );
this.cart_submit = this.cart_submit.bind( this );
this.submit_click = this.submit_click.bind( this );
this.apply_coupon = this.apply_coupon.bind( this );
this.remove_coupon_clicked = this.remove_coupon_clicked.bind( this );
this.quantity_update = this.quantity_update.bind( this );
this.item_remove_clicked = this.item_remove_clicked.bind( this );
this.quantity_update = this.quantity_update.bind( this );
this.item_remove_clicked = this.item_remove_clicked.bind( this );
this.update_cart = this.update_cart.bind( this );
$( document ).on(
'wc_update_cart',
this.update_cart );
$( document ).on(
'click',
'div.woocommerce > form input[type=submit]',
@ -258,6 +266,31 @@ jQuery( function( $ ) {
$( 'div.woocommerce > form input[name="update_cart"]' ).prop( 'disabled', false );
},
/**
* Update entire cart via ajax.
*/
update_cart: function() {
var $form = $( 'table.shop_table.cart' ).closest( 'form' );
block( $form );
block( $( 'div.cart_totals' ) );
// Make call to actual form post URL.
$.ajax( {
type: $form.attr( 'method' ),
url: $form.attr( 'action' ),
data: $form.serialize(),
dataType: 'html',
success: function( response ) {
update_wc_div( response );
},
complete: function() {
unblock( $form );
unblock( $( 'div.cart_totals' ) );
}
} );
},
/**
* Update the cart after something has changed.
*/
@ -269,6 +302,7 @@ jQuery( function( $ ) {
dataType: 'html',
success: function( response ) {
$( 'div.cart_totals' ).replaceWith( response );
$( document.body ).trigger( 'updated_cart_totals' );
}
} );
},
@ -385,9 +419,6 @@ jQuery( function( $ ) {
* @param {JQuery Object} $form The cart form.
*/
quantity_update: function( $form ) {
var cart = this;
// Provide the submit button value because wc-form-handler expects it.
$( '<input />' ).attr( 'type', 'hidden' )
.attr( 'name', 'update_cart' )
@ -395,6 +426,7 @@ jQuery( function( $ ) {
.appendTo( $form );
block( $form );
block( $( 'div.cart_totals' ) );
// Make call to actual form post URL.
$.ajax( {
@ -405,7 +437,7 @@ jQuery( function( $ ) {
success: update_wc_div,
complete: function() {
unblock( $form );
cart.update_cart_totals();
unblock( $( 'div.cart_totals' ) );
}
} );
},
@ -418,11 +450,11 @@ jQuery( function( $ ) {
item_remove_clicked: function( evt ) {
evt.preventDefault();
var cart = this;
var $a = $( evt.target );
var $form = $a.parents( 'form' );
block( $form );
block( $( 'div.cart_totals' ) );
$.ajax( {
type: 'GET',
@ -431,7 +463,7 @@ jQuery( function( $ ) {
success: update_wc_div,
complete: function() {
unblock( $form );
cart.update_cart_totals();
unblock( $( 'div.cart_totals' ) );
}
} );
}

File diff suppressed because one or more lines are too long

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

@ -2,10 +2,12 @@ jQuery( function( $ ) {
// Generated by CoffeeScript 1.7.1
(function() {
var cardFromNumber, cardFromType, cards, defaultFormat, formatBackCardNumber, formatBackExpiry, formatCardNumber, formatExpiry, formatForwardExpiry, formatForwardSlashAndSpace, hasTextSelected, luhnCheck, reFormatCVC, reFormatCardNumber, reFormatExpiry, reFormatNumeric, restrictCVC, restrictCardNumber, restrictExpiry, restrictNumeric, setCardType,
var cardFromNumber, cardFromType, cards, defaultFormat, formatBackCardNumber, formatBackExpiry, formatCardNumber, formatExpiry, formatForwardExpiry, formatForwardSlashAndSpace, hasTextSelected, luhnCheck, reFormatCVC, reFormatCardNumber, reFormatExpiry, reFormatNumeric, replaceFullWidthChars, restrictCVC, restrictCardNumber, restrictExpiry, restrictNumeric, safeVal, setCardType,
__slice = [].slice,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
$ = window.jQuery || window.Zepto || window.$;
$.payment = {};
$.payment.fn = {};
@ -21,77 +23,84 @@ jQuery( function( $ ) {
$.payment.cards = cards = [
{
type: 'visaelectron',
pattern: /^4(026|17500|405|508|844|91[37])/,
patterns: [4026, 417500, 4405, 4508, 4844, 4913, 4917],
format: defaultFormat,
length: [16],
cvcLength: [3],
luhn: true
}, {
type: 'maestro',
pattern: /^(5(018|0[23]|[68])|6(39|7))/,
patterns: [5018, 502, 503, 506, 56, 58, 639, 6220, 67],
format: defaultFormat,
length: [12, 13, 14, 15, 16, 17, 18, 19],
cvcLength: [3],
luhn: true
}, {
type: 'forbrugsforeningen',
pattern: /^600/,
patterns: [600],
format: defaultFormat,
length: [16],
cvcLength: [3],
luhn: true
}, {
type: 'dankort',
pattern: /^5019/,
patterns: [5019],
format: defaultFormat,
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',
pattern: /^4/,
patterns: [4],
format: defaultFormat,
length: [13, 16],
cvcLength: [3],
luhn: true
}, {
type: 'mastercard',
pattern: /^(5[0-5]|2[2-7])/,
patterns: [51, 52, 53, 54, 55, 22, 23, 24, 25, 26, 27],
format: defaultFormat,
length: [16],
cvcLength: [3],
luhn: true
}, {
type: 'amex',
pattern: /^3[47]/,
patterns: [34, 37],
format: /(\d{1,4})(\d{1,6})?(\d{1,5})?/,
length: [15],
cvcLength: [3, 4],
luhn: true
}, {
type: 'dinersclub',
pattern: /^3[0689]/,
patterns: [30, 36, 38, 39],
format: /(\d{1,4})(\d{1,6})?(\d{1,4})?/,
length: [14],
cvcLength: [3],
luhn: true
}, {
type: 'discover',
pattern: /^6([045]|22)/,
patterns: [60, 64, 65, 622],
format: defaultFormat,
length: [16],
cvcLength: [3],
luhn: true
}, {
type: 'unionpay',
pattern: /^(62|88)/,
patterns: [62, 88],
format: defaultFormat,
length: [16, 17, 18, 19],
cvcLength: [3],
luhn: false
}, {
type: 'jcb',
pattern: /^35/,
patterns: [35],
format: defaultFormat,
length: [16],
cvcLength: [3],
@ -100,12 +109,17 @@ jQuery( function( $ ) {
];
cardFromNumber = function(num) {
var card, _i, _len;
var card, p, pattern, _i, _j, _len, _len1, _ref;
num = (num + '').replace(/\D/g, '');
for (_i = 0, _len = cards.length; _i < _len; _i++) {
card = cards[_i];
if (card.pattern.test(num)) {
return card;
_ref = card.patterns;
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
pattern = _ref[_j];
p = pattern + '';
if (num.substr(0, p.length) === p) {
return card;
}
}
}
};
@ -152,23 +166,74 @@ jQuery( function( $ ) {
return false;
};
safeVal = function(value, $target) {
var currPair, cursor, digit, error, last, prevPair;
try {
cursor = $target.prop('selectionStart');
} catch (_error) {
error = _error;
cursor = null;
}
last = $target.val();
$target.val(value);
if (cursor !== null && $target.is(":focus")) {
if (cursor === last.length) {
cursor = value.length;
}
if (last !== value) {
prevPair = last.slice(cursor - 1, +cursor + 1 || 9e9);
currPair = value.slice(cursor - 1, +cursor + 1 || 9e9);
digit = value[cursor];
if (/\d/.test(digit) && prevPair === ("" + digit + " ") && currPair === (" " + digit)) {
cursor = cursor + 1;
}
}
$target.prop('selectionStart', cursor);
return $target.prop('selectionEnd', cursor);
}
};
replaceFullWidthChars = function(str) {
var chars, chr, fullWidth, halfWidth, idx, value, _i, _len;
if (str == null) {
str = '';
}
fullWidth = '\uff10\uff11\uff12\uff13\uff14\uff15\uff16\uff17\uff18\uff19';
halfWidth = '0123456789';
value = '';
chars = str.split('');
for (_i = 0, _len = chars.length; _i < _len; _i++) {
chr = chars[_i];
idx = fullWidth.indexOf(chr);
if (idx > -1) {
chr = halfWidth[idx];
}
value += chr;
}
return value;
};
reFormatNumeric = function(e) {
var $target;
$target = $(e.currentTarget);
return setTimeout(function() {
var $target, value;
$target = $(e.currentTarget);
var value;
value = $target.val();
value = replaceFullWidthChars(value);
value = value.replace(/\D/g, '');
return $target.val(value);
return safeVal(value, $target);
});
};
reFormatCardNumber = function(e) {
var $target;
$target = $(e.currentTarget);
return setTimeout(function() {
var $target, value;
$target = $(e.currentTarget);
var value;
value = $target.val();
value = replaceFullWidthChars(value);
value = $.payment.formatCardNumber(value);
return $target.val(value);
return safeVal(value, $target);
});
};
@ -234,12 +299,14 @@ jQuery( function( $ ) {
};
reFormatExpiry = function(e) {
var $target;
$target = $(e.currentTarget);
return setTimeout(function() {
var $target, value;
$target = $(e.currentTarget);
var value;
value = $target.val();
value = replaceFullWidthChars(value);
value = $.payment.formatExpiry(value);
return $target.val(value);
return safeVal(value, $target);
});
};
@ -259,7 +326,14 @@ jQuery( function( $ ) {
} else if (/^\d\d$/.test(val)) {
e.preventDefault();
return setTimeout(function() {
return $target.val("" + val + " / ");
var m1, m2;
m1 = parseInt(val[0], 10);
m2 = parseInt(val[1], 10);
if (m2 > 2 && m1 !== 0) {
return $target.val("0" + m1 + " / " + m2);
} else {
return $target.val("" + val + " / ");
}
});
}
};
@ -309,12 +383,14 @@ jQuery( function( $ ) {
};
reFormatCVC = function(e) {
var $target;
$target = $(e.currentTarget);
return setTimeout(function() {
var $target, value;
$target = $(e.currentTarget);
var value;
value = $target.val();
value = replaceFullWidthChars(value);
value = value.replace(/\D/g, '').slice(0, 4);
return $target.val(value);
return safeVal(value, $target);
});
};
@ -457,8 +533,7 @@ jQuery( function( $ ) {
$.payment.cardExpiryVal = function(value) {
var month, prefix, year, _ref;
value = value.replace(/\s/g, '');
_ref = value.split('/', 2), month = _ref[0], year = _ref[1];
_ref = value.split(/[\s\/]+/, 2), month = _ref[0], year = _ref[1];
if ((year != null ? year.length : void 0) === 2 && /^\d+$/.test(year)) {
prefix = (new Date).getFullYear();
prefix = prefix.toString().slice(0, 2);

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

View File

@ -261,7 +261,7 @@ return array(
'VN' => __( 'Vietnam', 'woocommerce' ),
'WF' => __( 'Wallis and Futuna', 'woocommerce' ),
'EH' => __( 'Western Sahara', 'woocommerce' ),
'WS' => __( 'Western Samoa', 'woocommerce' ),
'WS' => __( 'Samoa', 'woocommerce' ),
'YE' => __( 'Yemen', 'woocommerce' ),
'ZM' => __( 'Zambia', 'woocommerce' ),
'ZW' => __( 'Zimbabwe', 'woocommerce' )

File diff suppressed because it is too large Load Diff

View File

@ -85,8 +85,9 @@ class WC_Admin_Notices {
}
$simplify_options = get_option( 'woocommerce_simplify_commerce_settings', array() );
$location = wc_get_base_location();
if ( ! class_exists( 'WC_Gateway_Simplify_Commerce_Loader' ) && ! empty( $simplify_options['enabled'] ) && 'yes' === $simplify_options['enabled'] && in_array( WC()->countries->get_base_country(), apply_filters( 'woocommerce_gateway_simplify_commerce_supported_countries', array( 'US', 'IE' ) ) ) ) {
if ( ! class_exists( 'WC_Gateway_Simplify_Commerce_Loader' ) && ! empty( $simplify_options['enabled'] ) && 'yes' === $simplify_options['enabled'] && in_array( $location['country'], apply_filters( 'woocommerce_gateway_simplify_commerce_supported_countries', array( 'US', 'IE' ) ) ) ) {
WC_Admin_Notices::add_notice( 'simplify_commerce' );
}
@ -304,7 +305,9 @@ class WC_Admin_Notices {
* Simplify Commerce is being removed from core.
*/
public static function simplify_commerce_notice() {
if ( class_exists( 'WC_Gateway_Simplify_Commerce_Loader' ) || ! in_array( WC()->countries->get_base_country(), apply_filters( 'woocommerce_gateway_simplify_commerce_supported_countries', array( 'US', 'IE' ) ) ) ) {
$location = wc_get_base_location();
if ( class_exists( 'WC_Gateway_Simplify_Commerce_Loader' ) || ! in_array( $location['country'], apply_filters( 'woocommerce_gateway_simplify_commerce_supported_countries', array( 'US', 'IE' ) ) ) ) {
self::remove_notice( 'simplify_commerce' );
return;
}

View File

@ -397,17 +397,20 @@ class WC_Admin_Post_Types {
echo '</a>';
break;
case 'is_in_stock' :
if ( $the_product->is_in_stock() ) {
echo '<mark class="instock">' . __( 'In stock', 'woocommerce' ) . '</mark>';
$stock_html = '<mark class="instock">' . __( 'In stock', 'woocommerce' ) . '</mark>';
} else {
echo '<mark class="outofstock">' . __( 'Out of stock', 'woocommerce' ) . '</mark>';
$stock_html = '<mark class="outofstock">' . __( 'Out of stock', 'woocommerce' ) . '</mark>';
}
// If the product has children, a single stock level would be misleading as some could be -ve and some +ve, some managed/some unmanaged etc so hide stock level in this case.
if ( $the_product->managing_stock() && ! sizeof( $the_product->get_children() ) ) {
echo ' (' . $the_product->get_total_stock() . ')';
$stock_html .= ' (' . $the_product->get_total_stock() . ')';
}
echo apply_filters( 'woocommerce_admin_stock_html', $stock_html, $the_product );
break;
default :
break;

View File

@ -112,10 +112,11 @@ class WC_Report_Stock extends WP_List_Table {
case 'stock_status' :
if ( $product->is_in_stock() ) {
echo '<mark class="instock">' . __( 'In stock', 'woocommerce' ) . '</mark>';
$stock_html = '<mark class="instock">' . __( 'In stock', 'woocommerce' ) . '</mark>';
} else {
echo '<mark class="outofstock">' . __( 'Out of stock', 'woocommerce' ) . '</mark>';
$stock_html = '<mark class="outofstock">' . __( 'Out of stock', 'woocommerce' ) . '</mark>';
}
echo apply_filters( 'woocommerce_admin_stock_html', $stock_html, $product );
break;
case 'stock_level' :

View File

@ -10,8 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<div id="message" class="updated woocommerce-message woocommerce-legacy-shipping-notice">
<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'legacy_shipping' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php _e( 'Dismiss', 'woocommerce' ); ?></a>
<p class="main"><strong><?php _e( 'New feature: shipping zones!', 'woocommerce' ); ?></strong></p>
<p><?php _e( 'A shipping zone is a group of regions that can be assigned different shipping methods and rates.', 'woocommerce' ); ?></p>
<p class="main"><strong><?php _e( 'New:', 'woocommerce' ); ?> <?php _e( 'Shipping Zones', 'woocommerce' ); ?></strong> &#8211; <?php _e( 'a group of regions that can be assigned different shipping methods and rates.', 'woocommerce' ); ?></p>
<p><?php _e( 'Legacy shipping methods (Flat Rate, International Flat Rate, Local Pickup and Delivery, and Free Shipping) are deprecated but will continue to work as normal for now. <b><em>They will be removed in future versions of WooCommerce</em></b>. We recommend disabling these and setting up new rates within shipping zones as soon as possible.', 'woocommerce' ); ?></p>
<p class="submit">

View File

@ -10,6 +10,8 @@ if ( ! defined( 'ABSPATH' ) ) {
$theme = wp_get_theme();
?>
<div id="message" class="updated woocommerce-message">
<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'template_files' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php _e( 'Dismiss', 'woocommerce' ); ?></a>
<p><?php printf( __( '<strong>Your theme (%s) contains outdated copies of some WooCommerce template files.</strong> These files may need updating to ensure they are compatible with the current version of WooCommerce. You can see which files are affected from the %ssystem status page%s. If in doubt, check with the author of the theme.', 'woocommerce' ), esc_html( $theme['Name'] ), '<a href="' . esc_url( admin_url( 'admin.php?page=wc-status' ) ) . '">', '</a>' ); ?></p>
<p class="submit"><a class="button-primary" href="https://docs.woothemes.com/document/template-structure/" target="_blank"><?php _e( 'Learn More About Templates', 'woocommerce' ); ?></a> <a class="button-secondary skip" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'template_files' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php _e( 'Hide This Notice', 'woocommerce' ); ?></a></p>
<p class="submit"><a class="button-primary" href="https://docs.woothemes.com/document/template-structure/" target="_blank"><?php _e( 'Learn More About Templates', 'woocommerce' ); ?></a></p>
</div>

View File

@ -9,10 +9,11 @@ if ( ! defined( 'ABSPATH' ) ) {
?>
<div id="message" class="updated woocommerce-message wc-connect">
<a class="woocommerce-message-close notice-dismiss" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'theme_support' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php _e( 'Dismiss', 'woocommerce' ); ?></a>
<p><?php printf( __( '<strong>Your theme does not declare WooCommerce support</strong> &#8211; Please read our %sintegration%s guide or check out our %sStorefront%s theme which is totally free to download and designed specifically for use with WooCommerce.', 'woocommerce' ), '<a target="_blank" href="' . esc_url( apply_filters( 'woocommerce_docs_url', 'https://docs.woothemes.com/document/third-party-custom-theme-compatibility/', 'theme-compatibility' ) ) . '">', '</a>', '<a target="_blank" href="' . esc_url( admin_url( 'theme-install.php?theme=storefront' ) ) . '">', '</a>' ); ?></p>
<p class="submit">
<a href="https://www.woothemes.com/storefront/?utm_source=wpadmin&amp;utm_medium=notice&amp;utm_campaign=Storefront" class="button-primary" target="_blank"><?php _e( 'Read More About Storefront', 'woocommerce' ); ?></a>
<a href="<?php echo esc_url( apply_filters( 'woocommerce_docs_url', 'https://docs.woothemes.com/document/third-party-custom-theme-compatibility/', 'theme-compatibility' ) ); ?>" class="button-secondary" target="_blank"><?php _e( 'Theme Integration Guide', 'woocommerce' ); ?></a>
<a class="button-secondary skip" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-hide-notice', 'theme_support' ), 'woocommerce_hide_notices_nonce', '_wc_notice_nonce' ) ); ?>"><?php _e( 'Hide This Notice', 'woocommerce' ); ?></a>
</p>
</div>

View File

@ -36,6 +36,13 @@ class WC_REST_Order_Notes_Controller extends WC_REST_Controller {
*/
protected $rest_base = 'orders/(?P<order_id>[\d]+)/notes';
/**
* Post type.
*
* @var string
*/
protected $post_type = 'shop_order';
/**
* Register the routes for order notes.
*/
@ -91,7 +98,7 @@ class WC_REST_Order_Notes_Controller extends WC_REST_Controller {
* @return WP_Error|boolean
*/
public function get_items_permissions_check( $request ) {
if ( ! wc_rest_check_post_permissions( 'shop_order', 'read' ) ) {
if ( ! wc_rest_check_post_permissions( $this->post_type, 'read' ) ) {
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot list resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
}
@ -105,7 +112,7 @@ class WC_REST_Order_Notes_Controller extends WC_REST_Controller {
* @return boolean
*/
public function create_item_permissions_check( $request ) {
if ( ! wc_rest_check_post_permissions( 'shop_order', 'create' ) ) {
if ( ! wc_rest_check_post_permissions( $this->post_type, 'create' ) ) {
return new WP_Error( 'woocommerce_rest_cannot_create', __( 'Sorry, you are not allowed to create resources.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
}
@ -121,7 +128,7 @@ class WC_REST_Order_Notes_Controller extends WC_REST_Controller {
public function get_item_permissions_check( $request ) {
$post = get_post( (int) $request['order_id'] );
if ( $post && ! wc_rest_check_post_permissions( 'shop_order', 'read', $post->ID ) ) {
if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'read', $post->ID ) ) {
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
}
@ -137,7 +144,7 @@ class WC_REST_Order_Notes_Controller extends WC_REST_Controller {
public function delete_item_permissions_check( $request ) {
$post = get_post( (int) $request['order_id'] );
if ( $post && ! wc_rest_check_post_permissions( 'shop_order', 'delete', $post->ID ) ) {
if ( $post && ! wc_rest_check_post_permissions( $this->post_type, 'delete', $post->ID ) ) {
return new WP_Error( 'woocommerce_rest_cannot_delete', __( 'Sorry, you are not allowed to delete this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
}
@ -154,8 +161,8 @@ class WC_REST_Order_Notes_Controller extends WC_REST_Controller {
$id = (int) $request['id'];
$order = get_post( (int) $request['order_id'] );
if ( empty( $order->post_type ) || 'shop_order' !== $order->post_type ) {
return new WP_Error( 'woocommerce_rest_order_invalid_id', __( 'Invalid order id.', 'woocommerce' ), array( 'status' => 404 ) );
if ( empty( $order->post_type ) || $this->post_type !== $order->post_type ) {
return new WP_Error( 'woocommerce_rest_{$this->post_type}_invalid_id', __( 'Invalid order id.', 'woocommerce' ), array( 'status' => 404 ) );
}
$args = array(
@ -193,7 +200,7 @@ class WC_REST_Order_Notes_Controller extends WC_REST_Controller {
$order = get_post( (int) $request['order_id'] );
if ( empty( $order->post_type ) || 'shop_order' !== $order->post_type ) {
if ( empty( $order->post_type ) || $this->post_type !== $order->post_type ) {
return new WP_Error( 'woocommerce_rest_order_invalid_id', __( 'Invalid order id.', 'woocommerce' ), array( 'status' => 404 ) );
}
@ -237,7 +244,7 @@ class WC_REST_Order_Notes_Controller extends WC_REST_Controller {
$id = (int) $request['id'];
$order = get_post( (int) $request['order_id'] );
if ( empty( $order->post_type ) || 'shop_order' !== $order->post_type ) {
if ( empty( $order->post_type ) || $this->post_type !== $order->post_type ) {
return new WP_Error( 'woocommerce_rest_order_invalid_id', __( 'Invalid order id.', 'woocommerce' ), array( 'status' => 404 ) );
}
@ -270,7 +277,7 @@ class WC_REST_Order_Notes_Controller extends WC_REST_Controller {
$order = get_post( (int) $request['order_id'] );
if ( empty( $order->post_type ) || 'shop_order' !== $order->post_type ) {
if ( empty( $order->post_type ) || $this->post_type !== $order->post_type ) {
return new WP_Error( 'woocommerce_rest_order_invalid_id', __( 'Invalid order id.', 'woocommerce' ), array( 'status' => 404 ) );
}

View File

@ -159,6 +159,7 @@ class WC_REST_Orders_Controller extends WC_REST_Posts_Controller {
'shipping_lines' => array(),
'fee_lines' => array(),
'coupon_lines' => array(),
'refunds' => array(),
);
// Add addresses.
@ -320,6 +321,15 @@ class WC_REST_Orders_Controller extends WC_REST_Posts_Controller {
$data['coupon_lines'][] = $coupon_line;
}
// Add refunds.
foreach ( $order->get_refunds() as $refund ) {
$data['refunds'][] = array(
'id' => $refund->id,
'refund' => $refund->get_refund_reason() ? $refund->get_refund_reason() : '',
'total' => '-' . wc_format_decimal( $refund->get_refund_amount(), $dp ),
);
}
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
$data = $this->add_additional_fields_to_object( $data, $request );
$data = $this->filter_response_by_context( $data, $context );
@ -1685,6 +1695,32 @@ class WC_REST_Orders_Controller extends WC_REST_Posts_Controller {
),
),
),
'refunds' => array(
'description' => __( 'List of refunds.', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
'readonly' => true,
'properties' => array(
'id' => array(
'description' => __( 'Refund ID.', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'reason' => array(
'description' => __( 'Refund reason.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'total' => array(
'description' => __( 'Refund total.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
),
),
),
);

View File

@ -48,11 +48,12 @@ class WC_REST_Product_Attribute_Terms_Controller extends WC_REST_Terms_Controlle
$menu_order = get_woocommerce_term_meta( $item->term_id, 'order_' . $this->taxonomy );
$data = array(
'id' => (int) $item->term_id,
'name' => $item->name,
'slug' => $item->slug,
'menu_order' => (int) $menu_order,
'count' => (int) $item->count,
'id' => (int) $item->term_id,
'name' => $item->name,
'slug' => $item->slug,
'description' => $item->description,
'menu_order' => (int) $menu_order,
'count' => (int) $item->count,
);
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
@ -123,6 +124,14 @@ class WC_REST_Product_Attribute_Terms_Controller extends WC_REST_Terms_Controlle
'sanitize_callback' => 'sanitize_title',
),
),
'description' => array(
'description' => __( 'HTML description of the resource.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'arg_options' => array(
'sanitize_callback' => 'wp_filter_post_kses',
),
),
'menu_order' => array(
'description' => __( 'Menu order, used to custom sort the resource.', 'woocommerce' ),
'type' => 'integer',

View File

@ -54,12 +54,6 @@ class WC_REST_Product_Categories_Controller extends WC_REST_Terms_Controller {
// Get category display type.
$display_type = get_woocommerce_term_meta( $item->term_id, 'display_type' );
// Get category image.
$image = '';
if ( $image_id = get_woocommerce_term_meta( $item->term_id, 'thumbnail_id' ) ) {
$image = wp_get_attachment_url( $image_id );
}
// Get category order.
$menu_order = get_woocommerce_term_meta( $item->term_id, 'order' );
@ -70,11 +64,25 @@ class WC_REST_Product_Categories_Controller extends WC_REST_Terms_Controller {
'parent' => (int) $item->parent,
'description' => $item->description,
'display' => $display_type ? $display_type : 'default',
'image' => $image ? esc_url( $image ) : '',
'image' => array(),
'menu_order' => (int) $menu_order,
'count' => (int) $item->count,
);
// Get category image.
if ( $image_id = get_woocommerce_term_meta( $item->term_id, 'thumbnail_id' ) ) {
$attachment = get_post( $image_id );
$data['image'] = array(
'id' => (int) $image_id,
'date_created' => wc_rest_prepare_date_response( $attachment->post_date_gmt ),
'date_modified' => wc_rest_prepare_date_response( $attachment->post_modified_gmt ),
'src' => wp_get_attachment_url( $image_id ),
'title' => get_the_title( $attachment ),
'alt' => get_post_meta( $image_id, '_wp_attachment_image_alt', true ),
);
}
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
$data = $this->add_additional_fields_to_object( $data, $request );
$data = $this->filter_response_by_context( $data, $context );
@ -109,17 +117,31 @@ class WC_REST_Product_Categories_Controller extends WC_REST_Terms_Controller {
update_woocommerce_term_meta( $id, 'order', $request['menu_order'] );
if ( ! empty( $request['image'] ) ) {
$upload = wc_rest_upload_image_from_url( esc_url_raw( $request['image'] ) );
if ( empty( $request['image']['id'] ) && ! empty( $request['image']['src'] ) ) {
$upload = wc_rest_upload_image_from_url( esc_url_raw( $request['image']['src'] ) );
if ( is_wp_error( $upload ) ) {
return $upload;
if ( is_wp_error( $upload ) ) {
return $upload;
}
$image_id = wc_rest_set_uploaded_image_as_attachment( $upload );
} else {
$image_id = absint( $request['image']['id'] );
}
$image_id = wc_rest_set_uploaded_image_as_attachment( $upload );
// Check if image_id is a valid image attachment before updating the term meta.
if ( $image_id && wp_attachment_is_image( $image_id ) ) {
update_woocommerce_term_meta( $id, 'thumbnail_id', $image_id );
// Set the image alt.
if ( ! empty( $request['image']['alt'] ) ) {
update_post_meta( $image_id, '_wp_attachment_image_alt', wc_clean( $request['image']['alt'] ) );
}
// Set the image title.
if ( ! empty( $request['image']['title'] ) ) {
wp_update_post( array( 'ID' => $image_id, 'post_title' => wc_clean( $request['image']['title'] ) ) );
}
}
}
@ -180,10 +202,44 @@ class WC_REST_Product_Categories_Controller extends WC_REST_Terms_Controller {
'context' => array( 'view', 'edit' ),
),
'image' => array(
'description' => __( 'Image URL.', 'woocommerce' ),
'type' => 'string',
'format' => 'uri',
'description' => __( 'Image data.', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
'properties' => array(
'id' => array(
'description' => __( 'Image ID.', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
),
'date_created' => array(
'description' => __( "The date the image was created, in the site's timezone.", 'woocommerce' ),
'type' => 'date-time',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'date_modified' => array(
'description' => __( "The date the image was last modified, in the site's timezone.", 'woocommerce' ),
'type' => 'date-time',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'src' => array(
'description' => __( 'Image URL.', 'woocommerce' ),
'type' => 'string',
'format' => 'uri',
'context' => array( 'view', 'edit' ),
),
'name' => array(
'description' => __( 'Image name.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'alt' => array(
'description' => __( 'Image alternative text.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
),
),
'menu_order' => array(
'description' => __( 'Menu order, used to custom sort the resource.', 'woocommerce' ),

View File

@ -152,13 +152,13 @@ class WC_REST_Product_Reviews_Controller extends WC_REST_Controller {
*/
public function prepare_item_for_response( $review, $request ) {
$data = array(
'id' => (int) $review->comment_ID,
'date_created' => wc_rest_prepare_date_response( $review->comment_date_gmt ),
'review' => $review->comment_content,
'rating' => (int) get_comment_meta( $review->comment_ID, 'rating', true ),
'reviewer_name' => $review->comment_author,
'reviewer_email' => $review->comment_author_email,
'verified' => wc_review_is_from_verified_owner( $review->comment_ID ),
'id' => (int) $review->comment_ID,
'date_created' => wc_rest_prepare_date_response( $review->comment_date_gmt ),
'review' => $review->comment_content,
'rating' => (int) get_comment_meta( $review->comment_ID, 'rating', true ),
'name' => $review->comment_author,
'email' => $review->comment_author_email,
'verified' => wc_review_is_from_verified_owner( $review->comment_ID ),
);
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
@ -234,13 +234,13 @@ class WC_REST_Product_Reviews_Controller extends WC_REST_Controller {
'context' => array( 'view' ),
'readonly' => true,
),
'reviewer_name' => array(
'name' => array(
'description' => __( 'Reviewer name.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view' ),
'readonly' => true,
),
'reviewer_email' => array(
'email' => array(
'description' => __( 'Reviewer email.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view' ),

View File

@ -292,6 +292,19 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
return $images;
}
/**
* Get attribute taxonomy label.
*
* @param string $name
* @return string
*/
protected function get_attribute_taxonomy_label( $name ) {
$tax = get_taxonomy( $name );
$labels = get_taxonomy_labels( $tax );
return $labels->singular_name;
}
/**
* Get default attributes.
*
@ -303,11 +316,19 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
if ( $product->is_type( 'variable' ) ) {
foreach ( (array) get_post_meta( $product->id, '_default_attributes', true ) as $key => $value ) {
$default[] = array(
'name' => wc_attribute_label( str_replace( 'attribute_', '', $key ) ),
'slug' => str_replace( 'attribute_', '', str_replace( 'pa_', '', $key ) ),
'option' => $value,
);
if ( 0 === strpos( $key, 'pa_' ) ) {
$default[] = array(
'id' => wc_attribute_taxonomy_id_by_name( $key ),
'name' => $this->get_attribute_taxonomy_label( $key ),
'option' => $value,
);
} else {
$default[] = array(
'id' => 0,
'name' => str_replace( 'pa_', '', $key ),
'option' => $value,
);
}
}
}
@ -326,30 +347,45 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
if ( $product->is_type( 'variation' ) ) {
// Variation attributes.
foreach ( $product->get_variation_attributes() as $attribute_name => $attribute ) {
$name = str_replace( 'attribute_', '', $attribute_name );
// Taxonomy-based attributes are prefixed with `pa_`, otherwise simply `attribute_`.
$attributes[] = array(
'name' => wc_attribute_label( str_replace( 'attribute_', '', $attribute_name ), $product ),
'slug' => str_replace( 'attribute_', '', str_replace( 'pa_', '', $attribute_name ) ),
'option' => $attribute,
);
if ( 0 === strpos( $attribute_name, 'attribute_pa_' ) ) {
$attributes[] = array(
'id' => wc_attribute_taxonomy_id_by_name( $name ),
'name' => $this->get_attribute_taxonomy_label( $name ),
'option' => $attribute,
);
} else {
$attributes[] = array(
'id' => 0,
'name' => str_replace( 'pa_', '', $name ),
'option' => $attribute,
);
}
}
} else {
foreach ( $product->get_attributes() as $attribute ) {
// Taxonomy-based attributes are comma-separated, others are pipe (|) separated.
if ( $attribute['is_taxonomy'] ) {
$options = explode( ',', $product->get_attribute( $attribute['name'] ) );
$attributes[] = array(
'id' => $attribute['is_taxonomy'] ? wc_attribute_taxonomy_id_by_name( $attribute['name'] ) : 0,
'name' => $this->get_attribute_taxonomy_label( $attribute['name'] ),
'position' => (int) $attribute['position'],
'visible' => (bool) $attribute['is_visible'],
'variation' => (bool) $attribute['is_variation'],
'options' => array_map( 'trim', explode( ',', $product->get_attribute( $attribute['name'] ) ) ),
);
} else {
$options = explode( '|', $product->get_attribute( $attribute['name'] ) );
$attributes[] = array(
'id' => 0,
'name' => str_replace( 'pa_', '', $attribute['name'] ),
'position' => (int) $attribute['position'],
'visible' => (bool) $attribute['is_visible'],
'variation' => (bool) $attribute['is_variation'],
'options' => array_map( 'trim', explode( '|', $product->get_attribute( $attribute['name'] ) ) ),
);
}
$attributes[] = array(
'name' => wc_attribute_label( $attribute['name'], $product ),
'slug' => str_replace( 'pa_', '', $attribute['name'] ),
'position' => (int) $attribute['position'],
'visible' => (bool) $attribute['is_visible'],
'variation' => (bool) $attribute['is_variation'],
'options' => array_map( 'trim', $options ),
);
}
}
@ -406,8 +442,8 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'virtual' => $product->is_virtual(),
'downloadable' => $product->is_downloadable(),
'downloads' => $this->get_downloads( $product ),
'download_limit' => (int) $product->download_limit,
'download_expiry' => (int) $product->download_expiry,
'download_limit' => '' !== $product->download_limit ? (int) $product->download_limit : -1,
'download_expiry' => '' !== $product->download_expiry ? (int) $product->download_expiry : -1,
'download_type' => $product->download_type ? $product->download_type : 'standard',
'external_url' => $product->is_type( 'external' ) ? $product->get_product_url() : '',
'button_text' => $product->is_type( 'external' ) ? $product->get_button_text() : '',
@ -482,8 +518,8 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'virtual' => $variation->is_virtual(),
'downloadable' => $variation->is_downloadable(),
'downloads' => $this->get_downloads( $variation ),
'download_limit' => (int) $variation->download_limit,
'download_expiry' => (int) $variation->download_expiry,
'download_limit' => '' !== $variation->download_limit ? (int) $variation->download_limit : -1,
'download_expiry' => '' !== $variation->download_expiry ? (int) $variation->download_expiry : -1,
'tax_status' => $variation->get_tax_status(),
'tax_class' => $variation->get_tax_class(),
'manage_stock' => $variation->managing_stock(),
@ -651,27 +687,6 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}", $data, $request );
}
/**
* Get attribute taxonomy by slug.
*
* @param string $slug
* @return string|null
*/
private function get_attribute_taxonomy_by_slug( $slug ) {
$taxonomy = null;
$taxonomies = wc_get_attribute_taxonomies();
foreach ( $taxonomies as $key => $tax ) {
if ( $slug === $tax->attribute_name ) {
$taxonomy = 'pa_' . $tax->attribute_name;
break;
}
}
return $taxonomy;
}
/**
* Save product images.
*
@ -858,7 +873,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
}
// Default total sales.
add_post_meta( $product_id, 'total_sales', '0', true );
add_post_meta( $product->id, 'total_sales', '0', true );
// Virtual.
if ( isset( $request['virtual'] ) ) {
@ -919,25 +934,22 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
$attributes = array();
foreach ( $request['attributes'] as $attribute ) {
$is_taxonomy = 0;
$taxonomy = 0;
$attribute_id = 0;
$attribute_name = '';
if ( ! isset( $attribute['name'] ) ) {
// Check ID for global attributes or name for product attributes.
if ( ! empty( $attribute['id'] ) ) {
$attribute_id = absint( $attribute['id'] );
$attribute_name = wc_attribute_taxonomy_name_by_id( $attribute_id );
} elseif ( ! empty( $attribute['name'] ) ) {
$attribute_name = wc_clean( $attribute['name'] );
}
if ( ! $attribute_id && ! $attribute_name ) {
continue;
}
$attribute_slug = sanitize_title( $attribute['name'] );
if ( isset( $attribute['slug'] ) ) {
$taxonomy = $this->get_attribute_taxonomy_by_slug( $attribute['slug'] );
$attribute_slug = sanitize_title( $attribute['slug'] );
}
if ( $taxonomy ) {
$is_taxonomy = 1;
}
if ( $is_taxonomy ) {
if ( $attribute_id ) {
if ( isset( $attribute['options'] ) ) {
$options = $attribute['options'];
@ -954,19 +966,19 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
}
// Update post terms.
if ( taxonomy_exists( $taxonomy ) ) {
wp_set_object_terms( $product->id, $values, $taxonomy );
if ( taxonomy_exists( $attribute_name ) ) {
wp_set_object_terms( $product->id, $values, $attribute_name );
}
if ( $values ) {
// Add attribute to array, but don't set values.
$attributes[ $taxonomy ] = array(
'name' => $taxonomy,
$attributes[ $attribute_name ] = array(
'name' => $attribute_name,
'value' => '',
'position' => isset( $attribute['position'] ) ? absint( $attribute['position'] ) : 0,
'is_visible' => ( isset( $attribute['visible'] ) && $attribute['visible'] ) ? 1 : 0,
'is_variation' => ( isset( $attribute['variation'] ) && $attribute['variation'] ) ? 1 : 0,
'is_taxonomy' => $is_taxonomy
'is_taxonomy' => true,
);
}
@ -981,13 +993,13 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
}
// Custom attribute - Add attribute to array and set the values.
$attributes[ $attribute_slug ] = array(
'name' => wc_clean( $attribute['name'] ),
$attributes[ sanitize_title( $attribute_name ) ] = array(
'name' => $attribute_name,
'value' => $values,
'position' => isset( $attribute['position'] ) ? absint( $attribute['position'] ) : 0,
'is_visible' => ( isset( $attribute['visible'] ) && $attribute['visible'] ) ? 1 : 0,
'is_variation' => ( isset( $attribute['variation'] ) && $attribute['variation'] ) ? 1 : 0,
'is_taxonomy' => $is_taxonomy
'is_taxonomy' => false,
);
}
}
@ -1230,17 +1242,17 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
// Download limit.
if ( isset( $request['download_limit'] ) ) {
update_post_meta( $product->id, '_download_limit', ( '' === $request['download_limit'] ) ? '' : absint( $request['download_limit'] ) );
update_post_meta( $product->id, '_download_limit', -1 === $request['download_limit'] ? '' : absint( $request['download_limit'] ) );
}
// Download expiry.
if ( isset( $request['download_expiry'] ) ) {
update_post_meta( $product->id, '_download_expiry', ( '' === $request['download_expiry'] ) ? '' : absint( $request['download_expiry'] ) );
update_post_meta( $product->id, '_download_expiry', -1 === $request['download_expiry'] ? '' : absint( $request['download_expiry'] ) );
}
// Download type.
if ( isset( $request['download_type'] ) ) {
update_post_meta( $product->id, '_download_type', wc_clean( $request['download_type'] ) );
update_post_meta( $product->id, '_download_type', 'standard' === $request['download_type'] ? '' : wc_clean( $request['download_type'] ) );
}
}
@ -1270,7 +1282,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
global $wpdb;
$variations = $request['variations'];
$attributes = (array) maybe_unserialize( get_post_meta( $product->id, '_product_attributes', true ) );
$attributes = $product->get_attributes();
foreach ( $variations as $menu_order => $variation ) {
$variation_id = isset( $variation['id'] ) ? absint( $variation['id'] ) : 0;
@ -1467,14 +1479,12 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
// Download limit.
if ( isset( $variation['download_limit'] ) ) {
$download_limit = absint( $variation['download_limit'] );
update_post_meta( $variation_id, '_download_limit', ( ! $download_limit ) ? '' : $download_limit );
update_post_meta( $variation_id, '_download_limit', -1 === $variation['download_limit'] ? '' : absint( $variation['download_limit'] ) );
}
// Download expiry.
if ( isset( $variation['download_expiry'] ) ) {
$download_expiry = absint( $variation['download_expiry'] );
update_post_meta( $variation_id, '_download_expiry', ( ! $download_expiry ) ? '' : $download_expiry );
update_post_meta( $variation_id, '_download_expiry', -1 === $variation['download_expiry'] ? '' : absint( $variation['download_expiry'] ) );
}
} else {
update_post_meta( $variation_id, '_download_limit', '' );
@ -1491,24 +1501,24 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
if ( isset( $variation['attributes'] ) ) {
$updated_attribute_keys = array();
foreach ( $variation['attributes'] as $attribute_key => $attribute ) {
if ( ! isset( $attribute['name'] ) ) {
foreach ( $variation['attributes'] as $attribute ) {
$attribute_id = 0;
$attribute_name = '';
// Check ID for global attributes or name for product attributes.
if ( ! empty( $attribute['id'] ) ) {
$attribute_id = absint( $attribute['id'] );
$attribute_name = wc_attribute_taxonomy_name_by_id( $attribute_id );
} elseif ( ! empty( $attribute['name'] ) ) {
$attribute_name = sanitize_title( $attribute['name'] );
}
if ( ! $attribute_id && ! $attribute_name ) {
continue;
}
$taxonomy = 0;
$_attribute = array();
if ( isset( $attribute['slug'] ) ) {
$taxonomy = $this->get_attribute_taxonomy_by_slug( $attribute['slug'] );
}
if ( ! $taxonomy ) {
$taxonomy = sanitize_title( $attribute['name'] );
}
if ( isset( $attributes[ $taxonomy ] ) ) {
$_attribute = $attributes[ $taxonomy ];
if ( isset( $attributes[ $attribute_name ] ) ) {
$_attribute = $attributes[ $attribute_name ];
}
if ( isset( $_attribute['is_variation'] ) && $_attribute['is_variation'] ) {
@ -1548,34 +1558,39 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
if ( isset( $request['default_attributes'] ) && is_array( $request['default_attributes'] ) ) {
$default_attributes = array();
foreach ( $request['default_attributes'] as $default_attr_key => $default_attr ) {
if ( ! isset( $default_attr['name'] ) ) {
foreach ( $request['default_attributes'] as $attribute ) {
$attribute_id = 0;
$attribute_name = '';
// Check ID for global attributes or name for product attributes.
if ( ! empty( $attribute['id'] ) ) {
$attribute_id = absint( $attribute['id'] );
$attribute_name = wc_attribute_taxonomy_name_by_id( $attribute_id );
} elseif ( ! empty( $attribute['name'] ) ) {
$attribute_name = sanitize_title( $attribute['name'] );
}
if ( ! $attribute_id && ! $attribute_name ) {
continue;
}
$taxonomy = sanitize_title( $default_attr['name'] );
if ( isset( $default_attr['slug'] ) ) {
$taxonomy = $this->get_attribute_taxonomy_by_slug( $default_attr['slug'] );
}
if ( isset( $attributes[ $taxonomy ] ) ) {
$_attribute = $attributes[ $taxonomy ];
if ( isset( $attributes[ $attribute_name ] ) ) {
$_attribute = $attributes[ $attribute_name ];
if ( $_attribute['is_variation'] ) {
$value = '';
if ( isset( $default_attr['option'] ) ) {
if ( isset( $attribute['option'] ) ) {
if ( $_attribute['is_taxonomy'] ) {
// Don't use wc_clean as it destroys sanitized characters.
$value = sanitize_title( trim( stripslashes( $default_attr['option'] ) ) );
$value = sanitize_title( trim( stripslashes( $attribute['option'] ) ) );
} else {
$value = wc_clean( trim( stripslashes( $default_attr['option'] ) ) );
$value = wc_clean( trim( stripslashes( $attribute['option'] ) ) );
}
}
if ( $value ) {
$default_attributes[ $taxonomy ] = $value;
$default_attributes[ $attribute_name ] = $value;
}
}
}
@ -1689,7 +1704,9 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
* @return array
*/
public function get_item_schema() {
$schema = array(
$weight_unit = get_option( 'woocommerce_weight_unit' );
$dimension_unit = get_option( 'woocommerce_dimension_unit' );
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => $this->post_type,
'type' => 'object',
@ -1859,13 +1876,13 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'download_limit' => array(
'description' => __( 'Amount of times the product can be downloaded.', 'woocommerce' ),
'type' => 'integer',
'default' => null,
'default' => -1,
'context' => array( 'view', 'edit' ),
),
'download_expiry' => array(
'description' => __( 'Number of days that the customer has up to be able to download the product.', 'woocommerce' ),
'type' => 'integer',
'default' => null,
'default' => -1,
'context' => array( 'view', 'edit' ),
),
'download_type' => array(
@ -1941,7 +1958,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'context' => array( 'view', 'edit' ),
),
'weight' => array(
'description' => sprintf( __( 'Product weight (%s).', 'woocommerce' ), get_option( 'woocommerce_weight_unit' ) ),
'description' => sprintf( __( 'Product weight (%s).', 'woocommerce' ), $weight_unit ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
@ -1951,17 +1968,17 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'context' => array( 'view', 'edit' ),
'properties' => array(
'length' => array(
'description' => sprintf( __( 'Product length (%s).', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ),
'description' => sprintf( __( 'Product length (%s).', 'woocommerce' ), $dimension_unit ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'width' => array(
'description' => sprintf( __( 'Product width (%s).', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ),
'description' => sprintf( __( 'Product width (%s).', 'woocommerce' ), $dimension_unit ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'height' => array(
'description' => sprintf( __( 'Product height (%s).', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ),
'description' => sprintf( __( 'Product height (%s).', 'woocommerce' ), $dimension_unit ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
@ -2091,7 +2108,6 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'description' => __( 'Image ID.', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'date_created' => array(
'description' => __( "The date the image was created, in the site's timezone.", 'woocommerce' ),
@ -2133,16 +2149,15 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'type' => 'array',
'context' => array( 'view', 'edit' ),
'properties' => array(
'id' => array(
'description' => __( 'Attribute ID.', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
),
'name' => array(
'description' => __( 'Attribute name.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'required' => true,
),
'slug' => array(
'description' => __( 'Attribute slug.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'position' => array(
'description' => __( 'Attribute position.', 'woocommerce' ),
@ -2173,18 +2188,18 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'type' => 'array',
'context' => array( 'view', 'edit' ),
'properties' => array(
'id' => array(
'description' => __( 'Attribute ID.', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
),
'name' => array(
'description' => __( 'Attribute name.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'slug' => array(
'description' => __( 'Attribute slug.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'option' => array(
'description' => __( 'Selected term name of the attribute.', 'woocommerce' ),
'description' => __( 'Selected attribute term name.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
@ -2214,7 +2229,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'readonly' => true,
),
'permalink' => array(
'description' => __( 'Product URL.', 'woocommerce' ),
'description' => __( 'Variation URL.', 'woocommerce' ),
'type' => 'string',
'format' => 'uri',
'context' => array( 'view', 'edit' ),
@ -2226,18 +2241,18 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'context' => array( 'view', 'edit' ),
),
'price' => array(
'description' => __( 'Current product price.', 'woocommerce' ),
'description' => __( 'Current variation price.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'regular_price' => array(
'description' => __( 'Product regular price.', 'woocommerce' ),
'description' => __( 'Variation regular price.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'sale_price' => array(
'description' => __( 'Product sale price.', 'woocommerce' ),
'description' => __( 'Variation sale price.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
@ -2252,25 +2267,25 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'context' => array( 'view', 'edit' ),
),
'on_sale' => array(
'description' => __( 'Shows if the product is on sale.', 'woocommerce' ),
'description' => __( 'Shows if the variation is on sale.', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'purchasable' => array(
'description' => __( 'Shows if the product can be bought.', 'woocommerce' ),
'description' => __( 'Shows if the variation can be bought.', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'virtual' => array(
'description' => __( 'If the product is virtual.', 'woocommerce' ),
'description' => __( 'If the variation is virtual.', 'woocommerce' ),
'type' => 'boolean',
'default' => false,
'context' => array( 'view', 'edit' ),
),
'downloadable' => array(
'description' => __( 'If the product is downloadable.', 'woocommerce' ),
'description' => __( 'If the variation is downloadable.', 'woocommerce' ),
'type' => 'boolean',
'default' => false,
'context' => array( 'view', 'edit' ),
@ -2299,13 +2314,13 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
),
),
'download_limit' => array(
'description' => __( 'Amount of times the product can be downloaded.', 'woocommerce' ),
'description' => __( 'Amount of times the variation can be downloaded.', 'woocommerce' ),
'type' => 'integer',
'default' => null,
'context' => array( 'view', 'edit' ),
),
'download_expiry' => array(
'description' => __( 'Number of days that the customer has up to be able to download the product.', 'woocommerce' ),
'description' => __( 'Number of days that the customer has up to be able to download the variation.', 'woocommerce' ),
'type' => 'integer',
'default' => null,
'context' => array( 'view', 'edit' ),
@ -2323,7 +2338,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'context' => array( 'view', 'edit' ),
),
'manage_stock' => array(
'description' => __( 'Stock management at product level.', 'woocommerce' ),
'description' => __( 'Stock management at variation level.', 'woocommerce' ),
'type' => 'boolean',
'default' => false,
'context' => array( 'view', 'edit' ),
@ -2334,7 +2349,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'context' => array( 'view', 'edit' ),
),
'in_stock' => array(
'description' => __( 'Controls whether or not the product is listed as "in stock" or "out of stock" on the frontend.', 'woocommerce' ),
'description' => __( 'Controls whether or not the variation is listed as "in stock" or "out of stock" on the frontend.', 'woocommerce' ),
'type' => 'boolean',
'default' => true,
'context' => array( 'view', 'edit' ),
@ -2353,33 +2368,33 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'readonly' => true,
),
'backordered' => array(
'description' => __( 'Shows if a product is on backorder.', 'woocommerce' ),
'description' => __( 'Shows if a variation is on backorder.', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'weight' => array(
'description' => sprintf( __( 'Product weight (%s).', 'woocommerce' ), get_option( 'woocommerce_weight_unit' ) ),
'description' => sprintf( __( 'Variation weight (%s).', 'woocommerce' ), $weight_unit ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'dimensions' => array(
'description' => __( 'Product dimensions.', 'woocommerce' ),
'description' => __( 'Variation dimensions.', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
'properties' => array(
'length' => array(
'description' => sprintf( __( 'Product length (%s).', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ),
'description' => sprintf( __( 'Variation length (%s).', 'woocommerce' ), $dimension_unit ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'width' => array(
'description' => sprintf( __( 'Product width (%s).', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ),
'description' => sprintf( __( 'Variation width (%s).', 'woocommerce' ), $dimension_unit ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'height' => array(
'description' => sprintf( __( 'Product height (%s).', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ),
'description' => sprintf( __( 'Variation height (%s).', 'woocommerce' ), $dimension_unit ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
@ -2405,7 +2420,6 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'description' => __( 'Image ID.', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'date_created' => array(
'description' => __( "The date the image was created, in the site's timezone.", 'woocommerce' ),
@ -2447,39 +2461,21 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
'type' => 'array',
'context' => array( 'view', 'edit' ),
'properties' => array(
'id' => array(
'description' => __( 'Attribute ID.', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
),
'name' => array(
'description' => __( 'Attribute name.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'required' => true,
),
'slug' => array(
'description' => __( 'Attribute slug.', 'woocommerce' ),
'option' => array(
'description' => __( 'Selected attribute term name.', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'position' => array(
'description' => __( 'Attribute position.', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
),
'visible' => array(
'description' => __( "Define if the attribute is visible on the \"Additional Information\" tab in the product's page.", 'woocommerce' ),
'type' => 'boolean',
'default' => false,
'context' => array( 'view', 'edit' ),
),
'variation' => array(
'description' => __( 'Define if the attribute can be used as variation.', 'woocommerce' ),
'type' => 'boolean',
'default' => false,
'context' => array( 'view', 'edit' ),
),
'options' => array(
'description' => __( 'List of available term names of the attribute.', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
),
),
),
),
@ -2510,7 +2506,7 @@ class WC_REST_Products_Controller extends WC_REST_Posts_Controller {
$params = parent::get_collection_params();
$params['slug'] = array(
'description' => __( 'Limit result set to posts with a specific slug.', 'woocommerce', 'woocommerce' ),
'description' => __( 'Limit result set to products with a specific slug.', 'woocommerce', 'woocommerce' ),
'type' => 'string',
'validate_callback' => 'rest_validate_request_arg',
);

View File

@ -29,11 +29,31 @@ class WC_Background_Updater extends WP_Background_Process {
protected $action = 'wc_updater';
/**
* Dispatch
* @var string
*/
protected $error = '';
/**
* Dispatch updater.
*
* Updater will still run via cron job if this fails for any reason.
*/
public function dispatch() {
WC_Admin_Notices::add_notice( 'updating' );
parent::dispatch();
$dispatched = parent::dispatch();
if ( is_wp_error( $dispatched ) ) {
$this->error = $dispatched->get_error_message();
add_action( 'admin_notices', array( $this, 'dispatch_error' ) );
}
}
/**
* Error shown when the updater cannot dispatch.
*/
public function dispatch_error() {
echo '<div class="error"><p>' . __( 'Unable to dispatch WooCommerce updater:', 'woocommerce' ) . ' ' . esc_html( $this->error ) . '</p></div>';
}
/**

View File

@ -184,8 +184,8 @@ class WC_Checkout {
'status' => apply_filters( 'woocommerce_default_order_status', 'pending' ),
'customer_id' => $this->customer_id,
'customer_note' => isset( $this->posted['order_comments'] ) ? $this->posted['order_comments'] : '',
'cart_hash' => md5( print_r( WC()->cart->get_cart_for_session(), true ) . WC()->cart->total ),
'created_via' => 'checkout'
'cart_hash' => md5( json_encode( wc_clean( WC()->cart->get_cart_for_session() ) ) . WC()->cart->total ),
'created_via' => 'checkout',
);
// Insert or update the post data
@ -445,7 +445,7 @@ class WC_Checkout {
$this->posted[ $key ] = apply_filters( 'woocommerce_process_checkout_field_' . $key, $this->posted[ $key ] );
// Validation: Required fields
if ( isset( $field['required'] ) && $field['required'] && empty( $this->posted[ $key ] ) ) {
if ( isset( $field['required'] ) && $field['required'] && ( ! isset( $this->posted[ $key ] ) || "" === $this->posted[ $key ] ) ) {
switch ( $fieldset_key ) {
case 'shipping' :
$field_label = sprintf( _x( 'Shipping %s', 'Shipping FIELDNAME', 'woocommerce' ), $field['label'] );

View File

@ -32,7 +32,7 @@ class WC_Embed {
add_filter( 'the_excerpt_embed', array( __CLASS__, 'the_excerpt' ), 10 );
// Make sure no comments display. Doesn't make sense for products.
remove_action( 'embed_content_meta', 'print_embed_comments_button' );
add_action( 'embed_content_meta', array( __CLASS__, 'remove_comments_button' ), 5 );
// In the comments place let's display the product rating.
add_action( 'embed_content_meta', array( __CLASS__, 'get_ratings' ), 5 );
@ -41,6 +41,17 @@ class WC_Embed {
add_action( 'embed_head', array( __CLASS__, 'print_embed_styles' ) );
}
/**
* Remove comments button on product embeds.
*
* @since 2.6.0
*/
public static function remove_comments_button() {
if ( self::is_embedded_product() ) {
remove_action( 'embed_content_meta', 'print_embed_comments_button' );
}
}
/**
* Check if this is an embedded product - to make sure we don't mess up regular posts.
*

View File

@ -160,7 +160,7 @@ class WC_Frontend_Scripts {
// Register any scripts for later use, or used as dependencies
self::register_script( 'select2', $assets_path . 'js/select2/select2' . $suffix . '.js', array( 'jquery' ), '3.5.4' );
self::register_script( 'jquery-blockui', $assets_path . 'js/jquery-blockui/jquery.blockUI' . $suffix . '.js', array( 'jquery' ), '2.70' );
self::register_script( 'jquery-payment', $assets_path . 'js/jquery-payment/jquery.payment' . $suffix . '.js', array( 'jquery' ), '1.2.4' );
self::register_script( 'jquery-payment', $assets_path . 'js/jquery-payment/jquery.payment' . $suffix . '.js', array( 'jquery' ), '1.4.1' );
self::register_script( 'jquery-cookie', $assets_path . 'js/jquery-cookie/jquery.cookie' . $suffix . '.js', array( 'jquery' ), '1.4.1' );
self::register_script( 'wc-credit-card-form', $frontend_script_path . 'credit-card-form' . $suffix . '.js', array( 'jquery', 'jquery-payment' ) );
self::register_script( 'wc-add-to-cart-variation', $frontend_script_path . 'add-to-cart-variation' . $suffix . '.js', array( 'jquery', 'wp-util' ) );

View File

@ -150,17 +150,21 @@ class WC_Payment_Tokens {
*/
public static function get( $token_id, $token_result = null ) {
global $wpdb;
if ( is_null( $token_result ) ) {
$token_result = $wpdb->get_row( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}woocommerce_payment_tokens WHERE token_id = %d",
$token_id
) );
// Still empty? Token doesn't exist? Don't continue
if ( empty( $token_result ) ) {
return null;
}
}
$token_class = 'WC_Payment_Token_' . $token_result->type;
if ( class_exists( $token_class ) ) {
$meta = get_metadata( 'payment_token', $token_id );
$passed_meta = array();
@ -171,6 +175,8 @@ class WC_Payment_Tokens {
}
return new $token_class( $token_id, (array) $token_result, $passed_meta );
}
return null;
}
/**

View File

@ -196,11 +196,10 @@ class WC_Gateway_COD extends WC_Payment_Gateway {
* @return array
*/
public function process_payment( $order_id ) {
$order = wc_get_order( $order_id );
// Mark as processing (payment won't be taken until delivery)
$order->update_status( apply_filters( 'woocommerce_cod_process_payment_order_status', 'processing' ), __( 'Payment to be made upon delivery.', 'woocommerce' ) );
// Mark as processing or on-hold (payment won't be taken until delivery)
$order->update_status( apply_filters( 'woocommerce_cod_process_payment_order_status', $order->has_downloadable_item() ? 'on-hold' : 'processing', $order ), __( 'Payment to be made upon delivery.', 'woocommerce' ) );
// Reduce stock levels
$order->reduce_order_stock();

View File

@ -48,7 +48,7 @@ if ( ! class_exists( 'WP_Background_Process' ) ) {
$this->schedule_event();
// Perform remote post
parent::dispatch();
return parent::dispatch();
}
/**

View File

@ -120,12 +120,12 @@ class WC_Payment_Token_CC extends WC_Payment_Token {
}
/**
* Set the expiration month for the card (MM format).
* Set the expiration month for the card (formats into MM format).
* @since 2.6.0
* @param string $month
*/
public function set_expiry_month( $month ) {
$this->add_meta_data( 'expiry_month', $month, true );
$this->add_meta_data( 'expiry_month', str_pad( $month, 2, '0', STR_PAD_LEFT ), true );
}
/**

View File

@ -83,6 +83,20 @@ function wc_attribute_taxonomy_name_by_id( $attribute_id ) {
return '';
}
/**
* Get a product attribute ID by name.
*
* @since 2.6.0
* @param string $name Attribute name.
* @return int
*/
function wc_attribute_taxonomy_id_by_name( $name ) {
$name = str_replace( 'pa_', '', $name );
$taxonomies = wp_list_pluck( wc_get_attribute_taxonomies(), 'attribute_id', 'attribute_name' );
return isset( $taxonomies[ $name ] ) ? (int) $taxonomies[ $name ] : 0;
}
/**
* Get a product attributes label.
*

View File

@ -254,12 +254,17 @@ function wc_format_localized_decimal( $value ) {
}
/**
* Clean variables using sanitize_text_field.
* Clean variables using sanitize_text_field. Arrays are cleaned recursively.
* Non-scalar values are ignored.
* @param string|array $var
* @return string|array
*/
function wc_clean( $var ) {
return is_array( $var ) ? array_map( 'wc_clean', $var ) : sanitize_text_field( $var );
if ( is_array( $var ) ) {
return array_map( 'wc_clean', $var );
} else {
return is_scalar( $var ) ? sanitize_text_field( $var ) : $var;
}
}
/**

View File

@ -1215,7 +1215,7 @@ if ( ! function_exists( 'woocommerce_review_display_comment_text' ) ) {
* @return void
*/
function woocommerce_review_display_comment_text() {
echo '<div itemprop="description" class="description">' . comment_text() . '</div>';
echo '<div itemprop="description" class="description">' . get_comment_text() . '</div>';
}
}

View File

@ -33,7 +33,7 @@ do_action( 'woocommerce_account_navigation' ); ?>
<?php do_action( 'woocommerce_before_edit_account_form' ); ?>
<form class="woocommerce-EditAccountForm" action="" method="post">
<form class="woocommerce-EditAccountForm edit-account" action="" method="post">
<?php do_action( 'woocommerce_edit_account_form_start' ); ?>

View File

@ -68,7 +68,6 @@ if ( ! comments_open() ) {
$comment_form = array(
'title_reply' => have_comments() ? __( 'Add a review', 'woocommerce' ) : sprintf( __( 'Be the first to review &ldquo;%s&rdquo;', 'woocommerce' ), get_the_title() ),
'title_reply_to' => __( 'Leave a Reply to %s', 'woocommerce' ),
'comment_notes_before' => '',
'comment_notes_after' => '',
'fields' => array(
'author' => '<p class="comment-form-author">' . '<label for="author">' . __( 'Name', 'woocommerce' ) . ' <span class="required">*</span></label> ' .

View File

@ -41,7 +41,7 @@ class WC_Tests_Payment_Token_CC extends WC_Unit_Test_Case {
$this->assertTrue( $token->validate() );
$token->set_expiry_month( '8' );
$token->set_expiry_month( '888' );
$this->assertFalse( $token->validate() );
}

View File

@ -3,7 +3,7 @@
* Plugin Name: WooCommerce
* Plugin URI: https://www.woothemes.com/woocommerce/
* Description: An e-commerce toolkit that helps you sell anything. Beautifully.
* Version: 2.6.0-beta-3
* Version: 2.6.0-beta-4
* Author: WooThemes
* Author URI: https://woothemes.com
* Requires at least: 4.1