Merge branch 'master' of github.com:woothemes/woocommerce

This commit is contained in:
Nicola Mustone 2015-07-29 15:03:10 +02:00
commit 04d7e10982
75 changed files with 2241 additions and 1807 deletions

View File

@ -1,4 +1,4 @@
# [WooCommerce](http://www.woothemes.com/woocommerce/) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) [![Build Status](https://api.travis-ci.org/woothemes/woocommerce.svg?branch=master)](http://travis-ci.org/woothemes/woocommerce) [![Coverage Status](https://img.shields.io/coveralls/woothemes/woocommerce.svg)](https://coveralls.io/r/woothemes/woocommerce)
# [WooCommerce](http://www.woothemes.com/woocommerce/) [![Built with Grunt](https://cdn.gruntjs.com/builtwith.png)](http://gruntjs.com/) [![Build Status](https://api.travis-ci.org/woothemes/woocommerce.svg?branch=master)](http://travis-ci.org/woothemes/woocommerce) [![Coverage Status](https://coveralls.io/repos/woothemes/woocommerce/badge.svg?branch=master&service=github)](https://coveralls.io/github/woothemes/woocommerce?branch=master)
Welcome to the WooCommerce repository on GitHub. Here you can browse the source, look at open issues and keep track of development. We recommend all developers to follow the [WooCommerce development blog](http://develop.woothemes.com/woocommerce/) to stay up to date about everything happening in the project. You can also [follow @DevelopWC](https://twitter.com/DevelopWC) on Twitter for the latest development updates.

View File

@ -391,7 +391,7 @@ jQuery( function( $ ) {
url: woocommerce_admin_meta_boxes_variations.ajax_url,
data: data,
type: 'POST',
success: function() {
success: function( response ) {
// Allow change page, delete and add new variations
need_update.removeClass( 'variation-needs-update' );
$( 'button.cancel-variation-changes, button.save-variation-changes' ).attr( 'disabled', 'disabled' );
@ -399,7 +399,7 @@ jQuery( function( $ ) {
$( '#woocommerce-product-data' ).trigger( 'woocommerce_variations_saved' );
if ( typeof callback === 'function' ) {
callback();
callback( response );
}
wc_meta_boxes_product_variations_ajax.unblock();
@ -416,8 +416,15 @@ jQuery( function( $ ) {
save_variations: function() {
$( '#variable_product_options' ).trigger( 'woocommerce_variations_save_variations_button' );
wc_meta_boxes_product_variations_ajax.save_changes( function() {
var current = $( '#variable_product_options .woocommerce_variations' ).attr( 'data-page' );
wc_meta_boxes_product_variations_ajax.save_changes( function( error ) {
var wrapper = $( '#variable_product_options .woocommerce_variations' ),
current = wrapper.attr( 'data-page' );
$( '#variable_product_options #woocommerce_errors' ).remove();
if ( error ) {
wrapper.before( error );
}
$( '.variations-defaults select' ).each( function() {
$( this ).attr( 'data-current', $( this ).val() );
@ -666,6 +673,7 @@ jQuery( function( $ ) {
break;
default :
$( 'select.variation_actions' ).trigger( do_variation_action );
data = $( 'select.variation_actions' ).triggerHandler( do_variation_action + '_ajax_data', data );
break;
}

File diff suppressed because one or more lines are too long

View File

@ -520,7 +520,6 @@ jQuery( function( $ ) {
jQuery( '.add_product_images' ).on( 'click', 'a', function( event ) {
var $el = $( this );
var attachment_ids = $image_gallery_ids.val();
event.preventDefault();
@ -549,12 +548,13 @@ jQuery( function( $ ) {
// When an image is selected, run a callback.
product_gallery_frame.on( 'select', function() {
var selection = product_gallery_frame.state().get( 'selection' );
var attachment_ids = $image_gallery_ids.val();
selection.map( function( attachment ) {
attachment = attachment.toJSON();
if ( attachment.id ) {
var attachment_ids = attachment_ids ? attachment_ids + ',' + attachment.id : attachment.id;
attachment_ids = attachment_ids ? attachment_ids + ',' + attachment.id : attachment.id;
var attachment_image = attachment.sizes.thumbnail ? attachment.sizes.thumbnail.url : attachment.url;
$product_images.append( '<li class="image" data-attachment_id="' + attachment.id + '"><img src="' + attachment_image + '" /><ul class="actions"><li><a href="#" class="delete" title="' + $el.data('delete') + '">' + $el.data('text') + '</a></li></ul></li>' );

File diff suppressed because one or more lines are too long

View File

@ -94,7 +94,8 @@ jQuery( function( $ ) {
return {
term: term,
action: $( this ).data( 'action' ) || 'woocommerce_json_search_products_and_variations',
security: wc_enhanced_select_params.search_products_nonce
security: wc_enhanced_select_params.search_products_nonce,
exclude: $( this ).data( 'exclude' )
};
},
results: function( data ) {
@ -104,7 +105,9 @@ jQuery( function( $ ) {
terms.push( { id: id, text: text } );
});
}
return { results: terms };
return {
results: terms
};
},
cache: true
}
@ -117,7 +120,10 @@ jQuery( function( $ ) {
var selected = [];
$( element.val().split( ',' ) ).each( function( i, val ) {
selected.push( { id: val, text: data[ val ] } );
selected.push({
id: val,
text: data[ val ]
});
});
return callback( selected );
};
@ -127,7 +133,10 @@ jQuery( function( $ ) {
} else {
select2_args.multiple = false;
select2_args.initSelection = function( element, callback ) {
var data = {id: element.val(), text: element.attr( 'data-selected' )};
var data = {
id: element.val(),
text: element.attr( 'data-selected' )
};
return callback( data );
};
}
@ -161,7 +170,10 @@ jQuery( function( $ ) {
var terms = [];
if ( data ) {
$.each( data, function( id, text ) {
terms.push( { id: id, text: text } );
terms.push({
id: id,
text: text
});
});
}
return { results: terms };
@ -176,7 +188,10 @@ jQuery( function( $ ) {
var selected = [];
$( element.val().split( ',' ) ).each( function( i, val ) {
selected.push( { id: val, text: data[ val ] } );
selected.push({
id: val,
text: data[ val ]
});
});
return callback( selected );
};
@ -186,7 +201,10 @@ jQuery( function( $ ) {
} else {
select2_args.multiple = false;
select2_args.initSelection = function( element, callback ) {
var data = {id: element.val(), text: element.attr( 'data-selected' )};
var data = {
id: element.val(),
text: element.attr( 'data-selected' )
};
return callback( data );
};
}

View File

@ -1 +1 @@
jQuery(function(a){function b(){var a={formatMatches:function(a){return 1===a?wc_enhanced_select_params.i18n_matches_1:wc_enhanced_select_params.i18n_matches_n.replace("%qty%",a)},formatNoMatches:function(){return wc_enhanced_select_params.i18n_no_matches},formatAjaxError:function(){return wc_enhanced_select_params.i18n_ajax_error},formatInputTooShort:function(a,b){var c=b-a.length;return 1===c?wc_enhanced_select_params.i18n_input_too_short_1:wc_enhanced_select_params.i18n_input_too_short_n.replace("%qty%",c)},formatInputTooLong:function(a,b){var c=a.length-b;return 1===c?wc_enhanced_select_params.i18n_input_too_long_1:wc_enhanced_select_params.i18n_input_too_long_n.replace("%qty%",c)},formatSelectionTooBig:function(a){return 1===a?wc_enhanced_select_params.i18n_selection_too_long_1:wc_enhanced_select_params.i18n_selection_too_long_n.replace("%qty%",a)},formatLoadMore:function(){return wc_enhanced_select_params.i18n_load_more},formatSearching:function(){return wc_enhanced_select_params.i18n_searching}};return a}a(document.body).on("wc-enhanced-select-init",function(){a(":input.wc-enhanced-select, :input.chosen_select").filter(":not(.enhanced)").each(function(){var c=a.extend({minimumResultsForSearch:10,allowClear:a(this).data("allow_clear")?!0:!1,placeholder:a(this).data("placeholder")},b());a(this).select2(c).addClass("enhanced")}),a(":input.wc-enhanced-select-nostd, :input.chosen_select_nostd").filter(":not(.enhanced)").each(function(){var c=a.extend({minimumResultsForSearch:10,allowClear:!0,placeholder:a(this).data("placeholder")},b());a(this).select2(c).addClass("enhanced")}),a(":input.wc-product-search").filter(":not(.enhanced)").each(function(){var c={allowClear:a(this).data("allow_clear")?!0:!1,placeholder:a(this).data("placeholder"),minimumInputLength:a(this).data("minimum_input_length")?a(this).data("minimum_input_length"):"3",escapeMarkup:function(a){return a},ajax:{url:wc_enhanced_select_params.ajax_url,dataType:"json",quietMillis:250,data:function(b){return{term:b,action:a(this).data("action")||"woocommerce_json_search_products_and_variations",security:wc_enhanced_select_params.search_products_nonce}},results:function(b){var c=[];return b&&a.each(b,function(a,b){c.push({id:a,text:b})}),{results:c}},cache:!0}};a(this).data("multiple")===!0?(c.multiple=!0,c.initSelection=function(b,c){var d=a.parseJSON(b.attr("data-selected")),e=[];return a(b.val().split(",")).each(function(a,b){e.push({id:b,text:d[b]})}),c(e)},c.formatSelection=function(a){return'<div class="selected-option" data-id="'+a.id+'">'+a.text+"</div>"}):(c.multiple=!1,c.initSelection=function(a,b){var c={id:a.val(),text:a.attr("data-selected")};return b(c)}),c=a.extend(c,b()),a(this).select2(c).addClass("enhanced")}),a(":input.wc-customer-search").filter(":not(.enhanced)").each(function(){var c={allowClear:a(this).data("allow_clear")?!0:!1,placeholder:a(this).data("placeholder"),minimumInputLength:a(this).data("minimum_input_length")?a(this).data("minimum_input_length"):"3",escapeMarkup:function(a){return a},ajax:{url:wc_enhanced_select_params.ajax_url,dataType:"json",quietMillis:250,data:function(a){return{term:a,action:"woocommerce_json_search_customers",security:wc_enhanced_select_params.search_customers_nonce}},results:function(b){var c=[];return b&&a.each(b,function(a,b){c.push({id:a,text:b})}),{results:c}},cache:!0}};a(this).data("multiple")===!0?(c.multiple=!0,c.initSelection=function(b,c){var d=a.parseJSON(b.attr("data-selected")),e=[];return a(b.val().split(",")).each(function(a,b){e.push({id:b,text:d[b]})}),c(e)},c.formatSelection=function(a){return'<div class="selected-option" data-id="'+a.id+'">'+a.text+"</div>"}):(c.multiple=!1,c.initSelection=function(a,b){var c={id:a.val(),text:a.attr("data-selected")};return b(c)}),c=a.extend(c,b()),a(this).select2(c).addClass("enhanced")})}).on("wc_backbone_modal_before_remove",function(){a(":input.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search").select2("close")}).trigger("wc-enhanced-select-init")});
jQuery(function(a){function b(){var a={formatMatches:function(a){return 1===a?wc_enhanced_select_params.i18n_matches_1:wc_enhanced_select_params.i18n_matches_n.replace("%qty%",a)},formatNoMatches:function(){return wc_enhanced_select_params.i18n_no_matches},formatAjaxError:function(){return wc_enhanced_select_params.i18n_ajax_error},formatInputTooShort:function(a,b){var c=b-a.length;return 1===c?wc_enhanced_select_params.i18n_input_too_short_1:wc_enhanced_select_params.i18n_input_too_short_n.replace("%qty%",c)},formatInputTooLong:function(a,b){var c=a.length-b;return 1===c?wc_enhanced_select_params.i18n_input_too_long_1:wc_enhanced_select_params.i18n_input_too_long_n.replace("%qty%",c)},formatSelectionTooBig:function(a){return 1===a?wc_enhanced_select_params.i18n_selection_too_long_1:wc_enhanced_select_params.i18n_selection_too_long_n.replace("%qty%",a)},formatLoadMore:function(){return wc_enhanced_select_params.i18n_load_more},formatSearching:function(){return wc_enhanced_select_params.i18n_searching}};return a}a(document.body).on("wc-enhanced-select-init",function(){a(":input.wc-enhanced-select, :input.chosen_select").filter(":not(.enhanced)").each(function(){var c=a.extend({minimumResultsForSearch:10,allowClear:a(this).data("allow_clear")?!0:!1,placeholder:a(this).data("placeholder")},b());a(this).select2(c).addClass("enhanced")}),a(":input.wc-enhanced-select-nostd, :input.chosen_select_nostd").filter(":not(.enhanced)").each(function(){var c=a.extend({minimumResultsForSearch:10,allowClear:!0,placeholder:a(this).data("placeholder")},b());a(this).select2(c).addClass("enhanced")}),a(":input.wc-product-search").filter(":not(.enhanced)").each(function(){var c={allowClear:a(this).data("allow_clear")?!0:!1,placeholder:a(this).data("placeholder"),minimumInputLength:a(this).data("minimum_input_length")?a(this).data("minimum_input_length"):"3",escapeMarkup:function(a){return a},ajax:{url:wc_enhanced_select_params.ajax_url,dataType:"json",quietMillis:250,data:function(b){return{term:b,action:a(this).data("action")||"woocommerce_json_search_products_and_variations",security:wc_enhanced_select_params.search_products_nonce,exclude:a(this).data("exclude")}},results:function(b){var c=[];return b&&a.each(b,function(a,b){c.push({id:a,text:b})}),{results:c}},cache:!0}};a(this).data("multiple")===!0?(c.multiple=!0,c.initSelection=function(b,c){var d=a.parseJSON(b.attr("data-selected")),e=[];return a(b.val().split(",")).each(function(a,b){e.push({id:b,text:d[b]})}),c(e)},c.formatSelection=function(a){return'<div class="selected-option" data-id="'+a.id+'">'+a.text+"</div>"}):(c.multiple=!1,c.initSelection=function(a,b){var c={id:a.val(),text:a.attr("data-selected")};return b(c)}),c=a.extend(c,b()),a(this).select2(c).addClass("enhanced")}),a(":input.wc-customer-search").filter(":not(.enhanced)").each(function(){var c={allowClear:a(this).data("allow_clear")?!0:!1,placeholder:a(this).data("placeholder"),minimumInputLength:a(this).data("minimum_input_length")?a(this).data("minimum_input_length"):"3",escapeMarkup:function(a){return a},ajax:{url:wc_enhanced_select_params.ajax_url,dataType:"json",quietMillis:250,data:function(a){return{term:a,action:"woocommerce_json_search_customers",security:wc_enhanced_select_params.search_customers_nonce}},results:function(b){var c=[];return b&&a.each(b,function(a,b){c.push({id:a,text:b})}),{results:c}},cache:!0}};a(this).data("multiple")===!0?(c.multiple=!0,c.initSelection=function(b,c){var d=a.parseJSON(b.attr("data-selected")),e=[];return a(b.val().split(",")).each(function(a,b){e.push({id:b,text:d[b]})}),c(e)},c.formatSelection=function(a){return'<div class="selected-option" data-id="'+a.id+'">'+a.text+"</div>"}):(c.multiple=!1,c.initSelection=function(a,b){var c={id:a.val(),text:a.attr("data-selected")};return b(c)}),c=a.extend(c,b()),a(this).select2(c).addClass("enhanced")})}).on("wc_backbone_modal_before_remove",function(){a(":input.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search").select2("close")}).trigger("wc-enhanced-select-init")});

View File

@ -29,6 +29,12 @@
return false;
} )
// Reload product variations data
.on( 'reload_product_variations', function() {
$product_variations = $form.data( 'product_variations' );
$use_ajax = $product_variations === false;
} )
// Reset product data
.on( 'reset_data', function() {
var to_reset = {
@ -102,7 +108,7 @@
data.product_id = $product_id;
$xhr = $.ajax( {
url: wc_cart_fragments_params.wc_ajax_url + 'get_variation/',
url: wc_cart_fragments_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_variation' ),
type: 'POST',
data: data,
success: function( variation ) {

File diff suppressed because one or more lines are too long

View File

@ -31,7 +31,7 @@ jQuery( function( $ ) {
$( document.body ).trigger( 'adding_to_cart', [ $thisbutton, data ] );
// Ajax action
$.post( wc_add_to_cart_params.wc_ajax_url + 'add_to_cart/', data, function( response ) {
$.post( wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'add_to_cart' ), data, function( response ) {
if ( ! response ) {
return;

View File

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

View File

@ -95,13 +95,23 @@ jQuery( function( $ ) {
}
}
if ( key !== 'state' ) {
if ( 'state' !== key ) {
if ( typeof locale['default'][ key ].hidden === 'undefined' || locale['default'][ key ].hidden === false ) {
field.show();
} else if ( locale['default'][ key ].hidden === true ) {
field.hide().find( 'input' ).val( '' );
}
}
if ( 'postcode' === key ) {
if ( locale['default'][ key ].label ) {
field.find( 'label' ).html( locale['default'][ key ].label );
}
if ( locale['default'][ key ].placeholder ) {
field.find( 'input' ).attr( 'placeholder', locale['default'][ key ].placeholder );
}
}
}
});

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]&&(d["default"][a].required===!0&&0===e.find("label abbr").size()&&b(e,!0),"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("")))})})});
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]&&(d["default"][a].required===!0&&0===e.find("label abbr").size()&&b(e,!0),"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&&(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)))})})});

View File

@ -18,7 +18,7 @@ jQuery( function( $ ) {
}
var $fragment_refresh = {
url: wc_cart_fragments_params.wc_ajax_url + 'get_refreshed_fragments/',
url: wc_cart_fragments_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_refreshed_fragments' ),
type: 'POST',
success: function( data ) {
if ( data && data.fragments ) {

View File

@ -1 +1 @@
jQuery(function(a){if("undefined"==typeof wc_cart_fragments_params)return!1;var b;try{b="sessionStorage"in window&&null!==window.sessionStorage,window.sessionStorage.setItem("wc","test"),window.sessionStorage.removeItem("wc")}catch(c){b=!1}var d={url:wc_cart_fragments_params.wc_ajax_url+"get_refreshed_fragments/",type:"POST",success:function(c){c&&c.fragments&&(a.each(c.fragments,function(b,c){a(b).replaceWith(c)}),b&&(sessionStorage.setItem(wc_cart_fragments_params.fragment_name,JSON.stringify(c.fragments)),sessionStorage.setItem("wc_cart_hash",c.cart_hash)),a(document.body).trigger("wc_fragments_refreshed"))}};if(b){a(document.body).bind("added_to_cart",function(a,b,c){sessionStorage.setItem(wc_cart_fragments_params.fragment_name,JSON.stringify(b)),sessionStorage.setItem("wc_cart_hash",c)});try{var e=a.parseJSON(sessionStorage.getItem(wc_cart_fragments_params.fragment_name)),f=sessionStorage.getItem("wc_cart_hash"),g=a.cookie("woocommerce_cart_hash");if((null===f||void 0===f||""===f)&&(f=""),(null===g||void 0===g||""===g)&&(g=""),!e||!e["div.widget_shopping_cart_content"]||f!==g)throw"No fragment";a.each(e,function(b,c){a(b).replaceWith(c)}),a(document.body).trigger("wc_fragments_loaded")}catch(c){a.ajax(d)}}else a.ajax(d);a.cookie("woocommerce_items_in_cart")>0?a(".hide_cart_widget_if_empty").closest(".widget_shopping_cart").show():a(".hide_cart_widget_if_empty").closest(".widget_shopping_cart").hide(),a(document.body).bind("adding_to_cart",function(){a(".hide_cart_widget_if_empty").closest(".widget_shopping_cart").show()})});
jQuery(function(a){if("undefined"==typeof wc_cart_fragments_params)return!1;var b;try{b="sessionStorage"in window&&null!==window.sessionStorage,window.sessionStorage.setItem("wc","test"),window.sessionStorage.removeItem("wc")}catch(c){b=!1}var d={url:wc_cart_fragments_params.wc_ajax_url.toString().replace("%%endpoint%%","get_refreshed_fragments"),type:"POST",success:function(c){c&&c.fragments&&(a.each(c.fragments,function(b,c){a(b).replaceWith(c)}),b&&(sessionStorage.setItem(wc_cart_fragments_params.fragment_name,JSON.stringify(c.fragments)),sessionStorage.setItem("wc_cart_hash",c.cart_hash)),a(document.body).trigger("wc_fragments_refreshed"))}};if(b){a(document.body).bind("added_to_cart",function(a,b,c){sessionStorage.setItem(wc_cart_fragments_params.fragment_name,JSON.stringify(b)),sessionStorage.setItem("wc_cart_hash",c)});try{var e=a.parseJSON(sessionStorage.getItem(wc_cart_fragments_params.fragment_name)),f=sessionStorage.getItem("wc_cart_hash"),g=a.cookie("woocommerce_cart_hash");if((null===f||void 0===f||""===f)&&(f=""),(null===g||void 0===g||""===g)&&(g=""),!e||!e["div.widget_shopping_cart_content"]||f!==g)throw"No fragment";a.each(e,function(b,c){a(b).replaceWith(c)}),a(document.body).trigger("wc_fragments_loaded")}catch(c){a.ajax(d)}}else a.ajax(d);a.cookie("woocommerce_items_in_cart")>0?a(".hide_cart_widget_if_empty").closest(".widget_shopping_cart").show():a(".hide_cart_widget_if_empty").closest(".widget_shopping_cart").hide(),a(document.body).bind("adding_to_cart",function(){a(".hide_cart_widget_if_empty").closest(".widget_shopping_cart").show()})});

View File

@ -30,7 +30,7 @@ jQuery( function( $ ) {
shipping_method: shipping_methods
};
$.post( wc_cart_params.wc_ajax_url + 'update_shipping_method/', data, function( response ) {
$.post( wc_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'update_shipping_method' ), data, function( response ) {
$( 'div.cart_totals' ).replaceWith( response );
$( document.body ).trigger( 'updated_shipping_method' );
});

View File

@ -1 +1 @@
jQuery(function(a){return"undefined"==typeof wc_cart_params?!1:(a(document).on("click",".shipping-calculator-button",function(){return a(".shipping-calculator-form").slideToggle("slow"),!1}).on("change","select.shipping_method, input[name^=shipping_method]",function(){var b=[];a("select.shipping_method, input[name^=shipping_method][type=radio]:checked, input[name^=shipping_method][type=hidden]").each(function(){b[a(this).data("index")]=a(this).val()}),a("div.cart_totals").block({message:null,overlayCSS:{background:"#fff",opacity:.6}});var c={security:wc_cart_params.update_shipping_method_nonce,shipping_method:b};a.post(wc_cart_params.wc_ajax_url+"update_shipping_method/",c,function(b){a("div.cart_totals").replaceWith(b),a(document.body).trigger("updated_shipping_method")})}),void a(".shipping-calculator-form").hide())});
jQuery(function(a){return"undefined"==typeof wc_cart_params?!1:(a(document).on("click",".shipping-calculator-button",function(){return a(".shipping-calculator-form").slideToggle("slow"),!1}).on("change","select.shipping_method, input[name^=shipping_method]",function(){var b=[];a("select.shipping_method, input[name^=shipping_method][type=radio]:checked, input[name^=shipping_method][type=hidden]").each(function(){b[a(this).data("index")]=a(this).val()}),a("div.cart_totals").block({message:null,overlayCSS:{background:"#fff",opacity:.6}});var c={security:wc_cart_params.update_shipping_method_nonce,shipping_method:b};a.post(wc_cart_params.wc_ajax_url.toString().replace("%%endpoint%%","update_shipping_method"),c,function(b){a("div.cart_totals").replaceWith(b),a(document.body).trigger("updated_shipping_method")})}),void a(".shipping-calculator-form").hide())});

View File

@ -241,7 +241,7 @@ jQuery( function( $ ) {
wc_checkout_form.xhr = $.ajax({
type: 'POST',
url: wc_checkout_params.wc_ajax_url + 'update_order_review/',
url: wc_checkout_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'update_order_review' ),
data: data,
success: function( data ) {
// Always update the fragments
@ -410,7 +410,7 @@ jQuery( function( $ ) {
$.ajax({
type: 'POST',
url: wc_checkout_params.wc_ajax_url + 'apply_coupon/',
url: wc_checkout_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'apply_coupon' ),
data: data,
success: function( code ) {
$( '.woocommerce-error, .woocommerce-message' ).remove();
@ -449,7 +449,7 @@ jQuery( function( $ ) {
$.ajax({
type: 'POST',
url: wc_checkout_params.wc_ajax_url + 'remove_coupon/',
url: wc_checkout_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'remove_coupon' ),
data: data,
success: function( code ) {
$( '.woocommerce-error, .woocommerce-message' ).remove();

File diff suppressed because one or more lines are too long

View File

@ -31,7 +31,7 @@ jQuery( function( $ ) {
};
var $geolocate_customer = {
url: wc_geolocation_params.wc_ajax_url + 'get_customer_location/',
url: wc_geolocation_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_customer_location' ),
type: 'GET',
success: function( response ) {
if ( response.success && response.data.hash && response.data.hash !== wc_geolocation_params.hash ) {

View File

@ -1 +1 @@
jQuery(function(a){var b=window.location.toString(),c=function(){wc_geolocation_params.hash&&a('a[href^="'+wc_geolocation_params.home_url+'"]:not(a[href*="v="]), a[href^="/"]:not(a[href*="v="])').each(function(){var b=a(this),c=b.attr("href");c.indexOf("?")>0?b.attr("href",c+"&v="+wc_geolocation_params.hash):b.attr("href",c+"?v="+wc_geolocation_params.hash)})},d=function(a){b=b.indexOf("?v=")>0||b.indexOf("&v=")>0?b.replace(/v=[^&]+/,"v="+a):b.indexOf("?")>0?b+"&v="+a:b+"?v="+a,window.location=b},e={url:wc_geolocation_params.wc_ajax_url+"get_customer_location/",type:"GET",success:function(a){a.success&&a.data.hash&&a.data.hash!==wc_geolocation_params.hash&&d(a.data.hash)}};"1"!==wc_geolocation_params.is_checkout&&a.ajax(e),a(document.body).on("added_to_cart",function(){c()}),c()});
jQuery(function(a){var b=window.location.toString(),c=function(){wc_geolocation_params.hash&&a('a[href^="'+wc_geolocation_params.home_url+'"]:not(a[href*="v="]), a[href^="/"]:not(a[href*="v="])').each(function(){var b=a(this),c=b.attr("href");c.indexOf("?")>0?b.attr("href",c+"&v="+wc_geolocation_params.hash):b.attr("href",c+"?v="+wc_geolocation_params.hash)})},d=function(a){b=b.indexOf("?v=")>0||b.indexOf("&v=")>0?b.replace(/v=[^&]+/,"v="+a):b.indexOf("?")>0?b+"&v="+a:b+"?v="+a,window.location=b},e={url:wc_geolocation_params.wc_ajax_url.toString().replace("%%endpoint%%","get_customer_location"),type:"GET",success:function(a){a.success&&a.data.hash&&a.data.hash!==wc_geolocation_params.hash&&d(a.data.hash)}};"1"!==wc_geolocation_params.is_checkout&&a.ajax(e),a(document.body).on("added_to_cart",function(){c()}),c()});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -35,9 +35,9 @@ $states['JP'] = array(
'JP23' => __( 'Aichi', 'woocommerce' ),
'JP24' => __( 'Mie', 'woocommerce' ),
'JP25' => __( 'Shiga', 'woocommerce' ),
'JP26' => __( 'Kyouto', 'woocommerce' ),
'JP26' => __( 'Kyoto', 'woocommerce' ),
'JP27' => __( 'Osaka', 'woocommerce' ),
'JP28' => __( 'Hyougo', 'woocommerce' ),
'JP28' => __( 'Hyogo', 'woocommerce' ),
'JP29' => __( 'Nara', 'woocommerce' ),
'JP30' => __( 'Wakayama', 'woocommerce' ),
'JP31' => __( 'Tottori', 'woocommerce' ),

View File

@ -1180,36 +1180,27 @@ abstract class WC_Abstract_Order {
}
/**
* Gets order total - formatted for display.
*
* @param string $type
* Gets the count of order items of a certain type.
*
* @param string $item_type
* @return string
*/
public function get_item_count( $type = '' ) {
if ( empty( $type ) ) {
$type = array( 'line_item' );
public function get_item_count( $item_type = '' ) {
if ( empty( $item_type ) ) {
$item_type = array( 'line_item' );
}
if ( ! is_array( $item_type ) ) {
$item_type = array( $item_type );
}
if ( ! is_array( $type ) ) {
$type = array( $type );
}
$items = $this->get_items( $type );
$items = $this->get_items( $item_type );
$count = 0;
foreach ( $items as $item ) {
if ( ! empty( $item['qty'] ) ) {
$count += $item['qty'];
} else {
$count ++;
}
$count += empty( $item['qty'] ) ? 1 : $item['qty'];
}
return apply_filters( 'woocommerce_get_item_count', $count, $type, $this );
return apply_filters( 'woocommerce_get_item_count', $count, $item_type, $this );
}
/**
@ -1859,7 +1850,7 @@ abstract class WC_Abstract_Order {
if ( 'excl' == $tax_display ) {
$total_rows[ 'fee_' . $id ] = array(
'label' => $fee['name'] . ':',
'label' => ( $fee['name'] ? $fee['name'] : __( 'Fee', 'woocommerce' ) ) . ':',
'value' => wc_price( $fee['line_total'], array('currency' => $this->get_order_currency()) )
);

View File

@ -192,14 +192,15 @@ class WC_Product {
/**
* Check if the stock status needs changing
*/
protected function check_stock_status() {
// Update stock status
public function check_stock_status() {
if ( ! $this->backorders_allowed() && $this->get_total_stock() <= get_option( 'woocommerce_notify_no_stock_amount' ) ) {
$this->set_stock_status( 'outofstock' );
if ( $this->stock_status !== 'outofstock' ) {
$this->set_stock_status( 'outofstock' );
}
} elseif ( $this->backorders_allowed() || $this->get_total_stock() > get_option( 'woocommerce_notify_no_stock_amount' ) ) {
$this->set_stock_status( 'instock' );
if ( $this->stock_status !== 'instock' ) {
$this->set_stock_status( 'instock' );
}
}
}
@ -560,7 +561,6 @@ class WC_Product {
* @return bool
*/
public function is_in_stock() {
if ( $this->managing_stock() && $this->backorders_allowed() ) {
return true;
} elseif ( $this->managing_stock() && $this->get_total_stock() <= get_option( 'woocommerce_notify_no_stock_amount' ) ) {

View File

@ -3,7 +3,7 @@
* Admin Settings API used by Shipping Methods and Payment Gateways
*
* @class WC_Settings_API
* @version 2.3.0
* @version 2.4.0
* @package WooCommerce/Abstracts
* @category Abstract Class
* @author WooThemes
@ -849,12 +849,13 @@ abstract class WC_Settings_API {
$text = $this->get_option( $key );
$field = $this->get_field_key( $key );
$value = trim( stripslashes( $_POST[ $field ] ) );
if ( isset( $_POST[ $field ] ) ) {
$text = wc_clean( stripslashes( $_POST[ $field ] ) );
$text = wp_kses_post( $value );
}
return $text;
return $text === $value ? $text : '';
}
/**

View File

@ -158,7 +158,7 @@ class WC_Admin_API_Keys_Table_List extends WP_List_Table {
return apply_filters( 'woocommerce_api_key_last_access_datetime', $date, $key['last_access'] );
}
return __( 'Unknown' );
return __( 'Unknown', 'woocommerce' );
}
/**

View File

@ -20,7 +20,7 @@ if ( ! defined( 'ABSPATH' ) ) {
class WC_Admin_Meta_Boxes {
private static $saved_meta_boxes = false;
private static $meta_box_errors = array();
public static $meta_box_errors = array();
/**
* Constructor

View File

@ -2,10 +2,10 @@
/**
* Post Types Admin
*
* @author WooThemes
* @category Admin
* @package WooCommerce/Admin
* @version 2.3.0
* @author WooThemes
* @category Admin
* @package WooCommerce/Admin
* @version 2.4.0
*/
if ( ! defined( 'ABSPATH' ) ) {
@ -46,6 +46,9 @@ class WC_Admin_Post_Types {
add_filter( 'bulk_actions-edit-shop_order', array( $this, 'shop_order_bulk_actions' ) );
add_filter( 'list_table_primary_column', array( $this, 'list_table_primary_column' ), 10, 2 );
add_filter( 'post_row_actions', array( $this, 'row_actions' ), 2, 100 );
// Views
add_filter( 'views_edit-product', array( $this, 'product_sorting_link' ) );
@ -93,6 +96,9 @@ class WC_Admin_Post_Types {
// Download permissions
add_action( 'woocommerce_process_product_file_download_paths', array( $this, 'process_product_file_download_paths' ), 10, 3 );
// Disable DFW feature pointer
add_action( 'admin_footer', array( $this, 'disable_dfw_feature_pointer' ) );
}
/**
@ -265,7 +271,8 @@ class WC_Admin_Post_Types {
/**
* Ouput custom columns for products
* @param string $column
*
* @param string $column
*/
public function render_product_columns( $column ) {
global $post, $the_product;
@ -279,12 +286,10 @@ class WC_Admin_Post_Types {
echo '<a href="' . get_edit_post_link( $post->ID ) . '">' . $the_product->get_image( 'thumbnail' ) . '</a>';
break;
case 'name' :
$edit_link = get_edit_post_link( $post->ID );
$title = _draft_or_post_title();
$post_type_object = get_post_type_object( $post->post_type );
$can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID );
$edit_link = get_edit_post_link( $post->ID );
$title = _draft_or_post_title();
echo '<strong><a class="row-title" href="' . esc_url( $edit_link ) .'">' . $title.'</a>';
echo '<strong><a class="row-title" href="' . esc_url( $edit_link ) .'">' . $title .'</a>';
_post_states( $post );
@ -299,48 +304,7 @@ class WC_Admin_Post_Types {
echo apply_filters( 'the_excerpt', $post->post_excerpt );
}
// Get actions
$actions = array();
$actions['id'] = 'ID: ' . $post->ID;
if ( $can_edit_post && 'trash' != $post->post_status ) {
$actions['edit'] = '<a href="' . get_edit_post_link( $post->ID, true ) . '" title="' . esc_attr( __( 'Edit this item', 'woocommerce' ) ) . '">' . __( 'Edit', 'woocommerce' ) . '</a>';
$actions['inline hide-if-no-js'] = '<a href="#" class="editinline" title="' . esc_attr( __( 'Edit this item inline', 'woocommerce' ) ) . '">' . __( 'Quick&nbsp;Edit', 'woocommerce' ) . '</a>';
}
if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) {
if ( 'trash' == $post->post_status ) {
$actions['untrash'] = '<a title="' . esc_attr( __( 'Restore this item from the Trash', 'woocommerce' ) ) . '" href="' . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ) . '">' . __( 'Restore', 'woocommerce' ) . '</a>';
} elseif ( EMPTY_TRASH_DAYS ) {
$actions['trash'] = '<a class="submitdelete" title="' . esc_attr( __( 'Move this item to the Trash', 'woocommerce' ) ) . '" href="' . get_delete_post_link( $post->ID ) . '">' . __( 'Trash', 'woocommerce' ) . '</a>';
}
if ( 'trash' == $post->post_status || ! EMPTY_TRASH_DAYS ) {
$actions['delete'] = '<a class="submitdelete" title="' . esc_attr( __( 'Delete this item permanently', 'woocommerce' ) ) . '" href="' . get_delete_post_link( $post->ID, '', true ) . '">' . __( 'Delete Permanently', 'woocommerce' ) . '</a>';
}
}
if ( $post_type_object->public ) {
if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) {
if ( $can_edit_post )
$actions['view'] = '<a href="' . esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) . '" title="' . esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;', 'woocommerce' ), $title ) ) . '" rel="permalink">' . __( 'Preview', 'woocommerce' ) . '</a>';
} elseif ( 'trash' != $post->post_status ) {
$actions['view'] = '<a href="' . get_permalink( $post->ID ) . '" title="' . esc_attr( sprintf( __( 'View &#8220;%s&#8221;', 'woocommerce' ), $title ) ) . '" rel="permalink">' . __( 'View', 'woocommerce' ) . '</a>';
}
}
$actions = apply_filters( 'post_row_actions', $actions, $post );
echo '<div class="row-actions">';
$i = 0;
$action_count = sizeof( $actions );
foreach ( $actions as $action => $link ) {
++$i;
( $i == $action_count ) ? $sep = '' : $sep = ' | ';
echo '<span class="' . $action . '">' . $link . $sep . '</span>';
}
echo '</div>';
$this->_render_product_row_actions( $post, $title );
get_inline_data( $post );
@ -440,57 +404,85 @@ class WC_Admin_Post_Types {
}
}
/**
* Render product row actions for old version of WordPress
* Since WordPress 4.3 we don't have to build the row actions
*
* @param WP_Post $post
* @param string $title
*/
private function _render_product_row_actions( $post, $title ) {
global $wp_version;
if ( version_compare( $wp_version, '4.3-beta', '>=' ) ) {
return;
}
$post_type_object = get_post_type_object( $post->post_type );
$can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID );
// Get actions
$actions = array();
$actions['id'] = 'ID: ' . $post->ID;
if ( $can_edit_post && 'trash' != $post->post_status ) {
$actions['edit'] = '<a href="' . get_edit_post_link( $post->ID, true ) . '" title="' . esc_attr( __( 'Edit this item', 'woocommerce' ) ) . '">' . __( 'Edit', 'woocommerce' ) . '</a>';
$actions['inline hide-if-no-js'] = '<a href="#" class="editinline" title="' . esc_attr( __( 'Edit this item inline', 'woocommerce' ) ) . '">' . __( 'Quick&nbsp;Edit', 'woocommerce' ) . '</a>';
}
if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) {
if ( 'trash' == $post->post_status ) {
$actions['untrash'] = '<a title="' . esc_attr( __( 'Restore this item from the Trash', 'woocommerce' ) ) . '" href="' . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ) . '">' . __( 'Restore', 'woocommerce' ) . '</a>';
} elseif ( EMPTY_TRASH_DAYS ) {
$actions['trash'] = '<a class="submitdelete" title="' . esc_attr( __( 'Move this item to the Trash', 'woocommerce' ) ) . '" href="' . get_delete_post_link( $post->ID ) . '">' . __( 'Trash', 'woocommerce' ) . '</a>';
}
if ( 'trash' == $post->post_status || ! EMPTY_TRASH_DAYS ) {
$actions['delete'] = '<a class="submitdelete" title="' . esc_attr( __( 'Delete this item permanently', 'woocommerce' ) ) . '" href="' . get_delete_post_link( $post->ID, '', true ) . '">' . __( 'Delete Permanently', 'woocommerce' ) . '</a>';
}
}
if ( $post_type_object->public ) {
if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) {
if ( $can_edit_post )
$actions['view'] = '<a href="' . esc_url( add_query_arg( 'preview', 'true', get_permalink( $post->ID ) ) ) . '" title="' . esc_attr( sprintf( __( 'Preview &#8220;%s&#8221;', 'woocommerce' ), $title ) ) . '" rel="permalink">' . __( 'Preview', 'woocommerce' ) . '</a>';
} elseif ( 'trash' != $post->post_status ) {
$actions['view'] = '<a href="' . get_permalink( $post->ID ) . '" title="' . esc_attr( sprintf( __( 'View &#8220;%s&#8221;', 'woocommerce' ), $title ) ) . '" rel="permalink">' . __( 'View', 'woocommerce' ) . '</a>';
}
}
$actions = apply_filters( 'post_row_actions', $actions, $post );
echo '<div class="row-actions">';
$i = 0;
$action_count = sizeof( $actions );
foreach ( $actions as $action => $link ) {
++$i;
( $i == $action_count ) ? $sep = '' : $sep = ' | ';
echo '<span class="' . $action . '">' . $link . $sep . '</span>';
}
echo '</div>';
}
/**
* Output custom columns for coupons
* @param string $column
*
* @param string $column
*/
public function render_shop_coupon_columns( $column ) {
global $post, $woocommerce;
switch ( $column ) {
case 'coupon_code' :
$edit_link = get_edit_post_link( $post->ID );
$title = _draft_or_post_title();
$post_type_object = get_post_type_object( $post->post_type );
$edit_link = get_edit_post_link( $post->ID );
$title = _draft_or_post_title();
echo '<strong><a href="' . esc_attr( $edit_link ) . '" class="row-title">' . esc_html( $title ). '</a></strong>';
_post_states( $post );
// Get actions
$actions = array();
if ( current_user_can( $post_type_object->cap->edit_post, $post->ID ) ) {
$actions['edit'] = '<a href="' . admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=edit', $post->ID ) ) . '">' . __( 'Edit', 'woocommerce' ) . '</a>';
}
if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) {
if ( 'trash' == $post->post_status ) {
$actions['untrash'] = "<a title='" . esc_attr( __( 'Restore this item from the Trash', 'woocommerce' ) ) . "' href='" . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore', 'woocommerce' ) . "</a>";
} elseif ( EMPTY_TRASH_DAYS ) {
$actions['trash'] = "<a class='submitdelete' title='" . esc_attr( __( 'Move this item to the Trash', 'woocommerce' ) ) . "' href='" . get_delete_post_link( $post->ID ) . "'>" . __( 'Trash', 'woocommerce' ) . "</a>";
}
if ( 'trash' == $post->post_status || ! EMPTY_TRASH_DAYS ) {
$actions['delete'] = "<a class='submitdelete' title='" . esc_attr( __( 'Delete this item permanently', 'woocommerce' ) ) . "' href='" . get_delete_post_link( $post->ID, '', true ) . "'>" . __( 'Delete Permanently', 'woocommerce' ) . "</a>";
}
}
$actions = apply_filters( 'post_row_actions', $actions, $post );
echo '<div class="row-actions">';
$i = 0;
$action_count = sizeof( $actions );
foreach ( $actions as $action => $link ) {
++$i;
( $i == $action_count ) ? $sep = '' : $sep = ' | ';
echo "<span class='$action'>$link$sep</span>";
}
echo '</div>';
$this->_render_shop_coupon_row_actions( $post, $title );
break;
case 'type' :
echo esc_html( wc_get_coupon_type( get_post_meta( $post->ID, 'discount_type', true ) ) );
@ -543,6 +535,57 @@ class WC_Admin_Post_Types {
}
}
/**
* Render shop_coupon row actions for old version of WordPress
* Since WordPress 4.3 we don't have to build the row actions
*
* @param WP_Post $post
* @param string $title
*/
private function _render_shop_coupon_row_actions( $post, $title ) {
global $wp_version;
if ( version_compare( $wp_version, '4.3-beta', '>=' ) ) {
return;
}
$post_type_object = get_post_type_object( $post->post_type );
// Get actions
$actions = array();
if ( current_user_can( $post_type_object->cap->edit_post, $post->ID ) ) {
$actions['edit'] = '<a href="' . admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=edit', $post->ID ) ) . '">' . __( 'Edit', 'woocommerce' ) . '</a>';
}
if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) {
if ( 'trash' == $post->post_status ) {
$actions['untrash'] = "<a title='" . esc_attr( __( 'Restore this item from the Trash', 'woocommerce' ) ) . "' href='" . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&amp;action=untrash', $post->ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore', 'woocommerce' ) . "</a>";
} elseif ( EMPTY_TRASH_DAYS ) {
$actions['trash'] = "<a class='submitdelete' title='" . esc_attr( __( 'Move this item to the Trash', 'woocommerce' ) ) . "' href='" . get_delete_post_link( $post->ID ) . "'>" . __( 'Trash', 'woocommerce' ) . "</a>";
}
if ( 'trash' == $post->post_status || ! EMPTY_TRASH_DAYS ) {
$actions['delete'] = "<a class='submitdelete' title='" . esc_attr( __( 'Delete this item permanently', 'woocommerce' ) ) . "' href='" . get_delete_post_link( $post->ID, '', true ) . "'>" . __( 'Delete Permanently', 'woocommerce' ) . "</a>";
}
}
$actions = apply_filters( 'post_row_actions', $actions, $post );
echo '<div class="row-actions">';
$i = 0;
$action_count = sizeof( $actions );
foreach ( $actions as $action => $link ) {
++$i;
( $i == $action_count ) ? $sep = '' : $sep = ' | ';
echo "<span class='$action'>$link$sep</span>";
}
echo '</div>';
}
/**
* Output custom columns for coupons
* @param string $column
@ -814,6 +857,58 @@ class WC_Admin_Post_Types {
return $actions;
}
/**
* Set list table primary column for products and orders
* Support for WordPress 4.3
*
* @param string $default
* @param string $screen_id
*
* @return string
*/
public function list_table_primary_column( $default, $screen_id ) {
if ( 'edit-product' === $screen_id ) {
return 'name';
}
if ( 'edit-shop_order' === $screen_id ) {
return 'order_title';
}
if ( 'edit-shop_coupon' === $screen_id ) {
return 'coupon_code';
}
return $default;
}
/**
* Set row actions for products and orders
*
* @param array $actions
* @param WP_Post $post
*
* @return array
*/
public function row_actions( $actions, $post ) {
if ( 'product' === $post->post_type ) {
return array_merge( array( 'id' => 'ID: ' . $post->ID ), $actions );
}
if ( 'shop_order' === $post->post_type ) {
return array();
}
if ( 'shop_coupon' === $post->post_type ) {
if ( isset( $actions['inline hide-if-no-js'] ) ) {
unset( $actions['inline hide-if-no-js'] );
}
}
return $actions;
}
/**
* Product sorting link
*
@ -1560,7 +1655,7 @@ class WC_Admin_Post_Types {
break;
}
$output .= " ($term->count)</option>";
$output .= '</option>';
if ( 'simple' == $term->name ) {
@ -2130,6 +2225,18 @@ class WC_Admin_Post_Types {
}
}
}
/**
* Disable DFW feature pointer
*/
public function disable_dfw_feature_pointer() {
$screen = get_current_screen();
if ( 'product' === $screen->id && 'post' === $screen->base ) {
remove_action( 'admin_print_footer_scripts', array( 'WP_Internal_Pointers', 'pointer_wp410_dfw' ) );
}
}
}
endif;

View File

@ -471,7 +471,7 @@ class WC_Meta_Box_Product_Data {
<p class="form-field">
<label for="upsell_ids"><?php _e( 'Up-Sells', 'woocommerce' ); ?></label>
<input type="hidden" class="wc-product-search" style="width: 50%;" id="upsell_ids" name="upsell_ids" data-placeholder="<?php _e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products" data-multiple="true" data-selected="<?php
<input type="hidden" class="wc-product-search" style="width: 50%;" id="upsell_ids" name="upsell_ids" data-placeholder="<?php _e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products" data-multiple="true" data-exclude="<?php echo intval( $post->ID ); ?>" data-selected="<?php
$product_ids = array_filter( array_map( 'absint', (array) get_post_meta( $post->ID, '_upsell_ids', true ) ) );
$json_ids = array();
@ -488,7 +488,7 @@ class WC_Meta_Box_Product_Data {
<p class="form-field">
<label for="crosssell_ids"><?php _e( 'Cross-Sells', 'woocommerce' ); ?></label>
<input type="hidden" class="wc-product-search" style="width: 50%;" id="crosssell_ids" name="crosssell_ids" data-placeholder="<?php _e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products" data-multiple="true" data-selected="<?php
<input type="hidden" class="wc-product-search" style="width: 50%;" id="crosssell_ids" name="crosssell_ids" data-placeholder="<?php _e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products" data-multiple="true" data-exclude="<?php echo intval( $post->ID ); ?>" data-selected="<?php
$product_ids = array_filter( array_map( 'absint', (array) get_post_meta( $post->ID, '_crosssell_ids', true ) ) );
$json_ids = array();
@ -508,7 +508,7 @@ class WC_Meta_Box_Product_Data {
<p class="form-field">
<label for="parent_id"><?php _e( 'Grouping', 'woocommerce' ); ?></label>
<input type="hidden" class="wc-product-search" style="width: 50%;" id="parent_id" name="parent_id" data-placeholder="<?php _e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_grouped_products" data-allow_clear="true" data-multiple="false" data-selected="<?php
<input type="hidden" class="wc-product-search" style="width: 50%;" id="parent_id" name="parent_id" data-placeholder="<?php _e( 'Search for a product&hellip;', 'woocommerce' ); ?>" data-action="woocommerce_json_search_grouped_products" data-allow_clear="true" data-multiple="false" data-exclude="<?php echo intval( $post->ID ); ?>" data-selected="<?php
$parent_id = absint( $post->post_parent );
if ( $parent_id ) {
@ -643,7 +643,8 @@ class WC_Meta_Box_Product_Data {
$options = wc_get_text_attributes( $attribute['value'] );
foreach ( $options as $option ) {
echo '<option ' . selected( $variation_selected_value, $option, false ) . ' value="' . esc_attr( $option ) . '">' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>';
$selected = sanitize_title( $variation_selected_value ) === $variation_selected_value ? selected( $variation_selected_value, sanitize_title( $option ), false ) : selected( $variation_selected_value, $option, false );
echo '<option ' . $selected . ' value="' . esc_attr( $option ) . '">' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>';
}
}
@ -881,15 +882,18 @@ class WC_Meta_Box_Product_Data {
if ( $is_taxonomy ) {
$values_are_slugs = false;
if ( isset( $attribute_values[ $i ] ) ) {
// Select based attributes - Format values (posted values are slugs)
if ( is_array( $attribute_values[ $i ] ) ) {
$values = array_map( 'sanitize_title', $attribute_values[ $i ] );
$values = array_map( 'sanitize_title', $attribute_values[ $i ] );
$values_are_slugs = true;
// Text based attributes - Posted values are term names - don't change to slugs
} else {
$values = array_map( 'stripslashes', array_map( 'strip_tags', explode( WC_DELIMITER, $attribute_values[ $i ] ) ) );
$values = array_map( 'stripslashes', array_map( 'strip_tags', explode( WC_DELIMITER, $attribute_values[ $i ] ) ) );
}
// Remove empty items in the array
@ -903,7 +907,8 @@ class WC_Meta_Box_Product_Data {
if ( taxonomy_exists( $attribute_names[ $i ] ) ) {
foreach( $values as $key => $value ) {
$term = get_term_by( 'name', trim( $value ), $attribute_names[ $i ] );
$term = get_term_by( $values_are_slugs ? 'slug' : 'name', trim( $value ), $attribute_names[ $i ] );
if ( $term ) {
$values[ $key ] = intval( $term->term_id );
} else {
@ -1163,7 +1168,10 @@ class WC_Meta_Box_Product_Data {
// Validate the file exists
if ( 'relative' === $file_is ) {
$_file_url = '..' === substr( $file_url, 0, 2 ) ? realpath( ABSPATH . $file_url ) : $file_url;
$_file_url = $file_url;
if ( '..' === substr( $file_url, 0, 2 ) || '/' !== substr( $file_url, 0, 1 ) ) {
$_file_url = realpath( ABSPATH . $file_url );
}
if ( ! apply_filters( 'woocommerce_downloadable_file_exists', file_exists( $_file_url ), $file_url ) ) {
WC_Admin_Meta_Boxes::add_error( sprintf( __( 'The downloadable file %s cannot be used as it does not exist on the server.', 'woocommerce' ), '<code>' . $file_url . '</code>' ) );
@ -1205,9 +1213,6 @@ class WC_Meta_Box_Product_Data {
// Save variations
if ( 'variable' == $product_type ) {
// Deprecated since WooCommerce 2.4.0 in favor to WC_AJAX::save_variations()
// self::save_variations( $post_id, $post );
// Update parent if variable so price sorting works and stays in sync with the cheapest child
WC_Product_Variable::sync( $post_id );
}
@ -1225,7 +1230,6 @@ class WC_Meta_Box_Product_Data {
/**
* Save meta box data
*
* @deprecated 2.4.0 Deprecated in favor to WC_AJAX::save_variations()
*/
public static function save_variations( $post_id, $post ) {
global $wpdb;
@ -1233,7 +1237,6 @@ class WC_Meta_Box_Product_Data {
$attributes = (array) maybe_unserialize( get_post_meta( $post_id, '_product_attributes', true ) );
if ( isset( $_POST['variable_sku'] ) ) {
$variable_post_id = $_POST['variable_post_id'];
$variable_sku = $_POST['variable_sku'];
$variable_regular_price = $_POST['variable_regular_price'];
@ -1273,10 +1276,10 @@ class WC_Meta_Box_Product_Data {
$variation_id = absint( $variable_post_id[ $i ] );
// Checkboxes
$is_virtual = isset( $variable_is_virtual[ $i ] ) ? 'yes' : 'no';
$is_downloadable = isset( $variable_is_downloadable[ $i ] ) ? 'yes' : 'no';
$post_status = isset( $variable_enabled[ $i ] ) ? 'publish' : 'private';
$manage_stock = isset( $variable_manage_stock[ $i ] ) ? 'yes' : 'no';
$is_virtual = isset( $variable_is_virtual[ $i ] ) ? 'yes' : 'no';
$is_downloadable = isset( $variable_is_downloadable[ $i ] ) ? 'yes' : 'no';
$post_status = isset( $variable_enabled[ $i ] ) ? 'publish' : 'private';
$manage_stock = isset( $variable_manage_stock[ $i ] ) ? 'yes' : 'no';
// Generate a useful post title
$variation_post_title = sprintf( __( 'Variation #%s of %s', 'woocommerce' ), absint( $variation_id ), esc_html( get_the_title( $post_id ) ) );
@ -1323,7 +1326,7 @@ class WC_Meta_Box_Product_Data {
$unique_sku = wc_product_has_unique_sku( $variation_id, $new_sku );
if ( ! $unique_sku ) {
WC_Admin_Meta_Boxes::add_error( __( 'Variation SKU must be unique.', 'woocommerce' ) );
WC_Admin_Meta_Boxes::add_error( sprintf( __( '#%s &ndash; Variation SKU must be unique.', 'woocommerce' ), $variation_id ) );
} else {
update_post_meta( $variation_id, '_sku', $new_sku );
}
@ -1443,14 +1446,14 @@ class WC_Meta_Box_Product_Data {
$extension = pathinfo( $parsed_url, PATHINFO_EXTENSION );
if ( ! empty( $extension ) && ! in_array( $file_type['type'], $allowed_file_types ) ) {
WC_Admin_Meta_Boxes::add_error( sprintf( __( 'The downloadable file %s cannot be used as it does not have an allowed file type. Allowed types include: %s', 'woocommerce' ), '<code>' . basename( $file_url ) . '</code>', '<code>' . implode( ', ', array_keys( $allowed_file_types ) ) . '</code>' ) );
WC_Admin_Meta_Boxes::add_error( sprintf( __( '#%s &ndash; The downloadable file %s cannot be used as it does not have an allowed file type. Allowed types include: %s', 'woocommerce' ), $variation_id, '<code>' . basename( $file_url ) . '</code>', '<code>' . implode( ', ', array_keys( $allowed_file_types ) ) . '</code>' ) );
continue;
}
}
// Validate the file exists
if ( 'relative' === $file_is && ! apply_filters( 'woocommerce_downloadable_file_exists', file_exists( $file_url ), $file_url ) ) {
WC_Admin_Meta_Boxes::add_error( sprintf( __( 'The downloadable file %s cannot be used as it does not exist on the server.', 'woocommerce' ), '<code>' . $file_url . '</code>' ) );
WC_Admin_Meta_Boxes::add_error( sprintf( __( '#%s &ndash; The downloadable file %s cannot be used as it does not exist on the server.', 'woocommerce' ), $variation_id, '<code>' . $file_url . '</code>' ) );
continue;
}
@ -1515,12 +1518,15 @@ class WC_Meta_Box_Product_Data {
foreach ( $attributes as $attribute ) {
if ( $attribute['is_variation'] ) {
$value = '';
// Don't use wc_clean as it destroys sanitized characters
if ( isset( $_POST[ 'default_attribute_' . sanitize_title( $attribute['name'] ) ] ) ) {
$value = sanitize_title( trim( stripslashes( $_POST[ 'default_attribute_' . sanitize_title( $attribute['name'] ) ] ) ) );
} else {
$value = '';
if ( $attribute['is_taxonomy'] ) {
// Don't use wc_clean as it destroys sanitized characters
$value = sanitize_title( trim( stripslashes( $_POST[ 'default_attribute_' . sanitize_title( $attribute['name'] ) ] ) ) );
} else {
$value = wc_clean( trim( stripslashes( $_POST[ 'default_attribute_' . sanitize_title( $attribute['name'] ) ] ) ) );
}
}
if ( $value ) {

View File

@ -237,7 +237,7 @@ if ( wc_tax_enabled() ) {
<?php if ( wc_tax_enabled() && $order->is_editable() ) : ?>
<button type="button" class="button add-order-tax"><?php _e( 'Add Tax', 'woocommerce' ); ?></button>
<?php endif; ?>
<?php if ( ( $order->get_total() - $order->get_total_refunded() ) > 0 ) : ?>
<?php if ( 0 < $order->get_total() - $order->get_total_refunded() || 0 < absint( $order->get_item_count() - $order->get_item_count_refunded() ) ) : ?>
<button type="button" class="button refund-items"><?php _e( 'Refund', 'woocommerce' ); ?></button>
<?php endif; ?>
<?php
@ -261,7 +261,7 @@ if ( wc_tax_enabled() ) {
do_action( 'woocommerce_order_item_add_line_buttons', $order );
?>
</div>
<?php if ( ( $order->get_total() - $order->get_total_refunded() ) > 0 ) : ?>
<?php if ( 0 < $order->get_total() - $order->get_total_refunded() || 0 < absint( $order->get_item_count() - $order->get_item_count_refunded() ) ) : ?>
<div class="wc-order-data-row wc-order-refund-items" style="display: none;">
<table class="wc-order-totals">
<tr style="display:none;">

View File

@ -45,7 +45,8 @@ extract( $variation_data );
$options = wc_get_text_attributes( $attribute['value'] );
foreach ( $options as $option ) {
echo '<option ' . selected( $variation_selected_value, $option, false ) . ' value="' . esc_attr( $option ) . '">' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>';
$selected = sanitize_title( $variation_selected_value ) === $variation_selected_value ? selected( $variation_selected_value, sanitize_title( $option ), false ) : selected( $variation_selected_value, $option, false );
echo '<option ' . $selected . ' value="' . esc_attr( $option ) . '">' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>';
}
}

View File

@ -389,16 +389,6 @@ if ( ! defined( 'ABSPATH' ) ) {
</tr>
</thead>
<tbody>
<tr>
<td data-export-label="API Enabled"><?php _e( 'API Enabled', 'woocommerce' ); ?>:</td>
<td class="help"><?php echo '<a href="#" class="help_tip" data-tip="' . esc_attr__( 'Does your site have REST API enabled?', 'woocommerce' ) . '">[?]</a>'; ?></td>
<td><?php echo 'yes' === get_option( 'woocommerce_api_enabled' ) ? '<mark class="yes">'.'&#10004;'.'</mark>' : '<mark class="no">'.'&ndash;'.'</mark>'; ?></td>
</tr>
<tr>
<td data-export-label="API Version"><?php _e( 'API Version', 'woocommerce' ); ?>:</td>
<td class="help"><?php echo '<a href="#" class="help_tip" data-tip="' . esc_attr__( 'What version of the REST API does your site use?', 'woocommerce' ) . '">[?]</a>'; ?></td>
<td><?php echo WC_API::VERSION ?></td>
</tr>
<tr>
<td data-export-label="Force SSL"><?php _e( 'Force SSL', 'woocommerce' ); ?>:</td>
<td class="help"><?php echo '<a href="#" class="help_tip" data-tip="' . esc_attr__( 'Does your site force a SSL Certificate for transactions?', 'woocommerce' ) . '">[?]</a>'; ?></td>

View File

@ -226,7 +226,7 @@ class WC_API_Authentication {
$server_path = WC()->api->server->path;
// if the requested URL has a trailingslash, make sure our base URL does as well
if ( '/' === substr( $_SERVER['REDIRECT_URL'], -1 ) ) {
if ( isset( $_SERVER['REDIRECT_URL'] ) && '/' === substr( $_SERVER['REDIRECT_URL'], -1 ) ) {
$server_path .= '/';
}

View File

@ -358,8 +358,17 @@ class WC_API_Coupons extends WC_API_Resource {
throw new WC_API_Exception( 'woocommerce_api_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ), 400 );
}
$id = wp_update_post( array( 'ID' => intval( $id ), 'post_title' => $coupon_code, 'post_excerpt' => isset( $data['description'] ) ? $data['description'] : '' ) );
if ( 0 === $id ) {
$updated = wp_update_post( array( 'ID' => intval( $id ), 'post_title' => $coupon_code ) );
if ( 0 === $updated ) {
throw new WC_API_Exception( 'woocommerce_api_cannot_update_coupon', __( 'Failed to update coupon', 'woocommerce' ), 400 );
}
}
if ( isset( $data['description'] ) ) {
$updated = wp_update_post( array( 'ID' => intval( $id ), 'post_excerpt' => $data['description'] ) );
if ( 0 === $updated ) {
throw new WC_API_Exception( 'woocommerce_api_cannot_update_coupon', __( 'Failed to update coupon', 'woocommerce' ), 400 );
}
}

View File

@ -1467,11 +1467,17 @@ class WC_API_Products extends WC_API_Resource {
}
if ( isset( $_attribute['is_variation'] ) && $_attribute['is_variation'] ) {
$attribute_key = 'attribute_' . sanitize_title( $_attribute['name'] );
$attribute_value = isset( $attribute['option'] ) ? sanitize_title( stripslashes( $attribute['option'] ) ) : '';
$updated_attribute_keys[] = $attribute_key;
$_attribute_key = 'attribute_' . sanitize_title( $_attribute['name'] );
$updated_attribute_keys[] = $_attribute_key;
update_post_meta( $variation_id, $attribute_key, $attribute_value );
if ( isset( $_attribute['is_taxonomy'] ) && $_attribute['is_taxonomy'] ) {
// Don't use wc_clean as it destroys sanitized characters
$_attribute_value = isset( $attribute['option'] ) ? sanitize_title( stripslashes( $attribute['option'] ) ) : '';
} else {
$_attribute_value = isset( $attribute['option'] ) ? wc_clean( stripslashes( $attribute['option'] ) ) : '';
}
update_post_meta( $variation_id, $_attribute_key, $_attribute_value );
}
}
@ -1512,11 +1518,15 @@ class WC_API_Products extends WC_API_Resource {
$_attribute = $attributes[ $taxonomy ];
if ( $_attribute['is_variation'] ) {
// Don't use wc_clean as it destroys sanitized characters
$value = '';
if ( isset( $default_attr['option'] ) ) {
$value = sanitize_title( trim( stripslashes( $default_attr['option'] ) ) );
} else {
$value = '';
if ( $_attribute['is_taxonomy'] ) {
// Don't use wc_clean as it destroys sanitized characters
$value = sanitize_title( trim( stripslashes( $default_attr['option'] ) ) );
} else {
$value = wc_clean( trim( stripslashes( $default_attr['option'] ) ) );
}
}
if ( $value ) {

View File

@ -358,8 +358,17 @@ class WC_API_Coupons extends WC_API_Resource {
throw new WC_API_Exception( 'woocommerce_api_coupon_code_already_exists', __( 'The coupon code already exists', 'woocommerce' ), 400 );
}
$id = wp_update_post( array( 'ID' => intval( $id ), 'post_title' => $coupon_code, 'post_excerpt' => isset( $data['description'] ) ? $data['description'] : '' ) );
if ( 0 === $id ) {
$updated = wp_update_post( array( 'ID' => intval( $id ), 'post_title' => $coupon_code ) );
if ( 0 === $updated ) {
throw new WC_API_Exception( 'woocommerce_api_cannot_update_coupon', __( 'Failed to update coupon', 'woocommerce' ), 400 );
}
}
if ( isset( $data['description'] ) ) {
$updated = wp_update_post( array( 'ID' => intval( $id ), 'post_excerpt' => $data['description'] ) );
if ( 0 === $updated ) {
throw new WC_API_Exception( 'woocommerce_api_cannot_update_coupon', __( 'Failed to update coupon', 'woocommerce' ), 400 );
}
}

View File

@ -1467,11 +1467,17 @@ class WC_API_Products extends WC_API_Resource {
}
if ( isset( $_attribute['is_variation'] ) && $_attribute['is_variation'] ) {
$attribute_key = 'attribute_' . sanitize_title( $_attribute['name'] );
$attribute_value = isset( $attribute['option'] ) ? sanitize_title( stripslashes( $attribute['option'] ) ) : '';
$updated_attribute_keys[] = $attribute_key;
$_attribute_key = 'attribute_' . sanitize_title( $_attribute['name'] );
$updated_attribute_keys[] = $_attribute_key;
update_post_meta( $variation_id, $attribute_key, $attribute_value );
if ( isset( $_attribute['is_taxonomy'] ) && $_attribute['is_taxonomy'] ) {
// Don't use wc_clean as it destroys sanitized characters
$_attribute_value = isset( $attribute['option'] ) ? sanitize_title( stripslashes( $attribute['option'] ) ) : '';
} else {
$_attribute_value = isset( $attribute['option'] ) ? wc_clean( stripslashes( $attribute['option'] ) ) : '';
}
update_post_meta( $variation_id, $_attribute_key, $_attribute_value );
}
}
@ -1512,11 +1518,15 @@ class WC_API_Products extends WC_API_Resource {
$_attribute = $attributes[ $taxonomy ];
if ( $_attribute['is_variation'] ) {
// Don't use wc_clean as it destroys sanitized characters
$value = '';
if ( isset( $default_attr['option'] ) ) {
$value = sanitize_title( trim( stripslashes( $default_attr['option'] ) ) );
} else {
$value = '';
if ( $_attribute['is_taxonomy'] ) {
// Don't use wc_clean as it destroys sanitized characters
$value = sanitize_title( trim( stripslashes( $default_attr['option'] ) ) );
} else {
$value = wc_clean( trim( stripslashes( $default_attr['option'] ) ) );
}
}
if ( $value ) {

View File

@ -47,7 +47,7 @@ class WC_AJAX {
} elseif ( get_option( 'permalink_structure' ) ) {
$endpoint = trailingslashit( home_url( '/wc-ajax/' . $request, 'relative' ) );
} else {
$endpoint = add_query_arg( 'wc-ajax=', $request, trailingslashit( home_url( '', 'relative' ) ) );
$endpoint = add_query_arg( $request ? 'wc-ajax' : 'wc-ajax=', $request, trailingslashit( home_url( '', 'relative' ) ) );
}
return esc_url_raw( $endpoint );
}
@ -59,13 +59,16 @@ class WC_AJAX {
global $wp_query;
if ( ! empty( $_GET['wc-ajax'] ) ) {
$wp_query->set( 'wc-ajax', sanitize_text_field( $_GET['wc-ajax'] ) );
$wp_query->set( 'wc-ajax', sanitize_text_field( $_GET['wc-ajax'] ) );
}
if ( $action = $wp_query->get( 'wc-ajax' ) ) {
if ( ! defined( 'DOING_AJAX' ) ) {
define( 'DOING_AJAX', true );
}
if ( ! defined( 'WC_DOING_AJAX' ) ) {
define( 'WC_DOING_AJAX', true );
}
do_action( 'wc_ajax_' . sanitize_text_field( $action ) );
die();
}
@ -872,7 +875,7 @@ class WC_AJAX {
$options = explode( WC_DELIMITER, $attribute['value'] );
}
$options = array_map( 'sanitize_title', array_map( 'trim', $options ) );
$options = array_map( 'trim', $options );
$variations[ $attribute_field_name ] = $options;
}
@ -1739,39 +1742,50 @@ class WC_AJAX {
check_ajax_referer( 'search-products', 'security' );
$term = (string) wc_clean( stripslashes( $_GET['term'] ) );
$term = (string) wc_clean( stripslashes( $_GET['term'] ) );
$exclude = array();
if ( empty( $term ) ) {
die();
}
if ( ! empty( $_GET['exclude'] ) ) {
$exclude = array_map( 'intval', explode( ',', $_GET['exclude'] ) );
}
$args = array(
'post_type' => $post_types,
'post_status' => 'publish',
'posts_per_page' => -1,
's' => $term,
'fields' => 'ids'
'fields' => 'ids',
'exclude' => $exclude
);
if ( is_numeric( $term ) ) {
$args2 = array(
'post_type' => $post_types,
'post_status' => 'publish',
'posts_per_page' => -1,
'post__in' => array( 0, $term ),
'fields' => 'ids'
);
if ( false === array_search( $term, $exclude ) ) {
$posts2 = get_posts( array(
'post_type' => $post_types,
'post_status' => 'publish',
'posts_per_page' => -1,
'post__in' => array( 0, $term ),
'fields' => 'ids'
) );
} else {
$posts2 = array();
}
$args3 = array(
$posts3 = get_posts( array(
'post_type' => $post_types,
'post_status' => 'publish',
'posts_per_page' => -1,
'post_parent' => $term,
'fields' => 'ids'
);
'fields' => 'ids',
'exclude' => $exclude
) );
$args4 = array(
$posts4 = get_posts( array(
'post_type' => $post_types,
'post_status' => 'publish',
'posts_per_page' => -1,
@ -1782,10 +1796,11 @@ class WC_AJAX {
'compare' => 'LIKE'
)
),
'fields' => 'ids'
);
'fields' => 'ids',
'exclude' => $exclude
) );
$posts = array_unique( array_merge( get_posts( $args ), get_posts( $args2 ), get_posts( $args3 ), get_posts( $args4 ) ) );
$posts = array_unique( array_merge( get_posts( $args ), $posts2, $posts3, $posts4 ) );
} else {
@ -1800,7 +1815,8 @@ class WC_AJAX {
'compare' => 'LIKE'
)
),
'fields' => 'ids'
'fields' => 'ids',
'exclude' => $exclude
);
$posts = array_unique( array_merge( get_posts( $args ), get_posts( $args2 ) ) );
@ -1843,12 +1859,17 @@ class WC_AJAX {
check_ajax_referer( 'search-products', 'security' );
$term = (string) wc_clean( stripslashes( $_GET['term'] ) );
$term = (string) wc_clean( stripslashes( $_GET['term'] ) );
$exclude = array();
if ( empty( $term ) ) {
die();
}
if ( ! empty( $_GET['exclude'] ) ) {
$exclude = array_map( 'intval', explode( ',', $_GET['exclude'] ) );
}
$found_products = array();
if ( $grouped_term = get_term_by( 'slug', 'grouped', 'product_type' ) ) {
@ -1867,7 +1888,8 @@ class WC_AJAX {
'suppress_filters' => 0,
'include' => $posts_in,
's' => $term,
'fields' => 'ids'
'fields' => 'ids',
'exclude' => $exclude
);
$posts = get_posts( $args );
@ -1901,7 +1923,12 @@ class WC_AJAX {
check_ajax_referer( 'search-products', 'security' );
$term = (string) wc_clean( stripslashes( $_GET['term'] ) );
$term = (string) wc_clean( stripslashes( $_GET['term'] ) );
$exclude = array();
if ( ! empty( $_GET['exclude'] ) ) {
$exclude = array_map( 'intval', explode( ',', $_GET['exclude'] ) );
}
$args = array(
'post_type' => array( 'product', 'product_variation' ),
@ -1915,7 +1942,8 @@ class WC_AJAX {
'value' => 'yes'
)
),
's' => $term
's' => $term,
'exclude' => $exclude
);
$posts = get_posts( $args );
@ -2213,7 +2241,10 @@ class WC_AJAX {
}
}
if ( $refund_amount == $max_refund ) {
// Check if items are refunded fully
$max_remaining_items = absint( $order->get_item_count() - $order->get_item_count_refunded() );
if ( $refund_amount == $max_refund && 0 === $max_remaining_items ) {
$order->update_status( apply_filters( 'woocommerce_order_fully_refunded_status', 'refunded', $order_id, $refund->id ) );
$response_data['status'] = 'fully_refunded';
}
@ -2499,31 +2530,7 @@ class WC_AJAX {
}
// Add the variation attributes
foreach ( $variation_meta as $key => $value ) {
if ( 0 !== strpos( $key, 'attribute_' ) ) {
continue;
}
/**
* Pre 2.4 handling where 'slugs' were saved instead of the full text attribute.
* Attempt to get full version of the text attribute from the parent.
*/
if ( sanitize_title( $value[0] ) === $value[0] && version_compare( get_post_meta( $product_id, '_product_version', true ), '2.4.0', '<' ) ) {
foreach ( $attributes as $attribute ) {
if ( $key !== 'attribute_' . sanitize_title( $attribute['name'] ) ) {
continue;
}
$text_attributes = wc_get_text_attributes( $attribute['value'] );
foreach ( $text_attributes as $text_attribute ) {
if ( sanitize_title( $text_attribute ) === $value[0] ) {
$value[0] = $text_attribute;
}
}
}
}
$variation_data[ $key ] = $value[0];
}
$variation_data = array_merge( $variation_data, wc_get_product_variation_attributes( $variation_id ) );
// Formatting
$variation_data['_regular_price'] = wc_format_localized_price( $variation_data['_regular_price'] );
@ -2563,313 +2570,30 @@ class WC_AJAX {
die( -1 );
}
global $wpdb;
// Remove previous meta box errors
WC_Admin_Meta_Boxes::$meta_box_errors = array();
$product_id = absint( $_POST['product_id'] );
$attributes = (array) maybe_unserialize( get_post_meta( $product_id, '_product_attributes', true ) );
if ( isset( $_POST['variable_sku'] ) ) {
$variable_post_id = $_POST['variable_post_id'];
$variable_sku = $_POST['variable_sku'];
$variable_regular_price = $_POST['variable_regular_price'];
$variable_sale_price = $_POST['variable_sale_price'];
$upload_image_id = $_POST['upload_image_id'];
$variable_download_limit = $_POST['variable_download_limit'];
$variable_download_expiry = $_POST['variable_download_expiry'];
$variable_shipping_class = $_POST['variable_shipping_class'];
$variable_tax_class = isset( $_POST['variable_tax_class'] ) ? $_POST['variable_tax_class'] : array();
$variable_menu_order = $_POST['variation_menu_order'];
$variable_sale_price_dates_from = $_POST['variable_sale_price_dates_from'];
$variable_sale_price_dates_to = $_POST['variable_sale_price_dates_to'];
$variable_weight = isset( $_POST['variable_weight'] ) ? $_POST['variable_weight'] : array();
$variable_length = isset( $_POST['variable_length'] ) ? $_POST['variable_length'] : array();
$variable_width = isset( $_POST['variable_width'] ) ? $_POST['variable_width'] : array();
$variable_height = isset( $_POST['variable_height'] ) ? $_POST['variable_height'] : array();
$variable_enabled = isset( $_POST['variable_enabled'] ) ? $_POST['variable_enabled'] : array();
$variable_is_virtual = isset( $_POST['variable_is_virtual'] ) ? $_POST['variable_is_virtual'] : array();
$variable_is_downloadable = isset( $_POST['variable_is_downloadable'] ) ? $_POST['variable_is_downloadable'] : array();
$variable_manage_stock = isset( $_POST['variable_manage_stock'] ) ? $_POST['variable_manage_stock'] : array();
$variable_stock = isset( $_POST['variable_stock'] ) ? $_POST['variable_stock'] : array();
$variable_backorders = isset( $_POST['variable_backorders'] ) ? $_POST['variable_backorders'] : array();
$variable_stock_status = isset( $_POST['variable_stock_status'] ) ? $_POST['variable_stock_status'] : array();
$variable_description = isset( $_POST['variable_description'] ) ? $_POST['variable_description'] : array();
$max_loop = max( array_keys( $_POST['variable_post_id'] ) );
for ( $i = 0; $i <= $max_loop; $i ++ ) {
if ( ! isset( $variable_post_id[ $i ] ) ) {
continue;
}
$variation_id = absint( $variable_post_id[ $i ] );
// Checkboxes
$is_virtual = isset( $variable_is_virtual[ $i ] ) ? 'yes' : 'no';
$is_downloadable = isset( $variable_is_downloadable[ $i ] ) ? 'yes' : 'no';
$post_status = isset( $variable_enabled[ $i ] ) ? 'publish' : 'private';
$manage_stock = isset( $variable_manage_stock[ $i ] ) ? 'yes' : 'no';
// Generate a useful post title
$variation_post_title = sprintf( __( 'Variation #%s of %s', 'woocommerce' ), absint( $variation_id ), esc_html( get_the_title( $product_id ) ) );
// Update or Add post
if ( ! $variation_id ) {
$variation = array(
'post_title' => $variation_post_title,
'post_content' => '',
'post_status' => $post_status,
'post_author' => get_current_user_id(),
'post_parent' => $product_id,
'post_type' => 'product_variation',
'menu_order' => $variable_menu_order[ $i ]
);
$variation_id = wp_insert_post( $variation );
do_action( 'woocommerce_create_product_variation', $variation_id );
} else {
$wpdb->update( $wpdb->posts, array( 'post_status' => $post_status, 'post_title' => $variation_post_title, 'menu_order' => $variable_menu_order[ $i ] ), array( 'ID' => $variation_id ) );
do_action( 'woocommerce_update_product_variation', $variation_id );
}
// Only continue if we have a variation ID
if ( ! $variation_id ) {
continue;
}
// Unique SKU
$sku = get_post_meta( $variation_id, '_sku', true );
$new_sku = wc_clean( stripslashes( $variable_sku[ $i ] ) );
if ( '' == $new_sku ) {
update_post_meta( $variation_id, '_sku', '' );
} elseif ( $new_sku !== $sku ) {
if ( ! empty( $new_sku ) ) {
$unique_sku = wc_product_has_unique_sku( $variation_id, $new_sku );
if ( ! $unique_sku ) {
WC_Admin_Meta_Boxes::add_error( __( 'Variation SKU must be unique.', 'woocommerce' ) );
} else {
update_post_meta( $variation_id, '_sku', $new_sku );
}
} else {
update_post_meta( $variation_id, '_sku', '' );
}
}
// Update post meta
update_post_meta( $variation_id, '_thumbnail_id', absint( $upload_image_id[ $i ] ) );
update_post_meta( $variation_id, '_virtual', wc_clean( $is_virtual ) );
update_post_meta( $variation_id, '_downloadable', wc_clean( $is_downloadable ) );
if ( isset( $variable_weight[ $i ] ) ) {
update_post_meta( $variation_id, '_weight', ( '' === $variable_weight[ $i ] ) ? '' : wc_format_decimal( $variable_weight[ $i ] ) );
}
if ( isset( $variable_length[ $i ] ) ) {
update_post_meta( $variation_id, '_length', ( '' === $variable_length[ $i ] ) ? '' : wc_format_decimal( $variable_length[ $i ] ) );
}
if ( isset( $variable_width[ $i ] ) ) {
update_post_meta( $variation_id, '_width', ( '' === $variable_width[ $i ] ) ? '' : wc_format_decimal( $variable_width[ $i ] ) );
}
if ( isset( $variable_height[ $i ] ) ) {
update_post_meta( $variation_id, '_height', ( '' === $variable_height[ $i ] ) ? '' : wc_format_decimal( $variable_height[ $i ] ) );
}
// Stock handling
update_post_meta( $variation_id, '_manage_stock', $manage_stock );
// Only update stock status to user setting if changed by the user, but do so before looking at stock levels at variation level
if ( ! empty( $variable_stock_status[ $i ] ) ) {
wc_update_product_stock_status( $variation_id, $variable_stock_status[ $i ] );
}
if ( 'yes' === $manage_stock ) {
update_post_meta( $variation_id, '_backorders', wc_clean( $variable_backorders[ $i ] ) );
wc_update_product_stock( $variation_id, wc_stock_amount( $variable_stock[ $i ] ) );
} else {
delete_post_meta( $variation_id, '_backorders' );
delete_post_meta( $variation_id, '_stock' );
}
// Price handling
$regular_price = wc_format_decimal( $variable_regular_price[ $i ] );
$sale_price = $variable_sale_price[ $i ] === '' ? '' : wc_format_decimal( $variable_sale_price[ $i ] );
$date_from = wc_clean( $variable_sale_price_dates_from[ $i ] );
$date_to = wc_clean( $variable_sale_price_dates_to[ $i ] );
update_post_meta( $variation_id, '_regular_price', $regular_price );
update_post_meta( $variation_id, '_sale_price', $sale_price );
// Save Dates
update_post_meta( $variation_id, '_sale_price_dates_from', $date_from ? strtotime( $date_from ) : '' );
update_post_meta( $variation_id, '_sale_price_dates_to', $date_to ? strtotime( $date_to ) : '' );
if ( $date_to && ! $date_from ) {
update_post_meta( $variation_id, '_sale_price_dates_from', strtotime( 'NOW', current_time( 'timestamp' ) ) );
}
// Update price if on sale
if ( '' !== $sale_price && '' === $date_to && '' === $date_from ) {
update_post_meta( $variation_id, '_price', $sale_price );
} else {
update_post_meta( $variation_id, '_price', $regular_price );
}
if ( '' !== $sale_price && $date_from && strtotime( $date_from ) < strtotime( 'NOW', current_time( 'timestamp' ) ) ) {
update_post_meta( $variation_id, '_price', $sale_price );
}
if ( $date_to && strtotime( $date_to ) < strtotime( 'NOW', current_time( 'timestamp' ) ) ) {
update_post_meta( $variation_id, '_price', $regular_price );
update_post_meta( $variation_id, '_sale_price_dates_from', '' );
update_post_meta( $variation_id, '_sale_price_dates_to', '' );
}
if ( isset( $variable_tax_class[ $i ] ) && $variable_tax_class[ $i ] !== 'parent' ) {
update_post_meta( $variation_id, '_tax_class', wc_clean( $variable_tax_class[ $i ] ) );
} else {
delete_post_meta( $variation_id, '_tax_class' );
}
if ( 'yes' == $is_downloadable ) {
update_post_meta( $variation_id, '_download_limit', wc_clean( $variable_download_limit[ $i ] ) );
update_post_meta( $variation_id, '_download_expiry', wc_clean( $variable_download_expiry[ $i ] ) );
$files = array();
$file_names = isset( $_POST['_wc_variation_file_names'][ $variation_id ] ) ? array_map( 'wc_clean', $_POST['_wc_variation_file_names'][ $variation_id ] ) : array();
$file_urls = isset( $_POST['_wc_variation_file_urls'][ $variation_id ] ) ? array_map( 'wc_clean', $_POST['_wc_variation_file_urls'][ $variation_id ] ) : array();
$file_url_size = sizeof( $file_urls );
$allowed_file_types = get_allowed_mime_types();
for ( $ii = 0; $ii < $file_url_size; $ii ++ ) {
if ( ! empty( $file_urls[ $ii ] ) ) {
// Find type and file URL
if ( 0 === strpos( $file_urls[ $ii ], 'http' ) ) {
$file_is = 'absolute';
$file_url = esc_url_raw( $file_urls[ $ii ] );
} elseif ( '[' === substr( $file_urls[ $ii ], 0, 1 ) && ']' === substr( $file_urls[ $ii ], -1 ) ) {
$file_is = 'shortcode';
$file_url = wc_clean( $file_urls[ $ii ] );
} else {
$file_is = 'relative';
$file_url = wc_clean( $file_urls[ $ii ] );
}
$file_name = wc_clean( $file_names[ $ii ] );
$file_hash = md5( $file_url );
// Validate the file extension
if ( in_array( $file_is, array( 'absolute', 'relative' ) ) ) {
$file_type = wp_check_filetype( strtok( $file_url, '?' ) );
$parsed_url = parse_url( $file_url, PHP_URL_PATH );
$extension = pathinfo( $parsed_url, PATHINFO_EXTENSION );
if ( ! empty( $extension ) && ! in_array( $file_type['type'], $allowed_file_types ) ) {
WC_Admin_Meta_Boxes::add_error( sprintf( __( 'The downloadable file %s cannot be used as it does not have an allowed file type. Allowed types include: %s', 'woocommerce' ), '<code>' . basename( $file_url ) . '</code>', '<code>' . implode( ', ', array_keys( $allowed_file_types ) ) . '</code>' ) );
continue;
}
}
// Validate the file exists
if ( 'relative' === $file_is && ! apply_filters( 'woocommerce_downloadable_file_exists', file_exists( $file_url ), $file_url ) ) {
WC_Admin_Meta_Boxes::add_error( sprintf( __( 'The downloadable file %s cannot be used as it does not exist on the server.', 'woocommerce' ), '<code>' . $file_url . '</code>' ) );
continue;
}
$files[ $file_hash ] = array(
'name' => $file_name,
'file' => $file_url
);
}
}
// grant permission to any newly added files on any existing orders for this product prior to saving
do_action( 'woocommerce_process_product_file_download_paths', $product_id, $variation_id, $files );
update_post_meta( $variation_id, '_downloadable_files', $files );
} else {
update_post_meta( $variation_id, '_download_limit', '' );
update_post_meta( $variation_id, '_download_expiry', '' );
update_post_meta( $variation_id, '_downloadable_files', '' );
}
update_post_meta( $variation_id, '_variation_description', wp_kses_post( $variable_description[ $i ] ) );
// Save shipping class
$variable_shipping_class[ $i ] = ! empty( $variable_shipping_class[ $i ] ) ? (int) $variable_shipping_class[ $i ] : '';
wp_set_object_terms( $variation_id, $variable_shipping_class[ $i ], 'product_shipping_class');
// Update Attributes
$updated_attribute_keys = array();
foreach ( $attributes as $attribute ) {
if ( $attribute['is_variation'] ) {
$attribute_key = 'attribute_' . sanitize_title( $attribute['name'] );
$updated_attribute_keys[] = $attribute_key;
if ( $attribute['is_taxonomy'] ) {
// Don't use wc_clean as it destroys sanitized characters
$value = isset( $_POST[ $attribute_key ][ $i ] ) ? sanitize_title( stripslashes( $_POST[ $attribute_key ][ $i ] ) ) : '';
} else {
$value = isset( $_POST[ $attribute_key ][ $i ] ) ? wc_clean( stripslashes( $_POST[ $attribute_key ][ $i ] ) ) : '';
}
update_post_meta( $variation_id, $attribute_key, $value );
}
}
// Remove old taxonomies attributes so data is kept up to date - first get attribute key names
$delete_attribute_keys = $wpdb->get_col( $wpdb->prepare( "SELECT meta_key FROM {$wpdb->postmeta} WHERE meta_key LIKE 'attribute_%%' AND meta_key NOT IN ( '" . implode( "','", $updated_attribute_keys ) . "' ) AND post_id = %d;", $variation_id ) );
foreach ( $delete_attribute_keys as $key ) {
delete_post_meta( $variation_id, $key );
}
do_action( 'woocommerce_save_product_variation', $variation_id, $i );
}
}
// Update parent if variable so price sorting works and stays in sync with the cheapest child
WC_Product_Variable::sync( $product_id );
// Update default attribute options setting
$default_attributes = array();
foreach ( $attributes as $attribute ) {
if ( $attribute['is_variation'] ) {
// Don't use wc_clean as it destroys sanitized characters
if ( isset( $_POST[ 'default_attribute_' . sanitize_title( $attribute['name'] ) ] ) ) {
$value = sanitize_title( trim( stripslashes( $_POST[ 'default_attribute_' . sanitize_title( $attribute['name'] ) ] ) ) );
} else {
$value = '';
}
if ( $value ) {
$default_attributes[ sanitize_title( $attribute['name'] ) ] = $value;
}
}
}
update_post_meta( $product_id, '_default_attributes', $default_attributes );
WC_Meta_Box_Product_Data::save_variations( $product_id, get_post( $product_id ) );
do_action( 'woocommerce_ajax_save_product_variations', $product_id );
// Clear cache/transients
wc_delete_product_transients( $product_id );
if ( $errors = WC_Admin_Meta_Boxes::$meta_box_errors ) {
echo '<div id="woocommerce_errors" class="error">';
foreach ( $errors as $error ) {
echo '<p>' . wp_kses_post( $error ) . '</p>';
}
echo '</div>';
delete_option( 'woocommerce_meta_box_errors' );
}
die();
}
/**

View File

@ -1746,7 +1746,7 @@ class WC_Cart {
$discount_amount += $this->get_coupon_discount_tax_amount( $code );
}
return round( $discount_amount, $this->dp, WC_DISCOUNT_ROUNDING_MODE );
return wc_cart_round_discount( $discount_amount, $this->dp );
}
/**
@ -1756,7 +1756,7 @@ class WC_Cart {
* @return float discount amount
*/
public function get_coupon_discount_tax_amount( $code ) {
return round( isset( $this->coupon_discount_tax_amounts[ $code ] ) ? $this->coupon_discount_tax_amounts[ $code ] : 0, $this->dp, WC_DISCOUNT_ROUNDING_MODE );
return wc_cart_round_discount( isset( $this->coupon_discount_tax_amounts[ $code ] ) ? $this->coupon_discount_tax_amounts[ $code ] : 0, $this->dp );
}
/**
@ -2156,7 +2156,7 @@ class WC_Cart {
* @return float
*/
public function get_cart_discount_total() {
return round( $this->discount_cart, $this->dp, WC_DISCOUNT_ROUNDING_MODE );
return wc_cart_round_discount( $this->discount_cart, $this->dp );
}
/**
@ -2165,7 +2165,7 @@ class WC_Cart {
* @return float
*/
public function get_cart_discount_tax_total() {
return round( $this->discount_cart_tax, $this->dp, WC_DISCOUNT_ROUNDING_MODE );
return wc_cart_round_discount( $this->discount_cart_tax, $this->dp );
}
/**

View File

@ -143,14 +143,13 @@ class WC_Download_Handler {
/**
* Log the download + increase counts
* @param object $download_data
* @access private
* @param object $download_data
*/
private static function count_download( $download_data ) {
public static function count_download( $download_data ) {
global $wpdb;
$wpdb->update(
$wpdb->prefix . "woocommerce_downloadable_product_permissions",
$wpdb->prefix . 'woocommerce_downloadable_product_permissions',
array(
'download_count' => $download_data->download_count + 1,
'downloads_remaining' => $download_data->downloads_remaining > 0 ? $download_data->downloads_remaining - 1 : $download_data->downloads_remaining,
@ -247,19 +246,17 @@ class WC_Download_Handler {
public static function download_file_xsendfile( $file_path, $filename ) {
$parsed_file_path = self::parse_file_path( $file_path );
extract( $parsed_file_path );
if ( function_exists( 'apache_get_modules' ) && in_array( 'mod_xsendfile', apache_get_modules() ) ) {
self::download_headers( $file_path, $filename );
header( "X-Sendfile: $file_path" );
self::download_headers( $parsed_file_path['file_path'], $filename );
header( "X-Sendfile: " . $parsed_file_path['file_path'] );
exit;
} elseif ( stristr( getenv( 'SERVER_SOFTWARE' ), 'lighttpd' ) ) {
self::download_headers( $file_path, $filename );
header( "X-Lighttpd-Sendfile: $file_path" );
self::download_headers( $parsed_file_path['file_path'], $filename );
header( "X-Lighttpd-Sendfile: " . $parsed_file_path['file_path'] );
exit;
} elseif ( stristr( getenv( 'SERVER_SOFTWARE' ), 'nginx' ) || stristr( getenv( 'SERVER_SOFTWARE' ), 'cherokee' ) ) {
self::download_headers( $file_path, $filename );
$xsendfile_path = trim( preg_replace( '`^' . str_replace( '\\', '/', getcwd() ) . '`', '', $file_path ), '/' );
self::download_headers( $parsed_file_path['file_path'], $filename );
$xsendfile_path = trim( preg_replace( '`^' . str_replace( '\\', '/', getcwd() ) . '`', '', $parsed_file_path['file_path'] ), '/' );
header( "X-Accel-Redirect: /$xsendfile_path" );
exit;
}
@ -276,12 +273,10 @@ class WC_Download_Handler {
public static function download_file_force( $file_path, $filename ) {
$parsed_file_path = self::parse_file_path( $file_path );
extract( $parsed_file_path );
self::download_headers( $parsed_file_path['file_path'], $filename );
self::download_headers( $file_path, $filename );
if ( ! self::readfile_chunked( $file_path ) ) {
if ( $remote_file ) {
if ( ! self::readfile_chunked( $parsed_file_path['file_path'] ) ) {
if ( $parsed_file_path['remote_file'] ) {
self::download_file_redirect( $file_path );
} else {
self::download_error( __( 'File not found', 'woocommerce' ) );

View File

@ -622,20 +622,6 @@ class WC_Form_Handler {
// Allow if valid
if ( '' === $valid_value || $valid_value === $value ) {
// Pre 2.4 handling where 'slugs' were saved instead of the full text attribute
if ( ! $attribute['is_taxonomy'] ) {
if ( $value === sanitize_title( $value ) && version_compare( get_post_meta( $product_id, '_product_version', true ), '2.4.0', '<' ) ) {
$text_attributes = wc_get_text_attributes( $attribute['value'] );
foreach ( $text_attributes as $text_attribute ) {
if ( sanitize_title( $text_attribute ) === $value ) {
$value = $text_attribute;
break;
}
}
}
}
$variations[ $taxonomy ] = $value;
continue;
}

View File

@ -198,12 +198,12 @@ class WC_Frontend_Scripts {
case 'woocommerce' :
return array(
'ajax_url' => WC()->ajax_url(),
'wc_ajax_url' => WC_AJAX::get_endpoint()
'wc_ajax_url' => WC_AJAX::get_endpoint( "%%endpoint%%" )
);
break;
case 'wc-geolocation' :
return array(
'wc_ajax_url' => WC_AJAX::get_endpoint(),
'wc_ajax_url' => WC_AJAX::get_endpoint( "%%endpoint%%" ),
'home_url' => home_url(),
'is_checkout' => is_checkout() ? '1' : '0',
'hash' => isset( $_GET['v'] ) ? wc_clean( $_GET['v'] ) : ''
@ -218,7 +218,7 @@ class WC_Frontend_Scripts {
case 'wc-checkout' :
return array(
'ajax_url' => WC()->ajax_url(),
'wc_ajax_url' => WC_AJAX::get_endpoint(),
'wc_ajax_url' => WC_AJAX::get_endpoint( "%%endpoint%%" ),
'update_order_review_nonce' => wp_create_nonce( 'update-order-review' ),
'apply_coupon_nonce' => wp_create_nonce( 'apply-coupon' ),
'remove_coupon_nonce' => wp_create_nonce( 'remove-coupon' ),
@ -239,21 +239,21 @@ class WC_Frontend_Scripts {
case 'wc-cart' :
return array(
'ajax_url' => WC()->ajax_url(),
'wc_ajax_url' => WC_AJAX::get_endpoint(),
'wc_ajax_url' => WC_AJAX::get_endpoint( "%%endpoint%%" ),
'update_shipping_method_nonce' => wp_create_nonce( "update-shipping-method" ),
);
break;
case 'wc-cart-fragments' :
return array(
'ajax_url' => WC()->ajax_url(),
'wc_ajax_url' => WC_AJAX::get_endpoint(),
'wc_ajax_url' => WC_AJAX::get_endpoint( "%%endpoint%%" ),
'fragment_name' => apply_filters( 'woocommerce_cart_fragment_name', 'wc_fragments' )
);
break;
case 'wc-add-to-cart' :
return array(
'ajax_url' => WC()->ajax_url(),
'wc_ajax_url' => WC_AJAX::get_endpoint(),
'wc_ajax_url' => WC_AJAX::get_endpoint( "%%endpoint%%" ),
'i18n_view_cart' => esc_attr__( 'View Cart', 'woocommerce' ),
'cart_url' => apply_filters( 'woocommerce_add_to_cart_redirect', WC()->cart->get_cart_url() ),
'is_cart' => is_cart(),

View File

@ -140,6 +140,48 @@ class WC_Order extends WC_Abstract_Order {
return abs( $total );
}
/**
* Gets the count of order items of a certain type that have been refunded.
* @since 2.4.0
* @param string $item_type
* @return string
*/
public function get_item_count_refunded( $item_type = '' ) {
if ( empty( $item_type ) ) {
$item_type = array( 'line_item' );
}
if ( ! is_array( $item_type ) ) {
$item_type = array( $item_type );
}
$count = 0;
foreach ( $this->get_refunds() as $refund ) {
foreach ( $refund->get_items( $item_type ) as $refunded_item ) {
$count += empty( $refunded_item['qty'] ) ? 0 : $refunded_item['qty'];
}
}
return apply_filters( 'woocommerce_get_item_count_refunded', $count, $item_type, $this );
}
/**
* Get the total number of items refunded.
*
* @since 2.4.0
* @param int $item_id ID of the item we're checking
* @param string $item_type type of the item we're checking, if not a line_item
* @return integer
*/
public function get_total_qty_refunded( $item_type = 'line_item' ) {
$qty = 0;
foreach ( $this->get_refunds() as $refund ) {
foreach ( $refund->get_items( $item_type ) as $refunded_item ) {
$qty += $refunded_item['qty'];
}
}
return $qty;
}
/**
* Get the refunded amount for a line item
*

View File

@ -75,7 +75,11 @@ class WC_Payment_Gateways {
if ( 'US' === WC()->countries->get_base_country() ) {
if ( class_exists( 'WC_Subscriptions_Order' ) || class_exists( 'WC_Pre_Orders_Order' ) ) {
$load_gateways[] = 'WC_Addons_Gateway_Simplify_Commerce';
if ( ! function_exists( 'wcs_create_renewal_order' ) ) { // Subscriptions < 2.0
$load_gateways[] = 'WC_Addons_Gateway_Simplify_Commerce_Deprecated';
} else {
$load_gateways[] = 'WC_Addons_Gateway_Simplify_Commerce';
}
} else {
$load_gateways[] = 'WC_Gateway_Simplify_Commerce';
}

View File

@ -35,6 +35,7 @@ class WC_Post_Data {
add_filter( 'update_post_metadata', array( __CLASS__, 'update_post_metadata' ), 10, 5 );
add_filter( 'wp_insert_post_data', array( __CLASS__, 'wp_insert_post_data' ) );
add_action( 'pre_post_update', array( __CLASS__, 'pre_post_update' ) );
add_action( 'update_post_meta', array( __CLASS__, 'sync_product_stock_status' ), 10, 4 );
}
/**
@ -160,6 +161,20 @@ class WC_Post_Data {
return $check;
}
/**
* When setting stock level, ensure the stock status is kept in sync
* @param int $meta_id
* @param int $object_id
* @param string $meta_key
* @param mixed $_meta_value
*/
public static function sync_product_stock_status( $meta_id, $object_id, $meta_key, $_meta_value ) {
if ( '_stock' === $meta_key && 'product' !== get_post_type( $object_id ) ) {
$product = wc_get_product( $object_id );
$product->check_stock_status();
}
}
/**
* Forces the order posts to have a title in a certain format (containing the date).
* Forces certain product data based on the product's type, e.g. grouped products cannot have a parent.

View File

@ -88,7 +88,7 @@ class WC_Product_Variable extends WC_Product {
/**
* Performed after a stock level change at product level
*/
protected function check_stock_status() {
public function check_stock_status() {
$set_child_stock_status = '';
if ( ! $this->backorders_allowed() && $this->get_stock_quantity() <= get_option( 'woocommerce_notify_no_stock_amount' ) ) {
@ -249,7 +249,7 @@ class WC_Product_Variable extends WC_Product {
* @return array()
*/
public function get_variation_prices( $display = false ) {
$cache_key = 'var_prices_' . md5( json_encode( apply_filters( 'woocommerce_get_variation_prices_hash', array(
$cache_key = 'wc_var_prices' . md5( json_encode( apply_filters( 'woocommerce_get_variation_prices_hash', array(
$this->id,
$display ? WC_Tax::get_rates() : '',
WC_Cache_Helper::get_transient_version( 'product' )
@ -373,7 +373,7 @@ class WC_Product_Variable extends WC_Product {
if ( in_array( '', $values ) ) {
$values = $attribute['is_taxonomy'] ? wp_get_post_terms( $this->id, $attribute['name'], array( 'fields' => 'slugs' ) ) : wc_get_text_attributes( $attribute['value'] );
// Order custom attributes (non taxonomy) as defined
// Get custom attributes (non taxonomy) as defined
} elseif ( ! $attribute['is_taxonomy'] ) {
$text_attributes = wc_get_text_attributes( $attribute['value'] );
$assigned_text_attributes = $values;
@ -414,6 +414,18 @@ class WC_Product_Variable extends WC_Product {
return apply_filters( 'woocommerce_product_default_attributes', (array) maybe_unserialize( $default ), $this );
}
/**
* If set, get the default attributes for a variable product.
*
* @param string $attribute_name
* @return string
*/
public function get_variation_default_attribute( $attribute_name ) {
$defaults = $this->get_variation_default_attributes();
$attribute_name = sanitize_title( $attribute_name );
return isset( $defaults[ $attribute_name ] ) ? $defaults[ $attribute_name ] : '';
}
/**
* Match a variation to a given set of attributes using a WP_Query
* @since 2.4.0
@ -591,6 +603,53 @@ class WC_Product_Variable extends WC_Product {
wc_update_product_stock_status( $product_id, $stock_status );
}
/**
* Sync the variable product's attributes with the variations
*/
public static function sync_attributes( $product_id, $children = false ) {
if ( ! $children ) {
$children = get_posts( array(
'post_parent' => $product_id,
'posts_per_page'=> -1,
'post_type' => 'product_variation',
'fields' => 'ids',
'post_status' => 'any'
) );
}
/**
* Pre 2.4 handling where 'slugs' were saved instead of the full text attribute.
* Attempt to get full version of the text attribute from the parent and UPDATE meta.
*/
if ( version_compare( get_post_meta( $product_id, '_product_version', true ), '2.4.0', '<' ) ) {
$parent_attributes = array_filter( (array) get_post_meta( $product_id, '_product_attributes', true ) );
foreach ( $children as $child_id ) {
$all_meta = get_post_meta( $child_id );
foreach ( $all_meta as $name => $value ) {
if ( 0 !== strpos( $name, 'attribute_' ) ) {
continue;
}
if ( sanitize_title( $value[0] ) === $value[0] ) {
foreach ( $parent_attributes as $attribute ) {
if ( $name !== 'attribute_' . sanitize_title( $attribute['name'] ) ) {
continue;
}
$text_attributes = wc_get_text_attributes( $attribute['value'] );
foreach ( $text_attributes as $text_attribute ) {
if ( sanitize_title( $text_attribute ) === $value[0] ) {
update_post_meta( $child_id, $name, $text_attribute );
break;
}
}
}
}
}
}
}
}
/**
* Sync the variable product with it's children
*/
@ -691,6 +750,9 @@ class WC_Product_Variable extends WC_Product {
update_post_meta( $product_id, '_price', $min_price );
delete_transient( 'wc_products_onsale' );
// Sync attributes
self::sync_attributes( $product_id, $children );
do_action( 'woocommerce_variable_product_sync', $product_id, $children );
}
}

View File

@ -135,40 +135,7 @@ class WC_Product_Variation extends WC_Product {
}
} elseif ( 'variation_data' === $key ) {
$all_meta = get_post_meta( $this->variation_id );
// The variation data array
$this->variation_data = array();
// Get the variation attributes from meta
foreach ( $all_meta as $name => $value ) {
if ( 0 !== strpos( $name, 'attribute_' ) ) {
continue;
}
/**
* Pre 2.4 handling where 'slugs' were saved instead of the full text attribute.
* Attempt to get full version of the text attribute from the parent.
*/
if ( sanitize_title( $value[0] ) === $value[0] && version_compare( get_post_meta( $this->id, '_product_version', true ), '2.4.0', '<' ) ) {
$attributes = $this->parent->get_attributes();
foreach ( $attributes as $attribute ) {
if ( $name !== 'attribute_' . sanitize_title( $attribute['name'] ) ) {
continue;
}
$text_attributes = wc_get_text_attributes( $attribute['value'] );
foreach ( $text_attributes as $text_attribute ) {
if ( sanitize_title( $text_attribute ) === $value[0] ) {
$value[0] = $text_attribute;
}
}
}
}
$this->variation_data[ $name ] = $value[0];
}
return $this->variation_data;
return $this->variation_data = wc_get_product_variation_attributes( $this->variation_id );
} elseif ( 'variation_has_stock' === $key ) {
return $this->managing_stock();
@ -196,7 +163,7 @@ class WC_Product_Variation extends WC_Product {
* @return string
*/
public function get_permalink( $cart_item = null ) {
return add_query_arg( array_filter( isset( $cart_item['variation'] ) ? $cart_item['variation'] : $this->variation_data ), get_permalink( $this->id ) );
return add_query_arg( array_map( 'urlencode', array_filter( isset( $cart_item['variation'] ) ? $cart_item['variation'] : $this->variation_data ) ), get_permalink( $this->id ) );
}
/**

View File

@ -155,16 +155,17 @@ class WC_Gateway_Paypal_Request {
* @return array
*/
protected function get_line_item_args( $order ) {
/**
* Try passing a line item per product if supported
*/
if ( ( ! wc_tax_enabled() || ! wc_prices_include_tax() ) && $this->prepare_line_items( $order ) ) {
$line_item_args = $this->get_line_items();
$line_item_args['tax_cart'] = $order->get_total_tax();
$line_item_args['tax_cart'] = $this->number_format( $order->get_total_tax(), $order );
if ( $order->get_total_discount() > 0 ) {
$line_item_args['discount_amount_cart'] = round( $order->get_total_discount(), 2 );
$line_item_args['discount_amount_cart'] = $this->round( $order->get_total_discount(), $order );
}
/**
@ -176,8 +177,9 @@ class WC_Gateway_Paypal_Request {
$this->delete_line_items();
$this->add_line_item( $this->get_order_item_names( $order ), 1, number_format( $order->get_total() - round( $order->get_total_shipping() + $order->get_shipping_tax(), 2 ), 2, '.', '' ), $order->get_order_number() );
$this->add_line_item( sprintf( __( 'Shipping via %s', 'woocommerce' ), ucwords( $order->get_shipping_method() ) ), 1, number_format( $order->get_total_shipping() + $order->get_shipping_tax(), 2, '.', '' ) );
$all_items_name = $this->get_order_item_names( $order );
$this->add_line_item( $all_items_name ? $all_items_name : __( 'Order', 'woocommerce' ), 1, $this->number_format( $order->get_total() - $this->round( $order->get_total_shipping() + $order->get_shipping_tax(), $order ), $order ), $order->get_order_number() );
$this->add_line_item( sprintf( __( 'Shipping via %s', 'woocommerce' ), ucwords( $order->get_shipping_method() ) ), 1, $this->number_format( $order->get_total_shipping() + $order->get_shipping_tax(), $order ) );
$line_item_args = $this->get_line_items();
}
@ -244,12 +246,14 @@ class WC_Gateway_Paypal_Request {
// Products
foreach ( $order->get_items( array( 'line_item', 'fee' ) ) as $item ) {
if ( 'fee' === $item['type'] ) {
$line_item = $this->add_line_item( $item['name'], 1, $item['line_total'] );
$calculated_total += $item['line_total'];
$item_line_total = $this->number_format( $item['line_total'], $order );
$line_item = $this->add_line_item( $item['name'], 1, $item_line_total );
$calculated_total += $item_line_total;
} else {
$product = $order->get_product_from_item( $item );
$line_item = $this->add_line_item( $this->get_order_item_name( $order, $item ), $item['qty'], $order->get_item_subtotal( $item, false ), $product->get_sku() );
$calculated_total += $order->get_item_subtotal( $item, false ) * $item['qty'];
$item_line_total = $this->number_format( $order->get_item_subtotal( $item, false ), $order );
$line_item = $this->add_line_item( $this->get_order_item_name( $order, $item ), $item['qty'], $item_line_total, $product->get_sku() );
$calculated_total += $item_line_total * $item['qty'];
}
if ( ! $line_item ) {
@ -258,12 +262,12 @@ class WC_Gateway_Paypal_Request {
}
// Shipping Cost item - paypal only allows shipping per item, we want to send shipping for the order
if ( $order->get_total_shipping() > 0 && ! $this->add_line_item( sprintf( __( 'Shipping via %s', 'woocommerce' ), $order->get_shipping_method() ), 1, round( $order->get_total_shipping(), 2 ) ) ) {
if ( $order->get_total_shipping() > 0 && ! $this->add_line_item( sprintf( __( 'Shipping via %s', 'woocommerce' ), $order->get_shipping_method() ), 1, $this->round( $order->get_total_shipping(), $order ) ) ) {
return false;
}
// Check for mismatched totals
if ( wc_format_decimal( $calculated_total + $order->get_total_tax() + round( $order->get_total_shipping(), 2 ) - round( $order->get_total_discount(), 2 ), 2 ) != wc_format_decimal( $order->get_total(), 2 ) ) {
if ( $this->number_format( $calculated_total + $order->get_total_tax() + $this->round( $order->get_total_shipping(), $order ) - $this->round( $order->get_total_discount(), $order ), $order ) != $this->number_format( $order->get_total(), $order ) ) {
return false;
}
@ -281,11 +285,11 @@ class WC_Gateway_Paypal_Request {
protected function add_line_item( $item_name, $quantity = 1, $amount = 0, $item_number = '' ) {
$index = ( sizeof( $this->line_items ) / 4 ) + 1;
if ( ! $item_name || $amount < 0 || $index > 9 ) {
if ( $amount < 0 || $index > 9 ) {
return false;
}
$this->line_items[ 'item_name_' . $index ] = html_entity_decode( wc_trim_string( $item_name, 127 ), ENT_NOQUOTES, 'UTF-8' );
$this->line_items[ 'item_name_' . $index ] = html_entity_decode( wc_trim_string( $item_name ? $item_name : __( 'Item', 'woocommerce' ), 127 ), ENT_NOQUOTES, 'UTF-8' );
$this->line_items[ 'quantity_' . $index ] = $quantity;
$this->line_items[ 'amount_' . $index ] = $amount;
$this->line_items[ 'item_number_' . $index ] = $item_number;
@ -312,4 +316,55 @@ class WC_Gateway_Paypal_Request {
return $state;
}
/**
* Check if currency has decimals
*
* @param string $currency
*
* @return bool
*/
protected function currency_has_decimals( $currency ) {
if ( in_array( $currency, array( 'HUF', 'JPY', 'TWD' ) ) ) {
return false;
}
return true;
}
/**
* Round prices
*
* @param float|int $price
* @param WC_Order $order
*
* @return float|int
*/
protected function round( $price, $order ) {
$precision = 2;
if ( ! $this->currency_has_decimals( $order->get_order_currency() ) ) {
$precision = 0;
}
return round( $price, $precision );
}
/**
* Format prices
*
* @param float|int $price
* @param WC_Order $order
*
* @return float|int
*/
protected function number_format( $price, $order ) {
$decimals = 2;
if ( ! $this->currency_has_decimals( $order->get_order_currency() ) ) {
$decimals = 0;
}
return number_format( $price, $decimals, '.', '' );
}
}

View File

@ -0,0 +1,177 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Simplify Commerce Gateway for Subscriptions < 2.0
*
* @class WC_Addons_Gateway_Simplify_Commerce_Deprecated
* @extends WC_Addons_Gateway_Simplify_Commerce
* @since 2.4.0
* @version 1.0.0
* @package WooCommerce/Classes/Payment
* @author WooThemes
*/
class WC_Addons_Gateway_Simplify_Commerce_Deprecated extends WC_Addons_Gateway_Simplify_Commerce {
/**
* Constructor
*/
public function __construct() {
parent::__construct();
if ( class_exists( 'WC_Subscriptions_Order' ) ) {
add_action( 'scheduled_subscription_payment_' . $this->id, array( $this, 'process_scheduled_subscription_payment' ), 10, 3 );
add_filter( 'woocommerce_subscriptions_renewal_order_meta_query', array( $this, 'remove_renewal_order_meta' ), 10, 4 );
add_action( 'woocommerce_subscriptions_changed_failing_payment_method_' . $this->id, array( $this, 'change_failing_payment_method' ), 10, 3 );
}
}
/**
* Store the customer and card IDs on the order and subscriptions in the order
*
* @param int $order_id
* @param string $customer_id
* @return array
*/
protected function save_subscription_meta( $order_id, $customer_id ) {
update_post_meta( $order_id, '_simplify_customer_id', wc_clean( $customer_id ) );
}
/**
* process_subscription_payment function.
*
* @param WC_order $order
* @param integer $amount (default: 0)
* @uses Simplify_BadRequestException
* @return bool|WP_Error
*/
public function process_subscription_payment( $order, $amount = 0 ) {
if ( 0 == $amount ) {
// Payment complete
$order->payment_complete();
return true;
}
if ( $amount * 100 < 50 ) {
return new WP_Error( 'simplify_error', __( 'Sorry, the minimum allowed order total is 0.50 to use this payment method.', 'woocommerce' ) );
}
$order_items = $order->get_items();
$order_item = array_shift( $order_items );
$subscription_name = sprintf( __( '%s - Subscription for "%s"', 'woocommerce' ), esc_html( get_bloginfo( 'name', 'display' ) ), $order_item['name'] ) . ' ' . sprintf( __( '(Order #%s)', 'woocommerce' ), $order->get_order_number() );
$customer_id = get_post_meta( $order->id, '_simplify_customer_id', true );
if ( ! $customer_id ) {
return new WP_Error( 'simplify_error', __( 'Customer not found', 'woocommerce' ) );
}
try {
// Charge the customer
$payment = Simplify_Payment::createPayment( array(
'amount' => $amount * 100, // In cents
'customer' => $customer_id,
'description' => trim( substr( $subscription_name, 0, 1024 ) ),
'currency' => strtoupper( get_woocommerce_currency() ),
'reference' => $order->id,
'card.addressCity' => $order->billing_city,
'card.addressCountry' => $order->billing_country,
'card.addressLine1' => $order->billing_address_1,
'card.addressLine2' => $order->billing_address_2,
'card.addressState' => $order->billing_state,
'card.addressZip' => $order->billing_postcode
) );
} catch ( Exception $e ) {
$error_message = $e->getMessage();
if ( $e instanceof Simplify_BadRequestException && $e->hasFieldErrors() && $e->getFieldErrors() ) {
$error_message = '';
foreach ( $e->getFieldErrors() as $error ) {
$error_message .= ' ' . $error->getFieldName() . ': "' . $error->getMessage() . '" (' . $error->getErrorCode() . ')';
}
}
$order->add_order_note( sprintf( __( 'Simplify payment error: %s', 'woocommerce' ), $error_message ) );
return new WP_Error( 'simplify_payment_declined', $e->getMessage(), array( 'status' => $e->getCode() ) );
}
if ( 'APPROVED' == $payment->paymentStatus ) {
// Payment complete
$order->payment_complete( $payment->id );
// Add order note
$order->add_order_note( sprintf( __( 'Simplify payment approved (ID: %s, Auth Code: %s)', 'woocommerce' ), $payment->id, $payment->authCode ) );
return true;
} else {
$order->add_order_note( __( 'Simplify payment declined', 'woocommerce' ) );
return new WP_Error( 'simplify_payment_declined', __( 'Payment was declined - please try another card.', 'woocommerce' ) );
}
}
/**
* process_scheduled_subscription_payment function.
*
* @param float $amount_to_charge The amount to charge.
* @param WC_Order $order The WC_Order object of the order which the subscription was purchased in.
* @param int $product_id The ID of the subscription product for which this payment relates.
*/
public function process_scheduled_subscription_payment( $amount_to_charge, $order, $product_id ) {
$result = $this->process_subscription_payment( $order, $amount_to_charge );
if ( is_wp_error( $result ) ) {
WC_Subscriptions_Manager::process_subscription_payment_failure_on_order( $order, $product_id );
} else {
WC_Subscriptions_Manager::process_subscription_payments_on_order( $order );
}
}
/**
* Don't transfer customer meta when creating a parent renewal order.
*
* @param string $order_meta_query MySQL query for pulling the metadata
* @param int $original_order_id Post ID of the order being used to purchased the subscription being renewed
* @param int $renewal_order_id Post ID of the order created for renewing the subscription
* @param string $new_order_role The role the renewal order is taking, one of 'parent' or 'child'
* @return string
*/
public function remove_renewal_order_meta( $order_meta_query, $original_order_id, $renewal_order_id, $new_order_role ) {
if ( 'parent' == $new_order_role ) {
$order_meta_query .= " AND `meta_key` NOT LIKE '_simplify_customer_id' ";
}
return $order_meta_query;
}
/**
* Check if order contains subscriptions.
*
* @param int $order_id
* @return bool
*/
protected function order_contains_subscription( $order_id ) {
return class_exists( 'WC_Subscriptions_Order' ) && ( WC_Subscriptions_Order::order_contains_subscription( $order_id ) || WC_Subscriptions_Renewal_Order::is_renewal( $order_id ) );
}
/**
* Update the customer_id for a subscription after using Simplify to complete a payment to make up for
* an automatic renewal payment which previously failed.
*
* @param WC_Order $original_order The original order in which the subscription was purchased.
* @param WC_Order $renewal_order The order which recorded the successful payment (to make up for the failed automatic payment).
* @param string $subscription_key A subscription key of the form created by @see WC_Subscriptions_Manager::get_subscription_key()
*/
public function change_failing_payment_method( $original_order, $renewal_order, $subscription_key ) {
$new_customer_id = get_post_meta( $renewal_order->id, '_simplify_customer_id', true );
update_post_meta( $original_order->id, '_simplify_customer_id', $new_customer_id );
}
}

View File

@ -23,9 +23,14 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
parent::__construct();
if ( class_exists( 'WC_Subscriptions_Order' ) ) {
add_action( 'scheduled_subscription_payment_' . $this->id, array( $this, 'scheduled_subscription_payment' ), 10, 3 );
add_filter( 'woocommerce_subscriptions_renewal_order_meta_query', array( $this, 'remove_renewal_order_meta' ), 10, 4 );
add_action( 'woocommerce_subscriptions_changed_failing_payment_method_' . $this->id, array( $this, 'update_failing_payment_method' ), 10, 3 );
add_action( 'woocommerce_scheduled_subscription_payment_' . $this->id, array( $this, 'scheduled_subscription_payment' ), 10, 2 );
add_action( 'woocommerce_subscription_failing_payment_method_updated_' . $this->id, array( $this, 'update_failing_payment_method' ), 10, 2 );
add_action( 'wcs_resubscribe_order_created', array( $this, 'delete_resubscribe_meta' ), 10 );
// Allow store managers to manually set Simplify as the payment method on a subscription
add_filter( 'woocommerce_subscription_payment_meta', array( $this, 'add_subscription_payment_meta' ), 10, 2 );
add_filter( 'woocommerce_subscription_validate_payment_meta', array( $this, 'validate_subscription_payment_meta' ), 10, 2 );
}
if ( class_exists( 'WC_Pre_Orders_Order' ) ) {
@ -60,7 +65,7 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
* @return bool
*/
protected function order_contains_subscription( $order_id ) {
return class_exists( 'WC_Subscriptions_Order' ) && ( WC_Subscriptions_Order::order_contains_subscription( $order_id ) || WC_Subscriptions_Renewal_Order::is_renewal( $order_id ) );
return function_exists( 'wcs_order_contains_subscription' ) && ( wcs_order_contains_subscription( $order_id ) || wcs_order_contains_renewal( $order_id ) );
}
/**
@ -103,18 +108,14 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
) );
if ( is_object( $customer ) && '' != $customer->id ) {
$customer_id = wc_clean( $customer->id );
// Store the customer ID in the order
update_post_meta( $order->id, '_simplify_customer_id', $customer_id );
$this->save_subscription_meta( $order->id, $customer->id );
} else {
$error_msg = __( 'Error creating user in Simplify Commerce.', 'woocommerce' );
throw new Simplify_ApiException( $error_msg );
}
$initial_payment = WC_Subscriptions_Order::get_total_initial_payment( $order );
$payment_response = $this->process_subscription_payment( $order, $initial_payment );
$payment_response = $this->process_subscription_payment( $order, $order->get_total() );
if ( is_wp_error( $payment_response ) ) {
throw new Exception( $payment_response->get_error_message() );
@ -145,6 +146,24 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
}
}
/**
* Store the customer and card IDs on the order and subscriptions in the order
*
* @param int $order_id
* @param string $customer_id
*/
protected function save_subscription_meta( $order_id, $customer_id ) {
$customer_id = wc_clean( $customer_id );
update_post_meta( $order_id, '_simplify_customer_id', $customer_id );
// Also store it on the subscriptions being purchased in the order
foreach( wcs_get_subscriptions_for_order( $order_id ) as $subscription ) {
update_post_meta( $subscription->id, '_simplify_customer_id', $customer_id );
}
}
/**
* Process the pre-order
*
@ -239,7 +258,7 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
$order = wc_get_order( $order_id );
// Processing subscription
if ( 'standard' == $this->mode && $this->order_contains_subscription( $order->id ) ) {
if ( 'standard' == $this->mode && ( $this->order_contains_subscription( $order->id ) || ( function_exists( 'wcs_is_subscription' ) && wcs_is_subscription( $order_id ) ) ) ) {
return $this->process_subscription( $order, $cart_token );
// Processing pre-order
@ -272,10 +291,6 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
return new WP_Error( 'simplify_error', __( 'Sorry, the minimum allowed order total is 0.50 to use this payment method.', 'woocommerce' ) );
}
$order_items = $order->get_items();
$order_item = array_shift( $order_items );
$subscription_name = sprintf( __( '%s - Subscription for "%s"', 'woocommerce' ), esc_html( get_bloginfo( 'name', 'display' ) ), $order_item['name'] ) . ' ' . sprintf( __( '(Order #%s)', 'woocommerce' ), $order->get_order_number() );
$customer_id = get_post_meta( $order->id, '_simplify_customer_id', true );
if ( ! $customer_id ) {
@ -287,7 +302,7 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
$payment = Simplify_Payment::createPayment( array(
'amount' => $amount * 100, // In cents
'customer' => $customer_id,
'description' => trim( substr( $subscription_name, 0, 1024 ) ),
'description' => sprintf( __( '%s - Order #%s', 'woocommerce' ), esc_html( get_bloginfo( 'name', 'display' ) ), $order->get_order_number() ),
'currency' => strtoupper( get_woocommerce_currency() ),
'reference' => $order->id,
'card.addressCity' => $order->billing_city,
@ -333,48 +348,76 @@ class WC_Addons_Gateway_Simplify_Commerce extends WC_Gateway_Simplify_Commerce {
* scheduled_subscription_payment function.
*
* @param float $amount_to_charge The amount to charge.
* @param WC_Order $order The WC_Order object of the order which the subscription was purchased in.
* @param int $product_id The ID of the subscription product for which this payment relates.
* @param WC_Order $renewal_order A WC_Order object created to record the renewal payment.
*/
public function scheduled_subscription_payment( $amount_to_charge, $order, $product_id ) {
$result = $this->process_subscription_payment( $order, $amount_to_charge );
public function scheduled_subscription_payment( $amount_to_charge, $renewal_order ) {
$result = $this->process_subscription_payment( $renewal_order, $amount_to_charge );
if ( is_wp_error( $result ) ) {
WC_Subscriptions_Manager::process_subscription_payment_failure_on_order( $order, $product_id );
} else {
WC_Subscriptions_Manager::process_subscription_payments_on_order( $order );
$renewal_order->update_status( 'failed', sprintf( __( 'Simplify Transaction Failed (%s)', 'woocommerce' ), $result->get_error_message() ) );
}
}
/**
* Don't transfer customer meta when creating a parent renewal order.
*
* @param string $order_meta_query MySQL query for pulling the metadata
* @param int $original_order_id Post ID of the order being used to purchased the subscription being renewed
* @param int $renewal_order_id Post ID of the order created for renewing the subscription
* @param string $new_order_role The role the renewal order is taking, one of 'parent' or 'child'
* @return string
*/
public function remove_renewal_order_meta( $order_meta_query, $original_order_id, $renewal_order_id, $new_order_role ) {
if ( 'parent' == $new_order_role ) {
$order_meta_query .= " AND `meta_key` NOT LIKE '_simplify_customer_id' ";
}
return $order_meta_query;
}
/**
* Update the customer_id for a subscription after using Simplify to complete a payment to make up for
* an automatic renewal payment which previously failed.
*
* @param WC_Order $original_order The original order in which the subscription was purchased.
* @param WC_Subscription $subscription The subscription for which the failing payment method relates.
* @param WC_Order $renewal_order The order which recorded the successful payment (to make up for the failed automatic payment).
* @param string $subscription_key A subscription key of the form created by @see WC_Subscriptions_Manager::get_subscription_key()
*/
public function update_failing_payment_method( $original_order, $renewal_order, $subscription_key ) {
$new_customer_id = get_post_meta( $renewal_order->id, '_simplify_customer_id', true );
public function update_failing_payment_method( $subscription, $renewal_order ) {
update_post_meta( $original_order->id, '_simplify_customer_id', get_post_meta( $renewal_order->id, '_simplify_customer_id', true ) );
}
update_post_meta( $original_order->id, '_simplify_customer_id', $new_customer_id );
/**
* Include the payment meta data required to process automatic recurring payments so that store managers can
* manually set up automatic recurring payments for a customer via the Edit Subscription screen in Subscriptions v2.0+.
*
* @since 2.4
* @param array $payment_meta associative array of meta data required for automatic payments
* @param WC_Subscription $subscription An instance of a subscription object
* @return array
*/
public function add_subscription_payment_meta( $payment_meta, $subscription ) {
$payment_meta[ $this->id ] = array(
'post_meta' => array(
'_simplify_customer_id' => array(
'value' => get_post_meta( $subscription->id, '_simplify_customer_id', true ),
'label' => 'Simplify Customer ID',
),
),
);
return $payment_meta;
}
/**
* Validate the payment meta data required to process automatic recurring payments so that store managers can
* manually set up automatic recurring payments for a customer via the Edit Subscription screen in Subscriptions 2.0+.
*
* @since 2.4
* @param string $payment_method_id The ID of the payment method to validate
* @param array $payment_meta associative array of meta data required for automatic payments
* @return array
*/
public function validate_subscription_payment_meta( $payment_method_id, $payment_meta ) {
if ( $this->id === $payment_method_id ) {
if ( ! isset( $payment_meta['post_meta']['_simplify_customer_id']['value'] ) || empty( $payment_meta['post_meta']['_simplify_customer_id']['value'] ) ) {
throw new Exception( 'A "_simplify_customer_id" value is required.' );
}
}
}
/**
* Don't transfer customer meta to resubscribe orders.
*
* @access public
* @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
* @return void
*/
public function delete_resubscribe_meta( $resubscribe_order ) {
delete_post_meta( $resubscribe_order->id, '_simplify_customer_id' );
}
/**

View File

@ -31,8 +31,11 @@ class WC_Gateway_Simplify_Commerce extends WC_Payment_Gateway {
'subscription_reactivation',
'subscription_suspension',
'subscription_amount_changes',
'subscription_payment_method_change',
'subscription_payment_method_change', // Subscriptions 1.n compatibility
'subscription_payment_method_change_customer',
'subscription_payment_method_change_admin',
'subscription_date_changes',
'multiple_subscriptions',
'default_credit_card_form',
'refunds',
'pre-orders'

View File

@ -100,7 +100,7 @@ if ( WC()->shipping->get_shipping_classes() ) {
);
}
if ( $this->get_option( 'options', false ) ) {
if ( apply_filters( 'woocommerce_enable_deprecated_additional_flat_rates', $this->get_option( 'options', false ) ) ) {
$settings[ 'additional_rates' ] = array(
'title' => __( 'Additional Rates', 'woocommerce' ),
'type' => 'title',

View File

@ -287,3 +287,19 @@ function wc_cart_totals_shipping_method_label( $method ) {
return apply_filters( 'woocommerce_cart_shipping_method_full_label', $label, $method );
}
/**
* Round discount
*
* @param float $value
* @param int $precision
* @return float
*/
function wc_cart_round_discount( $value, $precision ) {
if ( version_compare( PHP_VERSION, '5.3.0', '>=' ) ) {
return round( $value, $precision, WC_DISCOUNT_ROUNDING_MODE );
} else {
return round( $value, $precision );
}
}

View File

@ -264,21 +264,20 @@ if ( ! function_exists( 'meta_is_product_attribute' ) ) {
/**
* Returns true when the passed meta name is a product attribute.
* @param string $name of the attribute
* @param mixed $value
* @param string $value
* @param int $product_id
* @return bool
*/
function meta_is_product_attribute( $name, $value, $product_id ) {
$product = wc_get_product( $product_id );
if ( $product->product_type != 'variable' ) {
if ( $product && method_exists( $product, 'get_variation_attributes' ) ) {
$variation_attributes = $product->get_variation_attributes();
$attributes = $product->get_attributes();
return ( in_array( $name, array_keys( $attributes ) ) && in_array( $value, $variation_attributes[ $attributes[ $name ]['name'] ] ) );
} else {
return false;
}
$variation_attributes = $product->get_variation_attributes();
$attributes = $product->get_attributes();
return ( in_array( $name, array_keys( $attributes ) ) && in_array( $value, $variation_attributes[ $attributes[ $name ]['name'] ] ) );
}
}

View File

@ -719,8 +719,9 @@ function wc_create_refund( $args = array() ) {
// Figure out if this is just a partial refund
$max_remaining_refund = wc_format_decimal( $order->get_total() - $order->get_total_refunded() );
$max_remaining_items = absint( $order->get_item_count() - $order->get_item_count_refunded() );
if ( $max_remaining_refund > 0 ) {
if ( $max_remaining_refund > 0 || $max_remaining_items > 0 ) {
do_action( 'woocommerce_order_partially_refunded', $args['order_id'], true, $refund_id );
}

View File

@ -613,3 +613,59 @@ function _wc_save_product_price( $product_id, $regular_price, $sale_price = '',
update_post_meta( $product_id, '_sale_price_dates_to', '' );
}
}
/**
* Get attibutes/data for an individual variation from the database and maintain it's integrity.
* @since 2.4.0
* @param int $variation_id
* @return array
*/
function wc_get_product_variation_attributes( $variation_id ) {
// Build variation data from meta
$all_meta = get_post_meta( $variation_id );
$parent_id = wp_get_post_parent_id( $variation_id );
$parent_attributes = array_filter( (array) get_post_meta( $parent_id, '_product_attributes', true ) );
$found_parent_attributes = array();
$variation_attributes = array();
// Compare to parent variable product attributes and ensure they match
foreach ( $parent_attributes as $attribute_name => $options ) {
$attribute = 'attribute_' . sanitize_title( $attribute_name );
$found_parent_attributes[] = $attribute;
if ( ! array_key_exists( $attribute, $variation_attributes ) ) {
$variation_attributes[ $attribute ] = ''; // Add it - 'any' will be asumed
}
}
// Get the variation attributes from meta
foreach ( $all_meta as $name => $value ) {
// Only look at valid attribute meta, and also compare variation level attributes and remove any which do not exist at parent level
if ( 0 !== strpos( $name, 'attribute_' ) || ! in_array( $name, $found_parent_attributes ) ) {
unset( $variation_attributes[ $name ] );
continue;
}
/**
* Pre 2.4 handling where 'slugs' were saved instead of the full text attribute.
* Attempt to get full version of the text attribute from the parent.
*/
if ( sanitize_title( $value[0] ) === $value[0] && version_compare( get_post_meta( $parent_id, '_product_version', true ), '2.4.0', '<' ) ) {
foreach ( $parent_attributes as $attribute ) {
if ( $name !== 'attribute_' . sanitize_title( $attribute['name'] ) ) {
continue;
}
$text_attributes = wc_get_text_attributes( $attribute['value'] );
foreach ( $text_attributes as $text_attribute ) {
if ( sanitize_title( $text_attribute ) === $value[0] ) {
$value[0] = $text_attribute;
break;
}
}
}
}
$variation_attributes[ $name ] = $value[0];
}
return $variation_attributes;
}

View File

@ -4,10 +4,10 @@
*
* Functions for the templating system.
*
* @author WooThemes
* @category Core
* @package WooCommerce/Functions
* @version 2.1.0
* @author WooThemes
* @category Core
* @package WooCommerce/Functions
* @version 2.4.0
*/
if ( ! defined( 'ABSPATH' ) ) {
@ -507,6 +507,15 @@ if ( ! function_exists( 'woocommerce_product_loop_end' ) ) {
return ob_get_clean();
}
}
if ( ! function_exists( 'woocommerce_template_loop_product_title' ) ) {
/**
* Show the product title in the product loop. By default this is an H3
*/
function woocommerce_template_loop_product_title() {
wc_get_template( 'loop/title.php' );
}
}
if ( ! function_exists( 'woocommerce_taxonomy_archive_description' ) ) {
/**
@ -1856,3 +1865,91 @@ if ( ! function_exists( 'woocommerce_output_auth_footer' ) ) {
wc_get_template( 'auth/footer.php' );
}
}
if ( ! function_exists( 'woocommerce_single_variation' ) ) {
/**
* Output placeholders for the single variation.
*/
function woocommerce_single_variation() {
echo '<div class="single_variation"></div>';
}
}
if ( ! function_exists( 'woocommerce_single_variation_add_to_cart_button' ) ) {
/**
* Output the add to cart button for variations.
*/
function woocommerce_single_variation_add_to_cart_button() {
global $product;
?>
<div class="variations_button">
<?php woocommerce_quantity_input( array( 'input_value' => isset( $_POST['quantity'] ) ? wc_stock_amount( $_POST['quantity'] ) : 1 ) ); ?>
<button type="submit" class="single_add_to_cart_button button alt"><?php echo esc_html( $product->single_add_to_cart_text() ); ?></button>
<input type="hidden" name="add-to-cart" value="<?php echo absint( $product->id ); ?>" />
<input type="hidden" name="product_id" value="<?php echo absint( $product->id ); ?>" />
<input type="hidden" name="variation_id" class="variation_id" value="" />
</div>
<?php
}
}
if ( ! function_exists( 'wc_dropdown_variation_attribute_options' ) ) {
/**
* Output a list of variation attributes for use in the cart forms.
*
* @param array $args
* @since 2.4.0
*/
function wc_dropdown_variation_attribute_options( $args = array() ) {
$args = wp_parse_args( $args, array(
'options' => false,
'attribute' => false,
'product' => false,
'selected' => false,
'name' => '',
'id' => '',
'show_option_none' => __( 'Choose an option', 'woocommerce' )
) );
$options = $args['options'];
$product = $args['product'];
$attribute = $args['attribute'];
$name = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
$id = $args['id'] ? $args['id'] : sanitize_title( $attribute );
if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
$attributes = $product->get_variation_attributes();
$options = $attributes[ $attribute ];
}
echo '<select id="' . esc_attr( $id ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '">';
if ( $args['show_option_none'] ) {
echo '<option value="">' . esc_html( $args['show_option_none'] ) . '</option>';
}
if ( ! empty( $options ) ) {
if ( $product && taxonomy_exists( $attribute ) ) {
// Get terms if this is a taxonomy - ordered. We need the names too.
$terms = wc_get_product_terms( $product->id, $attribute, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( in_array( $term->slug, $options ) ) {
echo '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . apply_filters( 'woocommerce_variation_option_name', $term->name ) . '</option>';
}
}
} else {
foreach ( $options as $option ) {
// This handles < 2.4.0 bw compatibility where text attributes were not sanitized.
$selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
echo '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>';
}
}
}
echo '</select>';
}
}

View File

@ -88,6 +88,7 @@ add_action( 'woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30 )
*/
add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
add_action( 'woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10 );
add_action( 'woocommerce_shop_loop_item_title', 'woocommerce_template_loop_product_title', 10 );
add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_rating', 5 );
@ -148,6 +149,8 @@ add_action( 'woocommerce_simple_add_to_cart', 'woocommerce_simple_add_to_cart',
add_action( 'woocommerce_grouped_add_to_cart', 'woocommerce_grouped_add_to_cart', 30 );
add_action( 'woocommerce_variable_add_to_cart', 'woocommerce_variable_add_to_cart', 30 );
add_action( 'woocommerce_external_add_to_cart', 'woocommerce_external_add_to_cart', 30 );
add_action( 'woocommerce_single_variation', 'woocommerce_single_variation', 10 );
add_action( 'woocommerce_single_variation', 'woocommerce_single_variation_add_to_cart_button', 20 );
/**
* Pagination after shop loops

View File

@ -50,7 +50,7 @@ class WC_Widget_Cart extends WC_Widget {
* @param array $instance
*/
public function widget( $args, $instance ) {
if ( is_cart() || is_checkout() ) {
if ( apply_filters( 'woocommerce_widget_cart_is_hidden', is_cart() || is_checkout() ) ) {
return;
}

View File

@ -6,7 +6,7 @@
*
* @author WooThemes
* @package WooCommerce/Templates
* @version 1.6.4
* @version 2.4.0
*/
if ( ! defined( 'ABSPATH' ) ) {
@ -56,11 +56,14 @@ if ( 0 == $woocommerce_loop['loop'] % $woocommerce_loop['columns'] ) {
* @hooked woocommerce_template_loop_product_thumbnail - 10
*/
do_action( 'woocommerce_before_shop_loop_item_title' );
?>
<h3><?php the_title(); ?></h3>
/**
* woocommerce_shop_loop_item_title hook
*
* @hooked woocommerce_template_loop_product_title - 10
*/
do_action( 'woocommerce_shop_loop_item_title' );
<?php
/**
* woocommerce_after_shop_loop_item_title hook
*

View File

@ -16,12 +16,12 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
<h2><a class="link" href="<?php echo admin_url( 'post.php?post=' . $order->id . '&action=edit' ); ?>"><?php printf( __( 'Order: %s', 'woocommerce'), $order->get_order_number() ); ?></a> (<?php printf( '<time datetime="%s">%s</time>', date_i18n( 'c', strtotime( $order->order_date ) ), date_i18n( wc_date_format(), strtotime( $order->order_date ) ) ); ?>)</h2>
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%;" border="1">
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;" border="1">
<thead>
<tr>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Price', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
@ -34,8 +34,8 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
foreach ( $totals as $total ) {
$i++;
?><tr>
<th class="td" scope="row" colspan="2" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
<th class="td" scope="row" colspan="2" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
</tr><?php
}
}

View File

@ -21,12 +21,12 @@ if ( ! defined( 'ABSPATH' ) ) {
<h2><a class="link" href="<?php echo admin_url( 'post.php?post=' . $order->id . '&action=edit' ); ?>"><?php printf( __( 'Order #%s', 'woocommerce'), $order->get_order_number() ); ?></a> (<?php printf( '<time datetime="%s">%s</time>', date_i18n( 'c', strtotime( $order->order_date ) ), date_i18n( wc_date_format(), strtotime( $order->order_date ) ) ); ?>)</h2>
<table cellspacing="0" cellpadding="6" style="width: 100%;" border="1" class="td">
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;" border="1">
<thead>
<tr>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Price', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
@ -40,7 +40,7 @@ if ( ! defined( 'ABSPATH' ) ) {
$i++;
?><tr>
<th class="td" scope="col" colspan="2" style="font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
<td class="td" scope="col" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
</tr><?php
}
}

View File

@ -21,12 +21,12 @@ if ( ! defined( 'ABSPATH' ) ) {
<h2><?php printf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ); ?></h2>
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%;" border="1">
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;" border="1">
<thead>
<tr>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Price', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
@ -39,8 +39,8 @@ if ( ! defined( 'ABSPATH' ) ) {
foreach ( $totals as $total ) {
$i++;
?><tr>
<th class="td" scope="row" colspan="2" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
<th class="td" scope="row" colspan="2" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
</tr><?php
}
}

View File

@ -25,12 +25,12 @@ if ( ! defined( 'ABSPATH' ) ) {
<h2><?php printf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ); ?> (<?php printf( '<time datetime="%s">%s</time>', date_i18n( 'c', strtotime( $order->order_date ) ), date_i18n( wc_date_format(), strtotime( $order->order_date ) ) ); ?>)</h2>
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%;" border="1">
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;" border="1">
<thead>
<tr>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Price', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
@ -55,8 +55,8 @@ if ( ! defined( 'ABSPATH' ) ) {
foreach ( $totals as $total ) {
$i++;
?><tr>
<th class="td" scope="row" colspan="2" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
<td class="td" colspan="2" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px !important;'; ?>"><?php echo $total['label']; ?></td>
<td class="td" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px !important;'; ?>"><?php echo strip_tags( $total['value'] ); ?></td>
</tr><?php
}
}

View File

@ -25,12 +25,12 @@ if ( ! defined( 'ABSPATH' ) ) {
<h2><?php printf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ); ?></h2>
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%;" border="1">
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;" border="1">
<thead>
<tr>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Price', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
@ -43,8 +43,8 @@ if ( ! defined( 'ABSPATH' ) ) {
foreach ( $totals as $total ) {
$i++;
?><tr>
<th class="td" scope="row" colspan="2" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
<th class="td" scope="row" colspan="2" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
</tr><?php
}
}

View File

@ -21,12 +21,12 @@ if ( ! defined( 'ABSPATH' ) ) {
<h2><?php printf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ); ?></h2>
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%;" border="1">
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;" border="1">
<thead>
<tr>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Price', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
@ -39,8 +39,8 @@ if ( ! defined( 'ABSPATH' ) ) {
foreach ( $totals as $total ) {
$i++;
?><tr>
<th class="td" scope="row" colspan="2" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
<th class="td" scope="row" colspan="2" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
</tr><?php
}
}

View File

@ -15,7 +15,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php do_action( 'woocommerce_email_header', $email_heading ); ?>
<p><?php
<p><?php
if ( $partial_refund ) {
printf( __( "Hi there. Your order on %s has been partially refunded.", 'woocommerce' ), get_option( 'blogname' ) );
}
@ -28,12 +28,12 @@ if ( ! defined( 'ABSPATH' ) ) {
<h2><?php printf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ); ?></h2>
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%;" border="1">
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;" border="1">
<thead>
<tr>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;"><?php _e( 'Price', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:left;"><?php _e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
@ -56,8 +56,8 @@ if ( ! defined( 'ABSPATH' ) ) {
foreach ( $totals as $total ) {
$i++;
?><tr>
<th class="td" scope="row" colspan="2" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" style="text-align:left; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
<th class="td" scope="row" colspan="2" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
<td class="td" style="text-align:left; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
</tr><?php
}
}

15
templates/loop/title.php Normal file
View File

@ -0,0 +1,15 @@
<?php
/**
* Product loop title
*
* @author WooThemes
* @package WooCommerce/Templates
* @version 2.4.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
?>
<h3><?php the_title(); ?></h3>

View File

@ -17,7 +17,7 @@ if ( $downloads = WC()->customer->get_downloadable_products() ) : ?>
<?php do_action( 'woocommerce_before_available_downloads' ); ?>
<h2><?php echo apply_filters( 'woocommerce_my_account_my_downloads_title', __( 'Available downloads', 'woocommerce' ) ); ?></h2>
<h2><?php echo apply_filters( 'woocommerce_my_account_my_downloads_title', __( 'Available Downloads', 'woocommerce' ) ); ?></h2>
<ul class="digital-downloads">
<?php foreach ( $downloads as $download ) : ?>

View File

@ -6,63 +6,34 @@
* @package WooCommerce/Templates
* @version 2.4.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $product, $post;
?>
global $product;
<?php do_action( 'woocommerce_before_add_to_cart_form' ); ?>
$attribute_keys = array_keys( $attributes );
<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo $post->ID; ?>" data-product_variations="<?php echo esc_attr( json_encode( $available_variations ) ) ?>">
do_action( 'woocommerce_before_add_to_cart_form' ); ?>
<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->id ); ?>" data-product_variations="<?php echo esc_attr( json_encode( $available_variations ) ) ?>">
<?php do_action( 'woocommerce_before_variations_form' ); ?>
<?php if ( ! empty( $available_variations ) || false === $available_variations ) : ?>
<?php if ( empty( $available_variations ) && false !== $available_variations ) : ?>
<p class="stock out-of-stock"><?php _e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></p>
<?php else : ?>
<table class="variations" cellspacing="0">
<tbody>
<?php $loop = 0; foreach ( $attributes as $name => $options ) : $loop++; ?>
<?php foreach ( $attributes as $attribute_name => $options ) : ?>
<tr>
<td class="label"><label for="<?php echo sanitize_title( $name ); ?>"><?php echo wc_attribute_label( $name ); ?></label></td>
<td class="value"><select id="<?php echo esc_attr( sanitize_title( $name ) ); ?>" name="attribute_<?php echo sanitize_title( $name ); ?>" data-attribute_name="attribute_<?php echo sanitize_title( $name ); ?>">
<option value=""><?php echo __( 'Choose an option', 'woocommerce' ) ?>&hellip;</option>
<td class="label"><label for="<?php echo sanitize_title( $attribute_name ); ?>"><?php echo wc_attribute_label( $attribute_name ); ?></label></td>
<td class="value">
<?php
if ( is_array( $options ) ) {
if ( isset( $_REQUEST[ 'attribute_' . sanitize_title( $name ) ] ) ) {
$selected_value = $_REQUEST[ 'attribute_' . sanitize_title( $name ) ];
} elseif ( isset( $selected_attributes[ sanitize_title( $name ) ] ) ) {
$selected_value = $selected_attributes[ sanitize_title( $name ) ];
} else {
$selected_value = '';
}
// Get terms if this is a taxonomy - ordered
if ( taxonomy_exists( $name ) ) {
$terms = wc_get_product_terms( $post->ID, $name, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( ! in_array( $term->slug, $options ) ) {
continue;
}
echo '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $selected_value ), sanitize_title( $term->slug ), false ) . '>' . apply_filters( 'woocommerce_variation_option_name', $term->name ) . '</option>';
}
} else {
foreach ( $options as $option ) {
echo '<option value="' . esc_attr( $option ) . '" ' . selected( $selected_value, $option, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option ) ) . '</option>';
}
}
}
$selected = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) : $product->get_variation_default_attribute( $attribute_name );
wc_dropdown_variation_attribute_options( array( 'options' => $options, 'attribute' => $attribute_name, 'product' => $product, 'selected' => $selected ) );
echo end( $attribute_keys ) === $attribute_name ? '<a class="reset_variations" href="#">' . __( 'Clear selection', 'woocommerce' ) . '</a>' : '';
?>
</select> <?php
if ( sizeof( $attributes ) === $loop ) {
echo '<a class="reset_variations" href="#">' . __( 'Clear selection', 'woocommerce' ) . '</a>';
}
?></td>
</td>
</tr>
<?php endforeach;?>
</tbody>
@ -71,34 +42,31 @@ global $product, $post;
<?php do_action( 'woocommerce_before_add_to_cart_button' ); ?>
<div class="single_variation_wrap" style="display:none;">
<?php do_action( 'woocommerce_before_single_variation' ); ?>
<?php
/**
* woocommerce_before_single_variation Hook
*/
do_action( 'woocommerce_before_single_variation' );
<div class="single_variation"></div>
/**
* woocommerce_single_variation hook. Used to output the cart button and placeholder for variation data.
* @since 2.4.0
* @hooked woocommerce_single_variation - 10 Empty div for variation data.
* @hooked woocommerce_single_variation_add_to_cart_button - 20 Qty and cart button.
*/
do_action( 'woocommerce_single_variation' );
<?php do_action( 'woocommerce_before_variations_button' ); ?>
<div class="variations_button">
<?php woocommerce_quantity_input( array(
'input_value' => ( isset( $_POST['quantity'] ) ? wc_stock_amount( $_POST['quantity'] ) : 1 )
) ); ?>
<button type="submit" class="single_add_to_cart_button button alt"><?php echo esc_html( $product->single_add_to_cart_text() ); ?></button>
</div>
<input type="hidden" name="add-to-cart" value="<?php echo $product->id; ?>" />
<input type="hidden" name="product_id" value="<?php echo esc_attr( $post->ID ); ?>" />
<input type="hidden" name="variation_id" class="variation_id" value="" />
<?php do_action( 'woocommerce_after_single_variation' ); ?>
/**
* woocommerce_after_single_variation Hook
*/
do_action( 'woocommerce_after_single_variation' );
?>
</div>
<?php do_action( 'woocommerce_after_add_to_cart_button' ); ?>
<?php else : ?>
<p class="stock out-of-stock"><?php _e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></p>
<?php endif; ?>
<?php do_action( 'woocommerce_after_variations_form' ); ?>
</form>
<?php do_action( 'woocommerce_after_add_to_cart_form' ); ?>

View File

@ -93,8 +93,8 @@ class WC_Helper_Product {
// Attributes
update_post_meta( $product_id, '_default_attributes', array() );
update_post_meta( $product_id, '_product_attributes', array(
'pa_dummyattribute' => array(
'name' => 'pa_dummyattribute',
'pa_size' => array(
'name' => 'pa_size',
'value' => '',
'position' => '1',
'is_visible' => 0,
@ -239,4 +239,4 @@ class WC_Helper_Product {
$wpdb->query( "DELETE FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_id = $attribute_id" );
}
}
}

View File

@ -66,6 +66,7 @@ class Main_Class extends \WC_Unit_Test_Case {
$this->assertInstanceOf( 'WC_Product_Factory', $this->wc->product_factory );
$this->assertInstanceOf( 'WC_Order_Factory', $this->wc->order_factory );
$this->assertInstanceOf( 'WC_Countries', $this->wc->countries );
$this->assertInstanceOf( 'WC_Integrations', $this->wc->integrations );
$this->assertInstanceOf( 'WC_Mock_Session_Handler', $this->wc->session );
$this->assertInstanceOf( 'WC_Cart', $this->wc->cart );
$this->assertInstanceOf( 'WC_Customer', $this->wc->customer );

View File

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