commit
f95ffe16d0
File diff suppressed because one or more lines are too long
|
@ -1182,6 +1182,11 @@ ul.wc_coupon_list_block {
|
|||
color: #bbbbbb;
|
||||
}
|
||||
}
|
||||
.shipping_method_name,
|
||||
.shipping_method {
|
||||
width: 100%;
|
||||
margin: 0 0 .5em;
|
||||
}
|
||||
}
|
||||
|
||||
th.line_tax {
|
||||
|
@ -2123,6 +2128,260 @@ table.wc_shipping {
|
|||
}
|
||||
}
|
||||
|
||||
table.wc-shipping-zones, table.wc-shipping-zone-methods, table.wc-shipping-classes {
|
||||
td, th {
|
||||
vertical-align: top;
|
||||
line-height: 30px;
|
||||
padding: 1em 1em;
|
||||
font-size: 14px;
|
||||
background: #fff;
|
||||
li {
|
||||
line-height: 30px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
td.wc-shipping-zones-blank-state, td.wc-shipping-zone-method-blank-state {
|
||||
background: #F7F1F6 !important;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
padding: 7.5em 10%;
|
||||
border-bottom: 2px solid #EEE2EC;
|
||||
p {
|
||||
color: #a46497;
|
||||
font-size: 1.5em;
|
||||
line-height: 1.5em;
|
||||
margin: 0 0 1em;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-shadow: 1px 1px 1px white;
|
||||
|
||||
&.main {
|
||||
font-size: 2em;
|
||||
}
|
||||
}
|
||||
&:before {
|
||||
content: "\f319";
|
||||
font-family: 'dashicons';
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
color: #EEE2EC;
|
||||
display: block;
|
||||
width: 17px;
|
||||
font-size: 40em;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
}
|
||||
.button-primary {
|
||||
background-color: #a16696;
|
||||
border-color: #a16696;
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba( 255, 255, 255, 0.2 ), 0 1px 0 rgba( 0, 0, 0, 0.15 );
|
||||
box-shadow: inset 0 1px 0 rgba( 255, 255, 255, 0.2 ), 0 1px 0 rgba( 0, 0, 0, 0.15 );
|
||||
margin: 0;
|
||||
opacity: 1;
|
||||
text-shadow: 0px -1px 1px #8a4f7f, 1px 0px 1px #8a4f7f, 0px 1px 1px #8a4f7f, -1px 0px 1px #8a4f7f;
|
||||
font-size: 1.5em;
|
||||
padding: .75em 1em;
|
||||
height: auto;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
&.wc-shipping-zone-method-blank-state {
|
||||
&:before {
|
||||
content: "\f231";
|
||||
}
|
||||
}
|
||||
}
|
||||
tbody.wc-shipping-zone-rows, .wc-shipping-zone-method-rows {
|
||||
tr:nth-child(odd) {
|
||||
td {
|
||||
background: #f9f9f9;
|
||||
}
|
||||
}
|
||||
}
|
||||
tr.odd {
|
||||
td {
|
||||
background: #f9f9f9;
|
||||
}
|
||||
}
|
||||
ul, p {
|
||||
margin: 0;
|
||||
}
|
||||
td.wc-shipping-zone-sort, td.wc-shipping-zone-method-sort {
|
||||
cursor: move;
|
||||
text-align: center;
|
||||
|
||||
&:before {
|
||||
content: "\e032";
|
||||
font-family: 'WooCommerce';
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
color: #999;
|
||||
display: block;
|
||||
width: 17px;
|
||||
float: left;
|
||||
height: 100%;
|
||||
line-height: 30px;
|
||||
}
|
||||
&:hover {
|
||||
&:before {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
td.wc-shipping-zone-worldwide {
|
||||
text-align: center;
|
||||
&:before {
|
||||
content: "\f319";
|
||||
font-family: 'dashicons';
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
color: #999;
|
||||
display: block;
|
||||
width: 17px;
|
||||
float: left;
|
||||
height: 100%;
|
||||
line-height: 30px;
|
||||
}
|
||||
}
|
||||
.wc-shipping-zone-method-enabled {
|
||||
text-align: center;
|
||||
.status-enabled {
|
||||
display: inline-block;
|
||||
&:before {
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
.wc-shipping-zone-name,
|
||||
.wc-shipping-zone-methods {
|
||||
width: 25%;
|
||||
}
|
||||
.wc-shipping-class-description,
|
||||
.wc-shipping-class-name,
|
||||
.wc-shipping-class-slug,
|
||||
.wc-shipping-zone-name,
|
||||
.wc-shipping-zone-region {
|
||||
input, select, textarea {
|
||||
width: 100%;
|
||||
}
|
||||
.wc-shipping-zone-postcodes-toggle {
|
||||
float: right;
|
||||
margin: 0;
|
||||
font-size: 0.9em;
|
||||
color: #999;
|
||||
}
|
||||
.wc-shipping-zone-postcodes {
|
||||
display:none;
|
||||
textarea {
|
||||
margin-top: 1em;
|
||||
}
|
||||
.description {
|
||||
font-size: 0.9em;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
.wc-shipping-class-count {
|
||||
text-align: center;
|
||||
}
|
||||
td.wc-shipping-zone-methods {
|
||||
color: #999;
|
||||
.method_disabled {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
ul {
|
||||
color: #999;
|
||||
li {
|
||||
display: inline;
|
||||
margin: 0 0 0 0;
|
||||
}
|
||||
li:before {
|
||||
content: ", ";
|
||||
}
|
||||
li:last-child:before, li:first-child:before {
|
||||
content: "";
|
||||
}
|
||||
li:last-child {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.button {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
.wc-shipping-zone-actions, .wc-shipping-zone-method-actions, .wc-shipping-class-actions {
|
||||
width: 4em;
|
||||
|
||||
a {
|
||||
@include ir();
|
||||
float: right;
|
||||
padding: .5em;
|
||||
cursor: pointer;
|
||||
|
||||
&:before {
|
||||
@include icon;
|
||||
color: #999;
|
||||
line-height: 30px;
|
||||
}
|
||||
&:hover {
|
||||
&:before {
|
||||
color: #0073aa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.wc-shipping-zone-delete, a.wc-shipping-zone-method-delete, a.wc-shipping-class-delete {
|
||||
&:before {
|
||||
content: "\e013";
|
||||
}
|
||||
&:hover {
|
||||
&:before {
|
||||
color: $red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.wc-shipping-class-edit {
|
||||
&:before {
|
||||
content: "\e603";
|
||||
}
|
||||
}
|
||||
|
||||
a.wc-shipping-zone-method-settings {
|
||||
&:before {
|
||||
@include icon("\f111");
|
||||
font-family: 'Dashicons';
|
||||
line-height: 2.26;
|
||||
}
|
||||
}
|
||||
}
|
||||
tfoot {
|
||||
input, select {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
.button-primary {
|
||||
float:right;
|
||||
}
|
||||
}
|
||||
.wc-shipping-zone-method-selector {
|
||||
float: left;
|
||||
select {
|
||||
margin:0;
|
||||
height: 29px;
|
||||
}
|
||||
}
|
||||
.editing {
|
||||
.wc-shipping-zone-view, .wc-shipping-zone-edit {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wc-backbone-modal .wc-shipping-zone-method-selector select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
img.help_tip {
|
||||
margin: 0 0 0 9px;
|
||||
vertical-align: middle;
|
||||
|
@ -2165,6 +2424,10 @@ img.help_tip {
|
|||
margin: -8px 0 0;
|
||||
}
|
||||
|
||||
.wc-admin-breadcrumb {
|
||||
margin-left: .5em;
|
||||
}
|
||||
|
||||
#template div {
|
||||
margin: 0;
|
||||
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/*global jQuery, Backbone, _ */
|
||||
( function( $, Backbone, _ ) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* WooCommerce Backbone Modal plugin
|
||||
*
|
||||
* @param {object} options
|
||||
*/
|
||||
$.fn.WCBackboneModal = function( options ) {
|
||||
return this.each( function() {
|
||||
( new $.WCBackboneModal( $( this ), options ) );
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the Backbone Modal
|
||||
*
|
||||
* @param {object} element [description]
|
||||
* @param {object} options [description]
|
||||
*/
|
||||
$.WCBackboneModal = function( element, options ) {
|
||||
// Set settings
|
||||
var settings = $.extend( {}, $.WCBackboneModal.defaultOptions, options );
|
||||
|
||||
if ( settings.template ) {
|
||||
new $.WCBackboneModal.View({
|
||||
target: settings.template,
|
||||
string: settings.variable
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set default options
|
||||
*
|
||||
* @type {object}
|
||||
*/
|
||||
$.WCBackboneModal.defaultOptions = {
|
||||
template: '',
|
||||
variable: {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the Backbone Modal
|
||||
*
|
||||
* @return {null}
|
||||
*/
|
||||
$.WCBackboneModal.View = Backbone.View.extend({
|
||||
tagName: 'div',
|
||||
id: 'wc-backbone-modal-dialog',
|
||||
_target: undefined,
|
||||
_string: undefined,
|
||||
events: {
|
||||
'click .modal-close': 'closeButton',
|
||||
'click #btn-ok': 'addButton',
|
||||
'touchstart #btn-ok': 'addButton',
|
||||
'keydown': 'keyboardActions'
|
||||
},
|
||||
initialize: function( data ) {
|
||||
this._target = data.target;
|
||||
this._string = data.string;
|
||||
_.bindAll( this, 'render' );
|
||||
this.render();
|
||||
},
|
||||
render: function() {
|
||||
var template = wp.template( this._target );
|
||||
|
||||
this.$el.attr( 'tabindex' , '0' ).append(
|
||||
template( this._string )
|
||||
);
|
||||
|
||||
$( document.body ).css({
|
||||
'overflow': 'hidden'
|
||||
}).append( this.$el );
|
||||
|
||||
var $content = $( '.wc-backbone-modal-content' ).find( 'article' );
|
||||
var content_h = ( $content.height() < 90 ) ? 90 : $content.height();
|
||||
var max_h = $( window ).height() - 200;
|
||||
|
||||
if ( max_h > 400 ) {
|
||||
max_h = 400;
|
||||
}
|
||||
|
||||
if ( content_h > max_h ) {
|
||||
$content.css({
|
||||
'overflow': 'auto',
|
||||
height: max_h + 'px'
|
||||
});
|
||||
} else {
|
||||
$content.css({
|
||||
'overflow': 'visible',
|
||||
height: ( content_h > 90 ) ? 'auto' : content_h + 'px'
|
||||
});
|
||||
}
|
||||
|
||||
$( '.wc-backbone-modal-content' ).css({
|
||||
'margin-top': '-' + ( $( '.wc-backbone-modal-content' ).height() / 2 ) + 'px',
|
||||
'margin-left': '-' + ( $( '.wc-backbone-modal-content' ).width() / 2 ) + 'px'
|
||||
});
|
||||
|
||||
$( document.body ).trigger( 'wc_backbone_modal_loaded', this._target );
|
||||
},
|
||||
closeButton: function( e ) {
|
||||
e.preventDefault();
|
||||
$( document.body ).trigger( 'wc_backbone_modal_before_remove', this._target );
|
||||
this.undelegateEvents();
|
||||
$( document ).off( 'focusin' );
|
||||
$( document.body ).css({
|
||||
'overflow': 'auto'
|
||||
});
|
||||
this.remove();
|
||||
$( document.body ).trigger( 'wc_backbone_modal_removed', this._target );
|
||||
},
|
||||
addButton: function( e ) {
|
||||
$( document.body ).trigger( 'wc_backbone_modal_response', [ this._target, this.getFormData() ] );
|
||||
this.closeButton( e );
|
||||
},
|
||||
getFormData: function() {
|
||||
var data = {};
|
||||
|
||||
$( document.body ).trigger( 'wc_backbone_modal_before_update', this._target );
|
||||
|
||||
$.each( $( 'form', this.$el ).serializeArray(), function( index, item ) {
|
||||
if ( data.hasOwnProperty( item.name ) ) {
|
||||
data[ item.name ] = $.makeArray( data[ item.name ] );
|
||||
data[ item.name ].push( item.value );
|
||||
} else {
|
||||
data[ item.name ] = item.value;
|
||||
}
|
||||
});
|
||||
|
||||
return data;
|
||||
},
|
||||
keyboardActions: function( e ) {
|
||||
var button = e.keyCode || e.which;
|
||||
|
||||
// Enter key
|
||||
if ( 13 === button && ! ( e.target.tagName && ( e.target.tagName.toLowerCase() === 'input' || e.target.tagName.toLowerCase() === 'textarea' ) ) ) {
|
||||
this.addButton( e );
|
||||
}
|
||||
|
||||
// ESC key
|
||||
if ( 27 === button ) {
|
||||
this.closeButton( e );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}( jQuery, Backbone, _ ));
|
|
@ -0,0 +1 @@
|
|||
!function(a,b,c){"use strict";a.fn.WCBackboneModal=function(b){return this.each(function(){new a.WCBackboneModal(a(this),b)})},a.WCBackboneModal=function(b,c){var d=a.extend({},a.WCBackboneModal.defaultOptions,c);d.template&&new a.WCBackboneModal.View({target:d.template,string:d.variable})},a.WCBackboneModal.defaultOptions={template:"",variable:{}},a.WCBackboneModal.View=b.View.extend({tagName:"div",id:"wc-backbone-modal-dialog",_target:void 0,_string:void 0,events:{"click .modal-close":"closeButton","click #btn-ok":"addButton","touchstart #btn-ok":"addButton",keydown:"keyboardActions"},initialize:function(a){this._target=a.target,this._string=a.string,c.bindAll(this,"render"),this.render()},render:function(){var b=wp.template(this._target);this.$el.attr("tabindex","0").append(b(this._string)),a(document.body).css({overflow:"hidden"}).append(this.$el);var c=a(".wc-backbone-modal-content").find("article"),d=c.height()<90?90:c.height(),e=a(window).height()-200;e>400&&(e=400),d>e?c.css({overflow:"auto",height:e+"px"}):c.css({overflow:"visible",height:d>90?"auto":d+"px"}),a(".wc-backbone-modal-content").css({"margin-top":"-"+a(".wc-backbone-modal-content").height()/2+"px","margin-left":"-"+a(".wc-backbone-modal-content").width()/2+"px"}),a(document.body).trigger("wc_backbone_modal_loaded",this._target)},closeButton:function(b){b.preventDefault(),a(document.body).trigger("wc_backbone_modal_before_remove",this._target),this.undelegateEvents(),a(document).off("focusin"),a(document.body).css({overflow:"auto"}),this.remove(),a(document.body).trigger("wc_backbone_modal_removed",this._target)},addButton:function(b){a(document.body).trigger("wc_backbone_modal_response",[this._target,this.getFormData()]),this.closeButton(b)},getFormData:function(){var b={};return a(document.body).trigger("wc_backbone_modal_before_update",this._target),a.each(a("form",this.$el).serializeArray(),function(c,d){b.hasOwnProperty(d.name)?(b[d.name]=a.makeArray(b[d.name]),b[d.name].push(d.value)):b[d.name]=d.value}),b},keyboardActions:function(a){var b=a.keyCode||a.which;13!==b||a.target.tagName&&("input"===a.target.tagName.toLowerCase()||"textarea"===a.target.tagName.toLowerCase())||this.addButton(a),27===b&&this.closeButton(a)}})}(jQuery,Backbone,_);
|
|
@ -802,7 +802,7 @@ jQuery( function ( $ ) {
|
|||
|
||||
add: function() {
|
||||
var $button = $( this );
|
||||
var $item = $button.closest( 'tr.item' );
|
||||
var $item = $button.closest( 'tr.item, tr.shipping' );
|
||||
|
||||
var data = {
|
||||
order_item_id: $item.attr( 'data-order_item_id' ),
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,210 @@
|
|||
/* global shippingClassesLocalizeScript, ajaxurl */
|
||||
( function( $, data, wp, ajaxurl ) {
|
||||
$( function() {
|
||||
var $table = $( '.wc-shipping-classes' ),
|
||||
$tbody = $( '.wc-shipping-class-rows' ),
|
||||
$save_button = $( '.wc-shipping-class-save' ),
|
||||
$row_template = wp.template( 'wc-shipping-class-row' ),
|
||||
$blank_template = wp.template( 'wc-shipping-class-row-blank' ),
|
||||
|
||||
// Backbone model
|
||||
ShippingClass = Backbone.Model.extend({
|
||||
changes: {},
|
||||
logChanges: function( changedRows ) {
|
||||
var changes = this.changes || {};
|
||||
|
||||
_.each( changedRows, function( row, id ) {
|
||||
changes[ id ] = _.extend( changes[ id ] || { term_id : id }, row );
|
||||
} );
|
||||
|
||||
this.changes = changes;
|
||||
this.trigger( 'change:classes' );
|
||||
},
|
||||
save: function() {
|
||||
if ( _.size( this.changes ) ) {
|
||||
$.post( ajaxurl + '?action=woocommerce_shipping_classes_save_changes', {
|
||||
wc_shipping_classes_nonce : data.wc_shipping_classes_nonce,
|
||||
changes : this.changes
|
||||
}, this.onSaveResponse, 'json' );
|
||||
} else {
|
||||
shippingClass.trigger( 'saved:classes' );
|
||||
}
|
||||
},
|
||||
onSaveResponse: function( response, textStatus ) {
|
||||
if ( 'success' === textStatus ) {
|
||||
if ( response.success ) {
|
||||
shippingClass.set( 'classes', response.data.shipping_classes );
|
||||
shippingClass.trigger( 'change:classes' );
|
||||
shippingClass.changes = {};
|
||||
shippingClass.trigger( 'saved:classes' );
|
||||
} else if ( response.data ) {
|
||||
window.alert( response.data );
|
||||
} else {
|
||||
window.alert( data.strings.save_failed );
|
||||
}
|
||||
}
|
||||
shippingClassView.unblock();
|
||||
}
|
||||
} ),
|
||||
|
||||
// Backbone view
|
||||
ShippingClassView = Backbone.View.extend({
|
||||
rowTemplate: $row_template,
|
||||
initialize: function() {
|
||||
this.listenTo( this.model, 'change:classes', this.setUnloadConfirmation );
|
||||
this.listenTo( this.model, 'saved:classes', this.clearUnloadConfirmation );
|
||||
this.listenTo( this.model, 'saved:classes', this.render );
|
||||
$tbody.on( 'change', { view: this }, this.updateModelOnChange );
|
||||
$( window ).on( 'beforeunload', { view: this }, this.unloadConfirmation );
|
||||
$save_button.on( 'click', { view: this }, this.onSubmit );
|
||||
$( document.body ).on( 'click', '.wc-shipping-class-add', { view: this }, this.onAddNewRow );
|
||||
$( document.body ).on( 'click', '.wc-shipping-class-save-changes', { view: this }, this.onSubmit );
|
||||
},
|
||||
block: function() {
|
||||
$( this.el ).block({
|
||||
message: null,
|
||||
overlayCSS: {
|
||||
background: '#fff',
|
||||
opacity: 0.6
|
||||
}
|
||||
});
|
||||
},
|
||||
unblock: function() {
|
||||
$( this.el ).unblock();
|
||||
},
|
||||
render: function() {
|
||||
var classes = _.indexBy( this.model.get( 'classes' ), 'term_id' ),
|
||||
view = this;
|
||||
|
||||
this.$el.empty();
|
||||
this.unblock();
|
||||
|
||||
if ( _.size( classes ) ) {
|
||||
// Sort classes
|
||||
classes = _.sortBy( classes, function( shipping_class ) {
|
||||
return shipping_class.name;
|
||||
} );
|
||||
|
||||
// Populate $tbody with the current classes
|
||||
$.each( classes, function( id, rowData ) {
|
||||
view.$el.append( view.rowTemplate( rowData ) );
|
||||
|
||||
var $tr = view.$el.find( 'tr[data-id="' + rowData.term_id + '"]');
|
||||
|
||||
// Editing?
|
||||
if ( rowData.editing ) {
|
||||
$tr.addClass( 'editing' );
|
||||
}
|
||||
} );
|
||||
|
||||
// Make the rows function
|
||||
this.$el.find('.view').show();
|
||||
this.$el.find('.edit').hide();
|
||||
this.$el.find( '.wc-shipping-class-edit' ).on( 'click', { view: this }, this.onEditRow );
|
||||
this.$el.find( '.wc-shipping-class-delete' ).on( 'click', { view: this }, this.onDeleteRow );
|
||||
this.$el.find( '.wc-shipping-class-postcodes-toggle' ).on( 'click', { view: this }, this.onTogglePostcodes );
|
||||
this.$el.find('.editing .wc-shipping-class-edit').trigger('click');
|
||||
|
||||
// Stripe
|
||||
if ( 0 === _.size( classes ) % 2) {
|
||||
$table.find( 'tbody.wc-shipping-class-rows' ).next( 'tbody' ).find( 'tr' ).addClass( 'odd' );
|
||||
} else {
|
||||
$table.find( 'tbody.wc-shipping-class-rows' ).next( 'tbody' ).find( 'tr' ).removeClass( 'odd' );
|
||||
}
|
||||
} else {
|
||||
view.$el.append( $blank_template );
|
||||
}
|
||||
},
|
||||
onSubmit: function( event ) {
|
||||
event.data.view.block();
|
||||
event.data.view.model.save();
|
||||
event.preventDefault();
|
||||
},
|
||||
onAddNewRow: function( event ) {
|
||||
event.preventDefault();
|
||||
|
||||
var view = event.data.view,
|
||||
model = view.model,
|
||||
classes = _.indexBy( model.get( 'classes' ), 'term_id' ),
|
||||
changes = {},
|
||||
size = _.size( classes ),
|
||||
newRow = _.extend( {}, data.default_class, {
|
||||
term_id: 'new-' + size + '-' + Date.now(),
|
||||
editing: true,
|
||||
newRow : true
|
||||
} );
|
||||
|
||||
classes[ newRow.term_id ] = newRow;
|
||||
changes[ newRow.term_id ] = newRow;
|
||||
|
||||
model.set( 'classes', classes );
|
||||
model.logChanges( changes );
|
||||
|
||||
view.render();
|
||||
},
|
||||
onEditRow: function( event ) {
|
||||
event.preventDefault();
|
||||
$( this ).closest('tr').addClass('editing');
|
||||
$( this ).closest('tr').find('.view').hide();
|
||||
$( this ).closest('tr').find('.edit').show();
|
||||
event.data.view.model.trigger( 'change:classes' );
|
||||
},
|
||||
onDeleteRow: function( event ) {
|
||||
var view = event.data.view,
|
||||
model = view.model,
|
||||
classes = _.indexBy( model.get( 'classes' ), 'term_id' ),
|
||||
changes = {},
|
||||
term_id = $( this ).closest('tr').data('id');
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
delete classes[ term_id ];
|
||||
changes[ term_id ] = _.extend( changes[ term_id ] || {}, { deleted : 'deleted' } );
|
||||
model.set( 'classes', classes );
|
||||
model.logChanges( changes );
|
||||
view.render();
|
||||
},
|
||||
setUnloadConfirmation: function() {
|
||||
this.needsUnloadConfirm = true;
|
||||
$save_button.removeAttr( 'disabled' );
|
||||
},
|
||||
clearUnloadConfirmation: function() {
|
||||
this.needsUnloadConfirm = false;
|
||||
$save_button.attr( 'disabled', 'disabled' );
|
||||
},
|
||||
unloadConfirmation: function( event ) {
|
||||
if ( event.data.view.needsUnloadConfirm ) {
|
||||
event.returnValue = data.strings.unload_confirmation_msg;
|
||||
window.event.returnValue = data.strings.unload_confirmation_msg;
|
||||
return data.strings.unload_confirmation_msg;
|
||||
}
|
||||
},
|
||||
updateModelOnChange: function( event ) {
|
||||
var model = event.data.view.model,
|
||||
$target = $( event.target ),
|
||||
term_id = $target.closest( 'tr' ).data( 'id' ),
|
||||
attribute = $target.data( 'attribute' ),
|
||||
value = $target.val(),
|
||||
classes = _.indexBy( model.get( 'classes' ), 'term_id' ),
|
||||
changes = {};
|
||||
|
||||
if ( classes[ term_id ][ attribute ] !== value ) {
|
||||
changes[ term_id ] = {};
|
||||
changes[ term_id ][ attribute ] = value;
|
||||
classes[ term_id ][ attribute ] = value;
|
||||
}
|
||||
|
||||
model.logChanges( changes );
|
||||
}
|
||||
} ),
|
||||
shippingClass = new ShippingClass({
|
||||
classes: data.classes
|
||||
} ),
|
||||
shippingClassView = new ShippingClassView({
|
||||
model: shippingClass,
|
||||
el: $tbody
|
||||
} );
|
||||
|
||||
shippingClassView.render();
|
||||
});
|
||||
})( jQuery, shippingClassesLocalizeScript, wp, ajaxurl );
|
|
@ -0,0 +1 @@
|
|||
!function(a,b,c,d){a(function(){var e=a(".wc-shipping-classes"),f=a(".wc-shipping-class-rows"),g=a(".wc-shipping-class-save"),h=c.template("wc-shipping-class-row"),i=c.template("wc-shipping-class-row-blank"),j=Backbone.Model.extend({changes:{},logChanges:function(a){var b=this.changes||{};_.each(a,function(a,c){b[c]=_.extend(b[c]||{term_id:c},a)}),this.changes=b,this.trigger("change:classes")},save:function(){_.size(this.changes)?a.post(d+"?action=woocommerce_shipping_classes_save_changes",{wc_shipping_classes_nonce:b.wc_shipping_classes_nonce,changes:this.changes},this.onSaveResponse,"json"):l.trigger("saved:classes")},onSaveResponse:function(a,c){"success"===c&&(a.success?(l.set("classes",a.data.shipping_classes),l.trigger("change:classes"),l.changes={},l.trigger("saved:classes")):a.data?window.alert(a.data):window.alert(b.strings.save_failed)),m.unblock()}}),k=Backbone.View.extend({rowTemplate:h,initialize:function(){this.listenTo(this.model,"change:classes",this.setUnloadConfirmation),this.listenTo(this.model,"saved:classes",this.clearUnloadConfirmation),this.listenTo(this.model,"saved:classes",this.render),f.on("change",{view:this},this.updateModelOnChange),a(window).on("beforeunload",{view:this},this.unloadConfirmation),g.on("click",{view:this},this.onSubmit),a(document.body).on("click",".wc-shipping-class-add",{view:this},this.onAddNewRow),a(document.body).on("click",".wc-shipping-class-save-changes",{view:this},this.onSubmit)},block:function(){a(this.el).block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){a(this.el).unblock()},render:function(){var b=_.indexBy(this.model.get("classes"),"term_id"),c=this;this.$el.empty(),this.unblock(),_.size(b)?(b=_.sortBy(b,function(a){return a.name}),a.each(b,function(a,b){c.$el.append(c.rowTemplate(b));var d=c.$el.find('tr[data-id="'+b.term_id+'"]');b.editing&&d.addClass("editing")}),this.$el.find(".view").show(),this.$el.find(".edit").hide(),this.$el.find(".wc-shipping-class-edit").on("click",{view:this},this.onEditRow),this.$el.find(".wc-shipping-class-delete").on("click",{view:this},this.onDeleteRow),this.$el.find(".wc-shipping-class-postcodes-toggle").on("click",{view:this},this.onTogglePostcodes),this.$el.find(".editing .wc-shipping-class-edit").trigger("click"),0===_.size(b)%2?e.find("tbody.wc-shipping-class-rows").next("tbody").find("tr").addClass("odd"):e.find("tbody.wc-shipping-class-rows").next("tbody").find("tr").removeClass("odd")):c.$el.append(i)},onSubmit:function(a){a.data.view.block(),a.data.view.model.save(),a.preventDefault()},onAddNewRow:function(a){a.preventDefault();var c=a.data.view,d=c.model,e=_.indexBy(d.get("classes"),"term_id"),f={},g=_.size(e),h=_.extend({},b.default_class,{term_id:"new-"+g+"-"+Date.now(),editing:!0,newRow:!0});e[h.term_id]=h,f[h.term_id]=h,d.set("classes",e),d.logChanges(f),c.render()},onEditRow:function(b){b.preventDefault(),a(this).closest("tr").addClass("editing"),a(this).closest("tr").find(".view").hide(),a(this).closest("tr").find(".edit").show(),b.data.view.model.trigger("change:classes")},onDeleteRow:function(b){var c=b.data.view,d=c.model,e=_.indexBy(d.get("classes"),"term_id"),f={},g=a(this).closest("tr").data("id");b.preventDefault(),delete e[g],f[g]=_.extend(f[g]||{},{deleted:"deleted"}),d.set("classes",e),d.logChanges(f),c.render()},setUnloadConfirmation:function(){this.needsUnloadConfirm=!0,g.removeAttr("disabled")},clearUnloadConfirmation:function(){this.needsUnloadConfirm=!1,g.attr("disabled","disabled")},unloadConfirmation:function(a){return a.data.view.needsUnloadConfirm?(a.returnValue=b.strings.unload_confirmation_msg,window.event.returnValue=b.strings.unload_confirmation_msg,b.strings.unload_confirmation_msg):void 0},updateModelOnChange:function(b){var c=b.data.view.model,d=a(b.target),e=d.closest("tr").data("id"),f=d.data("attribute"),g=d.val(),h=_.indexBy(c.get("classes"),"term_id"),i={};h[e][f]!==g&&(i[e]={},i[e][f]=g,h[e][f]=g),c.logChanges(i)}}),l=new j({classes:b.classes}),m=new k({model:l,el:f});m.render()})}(jQuery,shippingClassesLocalizeScript,wp,ajaxurl);
|
|
@ -0,0 +1,235 @@
|
|||
/* global shippingZoneMethodsLocalizeScript, ajaxurl */
|
||||
( function( $, data, wp, ajaxurl ) {
|
||||
$( function() {
|
||||
var $table = $( '.wc-shipping-zone-methods' ),
|
||||
$tbody = $( '.wc-shipping-zone-method-rows' ),
|
||||
$save_button = $( '.wc-shipping-zone-method-save' ),
|
||||
$row_template = wp.template( 'wc-shipping-zone-method-row' ),
|
||||
$blank_template = wp.template( 'wc-shipping-zone-method-row-blank' ),
|
||||
|
||||
// Backbone model
|
||||
ShippingMethod = Backbone.Model.extend({
|
||||
changes: {},
|
||||
logChanges: function( changedRows ) {
|
||||
var changes = this.changes || {};
|
||||
|
||||
_.each( changedRows, function( row, id ) {
|
||||
changes[ id ] = _.extend( changes[ id ] || { instance_id : id }, row );
|
||||
} );
|
||||
|
||||
this.changes = changes;
|
||||
this.trigger( 'change:methods' );
|
||||
},
|
||||
save: function() {
|
||||
if ( _.size( this.changes ) ) {
|
||||
$.post( ajaxurl + '?action=woocommerce_shipping_zone_methods_save_changes', {
|
||||
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
|
||||
changes : this.changes,
|
||||
zone_id : data.zone_id
|
||||
}, this.onSaveResponse, 'json' );
|
||||
} else {
|
||||
shippingMethod.trigger( 'saved:methods' );
|
||||
}
|
||||
},
|
||||
addMethod: function() {
|
||||
if ( _.size( this.changes ) ) {
|
||||
this.save();
|
||||
}
|
||||
$.post( ajaxurl + '?action=woocommerce_shipping_zone_add_method', {
|
||||
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
|
||||
method_id : $('select[name="add_method_id"]').val(),
|
||||
zone_id : data.zone_id
|
||||
}, this.onAddResponse, 'json' );
|
||||
},
|
||||
onSaveResponse: function( response, textStatus ) {
|
||||
if ( 'success' === textStatus ) {
|
||||
if ( response.success ) {
|
||||
shippingMethod.set( 'methods', response.data.methods );
|
||||
shippingMethod.trigger( 'change:methods' );
|
||||
shippingMethod.changes = {};
|
||||
shippingMethod.trigger( 'saved:methods' );
|
||||
} else {
|
||||
window.alert( data.strings.save_failed );
|
||||
}
|
||||
}
|
||||
},
|
||||
onAddResponse: function( response, textStatus ) {
|
||||
if ( 'success' === textStatus ) {
|
||||
if ( response.success && response.data.instance_id ) {
|
||||
shippingMethod.set( 'methods', response.data.methods );
|
||||
shippingMethod.trigger( 'change:methods' );
|
||||
shippingMethod.changes = {};
|
||||
shippingMethod.trigger( 'saved:methods' );
|
||||
} else {
|
||||
window.alert( data.strings.add_method_failed );
|
||||
}
|
||||
}
|
||||
}
|
||||
} ),
|
||||
|
||||
// Backbone view
|
||||
ShippingMethodView = Backbone.View.extend({
|
||||
rowTemplate: $row_template,
|
||||
initialize: function() {
|
||||
this.listenTo( this.model, 'change:methods', this.setUnloadConfirmation );
|
||||
this.listenTo( this.model, 'saved:methods', this.clearUnloadConfirmation );
|
||||
this.listenTo( this.model, 'saved:methods', this.render );
|
||||
$tbody.on( 'change', { view: this }, this.updateModelOnChange );
|
||||
$tbody.on( 'sortupdate', { view: this }, this.updateModelOnSort );
|
||||
$( window ).on( 'beforeunload', { view: this }, this.unloadConfirmation );
|
||||
$save_button.on( 'click', { view: this }, this.onSubmit );
|
||||
$('.wc-shipping-zone-add-method').on( 'click', { view: this }, this.onAdd );
|
||||
},
|
||||
block: function() {
|
||||
$( this.el ).block({
|
||||
message: null,
|
||||
overlayCSS: {
|
||||
background: '#fff',
|
||||
opacity: 0.6
|
||||
}
|
||||
});
|
||||
},
|
||||
unblock: function() {
|
||||
$( this.el ).unblock();
|
||||
},
|
||||
render: function() {
|
||||
var methods = _.indexBy( this.model.get( 'methods' ), 'instance_id' ),
|
||||
view = this;
|
||||
|
||||
// Blank out the contents.
|
||||
this.$el.empty();
|
||||
this.unblock();
|
||||
|
||||
if ( _.size( methods ) ) {
|
||||
// Sort methods
|
||||
methods = _.sortBy( methods, function( method ) {
|
||||
return parseInt( method.method_order, 10 );
|
||||
} );
|
||||
|
||||
// Populate $tbody with the current methods
|
||||
$.each( methods, function( id, rowData ) {
|
||||
if ( 'yes' === rowData.enabled ) {
|
||||
rowData.enabled_icon = '<span class="status-enabled tips" data-tip="' + data.strings.yes + '">' + data.strings.yes + '</span>';
|
||||
} else {
|
||||
rowData.enabled_icon = '–';
|
||||
}
|
||||
|
||||
view.$el.append( view.rowTemplate( rowData ) );
|
||||
|
||||
var $tr = view.$el.find( 'tr[data-id="' + rowData.instance_id + '"]');
|
||||
|
||||
if ( ! rowData.has_settings ) {
|
||||
$tr.find( '.wc-shipping-zone-method-title a').replaceWith( $tr.find( '.wc-shipping-zone-method-title' ).text() );
|
||||
$tr.find( '.wc-shipping-zone-method-settings' ).remove();
|
||||
}
|
||||
} );
|
||||
|
||||
// Make the rows function
|
||||
this.$el.find( '.wc-shipping-zone-method-delete' ).on( 'click', { view: this }, this.onDeleteRow );
|
||||
} else {
|
||||
view.$el.append( $blank_template );
|
||||
}
|
||||
|
||||
this.initTooltips();
|
||||
},
|
||||
initTooltips: function() {
|
||||
$( '#tiptip_holder' ).removeAttr( 'style' );
|
||||
$( '#tiptip_arrow' ).removeAttr( 'style' );
|
||||
$( '.tips' ).tipTip({ 'attribute': 'data-tip', 'fadeIn': 50, 'fadeOut': 50, 'delay': 50 });
|
||||
},
|
||||
onSubmit: function( event ) {
|
||||
event.data.view.block();
|
||||
event.data.view.model.save();
|
||||
event.preventDefault();
|
||||
},
|
||||
onAdd: function( event ) {
|
||||
event.data.view.block();
|
||||
event.data.view.model.addMethod();
|
||||
event.preventDefault();
|
||||
},
|
||||
onDeleteRow: function( event ) {
|
||||
var view = event.data.view,
|
||||
model = view.model,
|
||||
methods = _.indexBy( model.get( 'methods' ), 'instance_id' ),
|
||||
changes = {},
|
||||
instance_id = $( this ).closest('tr').data('id');
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
delete methods[ instance_id ];
|
||||
changes[ instance_id ] = _.extend( changes[ instance_id ] || {}, { deleted : 'deleted' } );
|
||||
model.set( 'methods', methods );
|
||||
model.logChanges( changes );
|
||||
view.render();
|
||||
},
|
||||
setUnloadConfirmation: function() {
|
||||
this.needsUnloadConfirm = true;
|
||||
$save_button.removeAttr( 'disabled' );
|
||||
},
|
||||
clearUnloadConfirmation: function() {
|
||||
this.needsUnloadConfirm = false;
|
||||
$save_button.attr( 'disabled', 'disabled' );
|
||||
},
|
||||
unloadConfirmation: function( event ) {
|
||||
if ( event.data.view.needsUnloadConfirm ) {
|
||||
event.returnValue = data.strings.unload_confirmation_msg;
|
||||
window.event.returnValue = data.strings.unload_confirmation_msg;
|
||||
return data.strings.unload_confirmation_msg;
|
||||
}
|
||||
},
|
||||
updateModelOnChange: function( event ) {
|
||||
var model = event.data.view.model,
|
||||
$target = $( event.target ),
|
||||
instance_id = $target.closest( 'tr' ).data( 'id' ),
|
||||
attribute = $target.data( 'attribute' ),
|
||||
value = $target.val(),
|
||||
methods = _.indexBy( model.get( 'methods' ), 'instance_id' ),
|
||||
changes = {};
|
||||
|
||||
if ( methods[ instance_id ][ attribute ] !== value ) {
|
||||
changes[ instance_id ] = {};
|
||||
changes[ instance_id ][ attribute ] = value;
|
||||
methods[ instance_id ][ attribute ] = value;
|
||||
}
|
||||
|
||||
model.logChanges( changes );
|
||||
},
|
||||
updateModelOnSort: function( event ) {
|
||||
var view = event.data.view,
|
||||
model = view.model,
|
||||
methods = _.indexBy( model.get( 'methods' ), 'instance_id' ),
|
||||
changes = {};
|
||||
|
||||
_.each( methods, function( method ) {
|
||||
var old_position = parseInt( method.method_order, 10 );
|
||||
var new_position = parseInt( $table.find( 'tr[data-id="' + method.instance_id + '"]').index() + 1, 10 );
|
||||
|
||||
if ( old_position !== new_position ) {
|
||||
changes[ method.instance_id ] = _.extend( changes[ method.instance_id ] || {}, { method_order : new_position } );
|
||||
}
|
||||
} );
|
||||
|
||||
if ( _.size( changes ) ) {
|
||||
model.logChanges( changes );
|
||||
}
|
||||
}
|
||||
} ),
|
||||
shippingMethod = new ShippingMethod({
|
||||
methods: data.methods
|
||||
} ),
|
||||
shippingMethodView = new ShippingMethodView({
|
||||
model: shippingMethod,
|
||||
el: $tbody
|
||||
} );
|
||||
|
||||
shippingMethodView.render();
|
||||
|
||||
$tbody.sortable({
|
||||
items: 'tr',
|
||||
cursor: 'move',
|
||||
axis: 'y',
|
||||
handle: 'td.wc-shipping-zone-method-sort',
|
||||
scrollSensitivity: 40
|
||||
});
|
||||
});
|
||||
})( jQuery, shippingZoneMethodsLocalizeScript, wp, ajaxurl );
|
|
@ -0,0 +1 @@
|
|||
!function(a,b,c,d){a(function(){var e=a(".wc-shipping-zone-methods"),f=a(".wc-shipping-zone-method-rows"),g=a(".wc-shipping-zone-method-save"),h=c.template("wc-shipping-zone-method-row"),i=c.template("wc-shipping-zone-method-row-blank"),j=Backbone.Model.extend({changes:{},logChanges:function(a){var b=this.changes||{};_.each(a,function(a,c){b[c]=_.extend(b[c]||{instance_id:c},a)}),this.changes=b,this.trigger("change:methods")},save:function(){_.size(this.changes)?a.post(d+"?action=woocommerce_shipping_zone_methods_save_changes",{wc_shipping_zones_nonce:b.wc_shipping_zones_nonce,changes:this.changes,zone_id:b.zone_id},this.onSaveResponse,"json"):l.trigger("saved:methods")},addMethod:function(){_.size(this.changes)&&this.save(),a.post(d+"?action=woocommerce_shipping_zone_add_method",{wc_shipping_zones_nonce:b.wc_shipping_zones_nonce,method_id:a('select[name="add_method_id"]').val(),zone_id:b.zone_id},this.onAddResponse,"json")},onSaveResponse:function(a,c){"success"===c&&(a.success?(l.set("methods",a.data.methods),l.trigger("change:methods"),l.changes={},l.trigger("saved:methods")):window.alert(b.strings.save_failed))},onAddResponse:function(a,c){"success"===c&&(a.success&&a.data.instance_id?(l.set("methods",a.data.methods),l.trigger("change:methods"),l.changes={},l.trigger("saved:methods")):window.alert(b.strings.add_method_failed))}}),k=Backbone.View.extend({rowTemplate:h,initialize:function(){this.listenTo(this.model,"change:methods",this.setUnloadConfirmation),this.listenTo(this.model,"saved:methods",this.clearUnloadConfirmation),this.listenTo(this.model,"saved:methods",this.render),f.on("change",{view:this},this.updateModelOnChange),f.on("sortupdate",{view:this},this.updateModelOnSort),a(window).on("beforeunload",{view:this},this.unloadConfirmation),g.on("click",{view:this},this.onSubmit),a(".wc-shipping-zone-add-method").on("click",{view:this},this.onAdd)},block:function(){a(this.el).block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},unblock:function(){a(this.el).unblock()},render:function(){var c=_.indexBy(this.model.get("methods"),"instance_id"),d=this;this.$el.empty(),this.unblock(),_.size(c)?(c=_.sortBy(c,function(a){return parseInt(a.method_order,10)}),a.each(c,function(a,c){"yes"===c.enabled?c.enabled_icon='<span class="status-enabled tips" data-tip="'+b.strings.yes+'">'+b.strings.yes+"</span>":c.enabled_icon="–",d.$el.append(d.rowTemplate(c));var e=d.$el.find('tr[data-id="'+c.instance_id+'"]');c.has_settings||(e.find(".wc-shipping-zone-method-title a").replaceWith(e.find(".wc-shipping-zone-method-title").text()),e.find(".wc-shipping-zone-method-settings").remove())}),this.$el.find(".wc-shipping-zone-method-delete").on("click",{view:this},this.onDeleteRow)):d.$el.append(i),this.initTooltips()},initTooltips:function(){a("#tiptip_holder").removeAttr("style"),a("#tiptip_arrow").removeAttr("style"),a(".tips").tipTip({attribute:"data-tip",fadeIn:50,fadeOut:50,delay:50})},onSubmit:function(a){a.data.view.block(),a.data.view.model.save(),a.preventDefault()},onAdd:function(a){a.data.view.block(),a.data.view.model.addMethod(),a.preventDefault()},onDeleteRow:function(b){var c=b.data.view,d=c.model,e=_.indexBy(d.get("methods"),"instance_id"),f={},g=a(this).closest("tr").data("id");b.preventDefault(),delete e[g],f[g]=_.extend(f[g]||{},{deleted:"deleted"}),d.set("methods",e),d.logChanges(f),c.render()},setUnloadConfirmation:function(){this.needsUnloadConfirm=!0,g.removeAttr("disabled")},clearUnloadConfirmation:function(){this.needsUnloadConfirm=!1,g.attr("disabled","disabled")},unloadConfirmation:function(a){return a.data.view.needsUnloadConfirm?(a.returnValue=b.strings.unload_confirmation_msg,window.event.returnValue=b.strings.unload_confirmation_msg,b.strings.unload_confirmation_msg):void 0},updateModelOnChange:function(b){var c=b.data.view.model,d=a(b.target),e=d.closest("tr").data("id"),f=d.data("attribute"),g=d.val(),h=_.indexBy(c.get("methods"),"instance_id"),i={};h[e][f]!==g&&(i[e]={},i[e][f]=g,h[e][f]=g),c.logChanges(i)},updateModelOnSort:function(a){var b=a.data.view,c=b.model,d=_.indexBy(c.get("methods"),"instance_id"),f={};_.each(d,function(a){var b=parseInt(a.method_order,10),c=parseInt(e.find('tr[data-id="'+a.instance_id+'"]').index()+1,10);b!==c&&(f[a.instance_id]=_.extend(f[a.instance_id]||{},{method_order:c}))}),_.size(f)&&c.logChanges(f)}}),l=new j({methods:b.methods}),m=new k({model:l,el:f});m.render(),f.sortable({items:"tr",cursor:"move",axis:"y",handle:"td.wc-shipping-zone-method-sort",scrollSensitivity:40})})}(jQuery,shippingZoneMethodsLocalizeScript,wp,ajaxurl);
|
|
@ -0,0 +1,388 @@
|
|||
/* global wc_enhanced_select_params, shippingZonesLocalizeScript, ajaxurl */
|
||||
( function( $, data, wp, ajaxurl ) {
|
||||
$( function() {
|
||||
var $table = $( '.wc-shipping-zones' ),
|
||||
$tbody = $( '.wc-shipping-zone-rows' ),
|
||||
$save_button = $( '.wc-shipping-zone-save' ),
|
||||
$row_template = wp.template( 'wc-shipping-zone-row' ),
|
||||
$blank_template = wp.template( 'wc-shipping-zone-row-blank' ),
|
||||
select2_args = $.extend({
|
||||
minimumResultsForSearch: 10,
|
||||
allowClear: $( this ).data( 'allow_clear' ) ? true : false,
|
||||
placeholder: $( this ).data( 'placeholder' ),
|
||||
matcher: function( term, text, opt ) {
|
||||
return text.toUpperCase().indexOf( term.toUpperCase() ) >= 0 || opt.attr( 'alt' ).toUpperCase().indexOf( term.toUpperCase() ) >= 0;
|
||||
}
|
||||
}, getEnhancedSelectFormatString() ),
|
||||
|
||||
// Backbone model
|
||||
ShippingZone = Backbone.Model.extend({
|
||||
changes: {},
|
||||
logChanges: function( changedRows ) {
|
||||
var changes = this.changes || {};
|
||||
|
||||
_.each( changedRows, function( row, id ) {
|
||||
changes[ id ] = _.extend( changes[ id ] || { zone_id : id }, row );
|
||||
} );
|
||||
|
||||
this.changes = changes;
|
||||
this.trigger( 'change:zones' );
|
||||
},
|
||||
save: function() {
|
||||
if ( _.size( this.changes ) ) {
|
||||
$.post( ajaxurl + '?action=woocommerce_shipping_zones_save_changes', {
|
||||
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
|
||||
changes : this.changes
|
||||
}, this.onSaveResponse, 'json' );
|
||||
} else {
|
||||
shippingZone.trigger( 'saved:zones' );
|
||||
}
|
||||
},
|
||||
onSaveResponse: function( response, textStatus ) {
|
||||
if ( 'success' === textStatus ) {
|
||||
if ( response.success ) {
|
||||
shippingZone.set( 'zones', response.data.zones );
|
||||
shippingZone.trigger( 'change:zones' );
|
||||
shippingZone.changes = {};
|
||||
shippingZone.trigger( 'saved:zones' );
|
||||
} else {
|
||||
window.alert( data.strings.save_failed );
|
||||
}
|
||||
}
|
||||
}
|
||||
} ),
|
||||
|
||||
// Backbone view
|
||||
ShippingZoneView = Backbone.View.extend({
|
||||
rowTemplate: $row_template,
|
||||
initialize: function() {
|
||||
this.listenTo( this.model, 'change:zones', this.setUnloadConfirmation );
|
||||
this.listenTo( this.model, 'saved:zones', this.clearUnloadConfirmation );
|
||||
this.listenTo( this.model, 'saved:zones', this.render );
|
||||
$tbody.on( 'change', { view: this }, this.updateModelOnChange );
|
||||
$tbody.on( 'sortupdate', { view: this }, this.updateModelOnSort );
|
||||
$( window ).on( 'beforeunload', { view: this }, this.unloadConfirmation );
|
||||
$save_button.on( 'click', { view: this }, this.onSubmit );
|
||||
$( document.body ).on( 'click', '.add_shipping_method', { view: this }, this.onAddShippingMethod );
|
||||
$( document.body ).on( 'click', '.wc-shipping-zone-add', { view: this }, this.onAddNewRow );
|
||||
$( document.body ).on( 'click', '.wc-shipping-zone-save-changes', { view: this }, this.onSubmit );
|
||||
$( document.body ).on( 'wc_backbone_modal_response', this.onAddShippingMethodSubmitted );
|
||||
},
|
||||
block: function() {
|
||||
$( this.el ).block({
|
||||
message: null,
|
||||
overlayCSS: {
|
||||
background: '#fff',
|
||||
opacity: 0.6
|
||||
}
|
||||
});
|
||||
},
|
||||
unblock: function() {
|
||||
$( this.el ).unblock();
|
||||
},
|
||||
render: function() {
|
||||
var zones = _.indexBy( this.model.get( 'zones' ), 'zone_id' ),
|
||||
view = this;
|
||||
|
||||
this.$el.empty();
|
||||
this.unblock();
|
||||
|
||||
if ( _.size( zones ) ) {
|
||||
// Sort zones
|
||||
zones = _.sortBy( zones, function( zone ) {
|
||||
return parseInt( zone.zone_order, 10 );
|
||||
} );
|
||||
|
||||
// Populate $tbody with the current zones
|
||||
$.each( zones, function( id, rowData ) {
|
||||
view.$el.append( view.rowTemplate( rowData ) );
|
||||
|
||||
var $tr = view.$el.find( 'tr[data-id="' + rowData.zone_id + '"]');
|
||||
|
||||
// Editing?
|
||||
if ( rowData.editing ) {
|
||||
$tr.addClass( 'editing' );
|
||||
}
|
||||
|
||||
// Select values in region select
|
||||
_.each( rowData.zone_locations, function( location ) {
|
||||
if ( 'postcode' === location.type ) {
|
||||
var postcode_field = $tr.find( '.wc-shipping-zone-postcodes :input' );
|
||||
|
||||
if ( postcode_field.val() ) {
|
||||
postcode_field.val( postcode_field.val() + '\n' + location.code );
|
||||
} else {
|
||||
postcode_field.val( location.code );
|
||||
}
|
||||
$tr.find( '.wc-shipping-zone-postcodes' ).show();
|
||||
$tr.find( '.wc-shipping-zone-postcodes-toggle' ).hide();
|
||||
} else {
|
||||
$tr.find( 'option[value="' + location.type + ':' + location.code + '"]' ).prop( 'selected', true );
|
||||
}
|
||||
} );
|
||||
|
||||
// List shipping methods
|
||||
view.renderShippingMethods( rowData.zone_id, rowData.shipping_methods );
|
||||
} );
|
||||
|
||||
// Make the rows function
|
||||
this.$el.find('.view').show();
|
||||
this.$el.find('.edit').hide();
|
||||
this.$el.find( '.wc-shipping-zone-edit' ).on( 'click', { view: this }, this.onEditRow );
|
||||
this.$el.find( '.wc-shipping-zone-delete' ).on( 'click', { view: this }, this.onDeleteRow );
|
||||
this.$el.find( '.wc-shipping-zone-postcodes-toggle' ).on( 'click', { view: this }, this.onTogglePostcodes );
|
||||
this.$el.find('.editing .wc-shipping-zone-edit').trigger('click');
|
||||
|
||||
// Stripe
|
||||
if ( 0 === _.size( zones ) % 2) {
|
||||
$table.find( 'tbody.wc-shipping-zone-rows' ).next( 'tbody' ).find( 'tr' ).addClass( 'odd' );
|
||||
} else {
|
||||
$table.find( 'tbody.wc-shipping-zone-rows' ).next( 'tbody' ).find( 'tr' ).removeClass( 'odd' );
|
||||
}
|
||||
} else {
|
||||
view.$el.append( $blank_template );
|
||||
}
|
||||
|
||||
this.initTooltips();
|
||||
},
|
||||
renderShippingMethods: function( zone_id, shipping_methods ) {
|
||||
var $tr = $( '.wc-shipping-zones tr[data-id="' + zone_id + '"]');
|
||||
var $method_list = $tr.find('.wc-shipping-zone-methods ul');
|
||||
|
||||
$method_list.empty();
|
||||
|
||||
if ( _.size( shipping_methods ) ) {
|
||||
_.each( shipping_methods, function( shipping_method, instance_id ) {
|
||||
var class_name = 'method_disabled';
|
||||
|
||||
if ( 'yes' === shipping_method.enabled ) {
|
||||
class_name = 'method_enabled';
|
||||
}
|
||||
|
||||
$method_list.append( '<li><a href="admin.php?page=wc-settings&tab=shipping&instance_id=' + instance_id + '" class="' + class_name + '">' + shipping_method.title + '</a></li>' );
|
||||
} );
|
||||
$method_list.append( '<li>' + data.strings.add_another_method + '</li>' );
|
||||
} else {
|
||||
$method_list.append( '<li>' + data.strings.no_methods + '</li>' );
|
||||
}
|
||||
},
|
||||
initTooltips: function() {
|
||||
$( '#tiptip_holder' ).removeAttr( 'style' );
|
||||
$( '#tiptip_arrow' ).removeAttr( 'style' );
|
||||
$( '.tips' ).tipTip({ 'attribute': 'data-tip', 'fadeIn': 50, 'fadeOut': 50, 'delay': 50 });
|
||||
},
|
||||
onSubmit: function( event ) {
|
||||
event.data.view.block();
|
||||
event.data.view.model.save();
|
||||
event.preventDefault();
|
||||
},
|
||||
onAddNewRow: function( event ) {
|
||||
event.preventDefault();
|
||||
|
||||
var view = event.data.view,
|
||||
model = view.model,
|
||||
zones = _.indexBy( model.get( 'zones' ), 'zone_id' ),
|
||||
changes = {},
|
||||
size = _.size( zones ),
|
||||
newRow = _.extend( {}, data.default_zone, {
|
||||
zone_id: 'new-' + size + '-' + Date.now(),
|
||||
editing: true
|
||||
} );
|
||||
|
||||
newRow.zone_order = 1 + _.max(
|
||||
_.pluck( zones, 'zone_order' ),
|
||||
function ( val ) {
|
||||
// Cast them all to integers, because strings compare funky. Sighhh.
|
||||
return parseInt( val, 10 );
|
||||
}
|
||||
);
|
||||
|
||||
zones[ newRow.zone_id ] = newRow;
|
||||
changes[ newRow.zone_id ] = newRow;
|
||||
|
||||
model.set( 'zones', zones );
|
||||
model.logChanges( changes );
|
||||
|
||||
view.render();
|
||||
},
|
||||
onTogglePostcodes: function( event ) {
|
||||
event.preventDefault();
|
||||
var $tr = $( this ).closest( 'tr');
|
||||
$tr.find( '.wc-shipping-zone-postcodes' ).show();
|
||||
$tr.find( '.wc-shipping-zone-postcodes-toggle' ).hide();
|
||||
},
|
||||
onEditRow: function( event ) {
|
||||
event.preventDefault();
|
||||
$( this ).closest('tr').addClass('editing');
|
||||
$( this ).closest('tr').find('.view').hide();
|
||||
$( this ).closest('tr').find('.edit').show();
|
||||
$( '.wc-shipping-zone-region-select:not(.enhanced)' ).select2( select2_args );
|
||||
$( '.wc-shipping-zone-region-select:not(.enhanced)' ).addClass('enhanced');
|
||||
event.data.view.model.trigger( 'change:zones' );
|
||||
},
|
||||
onDeleteRow: function( event ) {
|
||||
var view = event.data.view,
|
||||
model = view.model,
|
||||
zones = _.indexBy( model.get( 'zones' ), 'zone_id' ),
|
||||
changes = {},
|
||||
zone_id = $( this ).closest('tr').data('id');
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
delete zones[ zone_id ];
|
||||
changes[ zone_id ] = _.extend( changes[ zone_id ] || {}, { deleted : 'deleted' } );
|
||||
model.set( 'zones', zones );
|
||||
model.logChanges( changes );
|
||||
view.render();
|
||||
},
|
||||
setUnloadConfirmation: function() {
|
||||
this.needsUnloadConfirm = true;
|
||||
$save_button.removeAttr( 'disabled' );
|
||||
},
|
||||
clearUnloadConfirmation: function() {
|
||||
this.needsUnloadConfirm = false;
|
||||
$save_button.attr( 'disabled', 'disabled' );
|
||||
},
|
||||
unloadConfirmation: function( event ) {
|
||||
if ( event.data.view.needsUnloadConfirm ) {
|
||||
event.returnValue = data.strings.unload_confirmation_msg;
|
||||
window.event.returnValue = data.strings.unload_confirmation_msg;
|
||||
return data.strings.unload_confirmation_msg;
|
||||
}
|
||||
},
|
||||
updateModelOnChange: function( event ) {
|
||||
var model = event.data.view.model,
|
||||
$target = $( event.target ),
|
||||
zone_id = $target.closest( 'tr' ).data( 'id' ),
|
||||
attribute = $target.data( 'attribute' ),
|
||||
value = $target.val(),
|
||||
zones = _.indexBy( model.get( 'zones' ), 'zone_id' ),
|
||||
changes = {};
|
||||
|
||||
if ( zones[ zone_id ][ attribute ] !== value ) {
|
||||
changes[ zone_id ] = {};
|
||||
changes[ zone_id ][ attribute ] = value;
|
||||
zones[ zone_id ][ attribute ] = value;
|
||||
}
|
||||
|
||||
model.logChanges( changes );
|
||||
},
|
||||
updateModelOnSort: function( event ) {
|
||||
var view = event.data.view,
|
||||
model = view.model,
|
||||
zones = _.indexBy( model.get( 'zones' ), 'zone_id' ),
|
||||
changes = {};
|
||||
|
||||
_.each( zones, function( zone ) {
|
||||
var old_position = parseInt( zone.zone_order, 10 );
|
||||
var new_position = parseInt( $table.find( 'tr[data-id="' + zone.zone_id + '"]').index(), 10 );
|
||||
|
||||
if ( old_position !== new_position ) {
|
||||
changes[ zone.zone_id ] = _.extend( changes[ zone.zone_id ] || {}, { zone_order : new_position } );
|
||||
}
|
||||
} );
|
||||
|
||||
if ( _.size( changes ) ) {
|
||||
model.logChanges( changes );
|
||||
}
|
||||
},
|
||||
onAddShippingMethod: function( event ) {
|
||||
var zone_id = $( this ).closest('tr').data('id');
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
$( this ).WCBackboneModal({
|
||||
template : 'wc-modal-add-shipping-method',
|
||||
variable : {
|
||||
zone_id : zone_id
|
||||
}
|
||||
});
|
||||
},
|
||||
onAddShippingMethodSubmitted: function( event, target, posted_data ) {
|
||||
if ( 'wc-modal-add-shipping-method' === target ) {
|
||||
shippingZoneView.block();
|
||||
|
||||
// Add method to zone via ajax call
|
||||
$.post( ajaxurl + '?action=woocommerce_shipping_zone_add_method', {
|
||||
wc_shipping_zones_nonce : data.wc_shipping_zones_nonce,
|
||||
method_id : posted_data.add_method_id,
|
||||
zone_id : posted_data.zone_id
|
||||
}, function( response, textStatus ) {
|
||||
if ( 'success' === textStatus && response.success ) {
|
||||
// Method was added. Render methods.
|
||||
shippingZoneView.renderShippingMethods( posted_data.zone_id, response.data.methods );
|
||||
}
|
||||
shippingZoneView.unblock();
|
||||
}, 'json' );
|
||||
}
|
||||
}
|
||||
} ),
|
||||
shippingZone = new ShippingZone({
|
||||
zones: data.zones
|
||||
} ),
|
||||
shippingZoneView = new ShippingZoneView({
|
||||
model: shippingZone,
|
||||
el: $tbody
|
||||
} );
|
||||
|
||||
shippingZoneView.render();
|
||||
|
||||
$tbody.sortable({
|
||||
items: 'tr',
|
||||
cursor: 'move',
|
||||
axis: 'y',
|
||||
handle: 'td.wc-shipping-zone-sort',
|
||||
scrollSensitivity: 40
|
||||
});
|
||||
|
||||
function getEnhancedSelectFormatString() {
|
||||
var formatString = {
|
||||
formatMatches: function( matches ) {
|
||||
if ( 1 === matches ) {
|
||||
return wc_enhanced_select_params.i18n_matches_1;
|
||||
}
|
||||
return wc_enhanced_select_params.i18n_matches_n.replace( '%qty%', matches );
|
||||
},
|
||||
formatNoMatches: function() {
|
||||
return wc_enhanced_select_params.i18n_no_matches;
|
||||
},
|
||||
formatAjaxError: function() {
|
||||
return wc_enhanced_select_params.i18n_ajax_error;
|
||||
},
|
||||
formatInputTooShort: function( input, min ) {
|
||||
var number = min - input.length;
|
||||
|
||||
if ( 1 === number ) {
|
||||
return wc_enhanced_select_params.i18n_input_too_short_1;
|
||||
}
|
||||
|
||||
return wc_enhanced_select_params.i18n_input_too_short_n.replace( '%qty%', number );
|
||||
},
|
||||
formatInputTooLong: function( input, max ) {
|
||||
var number = input.length - max;
|
||||
|
||||
if ( 1 === number ) {
|
||||
return wc_enhanced_select_params.i18n_input_too_long_1;
|
||||
}
|
||||
|
||||
return wc_enhanced_select_params.i18n_input_too_long_n.replace( '%qty%', number );
|
||||
},
|
||||
formatSelectionTooBig: function( limit ) {
|
||||
if ( 1 === limit ) {
|
||||
return wc_enhanced_select_params.i18n_selection_too_long_1;
|
||||
}
|
||||
|
||||
return wc_enhanced_select_params.i18n_selection_too_long_n.replace( '%qty%', limit );
|
||||
},
|
||||
formatLoadMore: function() {
|
||||
return wc_enhanced_select_params.i18n_load_more;
|
||||
},
|
||||
formatSearching: function() {
|
||||
return wc_enhanced_select_params.i18n_searching;
|
||||
}
|
||||
};
|
||||
|
||||
return formatString;
|
||||
}
|
||||
});
|
||||
})( jQuery, shippingZonesLocalizeScript, wp, ajaxurl );
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
/**
|
||||
* Continents
|
||||
*
|
||||
* Returns an array of continents.
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category i18n
|
||||
* @package WooCommerce/i18n
|
||||
* @version 2.5.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
return array(
|
||||
'AF' => array(
|
||||
'name' => __( 'Africa', 'woocommerce' ),
|
||||
'countries' => array(
|
||||
'AO', 'BF', 'BI', 'BJ', 'BW', 'CD', 'CF', 'CG', 'CI', 'CM', 'CV', 'DJ', 'DZ', 'EG', 'EH', 'ER', 'ET', 'GA', 'GH', 'GM', 'GN', 'GQ', 'GW', 'KE', 'KM', 'LR', 'LS', 'LY', 'MA', 'MG', 'ML', 'MR', 'MU', 'MW', 'MZ', 'NA', 'NE', 'NG', 'RE', 'RW', 'SC', 'SD', 'SH', 'SL', 'SN', 'SO', 'ST', 'SZ', 'TD', 'TG', 'TN', 'TZ', 'UG', 'YT', 'ZA', 'ZM', 'ZW'
|
||||
)
|
||||
),
|
||||
'AN' => array(
|
||||
'name' => __( 'Antarctica', 'woocommerce' ),
|
||||
'countries' => array(
|
||||
'AQ', 'BV', 'GS', 'HM', 'TF'
|
||||
)
|
||||
),
|
||||
'AS' => array(
|
||||
'name' => __( 'Asia', 'woocommerce' ),
|
||||
'countries' => array(
|
||||
'AE', 'AF', 'AM', 'AZ', 'BD', 'BH', 'BN', 'BT', 'CC', 'CN', 'CX', 'CY', 'GE', 'HK', 'ID', 'IL', 'IN', 'IO', 'IQ', 'IR', 'JO', 'JP', 'KG', 'KH', 'KP', 'KR', 'KW', 'KZ', 'LA', 'LB', 'LK', 'MM', 'MN', 'MO', 'MV', 'MY', 'NP', 'OM', 'PH', 'PK', 'PS', 'QA', 'SA', 'SG', 'SY', 'TH', 'TJ', 'TL', 'TM', 'TW', 'UZ', 'VN', 'YE'
|
||||
)
|
||||
),
|
||||
'EU' => array(
|
||||
'name' => __( 'Europe', 'woocommerce' ),
|
||||
'countries' => array(
|
||||
'AD', 'AL', 'AT', 'AX', 'BA', 'BE', 'BG', 'BY', 'CH', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FO', 'FR', 'GB', 'GG', 'GI', 'GR', 'HR', 'HU', 'IE', 'IM', 'IS', 'IT', 'JE', 'LI', 'LT', 'LU', 'LV', 'MC', 'MD', 'ME', 'MK', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'RS', 'RU', 'SE', 'SI', 'SJ', 'SK', 'SM', 'TR', 'UA', 'VA'
|
||||
)
|
||||
),
|
||||
'NA' => array(
|
||||
'name' => __( 'North America', 'woocommerce' ),
|
||||
'countries' => array(
|
||||
'AG', 'AI', 'AN', 'AW', 'BB', 'BL', 'BM', 'BS', 'BZ', 'CA', 'CR', 'CU', 'DM', 'DO', 'GD', 'GL', 'GP', 'GT', 'HN', 'HT', 'JM', 'KN', 'KY', 'LC', 'MF', 'MQ', 'MS', 'MX', 'NI', 'PA', 'PM', 'PR', 'SV', 'TC', 'TT', 'US', 'VC', 'VG', 'VI'
|
||||
)
|
||||
),
|
||||
'OC' => array(
|
||||
'name' => __( 'Oceania', 'woocommerce' ),
|
||||
'countries' => array(
|
||||
'AS', 'AU', 'CK', 'FJ', 'FM', 'GU', 'KI', 'MH', 'MP', 'NC', 'NF', 'NR', 'NU', 'NZ', 'PF', 'PG', 'PN', 'PW', 'SB', 'TK', 'TO', 'TV', 'UM', 'VU', 'WF', 'WS'
|
||||
)
|
||||
),
|
||||
'SA' => array(
|
||||
'name' => __( 'South America', 'woocommerce' ),
|
||||
'countries' => array(
|
||||
'AR', 'BO', 'BR', 'CL', 'CO', 'EC', 'FK', 'GF', 'GY', 'PE', 'PY', 'SR', 'UY', 'VE'
|
||||
)
|
||||
)
|
||||
);
|
|
@ -7,11 +7,11 @@
|
|||
* @author WooThemes
|
||||
* @category i18n
|
||||
* @package WooCommerce/i18n
|
||||
* @version 2.2.0
|
||||
* @version 2.5.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
return array(
|
||||
|
@ -19,6 +19,7 @@ return array(
|
|||
'AX' => __( 'Åland Islands', 'woocommerce' ),
|
||||
'AL' => __( 'Albania', 'woocommerce' ),
|
||||
'DZ' => __( 'Algeria', 'woocommerce' ),
|
||||
'AS' => __( 'American Samoa', 'woocommerce' ),
|
||||
'AD' => __( 'Andorra', 'woocommerce' ),
|
||||
'AO' => __( 'Angola', 'woocommerce' ),
|
||||
'AI' => __( 'Anguilla', 'woocommerce' ),
|
||||
|
@ -104,6 +105,7 @@ return array(
|
|||
'GL' => __( 'Greenland', 'woocommerce' ),
|
||||
'GD' => __( 'Grenada', 'woocommerce' ),
|
||||
'GP' => __( 'Guadeloupe', 'woocommerce' ),
|
||||
'GU' => __( 'Guam', 'woocommerce' ),
|
||||
'GT' => __( 'Guatemala', 'woocommerce' ),
|
||||
'GG' => __( 'Guernsey', 'woocommerce' ),
|
||||
'GN' => __( 'Guinea', 'woocommerce' ),
|
||||
|
@ -177,6 +179,7 @@ return array(
|
|||
'NG' => __( 'Nigeria', 'woocommerce' ),
|
||||
'NU' => __( 'Niue', 'woocommerce' ),
|
||||
'NF' => __( 'Norfolk Island', 'woocommerce' ),
|
||||
'MP' => __( 'Northern Mariana Islands', 'woocommerce' ),
|
||||
'KP' => __( 'North Korea', 'woocommerce' ),
|
||||
'NO' => __( 'Norway', 'woocommerce' ),
|
||||
'OM' => __( 'Oman', 'woocommerce' ),
|
||||
|
@ -190,6 +193,7 @@ return array(
|
|||
'PN' => __( 'Pitcairn', 'woocommerce' ),
|
||||
'PL' => __( 'Poland', 'woocommerce' ),
|
||||
'PT' => __( 'Portugal', 'woocommerce' ),
|
||||
'PR' => __( 'Puerto Rico', 'woocommerce' ),
|
||||
'QA' => __( 'Qatar', 'woocommerce' ),
|
||||
'RE' => __( 'Reunion', 'woocommerce' ),
|
||||
'RO' => __( 'Romania', 'woocommerce' ),
|
||||
|
@ -247,6 +251,8 @@ return array(
|
|||
'AE' => __( 'United Arab Emirates', 'woocommerce' ),
|
||||
'GB' => __( 'United Kingdom (UK)', 'woocommerce' ),
|
||||
'US' => __( 'United States (US)', 'woocommerce' ),
|
||||
'UM' => __( 'United States (US) Minor Outlying Islands', 'woocommerce' ),
|
||||
'VI' => __( 'United States (US) Virgin Islands', 'woocommerce' ),
|
||||
'UY' => __( 'Uruguay', 'woocommerce' ),
|
||||
'UZ' => __( 'Uzbekistan', 'woocommerce' ),
|
||||
'VU' => __( 'Vanuatu', 'woocommerce' ),
|
||||
|
|
|
@ -17743,4 +17743,4 @@ msgstr ""
|
|||
#: templates/product-searchform.php:28
|
||||
msgctxt "submit button"
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
msgstr ""
|
||||
|
|
|
@ -64,10 +64,4 @@ $states['US'] = array(
|
|||
'AA' => __( 'Armed Forces (AA)', 'woocommerce' ),
|
||||
'AE' => __( 'Armed Forces (AE)', 'woocommerce' ),
|
||||
'AP' => __( 'Armed Forces (AP)', 'woocommerce' ),
|
||||
'AS' => __( 'American Samoa', 'woocommerce' ),
|
||||
'GU' => __( 'Guam', 'woocommerce' ),
|
||||
'MP' => __( 'Northern Mariana Islands', 'woocommerce' ),
|
||||
'PR' => __( 'Puerto Rico', 'woocommerce' ),
|
||||
'UM' => __( 'US Minor Outlying Islands', 'woocommerce' ),
|
||||
'VI' => __( 'US Virgin Islands', 'woocommerce' ),
|
||||
);
|
||||
|
|
|
@ -11,7 +11,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
*
|
||||
* @class WC_Integration
|
||||
* @extends WC_Settings_API
|
||||
* @version 2.0.0
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce/Abstracts
|
||||
* @category Abstract Class
|
||||
* @author WooThemes
|
||||
|
@ -19,24 +19,54 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
abstract class WC_Integration extends WC_Settings_API {
|
||||
|
||||
/**
|
||||
* Admin Options.
|
||||
*
|
||||
* Setup the gateway settings screen.
|
||||
* Override this in your gateway.
|
||||
* yes or no based on whether the integration is enabled.
|
||||
* @var string
|
||||
*/
|
||||
public function admin_options() { ?>
|
||||
public $enabled = 'yes';
|
||||
|
||||
<h3><?php echo isset( $this->method_title ) ? $this->method_title : __( 'Settings', 'woocommerce' ) ; ?></h3>
|
||||
/**
|
||||
* Integration title.
|
||||
* @var string
|
||||
*/
|
||||
public $method_title = '';
|
||||
|
||||
<?php echo isset( $this->method_description ) ? wpautop( $this->method_description ) : ''; ?>
|
||||
/**
|
||||
* Integration description.
|
||||
* @var string
|
||||
*/
|
||||
public $method_description = '';
|
||||
|
||||
<table class="form-table">
|
||||
<?php $this->generate_settings_html(); ?>
|
||||
</table>
|
||||
/**
|
||||
* Return the title for admin screens.
|
||||
* @return string
|
||||
*/
|
||||
public function get_method_title() {
|
||||
return apply_filters( 'woocommerce_integration_title', $this->method_title, $this );
|
||||
}
|
||||
|
||||
<!-- Section -->
|
||||
<div><input type="hidden" name="section" value="<?php echo $this->id; ?>" /></div>
|
||||
/**
|
||||
* Return the description for admin screens.
|
||||
* @return string
|
||||
*/
|
||||
public function get_method_description() {
|
||||
return apply_filters( 'woocommerce_integration_description', $this->method_description, $this );
|
||||
}
|
||||
|
||||
<?php
|
||||
/**
|
||||
* Output the gateway settings screen.
|
||||
*/
|
||||
public function admin_options() {
|
||||
echo '<h2>' . esc_html( $this->get_method_title() ) . '</h2>';
|
||||
echo wp_kses_post( wpautop( $this->get_method_description() ) );
|
||||
echo '<div><input type="hidden" name="section" value="' . esc_attr( $this->id ) . '" /></div>';
|
||||
parent::admin_options();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init settings for gateways.
|
||||
*/
|
||||
public function init_settings() {
|
||||
parent::init_settings();
|
||||
$this->enabled = ! empty( $this->settings['enabled'] ) && 'yes' === $this->settings['enabled'] ? 'yes' : 'no';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -450,6 +450,13 @@ abstract class WC_Abstract_Order {
|
|||
$taxes = array_map( 'wc_format_decimal', $shipping_rate->taxes );
|
||||
wc_add_order_item_meta( $item_id, 'taxes', $taxes );
|
||||
|
||||
// Store meta
|
||||
if ( ! empty( $shipping_rate->get_meta_data() ) ) {
|
||||
foreach ( $shipping_rate->get_meta_data() as $key => $value ) {
|
||||
wc_add_order_item_meta( $item_id, $key, $value );
|
||||
}
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_order_add_shipping', $this->id, $item_id, $shipping_rate );
|
||||
|
||||
// Update total
|
||||
|
@ -2630,7 +2637,7 @@ abstract class WC_Abstract_Order {
|
|||
* @return boolean
|
||||
*/
|
||||
public function needs_shipping_address() {
|
||||
if ( 'no' === get_option( 'woocommerce_calc_shipping' ) ) {
|
||||
if ( ! wc_shipping_enabled() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,17 +25,41 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
|
|||
public $order_button_text;
|
||||
|
||||
/**
|
||||
* Payment method title.
|
||||
* yes or no based on whether the method is enabled.
|
||||
* @var string
|
||||
*/
|
||||
public $enabled = 'yes';
|
||||
|
||||
/**
|
||||
* Payment method title for the frontend.
|
||||
* @var string
|
||||
*/
|
||||
public $title;
|
||||
|
||||
/**
|
||||
* Payment method description for the frontend.
|
||||
* @var string
|
||||
*/
|
||||
public $description;
|
||||
|
||||
/**
|
||||
* Chosen payment method id.
|
||||
* @var bool
|
||||
*/
|
||||
public $chosen;
|
||||
|
||||
/**
|
||||
* Gateway title.
|
||||
* @var string
|
||||
*/
|
||||
public $method_title = '';
|
||||
|
||||
/**
|
||||
* Gateway description.
|
||||
* @var string
|
||||
*/
|
||||
public $method_description = '';
|
||||
|
||||
/**
|
||||
* True if the gateway shows fields on the checkout.
|
||||
* @var bool
|
||||
|
@ -60,12 +84,6 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
|
|||
*/
|
||||
public $icon;
|
||||
|
||||
/**
|
||||
* Description for the gateway.
|
||||
* @var string
|
||||
*/
|
||||
public $description;
|
||||
|
||||
/**
|
||||
* Supported features such as 'default_credit_card_form', 'refunds'.
|
||||
* @var array
|
||||
|
@ -84,6 +102,39 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
|
|||
*/
|
||||
public $view_transaction_url = '';
|
||||
|
||||
/**
|
||||
* Return the title for admin screens.
|
||||
* @return string
|
||||
*/
|
||||
public function get_method_title() {
|
||||
return apply_filters( 'woocommerce_gateway_method_title', $this->method_title, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the description for admin screens.
|
||||
* @return string
|
||||
*/
|
||||
public function get_method_description() {
|
||||
return apply_filters( 'woocommerce_gateway_method_description', $this->method_description, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the gateway settings screen.
|
||||
*/
|
||||
public function admin_options() {
|
||||
echo '<h2>' . esc_html( $this->get_method_title() ) . '</h2>';
|
||||
echo wp_kses_post( wpautop( $this->get_method_description() ) );
|
||||
parent::admin_options();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init settings for gateways.
|
||||
*/
|
||||
public function init_settings() {
|
||||
parent::init_settings();
|
||||
$this->enabled = ! empty( $this->settings['enabled'] ) && 'yes' === $this->settings['enabled'] ? 'yes' : 'no';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the return url (thank you page).
|
||||
*
|
||||
|
@ -91,7 +142,6 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function get_return_url( $order = null ) {
|
||||
|
||||
if ( $order ) {
|
||||
$return_url = $order->get_checkout_order_received_url();
|
||||
} else {
|
||||
|
@ -152,7 +202,6 @@ abstract class WC_Payment_Gateway extends WC_Settings_API {
|
|||
* @return bool
|
||||
*/
|
||||
public function is_available() {
|
||||
|
||||
$is_available = ( 'yes' === $this->enabled );
|
||||
|
||||
if ( WC()->cart && 0 < $this->get_order_total() && 0 < $this->max_amount && $this->max_amount < $this->get_order_total() ) {
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
/**
|
||||
* Abstract Settings API Class
|
||||
*
|
||||
* Admin Settings API used by Shipping Methods and Payment Gateways.
|
||||
* Admin Settings API used by Integrations, Shipping Methods, and Payment Gateways.
|
||||
*
|
||||
* @class WC_Settings_API
|
||||
* @version 2.4.0
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce/Abstracts
|
||||
* @category Abstract Class
|
||||
* @author WooThemes
|
||||
|
@ -19,28 +19,16 @@ abstract class WC_Settings_API {
|
|||
public $plugin_id = 'woocommerce_';
|
||||
|
||||
/**
|
||||
* Method ID.
|
||||
* ID of the class extending the settings API. Used in option names.
|
||||
* @var string
|
||||
*/
|
||||
public $id = '';
|
||||
|
||||
/**
|
||||
* Method title.
|
||||
* @var string
|
||||
* Validation errors.
|
||||
* @var array of strings
|
||||
*/
|
||||
public $method_title = '';
|
||||
|
||||
/**
|
||||
* Method description.
|
||||
* @var string
|
||||
*/
|
||||
public $method_description = '';
|
||||
|
||||
/**
|
||||
* 'yes' if the method is enabled.
|
||||
* @var string
|
||||
*/
|
||||
public $enabled;
|
||||
public $errors = array();
|
||||
|
||||
/**
|
||||
* Setting values.
|
||||
|
@ -54,86 +42,126 @@ abstract class WC_Settings_API {
|
|||
*/
|
||||
public $form_fields = array();
|
||||
|
||||
/**
|
||||
* Validation errors.
|
||||
* @var array
|
||||
*/
|
||||
public $errors = array();
|
||||
|
||||
/**
|
||||
* Sanitized fields after validation.
|
||||
* @var array
|
||||
*/
|
||||
public $sanitized_fields = array();
|
||||
|
||||
/**
|
||||
* Admin Options.
|
||||
*
|
||||
* Setup the gateway settings screen.
|
||||
* Override this in your gateway.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function admin_options() { ?>
|
||||
|
||||
<h3><?php echo ( ! empty( $this->method_title ) ) ? $this->method_title : __( 'Settings', 'woocommerce' ) ; ?></h3>
|
||||
|
||||
<?php echo ( ! empty( $this->method_description ) ) ? wpautop( $this->method_description ) : ''; ?>
|
||||
|
||||
<table class="form-table">
|
||||
<?php $this->generate_settings_html(); ?>
|
||||
</table><?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise Settings Form Fields.
|
||||
*
|
||||
* Add an array of fields to be displayed
|
||||
* on the gateway's settings screen.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return string
|
||||
*/
|
||||
public function init_form_fields() {}
|
||||
|
||||
/**
|
||||
* Get the form fields after they are initialized.
|
||||
* @return array of options
|
||||
*/
|
||||
public function get_form_fields() {
|
||||
return apply_filters( 'woocommerce_settings_api_form_fields_' . $this->id, $this->form_fields );
|
||||
return apply_filters( 'woocommerce_settings_api_form_fields_' . $this->id, array_map( array( $this, 'set_defaults' ), $this->form_fields ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin Panel Options Processing.
|
||||
* - Saves the options to the DB.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @return bool
|
||||
* Set default required properties for each field.
|
||||
* @param array
|
||||
*/
|
||||
private function set_defaults( $field ) {
|
||||
if ( ! isset( $field['default'] ) ) {
|
||||
$field['default'] = '';
|
||||
}
|
||||
return $field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the admin options table.
|
||||
*/
|
||||
public function admin_options() {
|
||||
echo '<table class="form-table">' . $this->generate_settings_html( $this->get_form_fields(), false ) . '</table>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the option in the WP DB.
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_option_key() {
|
||||
return $this->plugin_id . $this->id . '_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fields type. Defaults to "text" if not set.
|
||||
* @param array $field
|
||||
* @return string
|
||||
*/
|
||||
public function get_field_type( $field ) {
|
||||
return empty( $field['type'] ) ? 'text' : $field['type'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a fields default value. Defaults to "" if not set.
|
||||
* @param array $field
|
||||
* @return string
|
||||
*/
|
||||
public function get_field_default( $field ) {
|
||||
return empty( $field['default'] ) ? '' : $field['default'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a field's posted and validated value.
|
||||
* @return string
|
||||
*/
|
||||
public function get_field_value( $key, $field ) {
|
||||
$type = $this->get_field_type( $field );
|
||||
$field_key = $this->get_field_key( $key );
|
||||
$value = isset( $_POST[ $field_key ] ) ? $_POST[ $field_key ] : null;
|
||||
|
||||
// Look for a validate_FIELDID_field method for special handling
|
||||
if ( is_callable( array( $this, 'validate_' . $key . '_field' ) ) ) {
|
||||
return $this->{'validate_' . $key . '_field'}( $key, $value );
|
||||
}
|
||||
|
||||
// Look for a validate_FIELDTYPE_field method
|
||||
if ( is_callable( array( $this, 'validate_' . $type . '_field' ) ) ) {
|
||||
return $this->{'validate_' . $type . '_field'}( $key, $value );
|
||||
}
|
||||
|
||||
// Fallback to text
|
||||
return $this->validate_text_field( $key, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes and saves options.
|
||||
* If there is an error thrown, will continue to save and validate fields, but will leave the erroring field out.
|
||||
* @return bool was anything saved?
|
||||
*/
|
||||
public function process_admin_options() {
|
||||
$this->init_settings();
|
||||
|
||||
$this->validate_settings_fields();
|
||||
|
||||
if ( count( $this->errors ) > 0 ) {
|
||||
$this->display_errors();
|
||||
return false;
|
||||
} else {
|
||||
update_option( $this->plugin_id . $this->id . '_settings', apply_filters( 'woocommerce_settings_api_sanitized_fields_' . $this->id, $this->sanitized_fields ) );
|
||||
$this->init_settings();
|
||||
return true;
|
||||
foreach ( $this->get_form_fields() as $key => $field ) {
|
||||
if ( 'title' !== $this->get_field_type( $field ) ) {
|
||||
try {
|
||||
$this->settings[ $key ] = $this->get_field_value( $key, $field );
|
||||
} catch ( Exception $e ) {
|
||||
$this->add_error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return update_option( $this->get_option_key(), apply_filters( 'woocommerce_settings_api_sanitized_fields_' . $this->id, $this->settings ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an error message for display in admin on save.
|
||||
* @param string $error
|
||||
*/
|
||||
public function add_error( $error ) {
|
||||
$this->errors[] = $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display admin error messages.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function display_errors() {}
|
||||
public function display_errors() {
|
||||
if ( count( $this->errors ) > 0 ) {
|
||||
echo '<div id="woocommerce_errors" class="error notice is-dismissible">';
|
||||
foreach ( $this->errors as $error ) {
|
||||
echo '<p>' . wp_kses_post( $error ) . '</p>';
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise Gateway Settings.
|
||||
* Initialise Settings.
|
||||
*
|
||||
* Store all settings in a single database entry
|
||||
* and make sure the $settings array is either the default
|
||||
|
@ -143,26 +171,12 @@ abstract class WC_Settings_API {
|
|||
* @uses get_option(), add_option()
|
||||
*/
|
||||
public function init_settings() {
|
||||
$this->settings = get_option( $this->get_option_key(), null );
|
||||
|
||||
// Load form_field settings.
|
||||
$this->settings = get_option( $this->plugin_id . $this->id . '_settings', null );
|
||||
|
||||
if ( ! $this->settings || ! is_array( $this->settings ) ) {
|
||||
|
||||
$this->settings = array();
|
||||
|
||||
// If there are no settings defined, load defaults.
|
||||
if ( $form_fields = $this->get_form_fields() ) {
|
||||
|
||||
foreach ( $form_fields as $k => $v ) {
|
||||
$this->settings[ $k ] = isset( $v['default'] ) ? $v['default'] : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $this->settings ) && is_array( $this->settings ) ) {
|
||||
$this->settings = array_map( array( $this, 'format_settings' ), $this->settings );
|
||||
$this->enabled = isset( $this->settings['enabled'] ) && $this->settings['enabled'] == 'yes' ? 'yes' : 'no';
|
||||
// If there are no settings defined, use defaults.
|
||||
if ( ! is_array( $this->settings ) ) {
|
||||
$form_fields = $this->get_form_fields();
|
||||
$this->settings = array_merge( array_fill_keys( array_keys( $form_fields ), '' ), wp_list_pluck( $form_fields, 'default' ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,7 +190,6 @@ abstract class WC_Settings_API {
|
|||
* @return mixed The value specified for the option or a default value for the option.
|
||||
*/
|
||||
public function get_option( $key, $empty_value = null ) {
|
||||
|
||||
if ( empty( $this->settings ) ) {
|
||||
$this->init_settings();
|
||||
}
|
||||
|
@ -184,10 +197,10 @@ abstract class WC_Settings_API {
|
|||
// Get option default if unset.
|
||||
if ( ! isset( $this->settings[ $key ] ) ) {
|
||||
$form_fields = $this->get_form_fields();
|
||||
$this->settings[ $key ] = isset( $form_fields[ $key ]['default'] ) ? $form_fields[ $key ]['default'] : '';
|
||||
$this->settings[ $key ] = isset( $form_fields[ $key ] ) ? $this->get_field_default( $form_fields[ $key ] ) : '';
|
||||
}
|
||||
|
||||
if ( ! is_null( $empty_value ) && empty( $this->settings[ $key ] ) && '' === $this->settings[ $key ] ) {
|
||||
if ( ! is_null( $empty_value ) && '' === $this->settings[ $key ] ) {
|
||||
$this->settings[ $key ] = $empty_value;
|
||||
}
|
||||
|
||||
|
@ -204,16 +217,6 @@ abstract class WC_Settings_API {
|
|||
return $this->plugin_id . $this->id . '_' . $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode values for settings.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
public function format_settings( $value ) {
|
||||
return is_array( $value ) ? $value : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Settings HTML.
|
||||
*
|
||||
|
@ -224,27 +227,27 @@ abstract class WC_Settings_API {
|
|||
* @uses method_exists()
|
||||
* @return string the html for the settings
|
||||
*/
|
||||
public function generate_settings_html( $form_fields = array() ) {
|
||||
|
||||
public function generate_settings_html( $form_fields = array(), $echo = true ) {
|
||||
if ( empty( $form_fields ) ) {
|
||||
$form_fields = $this->get_form_fields();
|
||||
}
|
||||
|
||||
$html = '';
|
||||
foreach ( $form_fields as $k => $v ) {
|
||||
$type = $this->get_field_type( $v );
|
||||
|
||||
if ( ! isset( $v['type'] ) || ( $v['type'] == '' ) ) {
|
||||
$v['type'] = 'text'; // Default to "text" field type.
|
||||
}
|
||||
|
||||
if ( method_exists( $this, 'generate_' . $v['type'] . '_html' ) ) {
|
||||
$html .= $this->{'generate_' . $v['type'] . '_html'}( $k, $v );
|
||||
if ( method_exists( $this, 'generate_' . $type . '_html' ) ) {
|
||||
$html .= $this->{'generate_' . $type . '_html'}( $k, $v );
|
||||
} else {
|
||||
$html .= $this->{'generate_text_html'}( $k, $v );
|
||||
$html .= $this->generate_text_html( $k, $v );
|
||||
}
|
||||
}
|
||||
|
||||
echo $html;
|
||||
if ( $echo ) {
|
||||
echo $html;
|
||||
} else {
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -272,7 +275,6 @@ abstract class WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function get_description_html( $data ) {
|
||||
|
||||
if ( $data['desc_tip'] === true ) {
|
||||
$description = '';
|
||||
} elseif ( ! empty( $data['desc_tip'] ) ) {
|
||||
|
@ -293,11 +295,9 @@ abstract class WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function get_custom_attribute_html( $data ) {
|
||||
|
||||
$custom_attributes = array();
|
||||
|
||||
if ( ! empty( $data['custom_attributes'] ) && is_array( $data['custom_attributes'] ) ) {
|
||||
|
||||
foreach ( $data['custom_attributes'] as $attribute => $attribute_value ) {
|
||||
$custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
|
||||
}
|
||||
|
@ -315,9 +315,8 @@ abstract class WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_text_html( $key, $data ) {
|
||||
|
||||
$field = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
$field_key = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
'title' => '',
|
||||
'disabled' => false,
|
||||
'class' => '',
|
||||
|
@ -326,7 +325,7 @@ abstract class WC_Settings_API {
|
|||
'type' => 'text',
|
||||
'desc_tip' => false,
|
||||
'description' => '',
|
||||
'custom_attributes' => array()
|
||||
'custom_attributes' => array(),
|
||||
);
|
||||
|
||||
$data = wp_parse_args( $data, $defaults );
|
||||
|
@ -335,13 +334,13 @@ abstract class WC_Settings_API {
|
|||
?>
|
||||
<tr valign="top">
|
||||
<th scope="row" class="titledesc">
|
||||
<label for="<?php echo esc_attr( $field ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<?php echo $this->get_tooltip_html( $data ); ?>
|
||||
</th>
|
||||
<td class="forminp">
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
|
||||
<input class="input-text regular-input <?php echo esc_attr( $data['class'] ); ?>" type="<?php echo esc_attr( $data['type'] ); ?>" name="<?php echo esc_attr( $field ); ?>" id="<?php echo esc_attr( $field ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( $this->get_option( $key ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?> />
|
||||
<input class="input-text regular-input <?php echo esc_attr( $data['class'] ); ?>" type="<?php echo esc_attr( $data['type'] ); ?>" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( $this->get_option( $key ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?> />
|
||||
<?php echo $this->get_description_html( $data ); ?>
|
||||
</fieldset>
|
||||
</td>
|
||||
|
@ -360,9 +359,8 @@ abstract class WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_price_html( $key, $data ) {
|
||||
|
||||
$field = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
$field_key = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
'title' => '',
|
||||
'disabled' => false,
|
||||
'class' => '',
|
||||
|
@ -371,7 +369,7 @@ abstract class WC_Settings_API {
|
|||
'type' => 'text',
|
||||
'desc_tip' => false,
|
||||
'description' => '',
|
||||
'custom_attributes' => array()
|
||||
'custom_attributes' => array(),
|
||||
);
|
||||
|
||||
$data = wp_parse_args( $data, $defaults );
|
||||
|
@ -380,13 +378,13 @@ abstract class WC_Settings_API {
|
|||
?>
|
||||
<tr valign="top">
|
||||
<th scope="row" class="titledesc">
|
||||
<label for="<?php echo esc_attr( $field ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<?php echo $this->get_tooltip_html( $data ); ?>
|
||||
</th>
|
||||
<td class="forminp">
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
|
||||
<input class="wc_input_price input-text regular-input <?php echo esc_attr( $data['class'] ); ?>" type="text" name="<?php echo esc_attr( $field ); ?>" id="<?php echo esc_attr( $field ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $this->get_option( $key ) ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?> />
|
||||
<input class="wc_input_price input-text regular-input <?php echo esc_attr( $data['class'] ); ?>" type="text" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $this->get_option( $key ) ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?> />
|
||||
<?php echo $this->get_description_html( $data ); ?>
|
||||
</fieldset>
|
||||
</td>
|
||||
|
@ -405,9 +403,8 @@ abstract class WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_decimal_html( $key, $data ) {
|
||||
|
||||
$field = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
$field_key = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
'title' => '',
|
||||
'disabled' => false,
|
||||
'class' => '',
|
||||
|
@ -416,7 +413,7 @@ abstract class WC_Settings_API {
|
|||
'type' => 'text',
|
||||
'desc_tip' => false,
|
||||
'description' => '',
|
||||
'custom_attributes' => array()
|
||||
'custom_attributes' => array(),
|
||||
);
|
||||
|
||||
$data = wp_parse_args( $data, $defaults );
|
||||
|
@ -425,13 +422,13 @@ abstract class WC_Settings_API {
|
|||
?>
|
||||
<tr valign="top">
|
||||
<th scope="row" class="titledesc">
|
||||
<label for="<?php echo esc_attr( $field ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<?php echo $this->get_tooltip_html( $data ); ?>
|
||||
</th>
|
||||
<td class="forminp">
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
|
||||
<input class="wc_input_decimal input-text regular-input <?php echo esc_attr( $data['class'] ); ?>" type="text" name="<?php echo esc_attr( $field ); ?>" id="<?php echo esc_attr( $field ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( wc_format_localized_decimal( $this->get_option( $key ) ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?> />
|
||||
<input class="wc_input_decimal input-text regular-input <?php echo esc_attr( $data['class'] ); ?>" type="text" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( wc_format_localized_decimal( $this->get_option( $key ) ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?> />
|
||||
<?php echo $this->get_description_html( $data ); ?>
|
||||
</fieldset>
|
||||
</td>
|
||||
|
@ -463,9 +460,8 @@ abstract class WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_color_html( $key, $data ) {
|
||||
|
||||
$field = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
$field_key = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
'title' => '',
|
||||
'disabled' => false,
|
||||
'class' => '',
|
||||
|
@ -473,7 +469,7 @@ abstract class WC_Settings_API {
|
|||
'placeholder' => '',
|
||||
'desc_tip' => false,
|
||||
'description' => '',
|
||||
'custom_attributes' => array()
|
||||
'custom_attributes' => array(),
|
||||
);
|
||||
|
||||
$data = wp_parse_args( $data, $defaults );
|
||||
|
@ -482,15 +478,15 @@ abstract class WC_Settings_API {
|
|||
?>
|
||||
<tr valign="top">
|
||||
<th scope="row" class="titledesc">
|
||||
<label for="<?php echo esc_attr( $field ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<?php echo $this->get_tooltip_html( $data ); ?>
|
||||
</th>
|
||||
<td class="forminp">
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
|
||||
<span class="colorpickpreview" style="background:<?php echo esc_attr( $this->get_option( $key ) ); ?>;"></span>
|
||||
<input class="colorpick <?php echo esc_attr( $data['class'] ); ?>" type="text" name="<?php echo esc_attr( $field ); ?>" id="<?php echo esc_attr( $field ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( $this->get_option( $key ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?> />
|
||||
<div id="colorPickerDiv_<?php echo esc_attr( $field ); ?>" class="colorpickdiv" style="z-index: 100; background: #eee; border: 1px solid #ccc; position: absolute; display: none;"></div>
|
||||
<input class="colorpick <?php echo esc_attr( $data['class'] ); ?>" type="text" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="<?php echo esc_attr( $this->get_option( $key ) ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?> />
|
||||
<div id="colorPickerDiv_<?php echo esc_attr( $field_key ); ?>" class="colorpickdiv" style="z-index: 100; background: #eee; border: 1px solid #ccc; position: absolute; display: none;"></div>
|
||||
<?php echo $this->get_description_html( $data ); ?>
|
||||
</fieldset>
|
||||
</td>
|
||||
|
@ -509,9 +505,8 @@ abstract class WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_textarea_html( $key, $data ) {
|
||||
|
||||
$field = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
$field_key = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
'title' => '',
|
||||
'disabled' => false,
|
||||
'class' => '',
|
||||
|
@ -520,7 +515,7 @@ abstract class WC_Settings_API {
|
|||
'type' => 'text',
|
||||
'desc_tip' => false,
|
||||
'description' => '',
|
||||
'custom_attributes' => array()
|
||||
'custom_attributes' => array(),
|
||||
);
|
||||
|
||||
$data = wp_parse_args( $data, $defaults );
|
||||
|
@ -529,13 +524,13 @@ abstract class WC_Settings_API {
|
|||
?>
|
||||
<tr valign="top">
|
||||
<th scope="row" class="titledesc">
|
||||
<label for="<?php echo esc_attr( $field ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<?php echo $this->get_tooltip_html( $data ); ?>
|
||||
</th>
|
||||
<td class="forminp">
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
|
||||
<textarea rows="3" cols="20" class="input-text wide-input <?php echo esc_attr( $data['class'] ); ?>" type="<?php echo esc_attr( $data['type'] ); ?>" name="<?php echo esc_attr( $field ); ?>" id="<?php echo esc_attr( $field ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?>><?php echo esc_textarea( $this->get_option( $key ) ); ?></textarea>
|
||||
<textarea rows="3" cols="20" class="input-text wide-input <?php echo esc_attr( $data['class'] ); ?>" type="<?php echo esc_attr( $data['type'] ); ?>" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" placeholder="<?php echo esc_attr( $data['placeholder'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?>><?php echo esc_textarea( $this->get_option( $key ) ); ?></textarea>
|
||||
<?php echo $this->get_description_html( $data ); ?>
|
||||
</fieldset>
|
||||
</td>
|
||||
|
@ -554,9 +549,8 @@ abstract class WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_checkbox_html( $key, $data ) {
|
||||
|
||||
$field = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
$field_key = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
'title' => '',
|
||||
'label' => '',
|
||||
'disabled' => false,
|
||||
|
@ -565,7 +559,7 @@ abstract class WC_Settings_API {
|
|||
'type' => 'text',
|
||||
'desc_tip' => false,
|
||||
'description' => '',
|
||||
'custom_attributes' => array()
|
||||
'custom_attributes' => array(),
|
||||
);
|
||||
|
||||
$data = wp_parse_args( $data, $defaults );
|
||||
|
@ -578,14 +572,14 @@ abstract class WC_Settings_API {
|
|||
?>
|
||||
<tr valign="top">
|
||||
<th scope="row" class="titledesc">
|
||||
<label for="<?php echo esc_attr( $field ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<?php echo $this->get_tooltip_html( $data ); ?>
|
||||
</th>
|
||||
<td class="forminp">
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
|
||||
<label for="<?php echo esc_attr( $field ); ?>">
|
||||
<input <?php disabled( $data['disabled'], true ); ?> class="<?php echo esc_attr( $data['class'] ); ?>" type="checkbox" name="<?php echo esc_attr( $field ); ?>" id="<?php echo esc_attr( $field ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="1" <?php checked( $this->get_option( $key ), 'yes' ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?> /> <?php echo wp_kses_post( $data['label'] ); ?></label><br/>
|
||||
<label for="<?php echo esc_attr( $field_key ); ?>">
|
||||
<input <?php disabled( $data['disabled'], true ); ?> class="<?php echo esc_attr( $data['class'] ); ?>" type="checkbox" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" value="1" <?php checked( $this->get_option( $key ), 'yes' ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?> /> <?php echo wp_kses_post( $data['label'] ); ?></label><br/>
|
||||
<?php echo $this->get_description_html( $data ); ?>
|
||||
</fieldset>
|
||||
</td>
|
||||
|
@ -604,9 +598,8 @@ abstract class WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_select_html( $key, $data ) {
|
||||
|
||||
$field = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
$field_key = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
'title' => '',
|
||||
'disabled' => false,
|
||||
'class' => '',
|
||||
|
@ -616,7 +609,7 @@ abstract class WC_Settings_API {
|
|||
'desc_tip' => false,
|
||||
'description' => '',
|
||||
'custom_attributes' => array(),
|
||||
'options' => array()
|
||||
'options' => array(),
|
||||
);
|
||||
|
||||
$data = wp_parse_args( $data, $defaults );
|
||||
|
@ -625,13 +618,13 @@ abstract class WC_Settings_API {
|
|||
?>
|
||||
<tr valign="top">
|
||||
<th scope="row" class="titledesc">
|
||||
<label for="<?php echo esc_attr( $field ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<?php echo $this->get_tooltip_html( $data ); ?>
|
||||
</th>
|
||||
<td class="forminp">
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
|
||||
<select class="select <?php echo esc_attr( $data['class'] ); ?>" name="<?php echo esc_attr( $field ); ?>" id="<?php echo esc_attr( $field ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?>>
|
||||
<select class="select <?php echo esc_attr( $data['class'] ); ?>" name="<?php echo esc_attr( $field_key ); ?>" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?>>
|
||||
<?php foreach ( (array) $data['options'] as $option_key => $option_value ) : ?>
|
||||
<option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( $option_key, esc_attr( $this->get_option( $key ) ) ); ?>><?php echo esc_attr( $option_value ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
|
@ -654,9 +647,8 @@ abstract class WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_multiselect_html( $key, $data ) {
|
||||
|
||||
$field = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
$field_key = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
'title' => '',
|
||||
'disabled' => false,
|
||||
'class' => '',
|
||||
|
@ -667,7 +659,7 @@ abstract class WC_Settings_API {
|
|||
'description' => '',
|
||||
'custom_attributes' => array(),
|
||||
'select_buttons' => false,
|
||||
'options' => array()
|
||||
'options' => array(),
|
||||
);
|
||||
|
||||
$data = wp_parse_args( $data, $defaults );
|
||||
|
@ -677,13 +669,13 @@ abstract class WC_Settings_API {
|
|||
?>
|
||||
<tr valign="top">
|
||||
<th scope="row" class="titledesc">
|
||||
<label for="<?php echo esc_attr( $field ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<label for="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></label>
|
||||
<?php echo $this->get_tooltip_html( $data ); ?>
|
||||
</th>
|
||||
<td class="forminp">
|
||||
<fieldset>
|
||||
<legend class="screen-reader-text"><span><?php echo wp_kses_post( $data['title'] ); ?></span></legend>
|
||||
<select multiple="multiple" class="multiselect <?php echo esc_attr( $data['class'] ); ?>" name="<?php echo esc_attr( $field ); ?>[]" id="<?php echo esc_attr( $field ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?>>
|
||||
<select multiple="multiple" class="multiselect <?php echo esc_attr( $data['class'] ); ?>" name="<?php echo esc_attr( $field_key ); ?>[]" id="<?php echo esc_attr( $field_key ); ?>" style="<?php echo esc_attr( $data['css'] ); ?>" <?php disabled( $data['disabled'], true ); ?> <?php echo $this->get_custom_attribute_html( $data ); ?>>
|
||||
<?php foreach ( (array) $data['options'] as $option_key => $option_value ) : ?>
|
||||
<option value="<?php echo esc_attr( $option_key ); ?>" <?php selected( in_array( $option_key, $value ), true ); ?>><?php echo esc_attr( $option_value ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
|
@ -709,11 +701,10 @@ abstract class WC_Settings_API {
|
|||
* @return string
|
||||
*/
|
||||
public function generate_title_html( $key, $data ) {
|
||||
|
||||
$field = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
'title' => '',
|
||||
'class' => ''
|
||||
$field_key = $this->get_field_key( $key );
|
||||
$defaults = array(
|
||||
'title' => '',
|
||||
'class' => '',
|
||||
);
|
||||
|
||||
$data = wp_parse_args( $data, $defaults );
|
||||
|
@ -721,7 +712,7 @@ abstract class WC_Settings_API {
|
|||
ob_start();
|
||||
?>
|
||||
</table>
|
||||
<h3 class="wc-settings-sub-title <?php echo esc_attr( $data['class'] ); ?>" id="<?php echo esc_attr( $field ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></h3>
|
||||
<h3 class="wc-settings-sub-title <?php echo esc_attr( $data['class'] ); ?>" id="<?php echo esc_attr( $field_key ); ?>"><?php echo wp_kses_post( $data['title'] ); ?></h3>
|
||||
<?php if ( ! empty( $data['description'] ) ) : ?>
|
||||
<p><?php echo wp_kses_post( $data['description'] ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
@ -731,63 +722,18 @@ abstract class WC_Settings_API {
|
|||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the data on the "Settings" form.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @param array $form_fields (default: array())
|
||||
*/
|
||||
public function validate_settings_fields( $form_fields = array() ) {
|
||||
if ( empty( $form_fields ) ) {
|
||||
$form_fields = $this->get_form_fields();
|
||||
}
|
||||
|
||||
$this->sanitized_fields = array();
|
||||
|
||||
foreach ( $form_fields as $key => $field ) {
|
||||
|
||||
// Default to "text" field type.
|
||||
$type = empty( $field['type'] ) ? 'text' : $field['type'];
|
||||
|
||||
// Look for a validate_FIELDID_field method for special handling
|
||||
if ( method_exists( $this, 'validate_' . $key . '_field' ) ) {
|
||||
$field = $this->{'validate_' . $key . '_field'}( $key );
|
||||
|
||||
// Exclude certain types from saving
|
||||
} elseif ( in_array( $type, array( 'title' ) ) ) {
|
||||
continue;
|
||||
|
||||
// Look for a validate_FIELDTYPE_field method
|
||||
} elseif ( method_exists( $this, 'validate_' . $type . '_field' ) ) {
|
||||
$field = $this->{'validate_' . $type . '_field'}( $key );
|
||||
|
||||
// Fallback to text
|
||||
} else {
|
||||
$field = $this->validate_text_field( $key );
|
||||
}
|
||||
|
||||
$this->sanitized_fields[ $key ] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Text Field.
|
||||
*
|
||||
* Make sure the data is escaped correctly, etc.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param string $key Field key
|
||||
* @param string|null $value Posted Value
|
||||
* @return string
|
||||
*/
|
||||
public function validate_text_field( $key ) {
|
||||
|
||||
$text = $this->get_option( $key );
|
||||
$field = $this->get_field_key( $key );
|
||||
|
||||
if ( isset( $_POST[ $field ] ) ) {
|
||||
$text = wp_kses_post( trim( stripslashes( $_POST[ $field ] ) ) );
|
||||
}
|
||||
|
||||
return $text;
|
||||
public function validate_text_field( $key, $value ) {
|
||||
$value = is_null( $value ) ? '' : $value;
|
||||
return wp_kses_post( trim( stripslashes( $value ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -795,24 +741,13 @@ abstract class WC_Settings_API {
|
|||
*
|
||||
* Make sure the data is escaped correctly, etc.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param string $key
|
||||
* @param string|null $value Posted Value
|
||||
* @return string
|
||||
*/
|
||||
public function validate_price_field( $key ) {
|
||||
|
||||
$text = $this->get_option( $key );
|
||||
$field = $this->get_field_key( $key );
|
||||
|
||||
if ( isset( $_POST[ $field ] ) ) {
|
||||
|
||||
if ( $_POST[ $field ] !== '' ) {
|
||||
$text = wc_format_decimal( trim( stripslashes( $_POST[ $field ] ) ) );
|
||||
} else {
|
||||
$text = '';
|
||||
}
|
||||
}
|
||||
|
||||
return $text;
|
||||
public function validate_price_field( $key, $value ) {
|
||||
$value = is_null( $value ) ? '' : $value;
|
||||
return $value === '' ? '' : wc_format_decimal( trim( stripslashes( $value ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -820,24 +755,13 @@ abstract class WC_Settings_API {
|
|||
*
|
||||
* Make sure the data is escaped correctly, etc.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param string $key
|
||||
* @param string|null $value Posted Value
|
||||
* @return string
|
||||
*/
|
||||
public function validate_decimal_field( $key ) {
|
||||
|
||||
$text = $this->get_option( $key );
|
||||
$field = $this->get_field_key( $key );
|
||||
|
||||
if ( isset( $_POST[ $field ] ) ) {
|
||||
|
||||
if ( $_POST[ $field ] !== '' ) {
|
||||
$text = wc_format_decimal( trim( stripslashes( $_POST[ $field ] ) ) );
|
||||
} else {
|
||||
$text = '';
|
||||
}
|
||||
}
|
||||
|
||||
return $text;
|
||||
public function validate_decimal_field( $key, $value ) {
|
||||
$value = is_null( $value ) ? '' : $value;
|
||||
return $value === '' ? '' : wc_format_decimal( trim( stripslashes( $value ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -845,43 +769,32 @@ abstract class WC_Settings_API {
|
|||
*
|
||||
* Make sure the data is escaped correctly, etc.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @since 1.0.0
|
||||
* @param string $key
|
||||
* @param string|null $value Posted Value
|
||||
* @return string
|
||||
*/
|
||||
public function validate_password_field( $key ) {
|
||||
$field = $this->get_field_key( $key );
|
||||
$value = wp_kses_post( trim( stripslashes( $_POST[ $field ] ) ) );
|
||||
return $value;
|
||||
public function validate_password_field( $key, $value ) {
|
||||
$value = is_null( $value ) ? '' : $value;
|
||||
return wp_kses_post( trim( stripslashes( $value ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Textarea Field.
|
||||
*
|
||||
* Make sure the data is escaped correctly, etc.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @since 1.0.0
|
||||
* @param string $key
|
||||
* @param string|null $value Posted Value
|
||||
* @return string
|
||||
*/
|
||||
public function validate_textarea_field( $key ) {
|
||||
|
||||
$text = $this->get_option( $key );
|
||||
$field = $this->get_field_key( $key );
|
||||
|
||||
if ( isset( $_POST[ $field ] ) ) {
|
||||
|
||||
$text = wp_kses( trim( stripslashes( $_POST[ $field ] ) ),
|
||||
array_merge(
|
||||
array(
|
||||
'iframe' => array( 'src' => true, 'style' => true, 'id' => true, 'class' => true )
|
||||
),
|
||||
wp_kses_allowed_html( 'post' )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $text;
|
||||
public function validate_textarea_field( $key, $value ) {
|
||||
$value = is_null( $value ) ? '' : $value;
|
||||
return wp_kses( trim( stripslashes( $value ) ),
|
||||
array_merge(
|
||||
array(
|
||||
'iframe' => array( 'src' => true, 'style' => true, 'id' => true, 'class' => true )
|
||||
),
|
||||
wp_kses_allowed_html( 'post' )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -889,62 +802,53 @@ abstract class WC_Settings_API {
|
|||
*
|
||||
* If not set, return "no", otherwise return "yes".
|
||||
*
|
||||
* @param mixed $key
|
||||
* @since 1.0.0
|
||||
* @param string $key
|
||||
* @param string|null $value Posted Value
|
||||
* @return string
|
||||
*/
|
||||
public function validate_checkbox_field( $key ) {
|
||||
|
||||
$status = 'no';
|
||||
$field = $this->get_field_key( $key );
|
||||
|
||||
if ( isset( $_POST[ $field ] ) && ( 1 == $_POST[ $field ] ) ) {
|
||||
$status = 'yes';
|
||||
}
|
||||
|
||||
return $status;
|
||||
public function validate_checkbox_field( $key, $value ) {
|
||||
return ! is_null( $value ) ? 'yes' : 'no';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Select Field.
|
||||
*
|
||||
* Make sure the data is escaped correctly, etc.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @since 1.0.0
|
||||
* @param string $key
|
||||
* @param string $value Posted Value
|
||||
* @return string
|
||||
*/
|
||||
public function validate_select_field( $key ) {
|
||||
|
||||
$value = $this->get_option( $key );
|
||||
$field = $this->get_field_key( $key );
|
||||
|
||||
if ( isset( $_POST[ $field ] ) ) {
|
||||
$value = wc_clean( stripslashes( $_POST[ $field ] ) );
|
||||
}
|
||||
|
||||
return $value;
|
||||
public function validate_select_field( $key, $value ) {
|
||||
$value = is_null( $value ) ? '' : $value;
|
||||
return wc_clean( stripslashes( $value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate Multiselect Field.
|
||||
*
|
||||
* Make sure the data is escaped correctly, etc.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @since 1.0.0
|
||||
* @param string $key
|
||||
* @param string $value Posted Value
|
||||
* @return string
|
||||
*/
|
||||
public function validate_multiselect_field( $key ) {
|
||||
public function validate_multiselect_field( $key, $value ) {
|
||||
return is_array( $value ) ? array_map( 'wc_clean', array_map( 'stripslashes', $value ) ) : '';
|
||||
}
|
||||
|
||||
$field = $this->get_field_key( $key );
|
||||
|
||||
if ( isset( $_POST[ $field ] ) ) {
|
||||
$value = array_map( 'wc_clean', array_map( 'stripslashes', (array) $_POST[ $field ] ) );
|
||||
} else {
|
||||
$value = '';
|
||||
}
|
||||
/**
|
||||
* Validate the data on the "Settings" form.
|
||||
* @deprecated 2.6.0 No longer used
|
||||
*/
|
||||
public function validate_settings_fields( $form_fields = array() ) {
|
||||
_deprecated_function( 'validate_settings_fields', '2.6' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Format settings if needed.
|
||||
* @deprecated 2.6.0 Unused
|
||||
* @param array $value
|
||||
* @return array
|
||||
*/
|
||||
public function format_settings( $value ) {
|
||||
_deprecated_function( 'format_settings', '2.6' );
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,180 +10,182 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* Extended by shipping methods to handle shipping calculations etc.
|
||||
*
|
||||
* @class WC_Shipping_Method
|
||||
* @version 2.3.0
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce/Abstracts
|
||||
* @category Abstract Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
abstract class WC_Shipping_Method extends WC_Settings_API {
|
||||
|
||||
/** @var string Unique ID for the shipping method - must be set. */
|
||||
public $id;
|
||||
/**
|
||||
* Features this method supports. Possible features used by core:
|
||||
* - shipping-zones Shipping zone functionality + instances
|
||||
* - instance-settings Instance settings screens.
|
||||
* - settings Non-instance settings screens. Enabled by default for BW compatibility with methods before instances existed.
|
||||
* @var array
|
||||
*/
|
||||
public $supports = array( 'settings' );
|
||||
|
||||
/** @var int Optional instance ID. */
|
||||
public $number;
|
||||
/**
|
||||
* Unique ID for the shipping method - must be set.
|
||||
* @var string
|
||||
*/
|
||||
public $id = '';
|
||||
|
||||
/** @var string Method title */
|
||||
public $method_title;
|
||||
/**
|
||||
* Method title.
|
||||
* @var string
|
||||
*/
|
||||
public $method_title = '';
|
||||
|
||||
/** @var string User set title */
|
||||
/**
|
||||
* Method description.
|
||||
* @var string
|
||||
*/
|
||||
public $method_description = '';
|
||||
|
||||
/**
|
||||
* yes or no based on whether the method is enabled.
|
||||
* @var string
|
||||
*/
|
||||
public $enabled = 'yes';
|
||||
|
||||
/**
|
||||
* Shipping method title for the frontend.
|
||||
* @var string
|
||||
*/
|
||||
public $title;
|
||||
|
||||
/** @var bool True if the method is available. */
|
||||
public $availability;
|
||||
/**
|
||||
* This is an array of rates - methods must populate this array to register shipping costs.
|
||||
* @var array
|
||||
*/
|
||||
public $rates = array();
|
||||
|
||||
/** @var array Array of countries this method is enabled for. */
|
||||
public $countries = array();
|
||||
/**
|
||||
* If 'taxable' tax will be charged for this method (if applicable).
|
||||
* @var string
|
||||
*/
|
||||
public $tax_status = 'taxable';
|
||||
|
||||
/** @var string If 'taxable' tax will be charged for this method (if applicable) */
|
||||
public $tax_status = 'taxable';
|
||||
|
||||
/** @var mixed Fees for the method */
|
||||
public $fee = 0;
|
||||
/**
|
||||
* Fee for the method (if applicable).
|
||||
* @var string
|
||||
*/
|
||||
public $fee = null;
|
||||
|
||||
/** @var float Minimum fee for the method */
|
||||
public $minimum_fee = null;
|
||||
/**
|
||||
* Minimum fee for the method (if applicable).
|
||||
* @var string
|
||||
*/
|
||||
public $minimum_fee = null;
|
||||
|
||||
/** @var bool Enabled for disabled */
|
||||
public $enabled = false;
|
||||
/**
|
||||
* Instance ID if used.
|
||||
* @var int
|
||||
*/
|
||||
public $instance_id = 0;
|
||||
|
||||
/** @var bool Whether the method has settings or not (In WooCommerce > Settings > Shipping) */
|
||||
public $has_settings = true;
|
||||
/**
|
||||
* Instance form fields.
|
||||
* @var array
|
||||
*/
|
||||
public $instance_form_fields = array();
|
||||
|
||||
/** @var array Features this method supports. */
|
||||
public $supports = array();
|
||||
/**
|
||||
* Instance settings.
|
||||
* @var array
|
||||
*/
|
||||
public $instance_settings = array();
|
||||
|
||||
/** @var array This is an array of rates - methods must populate this array to register shipping costs */
|
||||
public $rates = array();
|
||||
/**
|
||||
* Availability - legacy. Used for method Availability.
|
||||
* No longer useful for instance based shipping methods.
|
||||
* @deprecated 2.6.0
|
||||
* @var string
|
||||
*/
|
||||
public $availability;
|
||||
|
||||
/**
|
||||
* Availability countries - legacy. Used for method Availability.
|
||||
* No longer useful for instance based shipping methods.
|
||||
* @deprecated 2.6.0
|
||||
* @var array
|
||||
*/
|
||||
public $countries = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param int $instance_id
|
||||
*/
|
||||
public function __construct( $instance_id = 0 ) {
|
||||
$this->instance_id = absint( $instance_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a shipping method supports a given feature.
|
||||
*
|
||||
* Methods should override this to declare support (or lack of support) for a feature.
|
||||
*
|
||||
* @param $feature string The name of a feature to test support for.
|
||||
* @return bool True if the shipping method supports the feature, false otherwise.
|
||||
*/
|
||||
public function supports( $feature ) {
|
||||
return apply_filters( 'woocommerce_shipping_method_supports', in_array( $feature, $this->supports ), $feature, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to calculate shipping rates for this method. Rates can be added using the add_rate() method.
|
||||
*/
|
||||
public function calculate_shipping( $package = array() ) {}
|
||||
|
||||
/**
|
||||
* Whether or not we need to calculate tax on top of the shipping rate.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_taxable() {
|
||||
return ( wc_tax_enabled() && $this->tax_status == 'taxable' && ! WC()->customer->is_vat_exempt() );
|
||||
return wc_tax_enabled() && 'taxable' === $this->tax_status && ! WC()->customer->is_vat_exempt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a rate.
|
||||
*
|
||||
* Add a shipping rate. If taxes are not set they will be calculated based on cost.
|
||||
*
|
||||
* @param array $args (default: array())
|
||||
* Whether or not this method is enabled in settings.
|
||||
* @since 2.6.0
|
||||
* @return boolean
|
||||
*/
|
||||
public function add_rate( $args = array() ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'id' => '', // ID for the rate
|
||||
'label' => '', // Label for the rate
|
||||
'cost' => '0', // Amount or array of costs (per item shipping)
|
||||
'taxes' => '', // Pass taxes, nothing to have it calculated for you, or 'false' to calc no tax
|
||||
'calc_tax' => 'per_order' // Calc tax per_order or per_item. Per item needs an array of costs
|
||||
) );
|
||||
|
||||
// Id and label are required
|
||||
if ( ! $args['id'] || ! $args['label'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Total up the cost
|
||||
$total_cost = is_array( $args['cost'] ) ? array_sum( $args['cost'] ) : $args['cost'];
|
||||
$taxes = $args['taxes'];
|
||||
|
||||
// Taxes - if not an array and not set to false, calc tax based on cost and passed calc_tax variable
|
||||
// This saves shipping methods having to do complex tax calculations
|
||||
if ( ! is_array( $taxes ) && $taxes !== false && $total_cost > 0 && $this->is_taxable() ) {
|
||||
$taxes = array();
|
||||
|
||||
switch ( $args['calc_tax'] ) {
|
||||
case "per_item" :
|
||||
// If we have an array of costs we can look up each items tax class and add tax accordingly
|
||||
if ( is_array( $args['cost'] ) ) {
|
||||
|
||||
$cart = WC()->cart->get_cart();
|
||||
|
||||
foreach ( $args['cost'] as $cost_key => $amount ) {
|
||||
if ( ! isset( $cart[ $cost_key ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$item_taxes = WC_Tax::calc_shipping_tax( $amount, WC_Tax::get_shipping_tax_rates( $cart[ $cost_key ]['data']->get_tax_class() ) );
|
||||
|
||||
// Sum the item taxes
|
||||
foreach ( array_keys( $taxes + $item_taxes ) as $key ) {
|
||||
$taxes[ $key ] = ( isset( $item_taxes[ $key ] ) ? $item_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 );
|
||||
}
|
||||
}
|
||||
|
||||
// Add any cost for the order - order costs are in the key 'order'
|
||||
if ( isset( $args['cost']['order'] ) ) {
|
||||
$item_taxes = WC_Tax::calc_shipping_tax( $args['cost']['order'], WC_Tax::get_shipping_tax_rates() );
|
||||
|
||||
// Sum the item taxes
|
||||
foreach ( array_keys( $taxes + $item_taxes ) as $key ) {
|
||||
$taxes[ $key ] = ( isset( $item_taxes[ $key ] ) ? $item_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default :
|
||||
$taxes = WC_Tax::calc_shipping_tax( $total_cost, WC_Tax::get_shipping_tax_rates() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Round the total cost after taxes have been calculated.
|
||||
$total_cost = wc_format_decimal( $total_cost, wc_get_price_decimals() );
|
||||
$this->rates[] = new WC_Shipping_Rate( $args['id'], $args['label'], $total_cost, $taxes, $this->id );
|
||||
public function is_enabled() {
|
||||
return 'yes' === $this->enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the shipping method has settings or not.
|
||||
*
|
||||
* @return bool
|
||||
* Return the shipping method instance ID.
|
||||
* @since 2.6.0
|
||||
* @return int
|
||||
*/
|
||||
public function has_settings() {
|
||||
return $this->has_settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if shipping method is available or not.
|
||||
*
|
||||
* @param array $package
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available( $package ) {
|
||||
if ( 'no' == $this->enabled ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Country availability
|
||||
$countries = is_array( $this->countries ) ? $this->countries : array();
|
||||
|
||||
switch ( $this->availability ) {
|
||||
case 'specific' :
|
||||
case 'including' :
|
||||
$ship_to_countries = array_intersect( $countries, array_keys( WC()->countries->get_shipping_countries() ) );
|
||||
break;
|
||||
|
||||
case 'excluding' :
|
||||
$ship_to_countries = array_diff( array_keys( WC()->countries->get_shipping_countries() ), $countries );
|
||||
break;
|
||||
|
||||
default :
|
||||
$ship_to_countries = array_keys( WC()->countries->get_shipping_countries() );
|
||||
break;
|
||||
}
|
||||
|
||||
if ( ! in_array( $package['destination']['country'], $ship_to_countries ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', true, $package );
|
||||
public function get_instance_id() {
|
||||
return $this->instance_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the shipping method title.
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_method_title() {
|
||||
return apply_filters( 'woocommerce_shipping_method_title', $this->method_title, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the shipping method description.
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_method_description() {
|
||||
return apply_filters( 'woocommerce_shipping_method_description', $this->method_description, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the shipping title which is user set.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
@ -192,10 +194,137 @@ abstract class WC_Shipping_Method extends WC_Settings_API {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get fee for the shipping method.
|
||||
*
|
||||
* @param mixed $fee
|
||||
* @param mixed $total
|
||||
* Return calculated rates for a package.
|
||||
* @since 2.6.0
|
||||
* @param object $package
|
||||
* @return array
|
||||
*/
|
||||
public function get_rates_for_package( $package ) {
|
||||
$this->rates = array();
|
||||
if ( $this->is_available( $package ) && ( empty( $package['ship_via'] ) || in_array( $this->id, $package['ship_via'] ) ) ) {
|
||||
$this->calculate_shipping( $package );
|
||||
}
|
||||
return $this->rates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a shipping rate. If taxes are not set they will be calculated based on cost.
|
||||
* @param array $args (default: array())
|
||||
*/
|
||||
public function add_rate( $args = array() ) {
|
||||
$args = wp_parse_args( $args, array(
|
||||
'id' => '', // ID for the rate
|
||||
'label' => '', // Label for the rate
|
||||
'cost' => '0', // Amount or array of costs (per item shipping)
|
||||
'taxes' => '', // Pass taxes, or leave empty to have it calculated for you, or 'false' to disable calculations
|
||||
'calc_tax' => 'per_order', // Calc tax per_order or per_item. Per item needs an array of costs
|
||||
'meta_data' => array() // Array of misc meta data to store along with this rate - key value pairs.
|
||||
) );
|
||||
|
||||
// ID and label are required
|
||||
if ( ! $args['id'] || ! $args['label'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Total up the cost
|
||||
$total_cost = is_array( $args['cost'] ) ? array_sum( $args['cost'] ) : $args['cost'];
|
||||
$taxes = $args['taxes'];
|
||||
|
||||
// Taxes - if not an array and not set to false, calc tax based on cost and passed calc_tax variable. This saves shipping methods having to do complex tax calculations.
|
||||
if ( ! is_array( $taxes ) && $taxes !== false && $total_cost > 0 && $this->is_taxable() ) {
|
||||
$taxes = 'per_item' === $args['calc_tax'] ? $this->get_taxes_per_item( $args['cost'] ) : WC_Tax::calc_shipping_tax( $total_cost, WC_Tax::get_shipping_tax_rates() );
|
||||
}
|
||||
|
||||
// Round the total cost after taxes have been calculated.
|
||||
$total_cost = wc_format_decimal( $total_cost, wc_get_price_decimals() );
|
||||
|
||||
// Create rate object
|
||||
$rate = new WC_Shipping_Rate( $args['id'], $args['label'], $total_cost, $taxes, $this->id );
|
||||
|
||||
if ( ! empty( $args['meta_data'] ) ) {
|
||||
foreach ( $args['meta_data'] as $key => $value ) {
|
||||
$rate->add_meta_data( $key, $value );
|
||||
}
|
||||
}
|
||||
|
||||
$this->rates[ $args['id'] ] = $rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calc taxes per item being shipping in costs array.
|
||||
* @since 2.6.0
|
||||
* @access protected
|
||||
* @param array $costs
|
||||
* @return array of taxes
|
||||
*/
|
||||
protected function get_taxes_per_item( $costs ) {
|
||||
$taxes = array();
|
||||
|
||||
// If we have an array of costs we can look up each items tax class and add tax accordingly
|
||||
if ( is_array( $costs ) ) {
|
||||
|
||||
$cart = WC()->cart->get_cart();
|
||||
|
||||
foreach ( $costs as $cost_key => $amount ) {
|
||||
if ( ! isset( $cart[ $cost_key ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$item_taxes = WC_Tax::calc_shipping_tax( $amount, WC_Tax::get_shipping_tax_rates( $cart[ $cost_key ]['data']->get_tax_class() ) );
|
||||
|
||||
// Sum the item taxes
|
||||
foreach ( array_keys( $taxes + $item_taxes ) as $key ) {
|
||||
$taxes[ $key ] = ( isset( $item_taxes[ $key ] ) ? $item_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 );
|
||||
}
|
||||
}
|
||||
|
||||
// Add any cost for the order - order costs are in the key 'order'
|
||||
if ( isset( $costs['order'] ) ) {
|
||||
$item_taxes = WC_Tax::calc_shipping_tax( $costs['order'], WC_Tax::get_shipping_tax_rates() );
|
||||
|
||||
// Sum the item taxes
|
||||
foreach ( array_keys( $taxes + $item_taxes ) as $key ) {
|
||||
$taxes[ $key ] = ( isset( $item_taxes[ $key ] ) ? $item_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $taxes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this method available?
|
||||
* @param array $package
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available( $package ) {
|
||||
$available = $this->is_enabled();
|
||||
|
||||
// Country availability (legacy, for non-zone based methods)
|
||||
if ( ! $this->instance_id ) {
|
||||
$countries = is_array( $this->countries ) ? $this->countries : array();
|
||||
|
||||
switch ( $this->availability ) {
|
||||
case 'specific' :
|
||||
case 'including' :
|
||||
$available = in_array( $package['destination']['country'], array_intersect( $countries, array_keys( WC()->countries->get_shipping_countries() ) ) );
|
||||
break;
|
||||
case 'excluding' :
|
||||
$available = in_array( $package['destination']['country'], array_diff( array_keys( WC()->countries->get_shipping_countries() ), $countries ) );
|
||||
break;
|
||||
default :
|
||||
$available = in_array( $package['destination']['country'], array_keys( WC()->countries->get_shipping_countries() ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $available, $package );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get fee to add to shipping cost.
|
||||
* @param string|float $fee
|
||||
* @param float $total
|
||||
* @return float
|
||||
*/
|
||||
public function get_fee( $fee, $total ) {
|
||||
|
@ -209,15 +338,127 @@ abstract class WC_Shipping_Method extends WC_Settings_API {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if a shipping method supports a given feature.
|
||||
*
|
||||
* Methods should override this to declare support (or lack of support) for a feature.
|
||||
*
|
||||
* @param $feature string The name of a feature to test support for.
|
||||
* @return bool True if the gateway supports the feature, false otherwise.
|
||||
* @since 1.5.7
|
||||
* Does this method have a settings page?
|
||||
* @return bool
|
||||
*/
|
||||
public function supports( $feature ) {
|
||||
return apply_filters( 'woocommerce_shipping_method_supports', in_array( $feature, $this->supports ) ? true : false, $feature, $this );
|
||||
public function has_settings() {
|
||||
return $this->instance_id ? $this->supports( 'instance-settings' ) : $this->supports( 'settings' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the shipping settings screen.
|
||||
*/
|
||||
public function admin_options() {
|
||||
if ( $this->instance_id ) {
|
||||
echo wp_kses_post( wpautop( $this->get_method_description() ) );
|
||||
echo '<table class="form-table">' . $this->generate_settings_html( $this->get_instance_form_fields(), false ) . '</table>';
|
||||
} else {
|
||||
echo '<h2>' . esc_html( $this->get_method_title() ) . '</h2>';
|
||||
echo wp_kses_post( wpautop( $this->get_method_description() ) );
|
||||
echo '<table class="form-table">' . $this->generate_settings_html( $this->get_form_fields(), false ) . '</table>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get_option function.
|
||||
*
|
||||
* Gets and option from the settings API, using defaults if necessary to prevent undefined notices.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $empty_value
|
||||
* @return mixed The value specified for the option or a default value for the option.
|
||||
*/
|
||||
public function get_option( $key, $empty_value = null ) {
|
||||
// Instance options take priority over global options
|
||||
if ( array_key_exists( $key, $this->get_instance_form_fields() ) ) {
|
||||
return $this->get_instance_option( $key, $empty_value );
|
||||
}
|
||||
|
||||
// Return global option
|
||||
return parent::get_option( $key, $empty_value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an option from the settings API, using defaults if necessary to prevent undefined notices.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $empty_value
|
||||
* @return mixed The value specified for the option or a default value for the option.
|
||||
*/
|
||||
public function get_instance_option( $key, $empty_value = null ) {
|
||||
if ( empty( $this->instance_settings ) ) {
|
||||
$this->init_instance_settings();
|
||||
}
|
||||
|
||||
// Get option default if unset.
|
||||
if ( ! isset( $this->instance_settings[ $key ] ) ) {
|
||||
$form_fields = $this->get_instance_form_fields();
|
||||
$this->instance_settings[ $key ] = $this->get_field_default( $form_fields[ $key ] );
|
||||
}
|
||||
|
||||
if ( ! is_null( $empty_value ) && '' === $this->instance_settings[ $key ] ) {
|
||||
$this->instance_settings[ $key ] = $empty_value;
|
||||
}
|
||||
|
||||
return $this->instance_settings[ $key ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings fields for instances of this shipping method (within zones).
|
||||
* Should be overridden by shipping methods to add options.
|
||||
* @since 2.6.0
|
||||
* @return array
|
||||
*/
|
||||
public function get_instance_form_fields() {
|
||||
return apply_filters( 'woocommerce_shipping_instance_form_fields_' . $this->id, $this->instance_form_fields );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the option in the WP DB.
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_instance_option_key() {
|
||||
return $this->instance_id ? $this->plugin_id . $this->id . '_' . $this->instance_id . '_settings' : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise Settings for instances.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public function init_instance_settings() {
|
||||
$this->instance_settings = get_option( $this->get_instance_option_key(), null );
|
||||
|
||||
// If there are no settings defined, use defaults.
|
||||
if ( ! is_array( $this->instance_settings ) ) {
|
||||
$form_fields = $this->get_instance_form_fields();
|
||||
$this->instance_settings = array_merge( array_fill_keys( array_keys( $form_fields ), '' ), wp_list_pluck( $form_fields, 'default' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes and saves options.
|
||||
* If there is an error thrown, will continue to save and validate fields, but will leave the erroring field out.
|
||||
* @since 2.6.0
|
||||
* @return bool was anything saved?
|
||||
*/
|
||||
public function process_admin_options() {
|
||||
if ( $this->instance_id ) {
|
||||
$this->init_instance_settings();
|
||||
|
||||
foreach ( $this->get_instance_form_fields() as $key => $field ) {
|
||||
if ( 'title' !== $this->get_field_type( $field ) ) {
|
||||
try {
|
||||
$this->instance_settings[ $key ] = $this->get_field_value( $key, $field );
|
||||
} catch ( Exception $e ) {
|
||||
$this->add_error( $e->getMessage() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return update_option( $this->get_instance_option_key(), apply_filters( 'woocommerce_shipping_' . $this->id . '_instance_settings_values', $this->instance_settings, $this ) );
|
||||
} else {
|
||||
return parent::process_admin_options();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,6 +102,10 @@ class WC_Admin_Assets {
|
|||
wp_register_script( 'flot-pie', WC()->plugin_url() . '/assets/js/jquery-flot/jquery.flot.pie' . $suffix . '.js', array( 'jquery', 'flot' ), WC_VERSION );
|
||||
wp_register_script( 'flot-stack', WC()->plugin_url() . '/assets/js/jquery-flot/jquery.flot.stack' . $suffix . '.js', array( 'jquery', 'flot' ), WC_VERSION );
|
||||
wp_register_script( 'wc-settings-tax', WC()->plugin_url() . '/assets/js/admin/settings-views-html-settings-tax' . $suffix . '.js', array( 'jquery', 'wp-util', 'underscore', 'backbone', 'jquery-blockui' ), WC_VERSION );
|
||||
wp_register_script( 'wc-backbone-modal', WC()->plugin_url() . '/assets/js/admin/backbone-modal' . $suffix . '.js', array( 'underscore', 'backbone', 'wp-util' ), WC_VERSION );
|
||||
wp_register_script( 'wc-shipping-zones', WC()->plugin_url() . '/assets/js/admin/wc-shipping-zones' . $suffix . '.js', array( 'jquery', 'wp-util', 'underscore', 'backbone', 'jquery-ui-sortable', 'wc-enhanced-select', 'wc-backbone-modal' ), WC_VERSION );
|
||||
wp_register_script( 'wc-shipping-zone-methods', WC()->plugin_url() . '/assets/js/admin/wc-shipping-zone-methods' . $suffix . '.js', array( 'jquery', 'wp-util', 'underscore', 'backbone', 'jquery-ui-sortable' ), WC_VERSION );
|
||||
wp_register_script( 'wc-shipping-classes', WC()->plugin_url() . '/assets/js/admin/wc-shipping-classes' . $suffix . '.js', array( 'jquery', 'wp-util', 'underscore', 'backbone' ), WC_VERSION );
|
||||
wp_register_script( 'select2', WC()->plugin_url() . '/assets/js/select2/select2' . $suffix . '.js', array( 'jquery' ), '3.5.4' );
|
||||
wp_register_script( 'wc-enhanced-select', WC()->plugin_url() . '/assets/js/admin/wc-enhanced-select' . $suffix . '.js', array( 'jquery', 'select2' ), WC_VERSION );
|
||||
wp_localize_script( 'wc-enhanced-select', 'wc_enhanced_select_params', array(
|
||||
|
|
|
@ -101,10 +101,6 @@ class WC_Admin_Help {
|
|||
'title' => __( 'Product Categories, Tags, Shipping Classes, & Attributes', 'woocommerce' ),
|
||||
'url' => '//fast.wistia.net/embed/iframe/f0j5gzqigg?videoFoam=true'
|
||||
),
|
||||
'edit-product_shipping_class' => array(
|
||||
'title' => __( 'Product Categories, Tags, Shipping Classes, & Attributes', 'woocommerce' ),
|
||||
'url' => '//fast.wistia.net/embed/iframe/f0j5gzqigg?videoFoam=true'
|
||||
),
|
||||
'product_attributes' => array(
|
||||
'title' => __( 'Product Categories, Tags, Shipping Classes, & Attributes', 'woocommerce' ),
|
||||
'url' => '//fast.wistia.net/embed/iframe/f0j5gzqigg?videoFoam=true'
|
||||
|
|
|
@ -173,7 +173,7 @@ class WC_Admin_Menus {
|
|||
$woocommerce_menu_order[] = 'edit.php?post_type=product';
|
||||
unset( $menu_order[ $woocommerce_separator ] );
|
||||
unset( $menu_order[ $woocommerce_product ] );
|
||||
} elseif ( !in_array( $item, array( 'separator-woocommerce' ) ) ) {
|
||||
} elseif ( ! in_array( $item, array( 'separator-woocommerce' ) ) ) {
|
||||
$woocommerce_menu_order[] = $item;
|
||||
}
|
||||
|
||||
|
|
|
@ -52,8 +52,8 @@ class WC_Admin_Settings {
|
|||
$settings[] = include( 'settings/class-wc-settings-general.php' );
|
||||
$settings[] = include( 'settings/class-wc-settings-products.php' );
|
||||
$settings[] = include( 'settings/class-wc-settings-tax.php' );
|
||||
$settings[] = include( 'settings/class-wc-settings-checkout.php' );
|
||||
$settings[] = include( 'settings/class-wc-settings-shipping.php' );
|
||||
$settings[] = include( 'settings/class-wc-settings-checkout.php' );
|
||||
$settings[] = include( 'settings/class-wc-settings-accounts.php' );
|
||||
$settings[] = include( 'settings/class-wc-settings-emails.php' );
|
||||
$settings[] = include( 'settings/class-wc-settings-integrations.php' );
|
||||
|
@ -80,13 +80,11 @@ class WC_Admin_Settings {
|
|||
do_action( 'woocommerce_update_options_' . $current_tab );
|
||||
do_action( 'woocommerce_update_options' );
|
||||
|
||||
// Clear any unwanted data
|
||||
delete_transient( 'woocommerce_cache_excluded_uris' );
|
||||
|
||||
self::add_message( __( 'Your settings have been saved.', 'woocommerce' ) );
|
||||
self::check_download_folder_protection();
|
||||
|
||||
// Re-add endpoints and flush rules
|
||||
// Clear any unwanted data and flush rules
|
||||
delete_transient( 'woocommerce_cache_excluded_uris' );
|
||||
WC()->query->init_query_vars();
|
||||
WC()->query->add_endpoints();
|
||||
flush_rewrite_rules();
|
||||
|
|
|
@ -410,18 +410,6 @@ class WC_Admin_Setup_Wizard {
|
|||
* Shipping and taxes.
|
||||
*/
|
||||
public function wc_setup_shipping_taxes() {
|
||||
$domestic = new WC_Shipping_Flat_Rate();
|
||||
$international = new WC_Shipping_International_Delivery();
|
||||
$shipping_cost_domestic = '';
|
||||
$shipping_cost_international = '';
|
||||
|
||||
if ( 'yes' === $domestic->get_option( 'enabled' ) ) {
|
||||
$shipping_cost_domestic = $domestic->get_option( 'cost' );
|
||||
}
|
||||
|
||||
if ( 'yes' === $international->get_option( 'enabled' ) ) {
|
||||
$shipping_cost_international = $international->get_option( 'cost' );
|
||||
}
|
||||
?>
|
||||
<h1><?php _e( 'Shipping & Tax Setup', 'woocommerce' ); ?></h1>
|
||||
<form method="post">
|
||||
|
@ -435,20 +423,20 @@ class WC_Admin_Setup_Wizard {
|
|||
<tr>
|
||||
<th scope="row"><label for="woocommerce_calc_shipping"><?php _e( 'Will you be shipping products?', 'woocommerce' ); ?></label></th>
|
||||
<td>
|
||||
<input type="checkbox" id="woocommerce_calc_shipping" <?php checked( get_option( 'woocommerce_calc_shipping', 'no' ), 'yes' ); ?> name="woocommerce_calc_shipping" class="input-checkbox" value="1" />
|
||||
<input type="checkbox" id="woocommerce_calc_shipping" <?php checked( get_option( 'woocommerce_ship_to_countries', '' ) !== 'disabled', true ); ?> name="woocommerce_calc_shipping" class="input-checkbox" value="1" />
|
||||
<label for="woocommerce_calc_shipping"><?php _e( 'Yes, I will be shipping physical goods to customers', 'woocommerce' ); ?></label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="shipping_cost_domestic"><?php _e( '<strong>Domestic</strong> shipping costs:', 'woocommerce' ); ?></label></th>
|
||||
<th scope="row"><label for="shipping_cost_domestic"><?php _e( '<strong>Domestic</strong> shipping cost:', 'woocommerce' ); ?></label></th>
|
||||
<td>
|
||||
<?php printf( __( 'A total of %s per order and/or %s per item', 'woocommerce' ), get_woocommerce_currency_symbol() . ' <input type="text" id="shipping_cost_domestic" name="shipping_cost_domestic" size="5" value="' . esc_attr( $shipping_cost_domestic ) . '" />', get_woocommerce_currency_symbol() . ' <input type="text" id="shipping_cost_domestic_item" name="shipping_cost_domestic_item" size="5" />' ); ?>
|
||||
<?php printf( __( 'A total of %s per order and/or %s per item', 'woocommerce' ), get_woocommerce_currency_symbol() . ' <input type="text" id="shipping_cost_domestic" name="shipping_cost_domestic" size="5" />', get_woocommerce_currency_symbol() . ' <input type="text" id="shipping_cost_domestic_item" name="shipping_cost_domestic_item" size="5" />' ); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row"><label for="shipping_cost_international"><?php _e( '<strong>International</strong> shipping costs:', 'woocommerce' ); ?></label></th>
|
||||
<th scope="row"><label for="shipping_cost_worldwide"><?php _e( '<strong>Worldwide</strong> shipping cost:', 'woocommerce' ); ?></label></th>
|
||||
<td>
|
||||
<?php printf( __( 'A total of %s per order and/or %s per item', 'woocommerce' ), get_woocommerce_currency_symbol() . ' <input type="text" id="shipping_cost_international" name="shipping_cost_international" size="5" value="' . esc_attr( $shipping_cost_international ) . '" />', get_woocommerce_currency_symbol() . ' <input type="text" id="shipping_cost_international_item" name="shipping_cost_international_item" size="5" />' ); ?>
|
||||
<?php printf( __( 'A total of %s per order and/or %s per item', 'woocommerce' ), get_woocommerce_currency_symbol() . ' <input type="text" id="shipping_cost_worldwide" name="shipping_cost_worldwide" size="5" />', get_woocommerce_currency_symbol() . ' <input type="text" id="shipping_cost_worldwide_item" name="shipping_cost_worldwide_item" size="5" />' ); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="section_title">
|
||||
|
@ -543,56 +531,63 @@ class WC_Admin_Setup_Wizard {
|
|||
public function wc_setup_shipping_taxes_save() {
|
||||
check_admin_referer( 'wc-setup' );
|
||||
|
||||
$woocommerce_calc_shipping = isset( $_POST['woocommerce_calc_shipping'] ) ? 'yes' : 'no';
|
||||
$woocommerce_calc_taxes = isset( $_POST['woocommerce_calc_taxes'] ) ? 'yes' : 'no';
|
||||
$enable_shipping = isset( $_POST['woocommerce_calc_shipping'] );
|
||||
$enable_taxes = isset( $_POST['woocommerce_calc_taxes'] );
|
||||
|
||||
update_option( 'woocommerce_calc_shipping', $woocommerce_calc_shipping );
|
||||
update_option( 'woocommerce_calc_taxes', $woocommerce_calc_taxes );
|
||||
if ( $enable_shipping ) {
|
||||
update_option( 'woocommerce_ship_to_countries', '' );
|
||||
} else {
|
||||
update_option( 'woocommerce_ship_to_countries', 'disabled' );
|
||||
}
|
||||
|
||||
update_option( 'woocommerce_calc_taxes', $enable_taxes ? 'yes' : 'no' );
|
||||
update_option( 'woocommerce_prices_include_tax', sanitize_text_field( $_POST['woocommerce_prices_include_tax'] ) );
|
||||
|
||||
if ( 'yes' === $woocommerce_calc_shipping && ! empty( $_POST['shipping_cost_domestic'] ) ) {
|
||||
// Delete existing settings if they exist
|
||||
delete_option( 'woocommerce_flat_rate_settings' );
|
||||
if ( $enable_shipping && ! empty( $_POST['shipping_cost_domestic'] ) ) {
|
||||
// Create a domestic shipping zone
|
||||
$zone = new WC_Shipping_Zone( $zone_data['zone_id'] );
|
||||
$zone->set_zone_name( __( 'Domestic', 'woocommerce' ) );
|
||||
$zone->set_zone_order( 1 );
|
||||
$zone->add_location( WC()->countries->get_base_country(), 'country' );
|
||||
$zone->save();
|
||||
|
||||
// Init rate and settings
|
||||
$shipping_method = new WC_Shipping_Flat_Rate();
|
||||
// Add a flat rate shipping method to this domestic zone
|
||||
$instance_id = $zone->add_shipping_method( 'flat_rate' );
|
||||
$shipping_method = new WC_Shipping_Flat_Rate( $instance_id );
|
||||
$option_key = $shipping_method->get_instance_option_key();
|
||||
|
||||
// Update rate settings
|
||||
$costs = array();
|
||||
$costs[] = wc_format_decimal( sanitize_text_field( $_POST['shipping_cost_domestic'] ) );
|
||||
if ( $item_cost = sanitize_text_field( $_POST['shipping_cost_domestic_item'] ) ) {
|
||||
$costs[] = $item_cost . ' * [qty]';
|
||||
}
|
||||
$shipping_method->settings['cost'] = implode( ' + ', array_filter( $costs ) );
|
||||
$shipping_method->settings['enabled'] = 'yes';
|
||||
$shipping_method->settings['type'] = 'order';
|
||||
$shipping_method->settings['availability'] = 'specific';
|
||||
$shipping_method->settings['countries'] = array( WC()->countries->get_base_country() );
|
||||
|
||||
update_option( $shipping_method->plugin_id . $shipping_method->id . '_settings', $shipping_method->settings );
|
||||
$shipping_method->instance_settings['cost'] = implode( ' + ', array_filter( $costs ) );
|
||||
$shipping_method->instance_settings['enabled'] = 'yes';
|
||||
$shipping_method->instance_settings['type'] = 'order';
|
||||
update_option( $option_key, $shipping_method->instance_settings );
|
||||
}
|
||||
|
||||
if ( 'yes' === $woocommerce_calc_shipping && ! empty( $_POST['shipping_cost_international'] ) ) {
|
||||
// Delete existing settings if they exist
|
||||
delete_option( 'woocommerce_international_delivery_settings' );
|
||||
if ( $enable_shipping && ! empty( $_POST['shipping_cost_worldwide'] ) ) {
|
||||
// Add a flat rate shipping method to the worldwide zone
|
||||
$zone = WC_Shipping_Zones::get_zone( 0 );
|
||||
$instance_id = $zone->add_shipping_method( 'flat_rate' );
|
||||
$shipping_method = new WC_Shipping_Flat_Rate( $instance_id );
|
||||
$option_key = $shipping_method->get_instance_option_key();
|
||||
|
||||
// Init rate and settings
|
||||
$shipping_method = new WC_Shipping_International_Delivery();
|
||||
// Update rate settings
|
||||
$costs = array();
|
||||
$costs[] = wc_format_decimal( sanitize_text_field( $_POST['shipping_cost_international'] ) );
|
||||
if ( $item_cost = sanitize_text_field( $_POST['shipping_cost_international_item'] ) ) {
|
||||
$costs[] = wc_format_decimal( sanitize_text_field( $_POST['shipping_cost_worldwide'] ) );
|
||||
if ( $item_cost = sanitize_text_field( $_POST['shipping_cost_worldwide_item'] ) ) {
|
||||
$costs[] = $item_cost . ' * [qty]';
|
||||
}
|
||||
$shipping_method->settings['cost'] = implode( ' + ', array_filter( $costs ) );
|
||||
$shipping_method->settings['enabled'] = 'yes';
|
||||
$shipping_method->settings['type'] = 'order';
|
||||
if ( ! empty( $_POST['shipping_cost_domestic'] ) ) {
|
||||
$shipping_method->settings['availability'] = 'excluding';
|
||||
$shipping_method->settings['countries'] = array( WC()->countries->get_base_country() );
|
||||
}
|
||||
|
||||
update_option( $shipping_method->plugin_id . $shipping_method->id . '_settings', $shipping_method->settings );
|
||||
$shipping_method->instance_settings['cost'] = implode( ' + ', array_filter( $costs ) );
|
||||
$shipping_method->instance_settings['enabled'] = 'yes';
|
||||
$shipping_method->instance_settings['type'] = 'order';
|
||||
update_option( $option_key, $shipping_method->instance_settings );
|
||||
}
|
||||
|
||||
if ( 'yes' === $woocommerce_calc_taxes && ! empty( $_POST['woocommerce_import_tax_rates'] ) ) {
|
||||
if ( $enable_taxes && ! empty( $_POST['woocommerce_import_tax_rates'] ) ) {
|
||||
$locale_info = include( WC()->plugin_path() . '/i18n/locale-info.php' );
|
||||
$tax_rates = array();
|
||||
$country = WC()->countries->get_base_country();
|
||||
|
|
|
@ -108,8 +108,8 @@ class WC_Admin_Status {
|
|||
break;
|
||||
case 'delete_taxes' :
|
||||
|
||||
$wpdb->query( "TRUNCATE " . $wpdb->prefix . "woocommerce_tax_rates" );
|
||||
$wpdb->query( "TRUNCATE " . $wpdb->prefix . "woocommerce_tax_rate_locations" );
|
||||
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}woocommerce_tax_rates;" );
|
||||
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}woocommerce_tax_rate_locations;" );
|
||||
WC_Cache_Helper::incr_cache_prefix( 'taxes' );
|
||||
|
||||
echo '<div class="updated"><p>' . __( 'Tax rates successfully deleted', 'woocommerce' ) . '</p></div>';
|
||||
|
|
|
@ -38,7 +38,6 @@ class WC_Admin_Taxonomies {
|
|||
|
||||
// Taxonomy page descriptions
|
||||
add_action( 'product_cat_pre_add_form', array( $this, 'product_cat_description' ) );
|
||||
add_action( 'product_shipping_class_pre_add_form', array( $this, 'shipping_class_description' ) );
|
||||
|
||||
$attribute_taxonomies = wc_get_attribute_taxonomies();
|
||||
|
||||
|
@ -276,13 +275,6 @@ class WC_Admin_Taxonomies {
|
|||
echo wpautop( __( 'Product categories for your store can be managed here. To change the order of categories on the front-end you can drag and drop to sort them. To see more categories listed click the "screen options" link at the top of the page.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Description for shipping class page to aid users.
|
||||
*/
|
||||
public function shipping_class_description() {
|
||||
echo wpautop( __( 'Shipping classes can be used to group products of similar type. These groups can then be used by certain shipping methods to provide different rates to different products.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Description for shipping class page to aid users.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
<div class="view">
|
||||
<?php
|
||||
global $wpdb;
|
||||
|
||||
if ( $metadata = $order->has_meta( $item_id ) ) {
|
||||
echo '<table cellspacing="0" class="display_meta">';
|
||||
foreach ( $metadata as $meta ) {
|
||||
|
||||
// Skip hidden core fields
|
||||
if ( in_array( $meta['meta_key'], apply_filters( 'woocommerce_hidden_order_itemmeta', array(
|
||||
'_qty',
|
||||
'_tax_class',
|
||||
'_product_id',
|
||||
'_variation_id',
|
||||
'_line_subtotal',
|
||||
'_line_subtotal_tax',
|
||||
'_line_total',
|
||||
'_line_tax',
|
||||
'method_id',
|
||||
'cost'
|
||||
) ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip serialised meta
|
||||
if ( is_serialized( $meta['meta_value'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get attribute data
|
||||
if ( taxonomy_exists( wc_sanitize_taxonomy_name( $meta['meta_key'] ) ) ) {
|
||||
$term = get_term_by( 'slug', $meta['meta_value'], wc_sanitize_taxonomy_name( $meta['meta_key'] ) );
|
||||
$meta['meta_key'] = wc_attribute_label( wc_sanitize_taxonomy_name( $meta['meta_key'] ) );
|
||||
$meta['meta_value'] = isset( $term->name ) ? $term->name : $meta['meta_value'];
|
||||
} else {
|
||||
$meta['meta_key'] = apply_filters( 'woocommerce_attribute_label', wc_attribute_label( $meta['meta_key'], $_product ), $meta['meta_key'] );
|
||||
}
|
||||
|
||||
echo '<tr><th>' . wp_kses_post( rawurldecode( $meta['meta_key'] ) ) . ':</th><td>' . wp_kses_post( wpautop( make_clickable( rawurldecode( $meta['meta_value'] ) ) ) ) . '</td></tr>';
|
||||
}
|
||||
echo '</table>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<table class="meta" cellspacing="0">
|
||||
<tbody class="meta_items">
|
||||
<?php
|
||||
if ( $metadata = $order->has_meta( $item_id )) {
|
||||
foreach ( $metadata as $meta ) {
|
||||
|
||||
// Skip hidden core fields
|
||||
if ( in_array( $meta['meta_key'], apply_filters( 'woocommerce_hidden_order_itemmeta', array(
|
||||
'_qty',
|
||||
'_tax_class',
|
||||
'_product_id',
|
||||
'_variation_id',
|
||||
'_line_subtotal',
|
||||
'_line_subtotal_tax',
|
||||
'_line_total',
|
||||
'_line_tax',
|
||||
'method_id',
|
||||
'cost'
|
||||
) ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip serialised meta
|
||||
if ( is_serialized( $meta['meta_value'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$meta['meta_key'] = rawurldecode( $meta['meta_key'] );
|
||||
$meta['meta_value'] = esc_textarea( rawurldecode( $meta['meta_value'] ) ); // using a <textarea />
|
||||
$meta['meta_id'] = absint( $meta['meta_id'] );
|
||||
|
||||
echo '<tr data-meta_id="' . esc_attr( $meta['meta_id'] ) . '">
|
||||
<td>
|
||||
<input type="text" name="meta_key[' . $meta['meta_id'] . ']" value="' . esc_attr( $meta['meta_key'] ) . '" />
|
||||
<textarea name="meta_value[' . $meta['meta_id'] . ']">' . $meta['meta_value'] . '</textarea>
|
||||
</td>
|
||||
<td width="1%"><button class="remove_order_item_meta button">×</button></td>
|
||||
</tr>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="4"><button class="add_order_item_meta button"><?php _e( 'Add meta', 'woocommerce' ); ?></button></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
|
@ -39,9 +39,9 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
</td>
|
||||
<td class="name" data-sort-value="<?php echo esc_attr( $item['name'] ); ?>">
|
||||
|
||||
<?php echo ( $_product && $_product->get_sku() ) ? esc_html( $_product->get_sku() ) . ' – ' : ''; ?>
|
||||
|
||||
<?php if ( $_product ) : ?>
|
||||
<?php echo $_product->get_sku() ? esc_html( $_product->get_sku() ) . ' – ' : ''; ?>
|
||||
|
||||
<a target="_blank" href="<?php echo esc_url( admin_url( 'post.php?post=' . absint( $_product->id ) . '&action=edit' ) ); ?>">
|
||||
<?php echo esc_html( $item['name'] ); ?>
|
||||
</a>
|
||||
|
@ -53,100 +53,8 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
<input type="hidden" name="order_item_tax_class[<?php echo absint( $item_id ); ?>]" value="<?php echo isset( $item['tax_class'] ) ? esc_attr( $item['tax_class'] ) : ''; ?>" />
|
||||
|
||||
<?php do_action( 'woocommerce_before_order_itemmeta', $item_id, $item, $_product ) ?>
|
||||
|
||||
<div class="view">
|
||||
<?php
|
||||
global $wpdb;
|
||||
|
||||
if ( $metadata = $order->has_meta( $item_id ) ) {
|
||||
echo '<table cellspacing="0" class="display_meta">';
|
||||
foreach ( $metadata as $meta ) {
|
||||
|
||||
// Skip hidden core fields
|
||||
if ( in_array( $meta['meta_key'], apply_filters( 'woocommerce_hidden_order_itemmeta', array(
|
||||
'_qty',
|
||||
'_tax_class',
|
||||
'_product_id',
|
||||
'_variation_id',
|
||||
'_line_subtotal',
|
||||
'_line_subtotal_tax',
|
||||
'_line_total',
|
||||
'_line_tax',
|
||||
) ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip serialised meta
|
||||
if ( is_serialized( $meta['meta_value'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get attribute data
|
||||
if ( taxonomy_exists( wc_sanitize_taxonomy_name( $meta['meta_key'] ) ) ) {
|
||||
$term = get_term_by( 'slug', $meta['meta_value'], wc_sanitize_taxonomy_name( $meta['meta_key'] ) );
|
||||
$meta['meta_key'] = wc_attribute_label( wc_sanitize_taxonomy_name( $meta['meta_key'] ) );
|
||||
$meta['meta_value'] = isset( $term->name ) ? $term->name : $meta['meta_value'];
|
||||
} else {
|
||||
$meta['meta_key'] = apply_filters( 'woocommerce_attribute_label', wc_attribute_label( $meta['meta_key'], $_product ), $meta['meta_key'] );
|
||||
}
|
||||
|
||||
echo '<tr><th>' . wp_kses_post( rawurldecode( $meta['meta_key'] ) ) . ':</th><td>' . wp_kses_post( wpautop( make_clickable( rawurldecode( $meta['meta_value'] ) ) ) ) . '</td></tr>';
|
||||
}
|
||||
echo '</table>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<table class="meta" cellspacing="0">
|
||||
<tbody class="meta_items">
|
||||
<?php
|
||||
if ( $metadata = $order->has_meta( $item_id )) {
|
||||
foreach ( $metadata as $meta ) {
|
||||
|
||||
// Skip hidden core fields
|
||||
if ( in_array( $meta['meta_key'], apply_filters( 'woocommerce_hidden_order_itemmeta', array(
|
||||
'_qty',
|
||||
'_tax_class',
|
||||
'_product_id',
|
||||
'_variation_id',
|
||||
'_line_subtotal',
|
||||
'_line_subtotal_tax',
|
||||
'_line_total',
|
||||
'_line_tax',
|
||||
) ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip serialised meta
|
||||
if ( is_serialized( $meta['meta_value'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$meta['meta_key'] = rawurldecode( $meta['meta_key'] );
|
||||
$meta['meta_value'] = esc_textarea( rawurldecode( $meta['meta_value'] ) ); // using a <textarea />
|
||||
$meta['meta_id'] = absint( $meta['meta_id'] );
|
||||
|
||||
echo '<tr data-meta_id="' . esc_attr( $meta['meta_id'] ) . '">
|
||||
<td>
|
||||
<input type="text" name="meta_key[' . $meta['meta_id'] . ']" value="' . esc_attr( $meta['meta_key'] ) . '" />
|
||||
<textarea name="meta_value[' . $meta['meta_id'] . ']">' . $meta['meta_value'] . '</textarea>
|
||||
</td>
|
||||
<td width="1%"><button class="remove_order_item_meta button">×</button></td>
|
||||
</tr>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="4"><button class="add_order_item_meta button"><?php _e( 'Add meta', 'woocommerce' ); ?></button></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php include( 'html-order-item-meta.php' ); ?>
|
||||
<?php do_action( 'woocommerce_after_order_itemmeta', $item_id, $item, $_product ) ?>
|
||||
|
||||
</td>
|
||||
|
||||
<?php do_action( 'woocommerce_admin_order_item_values', $_product, $item, absint( $item_id ) ); ?>
|
||||
|
|
|
@ -20,8 +20,9 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
<?php echo ! empty( $item['name'] ) ? wc_clean( $item['name'] ) : __( 'Shipping', 'woocommerce' ); ?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<input type="text" placeholder="<?php esc_attr_e( 'Shipping Name', 'woocommerce' ); ?>" name="shipping_method_title[<?php echo $item_id; ?>]" value="<?php echo ( isset( $item['name'] ) ) ? wc_clean( $item['name'] ) : ''; ?>" />
|
||||
<select name="shipping_method[<?php echo $item_id; ?>]">
|
||||
<input type="hidden" name="shipping_method_id[]" value="<?php echo esc_attr( $item_id ); ?>" />
|
||||
<input type="text" class="shipping_method_name" placeholder="<?php esc_attr_e( 'Shipping Name', 'woocommerce' ); ?>" name="shipping_method_title[<?php echo $item_id; ?>]" value="<?php echo ( isset( $item['name'] ) ) ? wc_clean( $item['name'] ) : ''; ?>" />
|
||||
<select class="shipping_method" name="shipping_method[<?php echo esc_attr( $item_id ); ?>]">
|
||||
<optgroup label="<?php esc_attr_e( 'Shipping Method', 'woocommerce' ); ?>">
|
||||
<option value=""><?php _e( 'N/A', 'woocommerce' ); ?></option>
|
||||
<?php
|
||||
|
@ -46,8 +47,11 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
?>
|
||||
</optgroup>
|
||||
</select>
|
||||
<input type="hidden" name="shipping_method_id[]" value="<?php echo esc_attr( $item_id ); ?>" />
|
||||
</div>
|
||||
|
||||
<?php do_action( 'woocommerce_before_order_itemmeta', $item_id, $item, null ) ?>
|
||||
<?php include( 'html-order-item-meta.php' ); ?>
|
||||
<?php do_action( 'woocommerce_after_order_itemmeta', $item_id, $item, null ) ?>
|
||||
</td>
|
||||
|
||||
<?php do_action( 'woocommerce_admin_order_item_values', null, $item, absint( $item_id ) ); ?>
|
||||
|
|
|
@ -93,7 +93,7 @@ class WC_Settings_Payment_Gateways extends WC_Settings_Page {
|
|||
),
|
||||
|
||||
array(
|
||||
'title' => _x( 'Checkout', 'Settings group label', 'woocommerce' ),
|
||||
'title' => _x( 'Checkout Process', 'Settings group label', 'woocommerce' ),
|
||||
'desc' => __( 'Enable guest checkout', 'woocommerce' ),
|
||||
'desc_tip' => __( 'Allows customers to checkout without creating an account.', 'woocommerce' ),
|
||||
'id' => 'woocommerce_enable_guest_checkout',
|
||||
|
|
|
@ -75,7 +75,7 @@ class WC_Settings_General extends WC_Settings_Page {
|
|||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Specific Countries', 'woocommerce' ),
|
||||
'title' => __( 'Sell to Specific Countries', 'woocommerce' ),
|
||||
'desc' => '',
|
||||
'id' => 'woocommerce_specific_allowed_countries',
|
||||
'css' => 'min-width: 350px;',
|
||||
|
@ -84,21 +84,53 @@ class WC_Settings_General extends WC_Settings_Page {
|
|||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Default Customer Address', 'woocommerce' ),
|
||||
'title' => __( 'Shipping Location(s)', 'woocommerce' ),
|
||||
'desc' => __( 'Choose which countries you want to ship to, or choose to ship to all locations you sell to.', 'woocommerce' ),
|
||||
'id' => 'woocommerce_ship_to_countries',
|
||||
'default' => '',
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'desc_tip' => true,
|
||||
'options' => array(
|
||||
'' => __( 'Ship to all countries you sell to', 'woocommerce' ),
|
||||
'all' => __( 'Ship to all countries', 'woocommerce' ),
|
||||
'specific' => __( 'Ship to specific countries only', 'woocommerce' ),
|
||||
'disabled' => __( 'Disable shipping & shipping calculations', 'woocommerce' ),
|
||||
)
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Ship to Specific Countries', 'woocommerce' ),
|
||||
'desc' => '',
|
||||
'id' => 'woocommerce_specific_ship_to_countries',
|
||||
'css' => '',
|
||||
'default' => '',
|
||||
'type' => 'multi_select_countries'
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Default Customer Location', 'woocommerce' ),
|
||||
'id' => 'woocommerce_default_customer_address',
|
||||
'desc_tip' => __( 'This option determines the customers default address (before they input their details).', 'woocommerce' ),
|
||||
'desc' => sprintf( __( 'The %sMaxMind GeoLite Database%s will be periodically downloaded to your wp-content directory if using geolocation.', 'woocommerce' ), '<a href="http://dev.maxmind.com/geoip/legacy/geolite/">', '</a>' ),
|
||||
'desc_tip' => __( 'This option determines a customers default location. The MaxMind GeoLite Database will be periodically downloaded to your wp-content directory if using geolocation.', 'woocommerce' ),
|
||||
'default' => 'geolocation',
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'options' => array(
|
||||
'' => __( 'No address', 'woocommerce' ),
|
||||
'' => __( 'No location by default', 'woocommerce' ),
|
||||
'base' => __( 'Shop base address', 'woocommerce' ),
|
||||
'geolocation' => __( 'Geolocate', 'woocommerce' ),
|
||||
'geolocation_ajax' => __( 'Geolocate (with page caching support)', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Enable Taxes', 'woocommerce' ),
|
||||
'desc' => __( 'Enable taxes and tax calculations', 'woocommerce' ),
|
||||
'id' => 'woocommerce_calc_taxes',
|
||||
'default' => 'no',
|
||||
'type' => 'checkbox'
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Store Notice', 'woocommerce' ),
|
||||
'desc' => __( 'Enable site-wide store notice text', 'woocommerce' ),
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
* @author WooThemes
|
||||
* @category Admin
|
||||
* @package WooCommerce/Admin
|
||||
* @version 2.1.0
|
||||
* @version 2.6.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'WC_Settings_Shipping' ) ) :
|
||||
|
@ -25,14 +25,19 @@ class WC_Settings_Shipping extends WC_Settings_Page {
|
|||
public function __construct() {
|
||||
$this->id = 'shipping';
|
||||
$this->label = __( 'Shipping', 'woocommerce' );
|
||||
|
||||
add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
|
||||
add_action( 'woocommerce_sections_' . $this->id, array( $this, 'output_sections' ) );
|
||||
add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
|
||||
add_action( 'woocommerce_admin_field_shipping_methods', array( $this, 'shipping_methods_setting' ) );
|
||||
add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add this page to settings.
|
||||
*/
|
||||
public function add_settings_page( $pages ) {
|
||||
return wc_shipping_enabled() ? parent::add_settings_page( $pages ) : $pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sections.
|
||||
*
|
||||
|
@ -40,7 +45,9 @@ class WC_Settings_Shipping extends WC_Settings_Page {
|
|||
*/
|
||||
public function get_sections() {
|
||||
$sections = array(
|
||||
'' => __( 'Shipping Options', 'woocommerce' )
|
||||
'' => __( 'Shipping Zones', 'woocommerce' ),
|
||||
'options' => __( 'Shipping Options', 'woocommerce' ),
|
||||
'classes' => __( 'Shipping Classes', 'woocommerce' )
|
||||
);
|
||||
|
||||
if ( ! defined( 'WC_INSTALLING' ) ) {
|
||||
|
@ -65,26 +72,17 @@ class WC_Settings_Shipping extends WC_Settings_Page {
|
|||
* @return array
|
||||
*/
|
||||
public function get_settings() {
|
||||
|
||||
$settings = apply_filters('woocommerce_shipping_settings', array(
|
||||
$settings = apply_filters( 'woocommerce_shipping_settings', array(
|
||||
|
||||
array( 'title' => __( 'Shipping Options', 'woocommerce' ), 'type' => 'title', 'id' => 'shipping_options' ),
|
||||
|
||||
array(
|
||||
'title' => __( 'Shipping Calculations', 'woocommerce' ),
|
||||
'desc' => __( 'Enable shipping', 'woocommerce' ),
|
||||
'id' => 'woocommerce_calc_shipping',
|
||||
'default' => 'no',
|
||||
'type' => 'checkbox',
|
||||
'checkboxgroup' => 'start'
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Calculations', 'woocommerce' ),
|
||||
'desc' => __( 'Enable the shipping calculator on the cart page', 'woocommerce' ),
|
||||
'id' => 'woocommerce_enable_shipping_calc',
|
||||
'default' => 'yes',
|
||||
'type' => 'checkbox',
|
||||
'checkboxgroup' => '',
|
||||
'checkboxgroup' => 'start',
|
||||
'autoload' => false
|
||||
),
|
||||
|
||||
|
@ -104,43 +102,15 @@ class WC_Settings_Shipping extends WC_Settings_Page {
|
|||
'default' => 'billing',
|
||||
'type' => 'radio',
|
||||
'options' => array(
|
||||
'shipping' => __( 'Default to shipping address', 'woocommerce' ),
|
||||
'billing' => __( 'Default to billing address', 'woocommerce' ),
|
||||
'billing_only' => __( 'Only ship to the customer\'s billing address', 'woocommerce' ),
|
||||
'shipping' => __( 'Default to customer shipping address', 'woocommerce' ),
|
||||
'billing' => __( 'Default to customer billing address', 'woocommerce' ),
|
||||
'billing_only' => __( 'Force shipping to the customer billing address', 'woocommerce' ),
|
||||
),
|
||||
'autoload' => false,
|
||||
'desc_tip' => true,
|
||||
'show_if_checked' => 'option',
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Restrict shipping to Location(s)', 'woocommerce' ),
|
||||
'desc' => sprintf( __( 'Choose which countries you want to ship to, or choose to ship to all <a href="%s">locations you sell to</a>.', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=general' ) ),
|
||||
'id' => 'woocommerce_ship_to_countries',
|
||||
'default' => '',
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'desc_tip' => false,
|
||||
'options' => array(
|
||||
'' => __( 'Ship to all countries you sell to', 'woocommerce' ),
|
||||
'all' => __( 'Ship to all countries', 'woocommerce' ),
|
||||
'specific' => __( 'Ship to specific countries only', 'woocommerce' )
|
||||
)
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Specific Countries', 'woocommerce' ),
|
||||
'desc' => '',
|
||||
'id' => 'woocommerce_specific_ship_to_countries',
|
||||
'css' => '',
|
||||
'default' => '',
|
||||
'type' => 'multi_select_countries'
|
||||
),
|
||||
|
||||
array(
|
||||
'type' => 'shipping_methods',
|
||||
),
|
||||
|
||||
array( 'type' => 'sectionend', 'id' => 'shipping_options' ),
|
||||
|
||||
) );
|
||||
|
@ -152,83 +122,31 @@ class WC_Settings_Shipping extends WC_Settings_Page {
|
|||
* Output the settings.
|
||||
*/
|
||||
public function output() {
|
||||
global $current_section;
|
||||
global $current_section, $hide_save_button;
|
||||
|
||||
// Load shipping methods so we can show any global options they may have
|
||||
$shipping_methods = WC()->shipping->load_shipping_methods();
|
||||
|
||||
if ( $current_section ) {
|
||||
|
||||
foreach ( $shipping_methods as $method ) {
|
||||
|
||||
if ( strtolower( get_class( $method ) ) == strtolower( $current_section ) && $method->has_settings() ) {
|
||||
if ( 'options' === $current_section ) {
|
||||
$settings = $this->get_settings();
|
||||
WC_Admin_Settings::output_fields( $settings );
|
||||
return;
|
||||
} elseif ( 'classes' === $current_section ) {
|
||||
$hide_save_button = true;
|
||||
$this->output_shipping_class_screen();
|
||||
return;
|
||||
} else {
|
||||
foreach ( $shipping_methods as $method ) {
|
||||
if ( strtolower( get_class( $method ) ) === strtolower( $current_section ) && $method->has_settings() ) {
|
||||
$method->admin_options();
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$settings = $this->get_settings();
|
||||
|
||||
WC_Admin_Settings::output_fields( $settings );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output shipping method settings.
|
||||
*/
|
||||
public function shipping_methods_setting() {
|
||||
$selection_priority = get_option( 'woocommerce_shipping_method_selection_priority', array() );
|
||||
?>
|
||||
<tr valign="top">
|
||||
<th scope="row" class="titledesc"><?php _e( 'Shipping Methods', 'woocommerce' ) ?></th>
|
||||
<td class="forminp">
|
||||
<table class="wc_shipping widefat wp-list-table" cellspacing="0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sort"> </th>
|
||||
<th class="name"><?php _e( 'Name', 'woocommerce' ); ?></th>
|
||||
<th class="id"><?php _e( 'ID', 'woocommerce' ); ?></th>
|
||||
<th class="status"><?php _e( 'Enabled', 'woocommerce' ); ?></th>
|
||||
<th class="priority"><?php _e( 'Selection Priority', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'Available methods will be chosen by default in this order. If multiple methods have the same priority, they will be sorted by cost.', 'woocommerce' ) ); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ( WC()->shipping->load_shipping_methods() as $key => $method ) : ?>
|
||||
<tr>
|
||||
<td width="1%" class="sort">
|
||||
<input type="hidden" name="method_order[<?php echo esc_attr( $method->id ); ?>]" value="<?php echo esc_attr( $method->id ); ?>" />
|
||||
</td>
|
||||
<td class="name">
|
||||
<?php if ( $method->has_settings ) : ?><a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=' . strtolower( get_class( $method ) ) ) ); ?>"><?php endif; ?>
|
||||
<?php echo esc_html( $method->get_title() ); ?>
|
||||
<?php if ( $method->has_settings ) : ?></a><?php endif; ?>
|
||||
</td>
|
||||
<td class="id">
|
||||
<?php echo esc_attr( $method->id ); ?>
|
||||
</td>
|
||||
<td class="status">
|
||||
<?php if ( 'yes' === $method->enabled ) : ?>
|
||||
<span class="status-enabled tips" data-tip="<?php esc_attr_e( 'Yes', 'woocommerce' ); ?>"><?php _e( 'Yes', 'woocommerce' ); ?></span>
|
||||
<?php else : ?>
|
||||
<span class="na">-</span>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td width="1%" class="priority">
|
||||
<input type="number" step="1" min="0" name="method_priority[<?php echo esc_attr( $method->id ); ?>]" value="<?php echo isset( $selection_priority[ $method->id ] ) ? absint( $selection_priority[ $method->id ] ) : 1; ?>" />
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th colspan="4"><span class="description"><?php _e( 'Drag and drop the above shipping methods to control their display order.', 'woocommerce' ); ?></span></th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
// Default to zones screen
|
||||
$hide_save_button = true;
|
||||
$this->output_zones_screen();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,23 +155,150 @@ class WC_Settings_Shipping extends WC_Settings_Page {
|
|||
public function save() {
|
||||
global $current_section;
|
||||
|
||||
$wc_shipping = WC_Shipping::instance();
|
||||
switch ( $current_section ) {
|
||||
case 'options' :
|
||||
WC_Admin_Settings::save_fields( $this->get_settings() );
|
||||
break;
|
||||
case 'classes' :
|
||||
case '' :
|
||||
break;
|
||||
default :
|
||||
$wc_shipping = WC_Shipping::instance();
|
||||
|
||||
if ( ! $current_section ) {
|
||||
WC_Admin_Settings::save_fields( $this->get_settings() );
|
||||
$wc_shipping->process_admin_options();
|
||||
|
||||
} else {
|
||||
foreach ( $wc_shipping->load_shipping_methods() as $method_id => $method ) {
|
||||
if ( $current_section === sanitize_title( get_class( $method ) ) ) {
|
||||
do_action( 'woocommerce_update_options_' . $this->id . '_' . $method->id );
|
||||
foreach ( $wc_shipping->get_shipping_methods() as $method_id => $method ) {
|
||||
if ( $current_section === sanitize_title( get_class( $method ) ) ) {
|
||||
do_action( 'woocommerce_update_options_' . $this->id . '_' . $method->id );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Increments the transient version to invalidate cache
|
||||
WC_Cache_Helper::get_transient_version( 'shipping', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles output of the shipping zones page in admin.
|
||||
*/
|
||||
private function output_zones_screen() {
|
||||
if ( isset( $_REQUEST['zone_id'] ) ) {
|
||||
$this->zone_methods_screen( absint( $_REQUEST['zone_id'] ) );
|
||||
} elseif ( isset( $_REQUEST['instance_id'] ) ) {
|
||||
$this->instance_settings_screen( absint( $_REQUEST['instance_id'] ) );
|
||||
} else {
|
||||
$this->zones_screen();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show method for a zone
|
||||
* @param int $zone_id
|
||||
*/
|
||||
private function zone_methods_screen( $zone_id ) {
|
||||
$wc_shipping = WC_Shipping ::instance();
|
||||
$zone = WC_Shipping_Zones::get_zone( $zone_id );
|
||||
$shipping_methods = $wc_shipping ->get_shipping_methods();
|
||||
|
||||
if ( ! $zone ) {
|
||||
wp_die( __( 'Zone does not exist!', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
wp_localize_script( 'wc-shipping-zone-methods', 'shippingZoneMethodsLocalizeScript', array(
|
||||
'methods' => $zone->get_shipping_methods(),
|
||||
'zone_id' => $zone->get_zone_id(),
|
||||
'wc_shipping_zones_nonce' => wp_create_nonce( 'wc_shipping_zones_nonce' ),
|
||||
'strings' => array(
|
||||
'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
|
||||
'save_failed' => __( 'Your changes were not saved. Please retry.', 'woocommerce' ),
|
||||
'add_method_failed' => __( 'Shipping method could not be added. Please retry.', 'woocommerce' ),
|
||||
'yes' => __( 'Yes', 'woocommerce' ),
|
||||
),
|
||||
) );
|
||||
wp_enqueue_script( 'wc-shipping-zone-methods' );
|
||||
|
||||
include_once( 'views/html-admin-page-shipping-zone-methods.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Show zones
|
||||
*/
|
||||
private function zones_screen() {
|
||||
$allowed_countries = WC()->countries->get_allowed_countries();
|
||||
$continents = WC()->countries->get_continents();
|
||||
|
||||
wp_localize_script( 'wc-shipping-zones', 'shippingZonesLocalizeScript', array(
|
||||
'zones' => WC_Shipping_Zones::get_zones(),
|
||||
'default_zone' => array(
|
||||
'zone_id' => 0,
|
||||
'zone_name' => '',
|
||||
'zone_order' => null,
|
||||
),
|
||||
'wc_shipping_zones_nonce' => wp_create_nonce( 'wc_shipping_zones_nonce' ),
|
||||
'strings' => array(
|
||||
'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
|
||||
'save_failed' => __( 'Your changes were not saved. Please retry.', 'woocommerce' ),
|
||||
'no_methods' => '<a href="#" class="add_shipping_method button">' . __( 'Add Shipping Method', 'woocommerce' ) . '</a>',
|
||||
'add_another_method' => '<a href="#" class="add_shipping_method button">' . __( 'Add Shipping Method', 'woocommerce' ) . '</a>'
|
||||
),
|
||||
) );
|
||||
wp_enqueue_script( 'wc-shipping-zones' );
|
||||
|
||||
include_once( 'views/html-admin-page-shipping-zones.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Show instance settings
|
||||
* @param int $instance_id
|
||||
*/
|
||||
private function instance_settings_screen( $instance_id ) {
|
||||
$zone = WC_Shipping_Zones::get_zone_by( 'instance_id', $instance_id );
|
||||
$shipping_method = WC_Shipping_Zones::get_shipping_method( $instance_id );
|
||||
|
||||
if ( ! $shipping_method ) {
|
||||
wp_die( __( 'Invalid shipping method!', 'woocommerce' ) );
|
||||
}
|
||||
if ( ! $zone ) {
|
||||
wp_die( __( 'Zone does not exist!', 'woocommerce' ) );
|
||||
}
|
||||
if ( ! $shipping_method->has_settings() ) {
|
||||
wp_die( __( 'This shipping method does not have any settings to configure.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
if ( ! empty( $_POST['save_method'] ) ) {
|
||||
|
||||
if ( empty( $_POST['woocommerce_save_method_nonce'] ) || ! wp_verify_nonce( $_POST['woocommerce_save_method_nonce'], 'woocommerce_save_method' )) {
|
||||
echo '<div class="updated error"><p>' . __( 'Edit failed. Please try again.', 'woocommerce' ) . '</p></div>';
|
||||
}
|
||||
|
||||
$shipping_method->process_admin_options();
|
||||
$shipping_method->display_errors();
|
||||
}
|
||||
|
||||
include_once( 'views/html-admin-page-shipping-zones-instance.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles output of the shipping class settings screen.
|
||||
*/
|
||||
private function output_shipping_class_screen() {
|
||||
$wc_shipping = WC_Shipping::instance();
|
||||
wp_localize_script( 'wc-shipping-classes', 'shippingClassesLocalizeScript', array(
|
||||
'classes' => $wc_shipping->get_shipping_classes(),
|
||||
'default_shipping_class' => array(
|
||||
'term_id' => 0,
|
||||
'name' => '',
|
||||
'description' => '',
|
||||
),
|
||||
'wc_shipping_classes_nonce' => wp_create_nonce( 'wc_shipping_classes_nonce' ),
|
||||
'strings' => array(
|
||||
'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ),
|
||||
'save_failed' => __( 'Your changes were not saved. Please retry.', 'woocommerce' )
|
||||
),
|
||||
) );
|
||||
wp_enqueue_script( 'wc-shipping-classes' );
|
||||
|
||||
include_once( 'views/html-admin-page-shipping-classes.php' );
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
|
|
|
@ -34,6 +34,17 @@ class WC_Settings_Tax extends WC_Settings_Page {
|
|||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add this page to settings.
|
||||
*/
|
||||
public function add_settings_page( $pages ) {
|
||||
if ( wc_tax_enabled() ) {
|
||||
return parent::add_settings_page( $pages );
|
||||
} else {
|
||||
return $pages;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sections.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<h2><?php _e( 'Shipping Classes', 'woocommerce' ); ?></h2>
|
||||
<p><?php _e( 'Shipping classes can be used to group products of similar type. Assign classes to a product on the product edit screen. Once assigned, Shipping Classes can be used by some Shipping Methods (such as Flat Rate Shipping) to provide different rates to different classes of product.', 'woocommerce' ); ?><p>
|
||||
|
||||
<table class="wc-shipping-classes widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="wc-shipping-class-name"><?php esc_html_e( 'Shipping Class', 'woocommerce' ); ?></th>
|
||||
<th class="wc-shipping-class-slug"><?php esc_html_e( 'Slug', 'woocommerce' ); ?></th>
|
||||
<th class="wc-shipping-class-description"><?php esc_html_e( 'Description', 'woocommerce' ); ?></th>
|
||||
<th class="wc-shipping-class-count"><?php esc_html_e( 'Product Count', 'woocommerce' ); ?></th>
|
||||
<th class="wc-shipping-class-actions"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<a class="button button-secondary wc-shipping-class-add" href="#"><?php esc_html_e( 'Add Shipping Class', 'woocommerce' ); ?></a>
|
||||
<input type="submit" name="save" class="button button-primary wc-shipping-class-save" value="<?php esc_attr_e( 'Save Shipping Classes', 'woocommerce' ); ?>" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody class="wc-shipping-class-rows"></tbody>
|
||||
</table>
|
||||
|
||||
<script type="text/html" id="tmpl-wc-shipping-class-row-blank">
|
||||
<tr>
|
||||
<td class="wc-shipping-classes-blank-state" colspan="4"><p><?php _e( 'No Shipping Classes have been created.', 'woocommerce' ); ?></p></td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tmpl-wc-shipping-class-row">
|
||||
<tr data-id="{{ data.term_id }}">
|
||||
<td class="wc-shipping-class-name">
|
||||
<div class="view">{{ data.name }}</div>
|
||||
<div class="edit"><input type="text" name="name[{{ data.term_id }}]" data-attribute="name" value="{{ data.name }}" placeholder="<?php esc_attr_e( 'Shipping Class Name', 'woocommerce' ); ?>" /></div>
|
||||
</td>
|
||||
<td class="wc-shipping-class-slug">
|
||||
<div class="view">{{ data.slug }}</div>
|
||||
<div class="edit"><input type="text" name="slug[{{ data.term_id }}]" data-attribute="slug" value="{{ data.slug }}" placeholder="<?php esc_attr_e( 'Slug', 'woocommerce' ); ?>" /></div>
|
||||
</td>
|
||||
<td class="wc-shipping-class-description">
|
||||
<div class="view">{{ data.description }}</div>
|
||||
<div class="edit"><input type="text" name="description[{{ data.term_id }}]" data-attribute="description" value="{{ data.description }}" placeholder="<?php esc_attr_e( 'Description for your reference', 'woocommerce' ); ?>" /></div>
|
||||
</td>
|
||||
<td class="wc-shipping-class-count">
|
||||
<a href="<?php echo esc_url( admin_url( 'edit.php?post_type=product&product_shipping_class=' ) ); ?>{{data.slug}}">{{ data.count }}</a>
|
||||
</td>
|
||||
<td class="wc-shipping-class-actions">
|
||||
<a class="wc-shipping-class-delete tips" data-tip="<?php _e( 'Delete', 'woocommerce' ); ?>" href="#"><?php _e( 'Delete', 'woocommerce' ); ?></a>
|
||||
<a class="wc-shipping-class-edit tips" data-tip="<?php _e( 'Edit', 'woocommerce' ); ?>" href="#"><?php _e( 'Edit', 'woocommerce' ); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<h2><?php _e( 'Shipping Methods', 'woocommerce' ); ?> (<?php echo esc_html( $zone->get_zone_name() ); ?>) <small class="wc-admin-breadcrumb"><a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping' ) ); ?>" title="<?php echo esc_attr( __( 'Return to Shipping Zones', 'woocommerce' ) ); ?>">↩</a></small></h2>
|
||||
<p><?php _e( 'The following Shipping Methods apply to customers with shipping addresses within this zone.', 'woocommerce' ); ?><p>
|
||||
<table class="wc-shipping-zone-methods widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="wc-shipping-zone-method-sort"> </th>
|
||||
<th class="wc-shipping-zone-method-title"><?php esc_html_e( 'Title', 'woocommerce' ); ?></th>
|
||||
<th class="wc-shipping-zone-method-type"><?php esc_html_e( 'Type', 'woocommerce' ); ?></th>
|
||||
<th class="wc-shipping-zone-method-enabled"><?php esc_html_e( 'Enabled', 'woocommerce' ); ?></th>
|
||||
<th class="wc-shipping-zone-method-description"><?php esc_html_e( 'Description', 'woocommerce' ); ?></th>
|
||||
<th class="wc-shipping-zone-method-actions"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="6">
|
||||
<div class="wc-shipping-zone-method-selector">
|
||||
<select name="add_method_id">
|
||||
<?php
|
||||
foreach ( $shipping_methods as $method ) {
|
||||
if ( ! $method->supports( 'shipping-zones' ) ) {
|
||||
continue;
|
||||
}
|
||||
echo '<option value="' . esc_attr( $method->id ) . '">' . esc_attr( $method->title ) . '</li>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<input type="submit" class="button wc-shipping-zone-add-method" value="<?php esc_attr_e( 'Add Shipping Method', 'woocommerce' ); ?>" />
|
||||
</div>
|
||||
<input type="submit" name="save" class="button button-primary wc-shipping-zone-method-save" value="<?php esc_attr_e( 'Save Shipping Methods', 'woocommerce' ); ?>" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody class="wc-shipping-zone-method-rows"></tbody>
|
||||
</table>
|
||||
|
||||
<script type="text/html" id="tmpl-wc-shipping-zone-method-row-blank">
|
||||
<tr>
|
||||
<td class="wc-shipping-zone-method-blank-state" colspan="6">
|
||||
<p class="main"><?php _e( 'Add Shipping Methods to this zone', 'woocommerce' ); ?></p>
|
||||
<p><?php _e( 'You can add multiple Shipping Methods within this zone. Only customers within the zone will see them.', 'woocommerce' ); ?></p>
|
||||
<p><?php _e( 'Choose a method from the dropdown below and click "Add Shipping Method" to get started.', 'woocommerce' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tmpl-wc-shipping-zone-method-row">
|
||||
<tr data-id="{{ data.instance_id }}">
|
||||
<td width="1%" class="wc-shipping-zone-method-sort"></td>
|
||||
<td class="wc-shipping-zone-method-title"><a href="admin.php?page=wc-settings&tab=shipping&instance_id={{ data.instance_id }}">{{ data.title }}</a></td>
|
||||
<td class="wc-shipping-zone-method-type">{{ data.method_title }}</td>
|
||||
<td class="wc-shipping-zone-method-enabled">{{{ data.enabled_icon }}}</td>
|
||||
<td class="wc-shipping-zone-method-description">{{ data.method_description }}</td>
|
||||
<td class="wc-shipping-zone-method-actions">
|
||||
<a class="wc-shipping-zone-method-delete tips" data-tip="<?php esc_attr_e( 'Delete', 'woocommerce' ); ?>" href="#"><?php _e( 'Delete', 'woocommerce' ); ?></a><a class="wc-shipping-zone-method-settings tips" data-tip="<?php esc_attr_e( 'Settings', 'woocommerce' ); ?>" href="admin.php?page=wc-settings&tab=shipping&instance_id={{ data.instance_id }}"><?php _e( 'Settings', 'woocommerce' ); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<h2><?php echo esc_html( $shipping_method->get_method_title() ); ?> <small class="wc-admin-breadcrumb"><a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&zone_id=' . absint( $zone->get_zone_id() ) ) ); ?>" title="<?php echo esc_attr( __( 'Return to Shipping Methods', 'woocommerce' ) . ' (' . $zone->get_zone_name() . ')' ); ?>">↩</a></small></h2>
|
||||
<?php $shipping_method->admin_options(); ?>
|
||||
<p class="submit"><input type="submit" class="button button-primary" name="save_method" value="<?php _e( 'Save changes', 'woocommerce' ); ?>" /></p>
|
||||
<?php wp_nonce_field( 'woocommerce_save_method', 'woocommerce_save_method_nonce' ); ?>
|
|
@ -0,0 +1,161 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<h2><?php _e( 'Shipping Zones', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'Shipping Zones let you group regions with similar Shipping Methods and rates. WooCommerce will automatically choose the correct Shipping Zone based on your customer‘s shipping address and present the Shipping Methods within that zone to them.', 'woocommerce' ) ); ?></h2>
|
||||
|
||||
<table class="wc-shipping-zones widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="wc-shipping-zone-sort"> </th>
|
||||
<th class="wc-shipping-zone-name"><?php esc_html_e( 'Zone Name', 'woocommerce' ); ?></th>
|
||||
<th class="wc-shipping-zone-region"><?php esc_html_e( 'Region(s)', 'woocommerce' ); ?></th>
|
||||
<th class="wc-shipping-zone-methods"><?php esc_html_e( 'Shipping Method(s)', 'woocommerce' ); ?></th>
|
||||
<th class="wc-shipping-zone-actions"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="5">
|
||||
<a class="button button-secondary wc-shipping-zone-add" href="#"><?php esc_html_e( 'Add Shipping Zone', 'woocommerce' ); ?></a>
|
||||
<input type="submit" name="save" class="button button-primary wc-shipping-zone-save" value="<?php esc_attr_e( 'Save Shipping Zones', 'woocommerce' ); ?>" disabled />
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tbody class="wc-shipping-zone-rows"></tbody>
|
||||
<tbody>
|
||||
<tr data-id="0">
|
||||
<td width="1%" class="wc-shipping-zone-worldwide"></td>
|
||||
<td class="wc-shipping-zone-name">
|
||||
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&zone_id=0' ) ); ?>"><?php esc_html_e( 'Rest of the World', 'woocommerce' ); ?></a>
|
||||
<div class="row-actions">
|
||||
<a href="admin.php?page=wc-settings&tab=shipping&zone_id={{ data.zone_id }}"><?php _e( 'Edit Shipping Methods', 'woocommerce' ); ?></a>
|
||||
</div>
|
||||
</td>
|
||||
<td class="wc-shipping-zone-region"><?php esc_html_e( 'Shipping Methods added here will apply to shipping addresses that aren‘t included in any other Shipping Zone.', 'woocommerce' ); ?></td>
|
||||
<td class="wc-shipping-zone-methods">
|
||||
<?php
|
||||
$worldwide = new WC_Shipping_Zone( 0 );
|
||||
$methods = $worldwide->get_shipping_methods();
|
||||
|
||||
if ( ! $methods ) {
|
||||
echo '<ul><li><a href="#" class="add_shipping_method button">' . __( 'Add Shipping Method', 'woocommerce' ) . '</a></li></ul>';
|
||||
} else {
|
||||
echo '<ul>';
|
||||
foreach ( $methods as $method ) {
|
||||
$class_name = 'yes' === $method->enabled ? 'method_enabled' : 'method_disabled';
|
||||
echo '<li><a href="admin.php?page=wc-settings&tab=shipping&instance_id=' . absint( $method->instance_id ) . '" class="' . esc_attr( $class_name ) . '">' . esc_html( $method->get_title() ) . '</a></li>';
|
||||
}
|
||||
echo '<li><a href="#" class="add_shipping_method button">' . __( 'Add Shipping Method', 'woocommerce' ) . '</a></li>';
|
||||
echo '</ul>';
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
<td class="wc-shipping-zone-actions"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script type="text/html" id="tmpl-wc-shipping-zone-row-blank">
|
||||
<tr>
|
||||
<td class="wc-shipping-zones-blank-state" colspan="5">
|
||||
<p class="main"><?php _e( 'Shipping Zones let you group regions with similar Shipping Methods and rates.', 'woocommerce' ); ?></p>
|
||||
<p><?php _e( 'You can add as many Shipping Zones as you want, for example you could have "Local", "Domestic", and "Europe" zones.', 'woocommerce' ); ?></p>
|
||||
<p><?php _e( 'Once a Shipping Zone has been added, you can add one or more Shipping Methods to it. Customers will only see Shipping Methods that apply to their address.', 'woocommerce' ); ?></p>
|
||||
<a class="button button-primary wc-shipping-zone-add"><?php _e( 'Add Shipping Zone', 'woocommerce' ); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script type="text/html" id="tmpl-wc-shipping-zone-row">
|
||||
<tr data-id="{{ data.zone_id }}">
|
||||
<td width="1%" class="wc-shipping-zone-sort"></td>
|
||||
<td class="wc-shipping-zone-name">
|
||||
<div class="view">
|
||||
<a href="admin.php?page=wc-settings&tab=shipping&zone_id={{ data.zone_id }}">{{ data.zone_name }}</a>
|
||||
<div class="row-actions">
|
||||
<a class="wc-shipping-zone-edit" href="#"><?php _e( 'Edit Zone', 'woocommerce' ); ?></a> | <a href="admin.php?page=wc-settings&tab=shipping&zone_id={{ data.zone_id }}"><?php _e( 'Edit Shipping Methods', 'woocommerce' ); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="edit"><input type="text" name="zone_name[{{ data.zone_id }}]" data-attribute="zone_name" value="{{ data.zone_name }}" placeholder="<?php esc_attr_e( 'Zone Name', 'woocommerce' ); ?>" /></div>
|
||||
</td>
|
||||
<td class="wc-shipping-zone-region">
|
||||
<div class="view">{{ data.formatted_zone_location }}</div>
|
||||
<div class="edit">
|
||||
<select multiple="multiple" name="zone_locations[{{ data.zone_id }}]" data-attribute="zone_locations" data-placeholder="<?php _e( 'Select regions within this zone', 'woocommerce' ); ?>" class="wc-shipping-zone-region-select">
|
||||
<?php
|
||||
foreach ( $continents as $continent_code => $continent ) {
|
||||
echo '<option value="continent:' . esc_attr( $continent_code ) . '" alt="">' . esc_html( $continent['name'] ) . '</option>';
|
||||
|
||||
$countries = array_intersect( array_keys( $allowed_countries ), $continent['countries'] );
|
||||
|
||||
foreach ( $countries as $country_code ) {
|
||||
echo '<option value="country:' . esc_attr( $country_code ) . '" alt="' . esc_attr( $continent['name'] ) . '">' . esc_html( ' ' . $allowed_countries[ $country_code ] ) . '</option>';
|
||||
|
||||
if ( $states = WC()->countries->get_states( $country_code ) ) {
|
||||
foreach ( $states as $state_code => $state_name ) {
|
||||
echo '<option value="state:' . esc_attr( $country_code . ':' . $state_code ) . '" alt="' . esc_attr( $continent['name'] . ' ' . $allowed_countries[ $country_code ] ) . '">' . esc_html( ' ' . $state_name ) . '</option>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<a class="wc-shipping-zone-postcodes-toggle" href="#"><?php _e( 'Limit to specific ZIP/postcodes', 'woocommerce' ); ?></a>
|
||||
<div class="wc-shipping-zone-postcodes">
|
||||
<textarea name="zone_postcodes[{{ data.zone_id }}]" data-attribute="zone_postcodes" placeholder="<?php esc_attr_e( 'List 1 postcode per line', 'woocommerce' ); ?>" class="input-text large-text" cols="25" rows="5"></textarea>
|
||||
<span class="description"><?php _e( 'Wildcards and numerical ranges are supported too, for example, 90210-99000 and CB23*', 'woocommerce' ) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="wc-shipping-zone-methods">
|
||||
<div class="view">
|
||||
<ul></ul>
|
||||
</div>
|
||||
<div class="edit"><?php _e( '<a href="#" class="wc-shipping-zone-save-changes">Save changes</a> before adding methods.', 'woocommerce' ); ?></div>
|
||||
</td>
|
||||
<td class="wc-shipping-zone-actions">
|
||||
<a class="wc-shipping-zone-delete tips" data-tip="<?php _e( 'Delete', 'woocommerce' ); ?>" href="#"><?php _e( 'Delete', 'woocommerce' ); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-wc-modal-add-shipping-method">
|
||||
<div class="wc-backbone-modal">
|
||||
<div class="wc-backbone-modal-content">
|
||||
<section class="wc-backbone-modal-main" role="main">
|
||||
<header class="wc-backbone-modal-header">
|
||||
<h1><?php _e( 'Add Shipping Method', 'woocommerce' ); ?></h1>
|
||||
<button class="modal-close modal-close-link dashicons dashicons-no-alt">
|
||||
<span class="screen-reader-text"><?php _e( 'Close modal panel', 'woocommerce' ); ?></span>
|
||||
</button>
|
||||
</header>
|
||||
<article>
|
||||
<form action="" method="post">
|
||||
<div class="wc-shipping-zone-method-selector">
|
||||
<select name="add_method_id">
|
||||
<?php
|
||||
foreach ( WC()->shipping->load_shipping_methods() as $method ) {
|
||||
if ( ! $method->supports( 'shipping-zones' ) ) {
|
||||
continue;
|
||||
}
|
||||
echo '<option value="' . esc_attr( $method->id ) . '">' . esc_attr( $method->title ) . '</li>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<input type="hidden" name="zone_id" value="{{{ data.zone_id }}}" />
|
||||
</div>
|
||||
</form>
|
||||
</article>
|
||||
<footer>
|
||||
<div class="inner">
|
||||
<button id="btn-ok" class="button button-primary button-large"><?php _e( 'Add Shipping Method', 'woocommerce' ); ?></button>
|
||||
</div>
|
||||
</footer>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wc-backbone-modal-backdrop modal-close"></div>
|
||||
</script>
|
|
@ -8,14 +8,6 @@ return apply_filters( 'woocommerce_tax_settings', array(
|
|||
|
||||
array( 'title' => __( 'Tax Options', 'woocommerce' ), 'type' => 'title','desc' => '', 'id' => 'tax_options' ),
|
||||
|
||||
array(
|
||||
'title' => __( 'Enable Taxes', 'woocommerce' ),
|
||||
'desc' => __( 'Enable taxes and tax calculations', 'woocommerce' ),
|
||||
'id' => 'woocommerce_calc_taxes',
|
||||
'default' => 'no',
|
||||
'type' => 'checkbox'
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Prices Entered With Tax', 'woocommerce' ),
|
||||
'id' => 'woocommerce_prices_include_tax',
|
||||
|
|
|
@ -2,13 +2,10 @@
|
|||
/**
|
||||
* Admin View: Settings
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="wrap woocommerce">
|
||||
<form method="<?php echo esc_attr( apply_filters( 'woocommerce_settings_form_method_tab_' . $current_tab, 'post' ) ); ?>" id="mainform" action="" enctype="multipart/form-data">
|
||||
<div class="icon32 icon32-woocommerce-settings" id="icon-woocommerce"><br /></div>
|
||||
|
@ -23,9 +20,10 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
</h2>
|
||||
|
||||
<?php
|
||||
do_action( 'woocommerce_sections_' . $current_tab );
|
||||
|
||||
self::show_messages();
|
||||
|
||||
do_action( 'woocommerce_sections_' . $current_tab );
|
||||
do_action( 'woocommerce_settings_' . $current_tab );
|
||||
do_action( 'woocommerce_settings_tabs_' . $current_tab ); // @deprecated hook
|
||||
?>
|
||||
|
|
|
@ -23,6 +23,7 @@ function wc_get_screen_ids() {
|
|||
$screen_ids = array(
|
||||
'toplevel_page_' . $wc_screen_id,
|
||||
$wc_screen_id . '_page_wc-reports',
|
||||
$wc_screen_id . '_page_wc-shipping',
|
||||
$wc_screen_id . '_page_wc-settings',
|
||||
$wc_screen_id . '_page_wc-status',
|
||||
$wc_screen_id . '_page_wc-addons',
|
||||
|
@ -34,7 +35,6 @@ function wc_get_screen_ids() {
|
|||
'shop_coupon',
|
||||
'edit-product_cat',
|
||||
'edit-product_tag',
|
||||
'edit-product_shipping_class',
|
||||
'profile',
|
||||
'user-edit'
|
||||
);
|
||||
|
|
|
@ -141,6 +141,10 @@ class WC_AJAX {
|
|||
'save_variations' => false,
|
||||
'bulk_edit_variations' => false,
|
||||
'tax_rates_save_changes' => false,
|
||||
'shipping_zones_save_changes' => false,
|
||||
'shipping_zone_add_method' => false,
|
||||
'shipping_zone_methods_save_changes' => false,
|
||||
'shipping_classes_save_changes' => false,
|
||||
);
|
||||
|
||||
foreach ( $ajax_events as $ajax_event => $nopriv ) {
|
||||
|
@ -3030,6 +3034,242 @@ class WC_AJAX {
|
|||
'rates' => WC_Tax::get_rates_for_tax_class( $current_class ),
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle submissions from assets/js/wc-shipping-zones.js Backbone model.
|
||||
*/
|
||||
public static function shipping_zones_save_changes() {
|
||||
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['changes'] ) ) {
|
||||
wp_send_json_error( 'missing_fields' );
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! wp_verify_nonce( $_POST['wc_shipping_zones_nonce'], 'wc_shipping_zones_nonce' ) ) {
|
||||
wp_send_json_error( 'bad_nonce' );
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check User Caps
|
||||
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||
wp_send_json_error( 'missing_capabilities' );
|
||||
exit;
|
||||
}
|
||||
|
||||
$changes = $_POST['changes'];
|
||||
foreach ( $changes as $zone_id => $data ) {
|
||||
if ( isset( $data['deleted'] ) ) {
|
||||
if ( isset( $data['newRow'] ) ) {
|
||||
// So the user added and deleted a new row.
|
||||
// That's fine, it's not in the database anyways. NEXT!
|
||||
continue;
|
||||
}
|
||||
WC_Shipping_Zones::delete_zone( $zone_id );
|
||||
continue;
|
||||
}
|
||||
|
||||
$zone_data = array_intersect_key( $data, array(
|
||||
'zone_id' => 1,
|
||||
'zone_name' => 1,
|
||||
'zone_order' => 1,
|
||||
'zone_locations' => 1,
|
||||
'zone_postcodes' => 1
|
||||
) );
|
||||
|
||||
if ( isset( $zone_data['zone_id'] ) ) {
|
||||
$zone = new WC_Shipping_Zone( $zone_data['zone_id'] );
|
||||
|
||||
if ( isset( $zone_data['zone_name'] ) ) {
|
||||
$zone->set_zone_name( $zone_data['zone_name'] );
|
||||
}
|
||||
|
||||
if ( isset( $zone_data['zone_order'] ) ) {
|
||||
$zone->set_zone_order( $zone_data['zone_order'] );
|
||||
}
|
||||
|
||||
if ( isset( $zone_data['zone_locations'] ) ) {
|
||||
$zone->clear_locations( array( 'state', 'country', 'continent' ) );
|
||||
$locations = array_filter( array_map( 'wc_clean', (array) $zone_data['zone_locations'] ) );
|
||||
foreach ( $locations as $location ) {
|
||||
// Each posted location will be in the format type:code
|
||||
$location_parts = explode( ':', $location );
|
||||
switch ( $location_parts[0] ) {
|
||||
case 'state' :
|
||||
$zone->add_location( $location_parts[1] . ':' . $location_parts[2], 'state' );
|
||||
break;
|
||||
case 'country' :
|
||||
$zone->add_location( $location_parts[1], 'country' );
|
||||
break;
|
||||
case 'continent' :
|
||||
$zone->add_location( $location_parts[1], 'continent' );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $zone_data['zone_postcodes'] ) ) {
|
||||
$zone->clear_locations( 'postcode' );
|
||||
$postcodes = array_filter( array_map( 'strtoupper', array_map( 'wc_clean', explode( "\n", $zone_data['zone_postcodes'] ) ) ) );
|
||||
foreach ( $postcodes as $postcode ) {
|
||||
$zone->add_location( $postcode, 'postcode' );
|
||||
}
|
||||
}
|
||||
|
||||
$zone->save();
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json_success( array(
|
||||
'zones' => WC_Shipping_Zones::get_zones()
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle submissions from assets/js/wc-shipping-zone-methods.js Backbone model.
|
||||
*/
|
||||
public static function shipping_zone_add_method() {
|
||||
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['zone_id'], $_POST['method_id'] ) ) {
|
||||
wp_send_json_error( 'missing_fields' );
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! wp_verify_nonce( $_POST['wc_shipping_zones_nonce'], 'wc_shipping_zones_nonce' ) ) {
|
||||
wp_send_json_error( 'bad_nonce' );
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check User Caps
|
||||
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||
wp_send_json_error( 'missing_capabilities' );
|
||||
exit;
|
||||
}
|
||||
|
||||
$zone_id = absint( $_POST['zone_id'] );
|
||||
$zone = WC_Shipping_Zones::get_zone( $zone_id );
|
||||
$instance_id = $zone->add_shipping_method( wc_clean( $_POST['method_id'] ) );
|
||||
|
||||
wp_send_json_success( array(
|
||||
'instance_id' => $instance_id,
|
||||
'zone_id' => $zone_id,
|
||||
'methods' => $zone->get_shipping_methods()
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle submissions from assets/js/wc-shipping-zone-methods.js Backbone model.
|
||||
*/
|
||||
public static function shipping_zone_methods_save_changes() {
|
||||
if ( ! isset( $_POST['wc_shipping_zones_nonce'], $_POST['zone_id'], $_POST['changes'] ) ) {
|
||||
wp_send_json_error( 'missing_fields' );
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! wp_verify_nonce( $_POST['wc_shipping_zones_nonce'], 'wc_shipping_zones_nonce' ) ) {
|
||||
wp_send_json_error( 'bad_nonce' );
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||
wp_send_json_error( 'missing_capabilities' );
|
||||
exit;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$zone_id = absint( $_POST['zone_id'] );
|
||||
$zone = new WC_Shipping_Zone( $zone_id );
|
||||
$changes = $_POST['changes'];
|
||||
|
||||
foreach ( $changes as $instance_id => $data ) {
|
||||
if ( isset( $data['deleted'] ) ) {
|
||||
$wpdb->delete( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'instance_id' => $instance_id ) );
|
||||
continue;
|
||||
}
|
||||
|
||||
$method_data = array_intersect_key( $data, array(
|
||||
'method_order' => 1
|
||||
) );
|
||||
|
||||
if ( isset( $method_data['method_order'] ) ) {
|
||||
$wpdb->update( "{$wpdb->prefix}woocommerce_shipping_zone_methods", array( 'method_order' => absint( $method_data['method_order'] ) ), array( 'instance_id' => absint( $instance_id ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
wp_send_json_success( array(
|
||||
'methods' => $zone->get_shipping_methods()
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle submissions from assets/js/wc-shipping-classes.js Backbone model.
|
||||
*/
|
||||
public static function shipping_classes_save_changes() {
|
||||
if ( ! isset( $_POST['wc_shipping_classes_nonce'], $_POST['changes'] ) ) {
|
||||
wp_send_json_error( 'missing_fields' );
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! wp_verify_nonce( $_POST['wc_shipping_classes_nonce'], 'wc_shipping_classes_nonce' ) ) {
|
||||
wp_send_json_error( 'bad_nonce' );
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||
wp_send_json_error( 'missing_capabilities' );
|
||||
exit;
|
||||
}
|
||||
|
||||
$changes = $_POST['changes'];
|
||||
|
||||
foreach ( $changes as $term_id => $data ) {
|
||||
$term_id = absint( $term_id );
|
||||
|
||||
if ( isset( $data['deleted'] ) ) {
|
||||
if ( isset( $data['newRow'] ) ) {
|
||||
// So the user added and deleted a new row.
|
||||
// That's fine, it's not in the database anyways. NEXT!
|
||||
continue;
|
||||
}
|
||||
wp_delete_term( $term_id, 'product_shipping_class' );
|
||||
continue;
|
||||
}
|
||||
|
||||
$update_args = array();
|
||||
|
||||
if ( isset( $data['name'] ) ) {
|
||||
$update_args['name'] = wc_clean( $data['name'] );
|
||||
}
|
||||
|
||||
if ( isset( $data['slug'] ) ) {
|
||||
$update_args['slug'] = wc_clean( $data['slug'] );
|
||||
}
|
||||
|
||||
if ( isset( $data['description'] ) ) {
|
||||
$update_args['description'] = wc_clean( $data['description'] );
|
||||
}
|
||||
|
||||
if ( isset( $data['newRow'] ) ) {
|
||||
$update_args = array_filter( $update_args );
|
||||
if ( empty( $update_args['name'] ) ) {
|
||||
wp_send_json_error( __( 'Shipping Class name is required', 'woocommerce' ) );
|
||||
exit;
|
||||
}
|
||||
$result = wp_insert_term( $update_args['name'], 'product_shipping_class', $update_args );
|
||||
} else {
|
||||
$result = wp_update_term( $term_id, 'product_shipping_class', $update_args );
|
||||
}
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
wp_send_json_error( $result->get_error_message() );
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$wc_shipping = WC_Shipping::instance();
|
||||
|
||||
wp_send_json_success( array(
|
||||
'shipping_classes' => $wc_shipping->get_shipping_classes()
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
WC_AJAX::init();
|
||||
|
|
|
@ -1502,7 +1502,7 @@ class WC_Cart {
|
|||
* @return bool whether or not the cart needs shipping
|
||||
*/
|
||||
public function needs_shipping() {
|
||||
if ( get_option( 'woocommerce_calc_shipping' ) === 'no' ) {
|
||||
if ( ! wc_shipping_enabled() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1542,7 +1542,7 @@ class WC_Cart {
|
|||
* @return bool
|
||||
*/
|
||||
public function show_shipping() {
|
||||
if ( get_option('woocommerce_calc_shipping') == 'no' || ! is_array( $this->cart_contents ) )
|
||||
if ( ! wc_shipping_enabled() || ! is_array( $this->cart_contents ) )
|
||||
return false;
|
||||
|
||||
if ( get_option( 'woocommerce_shipping_cost_requires_address' ) == 'yes' ) {
|
||||
|
|
|
@ -50,6 +50,35 @@ class WC_Countries {
|
|||
return $this->countries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all continents.
|
||||
* @return array
|
||||
*/
|
||||
public function get_continents() {
|
||||
if ( empty( $this->continents ) ) {
|
||||
$this->continents = apply_filters( 'woocommerce_continents', include( WC()->plugin_path() . '/i18n/continents.php' ) );
|
||||
}
|
||||
return $this->continents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get continent code for a country code.
|
||||
* @since 2.6.0
|
||||
* @param $cc string
|
||||
* @return string
|
||||
*/
|
||||
public function get_continent_code_for_country( $cc ) {
|
||||
$cc = trim( strtoupper( $cc ) );
|
||||
$continents = $this->get_continents();
|
||||
$continents_and_ccs = wp_list_pluck( $continents, 'countries' );
|
||||
foreach ( $continents_and_ccs as $continent_code => $countries ) {
|
||||
if ( false !== array_search( $cc, $countries ) ) {
|
||||
return $continent_code;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the states.
|
||||
*/
|
||||
|
|
|
@ -330,7 +330,7 @@ class WC_Customer {
|
|||
$tax_based_on = get_option( 'woocommerce_tax_based_on' );
|
||||
|
||||
// Check shipping method at this point to see if we need special handling
|
||||
if ( true == apply_filters( 'woocommerce_apply_base_tax_for_local_pickup', true ) && WC()->cart->needs_shipping() && sizeof( array_intersect( WC()->session->get( 'chosen_shipping_methods', array() ), apply_filters( 'woocommerce_local_pickup_methods', array( 'local_pickup' ) ) ) ) > 0 ) {
|
||||
if ( true == apply_filters( 'woocommerce_apply_base_tax_for_local_pickup', true ) && WC()->cart->needs_shipping() && sizeof( array_intersect( WC()->session->get( 'chosen_shipping_methods', array() ), apply_filters( 'woocommerce_local_pickup_methods', array( 'legacy_local_pickup', 'local_pickup' ) ) ) ) > 0 ) {
|
||||
$tax_based_on = 'base';
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ class WC_Install {
|
|||
'2.4.0' => 'updates/woocommerce-update-2.4.php',
|
||||
'2.4.1' => 'updates/woocommerce-update-2.4.1.php',
|
||||
'2.5.0' => 'updates/woocommerce-update-2.5.php',
|
||||
'2.6.0' => 'updates/woocommerce-update-2.6.php'
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -176,6 +177,10 @@ class WC_Install {
|
|||
* Handle updates.
|
||||
*/
|
||||
private static function update() {
|
||||
if ( ! defined( 'WC_UPDATING' ) ) {
|
||||
define( 'WC_UPDATING', true );
|
||||
}
|
||||
|
||||
$current_db_version = get_option( 'woocommerce_db_version' );
|
||||
|
||||
foreach ( self::$db_updates as $version => $updater ) {
|
||||
|
@ -464,6 +469,29 @@ CREATE TABLE {$wpdb->prefix}woocommerce_tax_rate_locations (
|
|||
KEY tax_rate_id (tax_rate_id),
|
||||
KEY location_type (location_type),
|
||||
KEY location_type_code (location_type(40),location_code(90))
|
||||
) $collate;
|
||||
CREATE TABLE {$wpdb->prefix}woocommerce_shipping_zones (
|
||||
zone_id bigint(20) NOT NULL auto_increment,
|
||||
zone_name varchar(255) NOT NULL,
|
||||
zone_order bigint(20) NOT NULL,
|
||||
PRIMARY KEY (zone_id)
|
||||
) $collate;
|
||||
CREATE TABLE {$wpdb->prefix}woocommerce_shipping_zone_locations (
|
||||
location_id bigint(20) NOT NULL auto_increment,
|
||||
zone_id bigint(20) NOT NULL,
|
||||
location_code varchar(255) NOT NULL,
|
||||
location_type varchar(40) NOT NULL,
|
||||
PRIMARY KEY (location_id),
|
||||
KEY location_id (location_id),
|
||||
KEY location_type (location_type),
|
||||
KEY location_type_code (location_type(40),location_code(90))
|
||||
) $collate;
|
||||
CREATE TABLE {$wpdb->prefix}woocommerce_shipping_zone_methods (
|
||||
zone_id bigint(20) NOT NULL,
|
||||
instance_id bigint(20) NOT NULL auto_increment,
|
||||
method_id varchar(255) NOT NULL,
|
||||
method_order bigint(20) NOT NULL,
|
||||
PRIMARY KEY (instance_id)
|
||||
) $collate;
|
||||
";
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ class WC_Post_types {
|
|||
'add_new_item' => __( 'Add New Shipping Class', 'woocommerce' ),
|
||||
'new_item_name' => __( 'New Shipping Class Name', 'woocommerce' )
|
||||
),
|
||||
'show_ui' => true,
|
||||
'show_ui' => false,
|
||||
'show_in_quick_edit' => false,
|
||||
'show_in_nav_menus' => false,
|
||||
'query_var' => is_admin(),
|
||||
|
|
|
@ -10,7 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* Simple Class for storing rates.
|
||||
*
|
||||
* @class WC_Shipping_Rate
|
||||
* @version 2.3.0
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce/Classes/Shipping
|
||||
* @category Class
|
||||
* @author WooThemes
|
||||
|
@ -32,6 +32,13 @@ class WC_Shipping_Rate {
|
|||
/** @var string Label for the rate. */
|
||||
public $method_id = '';
|
||||
|
||||
/**
|
||||
* Stores meta data for this rate
|
||||
* @since 2.6.0
|
||||
* @var array
|
||||
*/
|
||||
private $meta_data = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
@ -42,11 +49,11 @@ class WC_Shipping_Rate {
|
|||
* @param string $method_id
|
||||
*/
|
||||
public function __construct( $id, $label, $cost, $taxes, $method_id ) {
|
||||
$this->id = $id;
|
||||
$this->label = $label;
|
||||
$this->cost = $cost;
|
||||
$this->taxes = $taxes ? $taxes : array();
|
||||
$this->method_id = $method_id;
|
||||
$this->id = $id;
|
||||
$this->label = $label;
|
||||
$this->cost = $cost;
|
||||
$this->taxes = ! empty( $taxes ) && is_array( $taxes ) ? $taxes : array();
|
||||
$this->method_id = $method_id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,11 +62,7 @@ class WC_Shipping_Rate {
|
|||
* @return array
|
||||
*/
|
||||
public function get_shipping_tax() {
|
||||
$taxes = 0;
|
||||
if ( $this->taxes && sizeof( $this->taxes ) > 0 && ! WC()->customer->is_vat_exempt() ) {
|
||||
$taxes = array_sum( $this->taxes );
|
||||
}
|
||||
return apply_filters( 'woocommerce_get_shipping_tax', $taxes, $this );
|
||||
return apply_filters( 'woocommerce_get_shipping_tax', sizeof( $this->taxes ) > 0 && ! WC()->customer->is_vat_exempt() ? array_sum( $this->taxes ) : 0, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,4 +73,24 @@ class WC_Shipping_Rate {
|
|||
public function get_label() {
|
||||
return apply_filters( 'woocommerce_shipping_rate_label', $this->label );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add some meta data for this rate.
|
||||
* @since 2.6.0
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*/
|
||||
public function add_meta_data( $key, $value ) {
|
||||
$this->meta_data[ wc_clean( $key ) ] = wc_clean( $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all meta data for this rate.
|
||||
* @since 2.6.0
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*/
|
||||
public function get_meta_data() {
|
||||
return $this->meta_data;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,423 @@
|
|||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a single shipping zone
|
||||
*
|
||||
* @class WC_Shipping_Zone
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce/Classes
|
||||
* @category Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Shipping_Zone implements WC_Data {
|
||||
|
||||
/**
|
||||
* Zone Data
|
||||
* @var array
|
||||
*/
|
||||
private $data = array(
|
||||
'zone_id' => 0,
|
||||
'zone_name' => '',
|
||||
'zone_order' => 0,
|
||||
'zone_locations' => array()
|
||||
);
|
||||
|
||||
/**
|
||||
* True when location data needs to be re-saved
|
||||
* @var bool
|
||||
*/
|
||||
private $_locations_changed = false;
|
||||
|
||||
/**
|
||||
* Constructor for zones
|
||||
* @param int|object $zone Zone ID to load from the DB (optional) or already queried data.
|
||||
*/
|
||||
public function __construct( $zone = 0 ) {
|
||||
if ( is_numeric( $zone ) && ! empty( $zone ) ) {
|
||||
$this->read( $zone );
|
||||
} elseif ( is_object( $zone ) ) {
|
||||
$this->set_zone_id( $zone->zone_id );
|
||||
$this->set_zone_name( $zone->zone_name );
|
||||
$this->set_zone_order( $zone->zone_order );
|
||||
$this->read_zone_locations( $zone->zone_id );
|
||||
} elseif ( 0 === $zone ) {
|
||||
$this->set_zone_name( __( 'Rest of the World', 'woocommerce' ) );
|
||||
$this->read_zone_locations( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ID
|
||||
* @return int
|
||||
*/
|
||||
public function get_id() {
|
||||
return $this->get_zone_id();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get class data array
|
||||
* @return array
|
||||
*/
|
||||
public function get_data() {
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert zone into the database
|
||||
*/
|
||||
public function create() {
|
||||
global $wpdb;
|
||||
$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zones', array(
|
||||
'zone_name' => $this->get_zone_name(),
|
||||
'zone_order' => $this->get_zone_order(),
|
||||
) );
|
||||
$this->set_zone_id( $wpdb->insert_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Read zone.
|
||||
* @param int ID to read from DB
|
||||
*/
|
||||
public function read( $id ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( $zone_data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zones WHERE zone_id = %d LIMIT 1;", $id ) ) ) {
|
||||
$this->set_zone_id( $zone_data->zone_id );
|
||||
$this->set_zone_name( $zone_data->zone_name );
|
||||
$this->set_zone_order( $zone_data->zone_order );
|
||||
$this->read_zone_locations( $zone_data->zone_id );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update zone in the database
|
||||
*/
|
||||
public function update() {
|
||||
global $wpdb;
|
||||
$wpdb->update( $wpdb->prefix . 'woocommerce_shipping_zones', array(
|
||||
'zone_name' => $this->get_zone_name(),
|
||||
'zone_order' => $this->get_zone_order(),
|
||||
), array( 'zone_id' => $this->get_zone_id() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a zone.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public function delete() {
|
||||
if ( $this->get_id() ) {
|
||||
global $wpdb;
|
||||
$wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_methods', array( 'zone_id' => $this->get_id() ) );
|
||||
$wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array( 'zone_id' => $this->get_id() ) );
|
||||
$wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zones', array( 'zone_id' => $this->get_id() ) );
|
||||
WC_Cache_Helper::incr_cache_prefix( 'shipping_zones' );
|
||||
$this->set_zone_id( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save zone data to the database.
|
||||
*/
|
||||
public function save() {
|
||||
if ( ! $this->get_zone_id() ) {
|
||||
$this->create();
|
||||
} else {
|
||||
$this->update();
|
||||
}
|
||||
|
||||
$this->save_locations();
|
||||
WC_Cache_Helper::incr_cache_prefix( 'shipping_zones' );
|
||||
|
||||
// Increments the transient version to invalidate cache.
|
||||
WC_Cache_Helper::get_transient_version( 'shipping', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get zone ID
|
||||
* @return int
|
||||
*/
|
||||
public function get_zone_id() {
|
||||
return absint( $this->data['zone_id'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get zone name
|
||||
* @return string
|
||||
*/
|
||||
public function get_zone_name() {
|
||||
return $this->data['zone_name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get zone order
|
||||
* @return int
|
||||
*/
|
||||
public function get_zone_order() {
|
||||
return absint( $this->data['zone_order'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get zone locations
|
||||
* @return array of zone objects
|
||||
*/
|
||||
public function get_zone_locations() {
|
||||
return $this->data['zone_locations'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a text string representing what this zone is for.
|
||||
* @return string
|
||||
*/
|
||||
public function get_formatted_location( $max = 10 ) {
|
||||
$location_parts = array();
|
||||
$all_continents = WC()->countries->get_continents();
|
||||
$all_countries = WC()->countries->get_countries();
|
||||
$all_states = WC()->countries->get_states();
|
||||
$locations = $this->get_zone_locations();
|
||||
$continents = array_filter( $locations, array( $this, 'location_is_continent' ) );
|
||||
$countries = array_filter( $locations, array( $this, 'location_is_country' ) );
|
||||
$states = array_filter( $locations, array( $this, 'location_is_state' ) );
|
||||
$postcodes = array_filter( $locations, array( $this, 'location_is_postcode' ) );
|
||||
|
||||
foreach ( $continents as $location ) {
|
||||
$location_parts[] = $all_continents[ $location->code ]['name'];
|
||||
}
|
||||
|
||||
foreach ( $countries as $location ) {
|
||||
$location_parts[] = $all_countries[ $location->code ];
|
||||
}
|
||||
|
||||
foreach ( $states as $location ) {
|
||||
$location_codes = explode( ':', $location->code );
|
||||
$location_parts[] = $all_states[ $location_codes[ 0 ] ][ $location_codes[ 1 ] ];
|
||||
}
|
||||
|
||||
foreach ( $postcodes as $location ) {
|
||||
$location_parts[] = $location->code;
|
||||
}
|
||||
|
||||
// Fix display of encoded characters.
|
||||
$location_parts = array_map( 'html_entity_decode', $location_parts );
|
||||
|
||||
if ( sizeof( $location_parts ) > $max ) {
|
||||
$remaining = sizeof( $location_parts ) - $max;
|
||||
return sprintf( _n( '%s and %d other region', '%s and %d other regions', $remaining, 'woocommerce' ), implode( ', ', array_splice( $location_parts, 0, $max ) ), $remaining );
|
||||
} else {
|
||||
return implode( ', ', $location_parts );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shipping methods linked to this zone
|
||||
* @return array of objects
|
||||
*/
|
||||
public function get_shipping_methods() {
|
||||
global $wpdb;
|
||||
|
||||
$raw_methods = $wpdb->get_results( $wpdb->prepare( "SELECT method_id, method_order, instance_id FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE zone_id = %d order by method_order ASC;", $this->get_zone_id() ) );
|
||||
$wc_shipping = WC_Shipping::instance();
|
||||
$allowed_classes = $wc_shipping->get_shipping_method_class_names();
|
||||
$methods = array();
|
||||
|
||||
foreach ( $raw_methods as $raw_method ) {
|
||||
if ( in_array( $raw_method->method_id, array_keys( $allowed_classes ) ) ) {
|
||||
$class_name = $allowed_classes[ $raw_method->method_id ];
|
||||
if ( class_exists( $class_name ) ) {
|
||||
$methods[ $raw_method->instance_id ] = new $class_name( $raw_method->instance_id );
|
||||
$methods[ $raw_method->instance_id ]->method_order = absint( $raw_method->method_order );
|
||||
$methods[ $raw_method->instance_id ]->has_settings = $methods[ $raw_method->instance_id ]->has_settings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location type detection
|
||||
* @param object $location
|
||||
* @return boolean
|
||||
*/
|
||||
private function location_is_continent( $location ) {
|
||||
return 'continent' === $location->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location type detection
|
||||
* @param object $location
|
||||
* @return boolean
|
||||
*/
|
||||
private function location_is_country( $location ) {
|
||||
return 'country' === $location->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location type detection
|
||||
* @param object $location
|
||||
* @return boolean
|
||||
*/
|
||||
private function location_is_state( $location ) {
|
||||
return 'state' === $location->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location type detection
|
||||
* @param object $location
|
||||
* @return boolean
|
||||
*/
|
||||
private function location_is_postcode( $location ) {
|
||||
return 'postcode' === $location->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set zone ID
|
||||
* @access private
|
||||
* @param int $set
|
||||
*/
|
||||
private function set_zone_id( $set ) {
|
||||
$this->data['zone_id'] = absint( $set );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set zone name
|
||||
* @param string $set
|
||||
*/
|
||||
public function set_zone_name( $set ) {
|
||||
$this->data['zone_name'] = wc_clean( $set );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set zone order
|
||||
* @param int $set
|
||||
*/
|
||||
public function set_zone_order( $set ) {
|
||||
$this->data['zone_order'] = absint( $set );
|
||||
}
|
||||
|
||||
/**
|
||||
* Is passed location type valid?
|
||||
* @param string $type
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_valid_location_type( $type ) {
|
||||
return in_array( $type, array( 'postcode', 'state', 'country', 'continent' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add location (state or postcode) to a zone.
|
||||
* @param string $code
|
||||
* @param string $type state or postcode
|
||||
*/
|
||||
public function add_location( $code, $type ) {
|
||||
if ( $this->is_valid_location_type( $type ) ) {
|
||||
$location = array(
|
||||
'code' => wc_clean( $code ),
|
||||
'type' => wc_clean( $type )
|
||||
);
|
||||
$this->data['zone_locations'][] = (object) $location;
|
||||
$this->_locations_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all locations for this zone.
|
||||
* @param array|string $types of location to clear
|
||||
*/
|
||||
public function clear_locations( $types = array( 'postcode', 'state', 'country', 'continent' ) ) {
|
||||
if ( ! is_array( $types ) ) {
|
||||
$types = array( $types );
|
||||
}
|
||||
foreach ( $this->data['zone_locations'] as $key => $values ) {
|
||||
if ( in_array( $values->type, $types ) ) {
|
||||
unset( $this->data['zone_locations'][ $key ] );
|
||||
$this->_locations_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set locations
|
||||
* @param array $locations Array of locations
|
||||
*/
|
||||
public function set_locations( $locations = array() ) {
|
||||
$this->clear_locations();
|
||||
|
||||
foreach ( $locations as $location ) {
|
||||
$this->add_location( $location['code'], $location['type'] );
|
||||
}
|
||||
|
||||
$this->_locations_changed = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read location data from the database
|
||||
* @param int $zone_id
|
||||
*/
|
||||
private function read_zone_locations( $zone_id ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( $locations = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE zone_id = %d;", $zone_id ) ) ) {
|
||||
foreach ( $locations as $location ) {
|
||||
$this->add_location( $location->location_code, $location->location_type );
|
||||
}
|
||||
}
|
||||
$this->_locations_changed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save locations to the DB.
|
||||
*
|
||||
* This function clears old locations, then re-inserts new if any changes are found.
|
||||
*/
|
||||
private function save_locations() {
|
||||
if ( ! $this->get_zone_id() || ! $this->_locations_changed ) {
|
||||
return false;
|
||||
}
|
||||
global $wpdb;
|
||||
$wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array( 'zone_id' => $this->get_zone_id() ) );
|
||||
|
||||
foreach ( $this->get_zone_locations() as $location ) {
|
||||
$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array(
|
||||
'zone_id' => $this->get_zone_id(),
|
||||
'location_code' => $location->code,
|
||||
'location_type' => $location->type
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a shipping method to this zone.
|
||||
* @param string $type shipping method type
|
||||
* @return int new instance_id, 0 on failure
|
||||
*/
|
||||
public function add_shipping_method( $type ) {
|
||||
global $wpdb;
|
||||
|
||||
$instance_id = 0;
|
||||
$wc_shipping = WC_Shipping::instance();
|
||||
$allowed_classes = $wc_shipping->get_shipping_method_class_names();
|
||||
|
||||
if ( in_array( $type, array_keys( $allowed_classes ) ) ) {
|
||||
$wpdb->insert(
|
||||
$wpdb->prefix . 'woocommerce_shipping_zone_methods',
|
||||
array(
|
||||
'method_id' => $type,
|
||||
'zone_id' => $this->get_zone_id(),
|
||||
'method_order' => 0
|
||||
),
|
||||
array(
|
||||
'%s',
|
||||
'%d',
|
||||
'%d'
|
||||
)
|
||||
);
|
||||
$instance_id = $wpdb->insert_id;
|
||||
}
|
||||
|
||||
return $instance_id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,219 @@
|
|||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles storage and retrieval of shipping zones
|
||||
*
|
||||
* @class WC_Shipping_Zones
|
||||
* @since 2.6.0
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce/Classes
|
||||
* @category Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Shipping_Zones {
|
||||
|
||||
/**
|
||||
* Get shipping zones from the database
|
||||
* @since 2.6.0
|
||||
* @return array of arrays
|
||||
*/
|
||||
public static function get_zones() {
|
||||
global $wpdb;
|
||||
|
||||
$raw_zones = $wpdb->get_results( "SELECT zone_id, zone_name, zone_order FROM {$wpdb->prefix}woocommerce_shipping_zones order by zone_order ASC;" );
|
||||
$zones = array();
|
||||
|
||||
foreach ( $raw_zones as $raw_zone ) {
|
||||
$zone = new WC_Shipping_Zone( $raw_zone );
|
||||
$zones[ $zone->get_zone_id() ] = $zone->get_data();
|
||||
$zones[ $zone->get_zone_id() ]['formatted_zone_location'] = $zone->get_formatted_location();
|
||||
$zones[ $zone->get_zone_id() ]['shipping_methods'] = $zone->get_shipping_methods();
|
||||
}
|
||||
|
||||
return $zones;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shipping zone using it's ID
|
||||
* @since 2.6.0
|
||||
* @param int $zone_id
|
||||
* @return WC_Shipping_Zone|bool
|
||||
*/
|
||||
public static function get_zone( $zone_id ) {
|
||||
return self::get_zone_by( 'zone_id', $zone_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shipping zone by an ID.
|
||||
* @since 2.6.0
|
||||
* @param string $by zone_id or instance_id
|
||||
* @param int $id
|
||||
* @return WC_Shipping_Zone|bool
|
||||
*/
|
||||
public static function get_zone_by( $by = 'zone_id', $id = 0 ) {
|
||||
global $wpdb;
|
||||
|
||||
$raw_zone = false;
|
||||
|
||||
switch ( $by ) {
|
||||
case 'zone_id' :
|
||||
if ( 0 === $id ) {
|
||||
return new WC_Shipping_Zone( 0 );
|
||||
} else {
|
||||
$raw_zone = $wpdb->get_row( $wpdb->prepare( "SELECT zone_id, zone_name, zone_order FROM {$wpdb->prefix}woocommerce_shipping_zones WHERE zone_id = %d LIMIT 1;", $id ) );
|
||||
}
|
||||
break;
|
||||
case 'instance_id' :
|
||||
$zone_id = $wpdb->get_var( $wpdb->prepare( "SELECT zone_id FROM {$wpdb->prefix}woocommerce_shipping_zone_methods as methods WHERE methods.instance_id = %d LIMIT 1;", $id ) );
|
||||
|
||||
if ( false !== $zone_id ) {
|
||||
return self::get_zone_by( 'zone_id', absint( $zone_id ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $raw_zone ? new WC_Shipping_Zone( $raw_zone ) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get shipping zone using it's ID
|
||||
* @since 2.6.0
|
||||
* @param int $zone_id
|
||||
* @return WC_Shipping_Meethod|bool
|
||||
*/
|
||||
public static function get_shipping_method( $instance_id ) {
|
||||
global $wpdb;
|
||||
$raw_shipping_method = $wpdb->get_row( $wpdb->prepare( "SELECT instance_id, method_id FROM {$wpdb->prefix}woocommerce_shipping_zone_methods WHERE instance_id = %d LIMIT 1;", $instance_id ) );
|
||||
$wc_shipping = WC_Shipping::instance();
|
||||
$allowed_classes = $wc_shipping->get_shipping_method_class_names();
|
||||
|
||||
if ( in_array( $raw_shipping_method->method_id, array_keys( $allowed_classes ) ) ) {
|
||||
$class_name = $allowed_classes[ $raw_shipping_method->method_id ];
|
||||
return new $class_name( $raw_shipping_method->instance_id );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a zone using it's ID
|
||||
* @param int $zone_id
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public static function delete_zone( $zone_id ) {
|
||||
$zone = new WC_Shipping_Zone( $zone_id );
|
||||
$zone->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get postcode wildcards in array format.
|
||||
*
|
||||
* Internal use only.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @access private
|
||||
*
|
||||
* @param string $postcode array of values
|
||||
* @return string[] Array of postcodes with wildcards
|
||||
*/
|
||||
private static function _get_wildcard_postcodes( $postcode ) {
|
||||
$postcodes = array( '*', strtoupper( $postcode ), strtoupper( $postcode ) . '*' );
|
||||
$postcode_length = strlen( $postcode );
|
||||
$wildcard_postcode = strtoupper( $postcode );
|
||||
|
||||
for ( $i = 0; $i < $postcode_length; $i ++ ) {
|
||||
$wildcard_postcode = substr( $wildcard_postcode, 0, -1 );
|
||||
$postcodes[] = $wildcard_postcode . '*';
|
||||
}
|
||||
return $postcodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a matching zone for a given package.
|
||||
* @since 2.6.0
|
||||
* @uses wc_make_numeric_postcode()
|
||||
* @param object $package
|
||||
* @return WC_Shipping_Zone
|
||||
*/
|
||||
public static function get_zone_matching_package( $package ) {
|
||||
global $wpdb;
|
||||
|
||||
$country = strtoupper( wc_clean( $package['destination']['country'] ) );
|
||||
$state = strtoupper( wc_clean( $package['destination']['state'] ) );
|
||||
$continent = strtoupper( wc_clean( WC()->countries->get_continent_code_for_country( $country ) ) );
|
||||
$postcode = strtoupper( wc_clean( $package['destination']['postcode'] ) );
|
||||
$valid_postcodes = array_map( 'wc_clean', self::_get_wildcard_postcodes( $postcode ) );
|
||||
$cache_key = WC_Cache_Helper::get_cache_prefix( 'shipping_zones' ) . 'wc_shipping_zone_' . md5( sprintf( '%s+%s+%s', $country, $state, $postcode ) );
|
||||
$matching_zone_id = wp_cache_get( $cache_key, 'shipping_zones' );
|
||||
|
||||
if ( false === $matching_zone_id ) {
|
||||
|
||||
// Work out criteria for our zone search
|
||||
$criteria = array();
|
||||
$criteria[] = $wpdb->prepare( "( ( location_type = 'country' AND location_code = %s )", $country );
|
||||
$criteria[] = $wpdb->prepare( "OR ( location_type = 'state' AND location_code = %s )", $country . ':' . $state );
|
||||
$criteria[] = $wpdb->prepare( "OR ( location_type = 'continent' AND location_code = %s ) )", $continent );
|
||||
|
||||
// Postcode range and wildcard matching
|
||||
$postcode_locations = $wpdb->get_results( "SELECT zone_id, location_code FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE location_type = 'postcode';" );
|
||||
|
||||
if ( $postcode_locations ) {
|
||||
$zone_ids_with_postcode_rules = array_map( 'absint', wp_list_pluck( $postcode_locations, 'zone_id' ) );
|
||||
$zone_id_matches = array();
|
||||
|
||||
foreach ( $postcode_locations as $postcode_location ) {
|
||||
$postcode_to_match = trim( strtoupper( $postcode_location->location_code ) );
|
||||
|
||||
// Ranges
|
||||
if ( strstr( '-', $postcode_to_match ) ) {
|
||||
$range = array_map( 'trim', explode( '-', $postcode_to_match ) );
|
||||
|
||||
if ( sizeof( $range ) != 2 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( is_numeric( $range[0] ) && is_numeric( $range[1] ) ) {
|
||||
$encoded_postcode = $postcode;
|
||||
$min = $range[0];
|
||||
$max = $range[1];
|
||||
} else {
|
||||
$min = wc_make_numeric_postcode( $range[0] );
|
||||
$max = wc_make_numeric_postcode( $range[1] );
|
||||
$min = str_pad( $min, $encoded_postcode_len, '0' );
|
||||
$max = str_pad( $max, $encoded_postcode_len, '9' );
|
||||
}
|
||||
|
||||
if ( $encoded_postcode >= $min && $encoded_postcode <= $max ) {
|
||||
$zone_id_matches[] = absint( $postcode_location->zone_id );
|
||||
}
|
||||
|
||||
// Wildcard/standard
|
||||
} elseif ( in_array( $postcode_to_match, $valid_postcodes ) ) {
|
||||
$zone_id_matches[] = absint( $postcode_location->zone_id );
|
||||
}
|
||||
}
|
||||
|
||||
$do_not_match = array_unique( array_diff( $zone_ids_with_postcode_rules, $zone_id_matches ) );
|
||||
|
||||
if ( $do_not_match ) {
|
||||
$criteria[] = "AND zones.zone_id NOT IN (" . implode( ',', $do_not_match ) . ")";
|
||||
}
|
||||
}
|
||||
|
||||
// Get matching zones
|
||||
$matching_zone_id = $wpdb->get_var( "
|
||||
SELECT zones.zone_id FROM {$wpdb->prefix}woocommerce_shipping_zones as zones
|
||||
LEFT OUTER JOIN {$wpdb->prefix}woocommerce_shipping_zone_locations as locations ON zones.zone_id = locations.zone_id
|
||||
WHERE " . implode( ' ', $criteria ) . "
|
||||
ORDER BY zone_order ASC LIMIT 1
|
||||
" );
|
||||
|
||||
wp_cache_set( $cache_key, $matching_zone_id, 'shipping_zones' );
|
||||
}
|
||||
|
||||
return new WC_Shipping_Zone( $matching_zone_id ? $matching_zone_id : 0 );
|
||||
}
|
||||
}
|
|
@ -5,35 +5,38 @@
|
|||
* Handles shipping and loads shipping methods via hooks.
|
||||
*
|
||||
* @class WC_Shipping
|
||||
* @version 2.3.0
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce/Classes/Shipping
|
||||
* @category Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Shipping
|
||||
*/
|
||||
class WC_Shipping {
|
||||
|
||||
/** @var bool True if shipping is enabled. */
|
||||
public $enabled = false;
|
||||
public $enabled = false;
|
||||
|
||||
/** @var array Stores methods loaded into woocommerce. */
|
||||
public $shipping_methods = array();
|
||||
public $shipping_methods = null;
|
||||
|
||||
/** @var float Stores the cost of shipping */
|
||||
public $shipping_total = 0;
|
||||
public $shipping_total = 0;
|
||||
|
||||
/** @var array Stores an array of shipping taxes. */
|
||||
public $shipping_taxes = array();
|
||||
/** @var array Stores an array of shipping taxes. */
|
||||
public $shipping_taxes = array();
|
||||
|
||||
/** @var array Stores the shipping classes. */
|
||||
public $shipping_classes = array();
|
||||
public $shipping_classes = array();
|
||||
|
||||
/** @var array Stores packages to ship and to get quotes for. */
|
||||
public $packages = array();
|
||||
public $packages = array();
|
||||
|
||||
/**
|
||||
* @var WC_Shipping The single instance of the class
|
||||
|
@ -51,8 +54,9 @@ class WC_Shipping {
|
|||
* @return WC_Shipping Main instance
|
||||
*/
|
||||
public static function instance() {
|
||||
if ( is_null( self::$_instance ) )
|
||||
if ( is_null( self::$_instance ) ) {
|
||||
self::$_instance = new self();
|
||||
}
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
|
@ -78,7 +82,11 @@ class WC_Shipping {
|
|||
* Initialize shipping.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->init();
|
||||
$this->enabled = wc_shipping_enabled();
|
||||
|
||||
if ( $this->enabled ) {
|
||||
$this->init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,57 +94,75 @@ class WC_Shipping {
|
|||
*/
|
||||
public function init() {
|
||||
do_action( 'woocommerce_shipping_init' );
|
||||
}
|
||||
|
||||
$this->enabled = ( get_option('woocommerce_calc_shipping') == 'no' ) ? false : true;
|
||||
/**
|
||||
* Shipping methods register themselves by returning their main class name through the woocommerce_shipping_methods filter.
|
||||
* @return array
|
||||
*/
|
||||
public function get_shipping_method_class_names() {
|
||||
// Unique Method ID => Method Class name
|
||||
$shipping_methods = apply_filters( 'woocommerce_shipping_methods', array(
|
||||
'flat_rate' => 'WC_Shipping_Flat_Rate',
|
||||
'free_shipping' => 'WC_Shipping_Free_Shipping',
|
||||
'local_pickup' => 'WC_Shipping_Local_Pickup',
|
||||
) );
|
||||
|
||||
// For backwards compatibility with 2.5.x we load any ENABLED legacy shipping methods here
|
||||
$maybe_load_legacy_methods = array( 'flat_rate', 'free_shipping', 'international_delivery', 'local_delivery', 'local_pickup' );
|
||||
|
||||
foreach ( $maybe_load_legacy_methods as $method ) {
|
||||
$options = get_option( 'woocommerce_' . $method . '_settings' );
|
||||
if ( $options && isset( $options['enabled'] ) && 'yes' === $options['enabled'] ) {
|
||||
$shipping_methods[ 'legacy_' . $method ] = 'WC_Shipping_Legacy_' . $method;
|
||||
}
|
||||
}
|
||||
|
||||
return $shipping_methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all shipping methods which are hooked in. If a $package is passed some methods may add themselves conditionally.
|
||||
*
|
||||
* Methods are sorted into their user-defined order after being loaded.
|
||||
* Loads all shipping methods which are hooked in.
|
||||
* If a $package is passed some methods may add themselves conditionally and zones will be used.
|
||||
*
|
||||
* @access public
|
||||
* @param array $package
|
||||
* @return array
|
||||
*/
|
||||
public function load_shipping_methods( $package = array() ) {
|
||||
|
||||
$this->unregister_shipping_methods();
|
||||
|
||||
// Methods can register themselves through this hook
|
||||
do_action( 'woocommerce_load_shipping_methods', $package );
|
||||
|
||||
// Register methods through a filter
|
||||
$shipping_methods_to_load = apply_filters( 'woocommerce_shipping_methods', array(
|
||||
'WC_Shipping_Flat_Rate',
|
||||
'WC_Shipping_Free_Shipping',
|
||||
'WC_Shipping_International_Delivery',
|
||||
'WC_Shipping_Local_Delivery',
|
||||
'WC_Shipping_Local_Pickup'
|
||||
) );
|
||||
|
||||
foreach ( $shipping_methods_to_load as $method ) {
|
||||
$this->register_shipping_method( $method );
|
||||
if ( $package ) {
|
||||
$shipping_zone = WC_Shipping_Zones::get_zone_matching_package( $package );
|
||||
$this->shipping_methods = $shipping_zone->get_shipping_methods();
|
||||
} else {
|
||||
$this->shipping_methods = array();
|
||||
}
|
||||
|
||||
$this->sort_shipping_methods();
|
||||
// For the settings in the backend, and for non-shipping zone methods, we still need to load any registered classes here.
|
||||
foreach ( $this->get_shipping_method_class_names() as $method_id => $method_class ) {
|
||||
$this->register_shipping_method( $method_class );
|
||||
}
|
||||
|
||||
return $this->shipping_methods;
|
||||
// Methods can register themselves manually through this hook if necessary.
|
||||
do_action( 'woocommerce_load_shipping_methods', $package );
|
||||
|
||||
// Return loaded methods
|
||||
return $this->get_shipping_methods();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a shipping method for use in calculations.
|
||||
* Register a shipping method.
|
||||
*
|
||||
* @param object|string $method Either the name of the method's class, or an instance of the method's class
|
||||
* @param object|string $method Either the name of the method's class, or an instance of the method's class.
|
||||
*/
|
||||
public function register_shipping_method( $method ) {
|
||||
if ( ! is_object( $method ) ) {
|
||||
if ( ! class_exists( $method ) ) {
|
||||
return false;
|
||||
}
|
||||
$method = new $method();
|
||||
}
|
||||
|
||||
$id = empty( $method->instance_id ) ? $method->id : $method->instance_id;
|
||||
|
||||
$this->shipping_methods[ $id ] = $method;
|
||||
$this->shipping_methods[ $method->id ] = $method;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,46 +172,6 @@ class WC_Shipping {
|
|||
$this->shipping_methods = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort shipping methods.
|
||||
*
|
||||
* Sorts shipping methods into the user defined order.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function sort_shipping_methods() {
|
||||
|
||||
$sorted_shipping_methods = array();
|
||||
|
||||
// Get order option
|
||||
$ordering = (array) get_option('woocommerce_shipping_method_order');
|
||||
$order_end = 999;
|
||||
|
||||
// Load shipping methods in order
|
||||
foreach ( $this->shipping_methods as $method ) {
|
||||
|
||||
if ( isset( $ordering[ $method->id ] ) && is_numeric( $ordering[ $method->id ] ) ) {
|
||||
// Add in position
|
||||
$sorted_shipping_methods[ $ordering[ $method->id ] ][] = $method;
|
||||
} else {
|
||||
// Add to end of the array
|
||||
$sorted_shipping_methods[ $order_end ][] = $method;
|
||||
}
|
||||
}
|
||||
|
||||
ksort( $sorted_shipping_methods );
|
||||
|
||||
$this->shipping_methods = array();
|
||||
|
||||
foreach ( $sorted_shipping_methods as $methods )
|
||||
foreach ( $methods as $method ) {
|
||||
$id = empty( $method->instance_id ) ? $method->id : $method->instance_id;
|
||||
$this->shipping_methods[ $id ] = $method;
|
||||
}
|
||||
|
||||
return $this->shipping_methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all registered shipping methods for usage.
|
||||
*
|
||||
|
@ -193,19 +179,22 @@ class WC_Shipping {
|
|||
* @return array
|
||||
*/
|
||||
public function get_shipping_methods() {
|
||||
if ( is_null( $this->shipping_methods ) ) {
|
||||
$this->load_shipping_methods();
|
||||
}
|
||||
return $this->shipping_methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load shipping classes taxonomy terms.
|
||||
* Get an array of shipping classes.
|
||||
*
|
||||
* @access public
|
||||
* @return array
|
||||
*/
|
||||
public function get_shipping_classes() {
|
||||
if ( empty( $this->shipping_classes ) ) {
|
||||
$classes = get_terms( 'product_shipping_class', array( 'hide_empty' => '0' ) );
|
||||
$this->shipping_classes = $classes && ! is_wp_error( $classes ) ? $classes : array();
|
||||
$classes = get_terms( 'product_shipping_class', array( 'hide_empty' => '0', 'orderby' => 'name' ) );
|
||||
$this->shipping_classes = ! is_wp_error( $classes ) ? $classes : array();
|
||||
}
|
||||
return $this->shipping_classes;
|
||||
}
|
||||
|
@ -217,41 +206,21 @@ class WC_Shipping {
|
|||
* @return string
|
||||
*/
|
||||
private function get_default_method( $available_methods, $current_chosen_method = false ) {
|
||||
$selection_priority = get_option( 'woocommerce_shipping_method_selection_priority', array() );
|
||||
|
||||
if ( ! empty( $available_methods ) ) {
|
||||
|
||||
// Is a method already chosen?
|
||||
if ( ! empty( $current_chosen_method ) && ! isset( $available_methods[ $current_chosen_method ] ) ) {
|
||||
foreach ( $available_methods as $method_key => $method ) {
|
||||
if ( strpos( $method->id, $current_chosen_method ) === 0 ) {
|
||||
return $method->id;
|
||||
if ( ! empty( $current_chosen_method ) ) {
|
||||
if ( isset( $available_methods[ $current_chosen_method ] ) ) {
|
||||
return $available_methods[ $current_chosen_method ]->id;
|
||||
} else {
|
||||
foreach ( $available_methods as $method_key => $method ) {
|
||||
if ( strpos( $method->id, $current_chosen_method ) === 0 ) {
|
||||
return $method->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Order by priorities and costs
|
||||
$prioritized_methods = array();
|
||||
|
||||
foreach ( $available_methods as $method_key => $method ) {
|
||||
// Some IDs contain : if they have multiple rates so use $method->method_id
|
||||
$priority = isset( $selection_priority[ $method->method_id ] ) ? absint( $selection_priority[ $method->method_id ] ): 1;
|
||||
|
||||
if ( empty( $prioritized_methods[ $priority ] ) ) {
|
||||
$prioritized_methods[ $priority ] = array();
|
||||
}
|
||||
|
||||
$prioritized_methods[ $priority ][ $method_key ] = $method->cost;
|
||||
}
|
||||
|
||||
ksort( $prioritized_methods );
|
||||
$prioritized_methods = current( $prioritized_methods );
|
||||
asort( $prioritized_methods );
|
||||
|
||||
return current( array_keys( $prioritized_methods ) );
|
||||
return current( $available_methods )->id;
|
||||
}
|
||||
|
||||
return false;
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -269,11 +238,8 @@ class WC_Shipping {
|
|||
}
|
||||
|
||||
// Calculate costs for passed packages
|
||||
$package_keys = array_keys( $packages );
|
||||
$package_keys_size = sizeof( $package_keys );
|
||||
|
||||
for ( $i = 0; $i < $package_keys_size; $i ++ ) {
|
||||
$this->packages[ $package_keys[ $i ] ] = $this->calculate_shipping_for_package( $packages[ $package_keys[ $i ] ] );
|
||||
foreach ( $packages as $package_key => $package ) {
|
||||
$this->packages[ $package_key ] = $this->calculate_shipping_for_package( $package );
|
||||
}
|
||||
|
||||
// Get all chosen methods
|
||||
|
@ -290,25 +256,22 @@ class WC_Shipping {
|
|||
}
|
||||
|
||||
if ( ! empty( $method_counts[ $i ] ) ) {
|
||||
$method_count = $method_counts[ $i ];
|
||||
$method_count = absint( $method_counts[ $i ] );
|
||||
}
|
||||
|
||||
// Get available methods for package
|
||||
$available_methods = $package['rates'];
|
||||
|
||||
if ( sizeof( $available_methods ) > 0 ) {
|
||||
if ( sizeof( $package['rates'] ) > 0 ) {
|
||||
|
||||
// If not set, not available, or available methods have changed, set to the DEFAULT option
|
||||
if ( empty( $chosen_method ) || ! isset( $available_methods[ $chosen_method ] ) || $method_count != sizeof( $available_methods ) ) {
|
||||
$chosen_method = apply_filters( 'woocommerce_shipping_chosen_method', $this->get_default_method( $available_methods, $chosen_method ), $available_methods );
|
||||
if ( empty( $chosen_method ) || ! isset( $package['rates'][ $chosen_method ] ) || $method_count !== sizeof( $package['rates'] ) ) {
|
||||
$chosen_method = apply_filters( 'woocommerce_shipping_chosen_method', $this->get_default_method( $package['rates'], $chosen_method ), $package['rates'] );
|
||||
$chosen_methods[ $i ] = $chosen_method;
|
||||
$method_counts[ $i ] = sizeof( $available_methods );
|
||||
$method_counts[ $i ] = sizeof( $package['rates'] );
|
||||
do_action( 'woocommerce_shipping_method_chosen', $chosen_method );
|
||||
}
|
||||
|
||||
// Store total costs
|
||||
if ( $chosen_method ) {
|
||||
$rate = $available_methods[ $chosen_method ];
|
||||
$rate = $package['rates'][ $chosen_method ];
|
||||
|
||||
// Merge cost and taxes - label and ID will be the same
|
||||
$this->shipping_total += $rate->cost;
|
||||
|
@ -350,20 +313,9 @@ class WC_Shipping {
|
|||
$package['rates'] = array();
|
||||
|
||||
foreach ( $this->load_shipping_methods( $package ) as $shipping_method ) {
|
||||
if ( $shipping_method->is_available( $package ) && ( empty( $package['ship_via'] ) || in_array( $shipping_method->id, $package['ship_via'] ) ) ) {
|
||||
|
||||
// Reset Rates
|
||||
$shipping_method->rates = array();
|
||||
|
||||
// Calculate Shipping for package
|
||||
$shipping_method->calculate_shipping( $package );
|
||||
|
||||
// Place rates in package array
|
||||
if ( ! empty( $shipping_method->rates ) && is_array( $shipping_method->rates ) ) {
|
||||
foreach ( $shipping_method->rates as $rate ) {
|
||||
$package['rates'][ $rate->id ] = $rate;
|
||||
}
|
||||
}
|
||||
// Shipping instances need an ID
|
||||
if ( ! $shipping_method->supports( 'shipping-zones' ) || $shipping_method->get_instance_id() ) {
|
||||
$package['rates'] = $package['rates'] + $shipping_method->get_rates_for_package( $package ); // + instead of array_merge maintains numeric keys
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,7 +336,6 @@ class WC_Shipping {
|
|||
|
||||
/**
|
||||
* Get packages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_packages() {
|
||||
|
@ -404,39 +355,10 @@ class WC_Shipping {
|
|||
}
|
||||
|
||||
/**
|
||||
* Process admin options.
|
||||
*
|
||||
* Saves options on the shipping setting page.
|
||||
* @deprecated 2.6.0 Was previously used to determine sort order of methods, but this is now controlled by zones and thus unused.
|
||||
*/
|
||||
public function process_admin_options() {
|
||||
$method_order = isset( $_POST['method_order'] ) ? $_POST['method_order'] : '';
|
||||
$method_priority = isset( $_POST['method_priority'] ) ? $_POST['method_priority'] : '';
|
||||
$order = array();
|
||||
$selection_priority = array();
|
||||
|
||||
if ( is_array( $method_order ) && sizeof( $method_order ) > 0 ) {
|
||||
$loop = 0;
|
||||
foreach ( $method_order as $method_id ) {
|
||||
$order[ $method_id ] = $loop;
|
||||
$selection_priority[ $method_id ] = absint( $method_priority[ $method_id ] );
|
||||
$loop ++;
|
||||
}
|
||||
}
|
||||
|
||||
update_option( 'woocommerce_shipping_method_selection_priority', $selection_priority );
|
||||
update_option( 'woocommerce_shipping_method_order', $order );
|
||||
public function sort_shipping_methods() {
|
||||
_deprecated_function( 'sort_shipping_methods', '2.6', '' );
|
||||
return $this->shipping_methods;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a shipping method.
|
||||
*
|
||||
* Registers a shipping method ready to be loaded. Accepts a class name (string) or a class object.
|
||||
*
|
||||
* @package WooCommerce/Classes/Shipping
|
||||
* @since 1.5.7
|
||||
*/
|
||||
function woocommerce_register_shipping_method( $shipping_method ) {
|
||||
WC()->shipping->register_shipping_method( $shipping_method );
|
||||
}
|
||||
|
|
|
@ -7,55 +7,44 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* Flat Rate Shipping Method.
|
||||
*
|
||||
* @class WC_Shipping_Flat_Rate
|
||||
* @version 2.4.0
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce/Classes/Shipping
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Shipping_Flat_Rate extends WC_Shipping_Method {
|
||||
|
||||
/**
|
||||
* Cost passed to [fee] shortcode.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
/** @var string cost passed to [fee] shortcode */
|
||||
protected $fee_cost = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'flat_rate';
|
||||
$this->method_title = __( 'Flat Rate', 'woocommerce' );
|
||||
$this->method_description = __( 'Flat Rate Shipping lets you charge a fixed rate for shipping.', 'woocommerce' );
|
||||
public function __construct( $instance_id = 0 ) {
|
||||
$this->id = 'flat_rate';
|
||||
$this->instance_id = absint( $instance_id );
|
||||
$this->method_title = __( 'Flat Rate', 'woocommerce' );
|
||||
$this->method_description = __( 'Lets you charge a fixed rate for shipping.', 'woocommerce' );
|
||||
$this->supports = array(
|
||||
'shipping-zones',
|
||||
'instance-settings'
|
||||
);
|
||||
$this->init();
|
||||
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
add_action( 'woocommerce_flat_rate_shipping_add_rate', array( $this, 'calculate_extra_shipping' ), 10, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize flat rate shipping.
|
||||
* init user set variables.
|
||||
*/
|
||||
public function init() {
|
||||
// Load the settings.
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
// Define user set variables
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->availability = $this->get_option( 'availability' );
|
||||
$this->countries = $this->get_option( 'countries' );
|
||||
$this->tax_status = $this->get_option( 'tax_status' );
|
||||
$this->cost = $this->get_option( 'cost' );
|
||||
$this->type = $this->get_option( 'type', 'class' );
|
||||
$this->options = $this->get_option( 'options', false ); // @deprecated in 2.4.0
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Settings Form Fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->form_fields = include( 'includes/settings-flat-rate.php' );
|
||||
$this->instance_form_fields = include( 'includes/settings-flat-rate.php' );
|
||||
$this->enabled = $this->get_option( 'enabled' );
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->availability = $this->get_option( 'availability' );
|
||||
$this->countries = $this->get_option( 'countries' );
|
||||
$this->tax_status = $this->get_option( 'tax_status' );
|
||||
$this->cost = $this->get_option( 'cost' );
|
||||
$this->type = $this->get_option( 'type', 'class' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,7 +123,7 @@ class WC_Shipping_Flat_Rate extends WC_Shipping_Method {
|
|||
*/
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$rate = array(
|
||||
'id' => $this->id,
|
||||
'id' => $this->id . $this->instance_id,
|
||||
'label' => $this->title,
|
||||
'cost' => 0,
|
||||
);
|
||||
|
@ -246,112 +235,4 @@ class WC_Shipping_Flat_Rate extends WC_Shipping_Method {
|
|||
|
||||
return $found_shipping_classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds extra calculated flat rates.
|
||||
*
|
||||
* @deprecated 2.4.0
|
||||
*
|
||||
* Additonal rates defined like this:
|
||||
* Option Name | Additional Cost [+- Percents%] | Per Cost Type (order, class, or item).
|
||||
*/
|
||||
public function calculate_extra_shipping( $method, $rate, $package ) {
|
||||
if ( $this->options ) {
|
||||
$options = array_filter( (array) explode( "\n", $this->options ) );
|
||||
|
||||
foreach ( $options as $option ) {
|
||||
$this_option = array_map( 'trim', explode( WC_DELIMITER, $option ) );
|
||||
if ( sizeof( $this_option ) !== 3 ) {
|
||||
continue;
|
||||
}
|
||||
$extra_rate = $rate;
|
||||
$extra_rate['id'] = $this->id . ':' . urldecode( sanitize_title( $this_option[0] ) );
|
||||
$extra_rate['label'] = $this_option[0];
|
||||
$extra_cost = $this->get_extra_cost( $this_option[1], $this_option[2], $package );
|
||||
if ( is_array( $extra_rate['cost'] ) ) {
|
||||
$extra_rate['cost']['order'] = $extra_rate['cost']['order'] + $extra_cost;
|
||||
} else {
|
||||
$extra_rate['cost'] += $extra_cost;
|
||||
}
|
||||
$this->add_rate( $extra_rate );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the percentage adjustment for each shipping rate.
|
||||
*
|
||||
* @deprecated 2.4.0
|
||||
* @param float $cost
|
||||
* @param float $percent_adjustment
|
||||
* @param string $percent_operator
|
||||
* @param float $base_price
|
||||
* @return float
|
||||
*/
|
||||
public function calc_percentage_adjustment( $cost, $percent_adjustment, $percent_operator, $base_price ) {
|
||||
if ( '+' == $percent_operator ) {
|
||||
$cost += $percent_adjustment * $base_price;
|
||||
} else {
|
||||
$cost -= $percent_adjustment * $base_price;
|
||||
}
|
||||
return $cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extra cost.
|
||||
*
|
||||
* @deprecated 2.4.0
|
||||
* @param string $cost_string
|
||||
* @param string $type
|
||||
* @param array $package
|
||||
* @return float
|
||||
*/
|
||||
public function get_extra_cost( $cost_string, $type, $package ) {
|
||||
$cost = $cost_string;
|
||||
$cost_percent = false;
|
||||
$pattern =
|
||||
'/' . // start regex
|
||||
'(\d+\.?\d*)' . // capture digits, optionally capture a `.` and more digits
|
||||
'\s*' . // match whitespace
|
||||
'(\+|-)' . // capture the operand
|
||||
'\s*'. // match whitespace
|
||||
'(\d+\.?\d*)'. // capture digits, optionally capture a `.` and more digits
|
||||
'\%/'; // match the percent sign & end regex
|
||||
if ( preg_match( $pattern, $cost_string, $this_cost_matches ) ) {
|
||||
$cost_operator = $this_cost_matches[2];
|
||||
$cost_percent = $this_cost_matches[3] / 100;
|
||||
$cost = $this_cost_matches[1];
|
||||
}
|
||||
switch ( $type ) {
|
||||
case 'class' :
|
||||
$cost = $cost * sizeof( $this->find_shipping_classes( $package ) );
|
||||
break;
|
||||
case 'item' :
|
||||
$cost = $cost * $this->get_package_item_qty( $package );
|
||||
break;
|
||||
}
|
||||
if ( $cost_percent ) {
|
||||
switch ( $type ) {
|
||||
case 'class' :
|
||||
$shipping_classes = $this->find_shipping_classes( $package );
|
||||
foreach ( $shipping_classes as $shipping_class => $items ){
|
||||
foreach ( $items as $item_id => $values ) {
|
||||
$cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $values['line_total'] );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'item' :
|
||||
foreach ( $package['contents'] as $item_id => $values ) {
|
||||
if ( $values['data']->needs_shipping() ) {
|
||||
$cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $values['line_total'] );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'order' :
|
||||
$cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $package['contents_cost'] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $cost;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,365 +3,366 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class WC_Eval_Math. Supports basic math only (removed eval function).
|
||||
*
|
||||
* Based on EvalMath by Miles Kaufman Copyright (C) 2005 Miles Kaufmann http://www.twmagic.com/.
|
||||
*/
|
||||
class WC_Eval_Math {
|
||||
|
||||
if ( ! class_exists( 'WC_Eval_Math' ) ) {
|
||||
/**
|
||||
* Last error.
|
||||
* Class WC_Eval_Math. Supports basic math only (removed eval function).
|
||||
*
|
||||
* @var string
|
||||
* Based on EvalMath by Miles Kaufman Copyright (C) 2005 Miles Kaufmann http://www.twmagic.com/.
|
||||
*/
|
||||
public static $last_error = null;
|
||||
class WC_Eval_Math {
|
||||
|
||||
/**
|
||||
* Variables (and constants).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $v = array( 'e' => 2.71, 'pi' => 3.14 );
|
||||
/**
|
||||
* Last error.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $last_error = null;
|
||||
|
||||
/**
|
||||
* User-defined functions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $f = array();
|
||||
/**
|
||||
* Variables (and constants).
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $v = array( 'e' => 2.71, 'pi' => 3.14 );
|
||||
|
||||
/**
|
||||
* Constants.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $vb = array( 'e', 'pi' );
|
||||
/**
|
||||
* User-defined functions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $f = array();
|
||||
|
||||
/**
|
||||
* Built-in functions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $fb = array();
|
||||
/**
|
||||
* Constants.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $vb = array( 'e', 'pi' );
|
||||
|
||||
/**
|
||||
* Evaluate maths string.
|
||||
*
|
||||
* @param string $expr
|
||||
* @return mixed
|
||||
*/
|
||||
public static function evaluate( $expr ) {
|
||||
self::$last_error = null;
|
||||
$expr = trim( $expr );
|
||||
if ( substr( $expr, -1, 1 ) == ';' ) $expr = substr( $expr, 0, strlen( $expr )-1 ); // strip semicolons at the end
|
||||
//===============
|
||||
// is it a variable assignment?
|
||||
if ( preg_match( '/^\s*([a-z]\w*)\s*=\s*(.+)$/', $expr, $matches ) ) {
|
||||
if ( in_array( $matches[1], self::$vb ) ) { // make sure we're not assigning to a constant
|
||||
return self::trigger( "cannot assign to constant '$matches[1]'" );
|
||||
}
|
||||
if ( ( $tmp = self::pfx( self::nfx( $matches[2] ) ) ) === false ) return false; // get the result and make sure it's good
|
||||
self::$v[$matches[1]] = $tmp; // if so, stick it in the variable array
|
||||
return self::$v[$matches[1]]; // and return the resulting value
|
||||
/**
|
||||
* Built-in functions.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $fb = array();
|
||||
|
||||
/**
|
||||
* Evaluate maths string.
|
||||
*
|
||||
* @param string $expr
|
||||
* @return mixed
|
||||
*/
|
||||
public static function evaluate( $expr ) {
|
||||
self::$last_error = null;
|
||||
$expr = trim( $expr );
|
||||
if ( substr( $expr, -1, 1 ) == ';' ) $expr = substr( $expr, 0, strlen( $expr )-1 ); // strip semicolons at the end
|
||||
//===============
|
||||
// is it a function assignment?
|
||||
} elseif ( preg_match( '/^\s*([a-z]\w*)\s*\(\s*([a-z]\w*(?:\s*,\s*[a-z]\w*)*)\s*\)\s*=\s*(.+)$/', $expr, $matches ) ) {
|
||||
$fnn = $matches[1]; // get the function name
|
||||
if ( in_array( $matches[1], self::$fb ) ) { // make sure it isn't built in
|
||||
return self::trigger( "cannot redefine built-in function '$matches[1]()'" );
|
||||
}
|
||||
$args = explode( ",", preg_replace( "/\s+/", "", $matches[2] ) ); // get the arguments
|
||||
if ( ( $stack = self::nfx( $matches[3] ) ) === false ) return false; // see if it can be converted to postfix
|
||||
for ( $i = 0; $i<count( $stack ); $i++ ) { // freeze the state of the non-argument variables
|
||||
$token = $stack[$i];
|
||||
if ( preg_match( '/^[a-z]\w*$/', $token ) and !in_array( $token, $args ) ) {
|
||||
if ( array_key_exists( $token, self::$v ) ) {
|
||||
$stack[$i] = self::$v[$token];
|
||||
} else {
|
||||
return self::trigger( "undefined variable '$token' in function definition" );
|
||||
// is it a variable assignment?
|
||||
if ( preg_match( '/^\s*([a-z]\w*)\s*=\s*(.+)$/', $expr, $matches ) ) {
|
||||
if ( in_array( $matches[1], self::$vb ) ) { // make sure we're not assigning to a constant
|
||||
return self::trigger( "cannot assign to constant '$matches[1]'" );
|
||||
}
|
||||
if ( ( $tmp = self::pfx( self::nfx( $matches[2] ) ) ) === false ) return false; // get the result and make sure it's good
|
||||
self::$v[$matches[1]] = $tmp; // if so, stick it in the variable array
|
||||
return self::$v[$matches[1]]; // and return the resulting value
|
||||
//===============
|
||||
// is it a function assignment?
|
||||
} elseif ( preg_match( '/^\s*([a-z]\w*)\s*\(\s*([a-z]\w*(?:\s*,\s*[a-z]\w*)*)\s*\)\s*=\s*(.+)$/', $expr, $matches ) ) {
|
||||
$fnn = $matches[1]; // get the function name
|
||||
if ( in_array( $matches[1], self::$fb ) ) { // make sure it isn't built in
|
||||
return self::trigger( "cannot redefine built-in function '$matches[1]()'" );
|
||||
}
|
||||
$args = explode( ",", preg_replace( "/\s+/", "", $matches[2] ) ); // get the arguments
|
||||
if ( ( $stack = self::nfx( $matches[3] ) ) === false ) return false; // see if it can be converted to postfix
|
||||
for ( $i = 0; $i<count( $stack ); $i++ ) { // freeze the state of the non-argument variables
|
||||
$token = $stack[$i];
|
||||
if ( preg_match( '/^[a-z]\w*$/', $token ) and !in_array( $token, $args ) ) {
|
||||
if ( array_key_exists( $token, self::$v ) ) {
|
||||
$stack[$i] = self::$v[$token];
|
||||
} else {
|
||||
return self::trigger( "undefined variable '$token' in function definition" );
|
||||
}
|
||||
}
|
||||
}
|
||||
self::$f[$fnn] = array( 'args'=>$args, 'func'=>$stack );
|
||||
return true;
|
||||
//===============
|
||||
} else {
|
||||
return self::pfx( self::nfx( $expr ) ); // straight up evaluation, woo
|
||||
}
|
||||
self::$f[$fnn] = array( 'args'=>$args, 'func'=>$stack );
|
||||
return true;
|
||||
//===============
|
||||
} else {
|
||||
return self::pfx( self::nfx( $expr ) ); // straight up evaluation, woo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert infix to postfix notation.
|
||||
*
|
||||
* @param string $expr
|
||||
* @return string
|
||||
*/
|
||||
private static function nfx( $expr ) {
|
||||
|
||||
$index = 0;
|
||||
$stack = new WC_Eval_Math_Stack;
|
||||
$output = array(); // postfix form of expression, to be passed to pfx()
|
||||
// $expr = trim(strtolower($expr));
|
||||
$expr = trim( $expr );
|
||||
|
||||
$ops = array( '+', '-', '*', '/', '^', '_' );
|
||||
$ops_r = array( '+'=>0, '-'=>0, '*'=>0, '/'=>0, '^'=>1 ); // right-associative operator?
|
||||
$ops_p = array( '+'=>0, '-'=>0, '*'=>1, '/'=>1, '_'=>1, '^'=>2 ); // operator precedence
|
||||
|
||||
$expecting_op = false; // we use this in syntax-checking the expression
|
||||
// and determining when a - is a negation
|
||||
|
||||
if ( preg_match( "/[^\w\s+*^\/()\.,-]/", $expr, $matches ) ) { // make sure the characters are all good
|
||||
return self::trigger( "illegal character '{$matches[0]}'" );
|
||||
}
|
||||
|
||||
while ( 1 ) { // 1 Infinite Loop ;)
|
||||
$op = substr( $expr, $index, 1 ); // get the first character at the current index
|
||||
// find out if we're currently at the beginning of a number/variable/function/parenthesis/operand
|
||||
$ex = preg_match( '/^([A-Za-z]\w*\(?|\d+(?:\.\d*)?|\.\d+|\()/', substr( $expr, $index ), $match );
|
||||
//===============
|
||||
if ( $op == '-' and !$expecting_op ) { // is it a negation instead of a minus?
|
||||
$stack->push( '_' ); // put a negation on the stack
|
||||
$index++;
|
||||
} elseif ( $op == '_' ) { // we have to explicitly deny this, because it's legal on the stack
|
||||
return self::trigger( "illegal character '_'" ); // but not in the input expression
|
||||
/**
|
||||
* Convert infix to postfix notation.
|
||||
*
|
||||
* @param string $expr
|
||||
* @return string
|
||||
*/
|
||||
private static function nfx( $expr ) {
|
||||
|
||||
$index = 0;
|
||||
$stack = new WC_Eval_Math_Stack;
|
||||
$output = array(); // postfix form of expression, to be passed to pfx()
|
||||
// $expr = trim(strtolower($expr));
|
||||
$expr = trim( $expr );
|
||||
|
||||
$ops = array( '+', '-', '*', '/', '^', '_' );
|
||||
$ops_r = array( '+'=>0, '-'=>0, '*'=>0, '/'=>0, '^'=>1 ); // right-associative operator?
|
||||
$ops_p = array( '+'=>0, '-'=>0, '*'=>1, '/'=>1, '_'=>1, '^'=>2 ); // operator precedence
|
||||
|
||||
$expecting_op = false; // we use this in syntax-checking the expression
|
||||
// and determining when a - is a negation
|
||||
|
||||
if ( preg_match( "/[^\w\s+*^\/()\.,-]/", $expr, $matches ) ) { // make sure the characters are all good
|
||||
return self::trigger( "illegal character '{$matches[0]}'" );
|
||||
}
|
||||
|
||||
while ( 1 ) { // 1 Infinite Loop ;)
|
||||
$op = substr( $expr, $index, 1 ); // get the first character at the current index
|
||||
// find out if we're currently at the beginning of a number/variable/function/parenthesis/operand
|
||||
$ex = preg_match( '/^([A-Za-z]\w*\(?|\d+(?:\.\d*)?|\.\d+|\()/', substr( $expr, $index ), $match );
|
||||
//===============
|
||||
} elseif ( ( in_array( $op, $ops ) or $ex ) and $expecting_op ) { // are we putting an operator on the stack?
|
||||
if ( $ex ) { // are we expecting an operator but have a number/variable/function/opening parethesis?
|
||||
$op = '*'; $index--; // it's an implicit multiplication
|
||||
}
|
||||
// heart of the algorithm:
|
||||
while ( $stack->count > 0 and ( $o2 = $stack->last() ) and in_array( $o2, $ops ) and ( $ops_r[$op] ? $ops_p[$op] < $ops_p[$o2] : $ops_p[$op] <= $ops_p[$o2] ) ) {
|
||||
$output[] = $stack->pop(); // pop stuff off the stack into the output
|
||||
}
|
||||
// many thanks: http://en.wikipedia.org/wiki/Reverse_Polish_notation#The_algorithm_in_detail
|
||||
$stack->push( $op ); // finally put OUR operator onto the stack
|
||||
$index++;
|
||||
$expecting_op = false;
|
||||
//===============
|
||||
} elseif ( $op == ')' and $expecting_op ) { // ready to close a parenthesis?
|
||||
while ( ( $o2 = $stack->pop() ) != '(' ) { // pop off the stack back to the last (
|
||||
if ( is_null( $o2 ) ) return self::trigger( "unexpected ')'" );
|
||||
else $output[] = $o2;
|
||||
}
|
||||
if ( preg_match( "/^([A-Za-z]\w*)\($/", $stack->last( 2 ), $matches ) ) { // did we just close a function?
|
||||
$fnn = $matches[1]; // get the function name
|
||||
$arg_count = $stack->pop(); // see how many arguments there were (cleverly stored on the stack, thank you)
|
||||
$output[] = $stack->pop(); // pop the function and push onto the output
|
||||
if ( in_array( $fnn, self::$fb ) ) { // check the argument count
|
||||
if ( $arg_count > 1 )
|
||||
return self::trigger( "too many arguments ($arg_count given, 1 expected)" );
|
||||
} elseif ( array_key_exists( $fnn, self::$f ) ) {
|
||||
if ( $arg_count != count( self::$f[$fnn]['args'] ) )
|
||||
return self::trigger( "wrong number of arguments ($arg_count given, " . count( self::$f[$fnn]['args'] ) . " expected)" );
|
||||
} else { // did we somehow push a non-function on the stack? this should never happen
|
||||
return self::trigger( "internal error" );
|
||||
if ( $op == '-' and !$expecting_op ) { // is it a negation instead of a minus?
|
||||
$stack->push( '_' ); // put a negation on the stack
|
||||
$index++;
|
||||
} elseif ( $op == '_' ) { // we have to explicitly deny this, because it's legal on the stack
|
||||
return self::trigger( "illegal character '_'" ); // but not in the input expression
|
||||
//===============
|
||||
} elseif ( ( in_array( $op, $ops ) or $ex ) and $expecting_op ) { // are we putting an operator on the stack?
|
||||
if ( $ex ) { // are we expecting an operator but have a number/variable/function/opening parethesis?
|
||||
$op = '*'; $index--; // it's an implicit multiplication
|
||||
}
|
||||
}
|
||||
$index++;
|
||||
//===============
|
||||
} elseif ( $op == ',' and $expecting_op ) { // did we just finish a function argument?
|
||||
while ( ( $o2 = $stack->pop() ) != '(' ) {
|
||||
if ( is_null( $o2 ) ) return self::trigger( "unexpected ','" ); // oops, never had a (
|
||||
else $output[] = $o2; // pop the argument expression stuff and push onto the output
|
||||
}
|
||||
// make sure there was a function
|
||||
if ( !preg_match( "/^([A-Za-z]\w*)\($/", $stack->last( 2 ), $matches ) )
|
||||
return self::trigger( "unexpected ','" );
|
||||
$stack->push( $stack->pop()+1 ); // increment the argument count
|
||||
$stack->push( '(' ); // put the ( back on, we'll need to pop back to it again
|
||||
$index++;
|
||||
$expecting_op = false;
|
||||
//===============
|
||||
} elseif ( $op == '(' and !$expecting_op ) {
|
||||
$stack->push( '(' ); // that was easy
|
||||
$index++;
|
||||
//===============
|
||||
} elseif ( $ex and !$expecting_op ) { // do we now have a function/variable/number?
|
||||
$expecting_op = true;
|
||||
$val = $match[1];
|
||||
if ( preg_match( "/^([A-Za-z]\w*)\($/", $val, $matches ) ) { // may be func, or variable w/ implicit multiplication against parentheses...
|
||||
if ( in_array( $matches[1], self::$fb ) or array_key_exists( $matches[1], self::$f ) ) { // it's a func
|
||||
$stack->push( $val );
|
||||
$stack->push( 1 );
|
||||
$stack->push( '(' );
|
||||
$expecting_op = false;
|
||||
} else { // it's a var w/ implicit multiplication
|
||||
$val = $matches[1];
|
||||
// heart of the algorithm:
|
||||
while ( $stack->count > 0 and ( $o2 = $stack->last() ) and in_array( $o2, $ops ) and ( $ops_r[$op] ? $ops_p[$op] < $ops_p[$o2] : $ops_p[$op] <= $ops_p[$o2] ) ) {
|
||||
$output[] = $stack->pop(); // pop stuff off the stack into the output
|
||||
}
|
||||
// many thanks: http://en.wikipedia.org/wiki/Reverse_Polish_notation#The_algorithm_in_detail
|
||||
$stack->push( $op ); // finally put OUR operator onto the stack
|
||||
$index++;
|
||||
$expecting_op = false;
|
||||
//===============
|
||||
} elseif ( $op == ')' and $expecting_op ) { // ready to close a parenthesis?
|
||||
while ( ( $o2 = $stack->pop() ) != '(' ) { // pop off the stack back to the last (
|
||||
if ( is_null( $o2 ) ) return self::trigger( "unexpected ')'" );
|
||||
else $output[] = $o2;
|
||||
}
|
||||
if ( preg_match( "/^([A-Za-z]\w*)\($/", $stack->last( 2 ), $matches ) ) { // did we just close a function?
|
||||
$fnn = $matches[1]; // get the function name
|
||||
$arg_count = $stack->pop(); // see how many arguments there were (cleverly stored on the stack, thank you)
|
||||
$output[] = $stack->pop(); // pop the function and push onto the output
|
||||
if ( in_array( $fnn, self::$fb ) ) { // check the argument count
|
||||
if ( $arg_count > 1 )
|
||||
return self::trigger( "too many arguments ($arg_count given, 1 expected)" );
|
||||
} elseif ( array_key_exists( $fnn, self::$f ) ) {
|
||||
if ( $arg_count != count( self::$f[$fnn]['args'] ) )
|
||||
return self::trigger( "wrong number of arguments ($arg_count given, " . count( self::$f[$fnn]['args'] ) . " expected)" );
|
||||
} else { // did we somehow push a non-function on the stack? this should never happen
|
||||
return self::trigger( "internal error" );
|
||||
}
|
||||
}
|
||||
$index++;
|
||||
//===============
|
||||
} elseif ( $op == ',' and $expecting_op ) { // did we just finish a function argument?
|
||||
while ( ( $o2 = $stack->pop() ) != '(' ) {
|
||||
if ( is_null( $o2 ) ) return self::trigger( "unexpected ','" ); // oops, never had a (
|
||||
else $output[] = $o2; // pop the argument expression stuff and push onto the output
|
||||
}
|
||||
// make sure there was a function
|
||||
if ( !preg_match( "/^([A-Za-z]\w*)\($/", $stack->last( 2 ), $matches ) )
|
||||
return self::trigger( "unexpected ','" );
|
||||
$stack->push( $stack->pop()+1 ); // increment the argument count
|
||||
$stack->push( '(' ); // put the ( back on, we'll need to pop back to it again
|
||||
$index++;
|
||||
$expecting_op = false;
|
||||
//===============
|
||||
} elseif ( $op == '(' and !$expecting_op ) {
|
||||
$stack->push( '(' ); // that was easy
|
||||
$index++;
|
||||
//===============
|
||||
} elseif ( $ex and !$expecting_op ) { // do we now have a function/variable/number?
|
||||
$expecting_op = true;
|
||||
$val = $match[1];
|
||||
if ( preg_match( "/^([A-Za-z]\w*)\($/", $val, $matches ) ) { // may be func, or variable w/ implicit multiplication against parentheses...
|
||||
if ( in_array( $matches[1], self::$fb ) or array_key_exists( $matches[1], self::$f ) ) { // it's a func
|
||||
$stack->push( $val );
|
||||
$stack->push( 1 );
|
||||
$stack->push( '(' );
|
||||
$expecting_op = false;
|
||||
} else { // it's a var w/ implicit multiplication
|
||||
$val = $matches[1];
|
||||
$output[] = $val;
|
||||
}
|
||||
} else { // it's a plain old var or num
|
||||
$output[] = $val;
|
||||
}
|
||||
} else { // it's a plain old var or num
|
||||
$output[] = $val;
|
||||
$index += strlen( $val );
|
||||
//===============
|
||||
} elseif ( $op == ')' ) { // miscellaneous error checking
|
||||
return self::trigger( "unexpected ')'" );
|
||||
} elseif ( in_array( $op, $ops ) and !$expecting_op ) {
|
||||
return self::trigger( "unexpected operator '$op'" );
|
||||
} else { // I don't even want to know what you did to get here
|
||||
return self::trigger( "an unexpected error occured" );
|
||||
}
|
||||
$index += strlen( $val );
|
||||
//===============
|
||||
} elseif ( $op == ')' ) { // miscellaneous error checking
|
||||
return self::trigger( "unexpected ')'" );
|
||||
} elseif ( in_array( $op, $ops ) and !$expecting_op ) {
|
||||
return self::trigger( "unexpected operator '$op'" );
|
||||
} else { // I don't even want to know what you did to get here
|
||||
return self::trigger( "an unexpected error occured" );
|
||||
}
|
||||
if ( $index == strlen( $expr ) ) {
|
||||
if ( in_array( $op, $ops ) ) { // did we end with an operator? bad.
|
||||
return self::trigger( "operator '$op' lacks operand" );
|
||||
} else {
|
||||
break;
|
||||
if ( $index == strlen( $expr ) ) {
|
||||
if ( in_array( $op, $ops ) ) { // did we end with an operator? bad.
|
||||
return self::trigger( "operator '$op' lacks operand" );
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while ( substr( $expr, $index, 1 ) == ' ' ) { // step the index past whitespace (pretty much turns whitespace
|
||||
$index++; // into implicit multiplication if no operator is there)
|
||||
}
|
||||
}
|
||||
while ( substr( $expr, $index, 1 ) == ' ' ) { // step the index past whitespace (pretty much turns whitespace
|
||||
$index++; // into implicit multiplication if no operator is there)
|
||||
}
|
||||
|
||||
}
|
||||
while ( !is_null( $op = $stack->pop() ) ) { // pop everything off the stack and push onto output
|
||||
if ( $op == '(' ) return self::trigger( "expecting ')'" ); // if there are (s on the stack, ()s were unbalanced
|
||||
$output[] = $op;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
while ( !is_null( $op = $stack->pop() ) ) { // pop everything off the stack and push onto output
|
||||
if ( $op == '(' ) return self::trigger( "expecting ')'" ); // if there are (s on the stack, ()s were unbalanced
|
||||
$output[] = $op;
|
||||
|
||||
/**
|
||||
* Evaluate postfix notation.
|
||||
*
|
||||
* @param mixed $tokens
|
||||
* @param array $vars
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private static function pfx( $tokens, $vars = array() ) {
|
||||
if ( $tokens == false ) return false;
|
||||
$stack = new WC_Eval_Math_Stack;
|
||||
|
||||
foreach ( $tokens as $token ) { // nice and easy
|
||||
// if the token is a binary operator, pop two values off the stack, do the operation, and push the result back on
|
||||
if ( in_array( $token, array( '+', '-', '*', '/', '^' ) ) ) {
|
||||
if ( is_null( $op2 = $stack->pop() ) ) return self::trigger( "internal error" );
|
||||
if ( is_null( $op1 = $stack->pop() ) ) return self::trigger( "internal error" );
|
||||
switch ( $token ) {
|
||||
case '+':
|
||||
$stack->push( $op1+$op2 ); break;
|
||||
case '-':
|
||||
$stack->push( $op1-$op2 ); break;
|
||||
case '*':
|
||||
$stack->push( $op1*$op2 ); break;
|
||||
case '/':
|
||||
if ( $op2 == 0 ) return self::trigger( "division by zero" );
|
||||
$stack->push( $op1/$op2 ); break;
|
||||
case '^':
|
||||
$stack->push( pow( $op1, $op2 ) ); break;
|
||||
}
|
||||
// if the token is a unary operator, pop one value off the stack, do the operation, and push it back on
|
||||
} elseif ( $token == "_" ) {
|
||||
$stack->push( -1*$stack->pop() );
|
||||
// if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on
|
||||
} elseif ( ! preg_match( "/^([a-z]\w*)\($/", $token, $matches ) ) {
|
||||
if ( is_numeric( $token ) ) {
|
||||
$stack->push( $token );
|
||||
} elseif ( array_key_exists( $token, self::$v ) ) {
|
||||
$stack->push( self::$v[$token] );
|
||||
} elseif ( array_key_exists( $token, $vars ) ) {
|
||||
$stack->push( $vars[$token] );
|
||||
} else {
|
||||
return self::trigger( "undefined variable '$token'" );
|
||||
}
|
||||
}
|
||||
}
|
||||
// when we're out of tokens, the stack should have a single element, the final result
|
||||
if ( $stack->count != 1 ) return self::trigger( "internal error" );
|
||||
return $stack->pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger an error, but nicely, if need be.
|
||||
*
|
||||
* @param string $msg
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function trigger( $msg ) {
|
||||
self::$last_error = $msg;
|
||||
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
||||
echo "\nError found in:";
|
||||
self::debugPrintCallingFunction();
|
||||
trigger_error( $msg, E_USER_WARNING );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the file name, function name, and
|
||||
* line number which called your function
|
||||
* (not this function, then one that called
|
||||
* it to begin with)
|
||||
*/
|
||||
private static function debugPrintCallingFunction() {
|
||||
$file = 'n/a';
|
||||
$func = 'n/a';
|
||||
$line = 'n/a';
|
||||
$debugTrace = debug_backtrace();
|
||||
if ( isset( $debugTrace[1] ) ) {
|
||||
$file = $debugTrace[1]['file'] ? $debugTrace[1]['file'] : 'n/a';
|
||||
$line = $debugTrace[1]['line'] ? $debugTrace[1]['line'] : 'n/a';
|
||||
}
|
||||
if ( isset( $debugTrace[2] ) ) $func = $debugTrace[2]['function'] ? $debugTrace[2]['function'] : 'n/a';
|
||||
echo "\n$file, $func, $line\n";
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate postfix notation.
|
||||
*
|
||||
* @param mixed $tokens
|
||||
* @param array $vars
|
||||
*
|
||||
* @return mixed
|
||||
* Class WC_Eval_Math_Stack.
|
||||
*/
|
||||
private static function pfx( $tokens, $vars = array() ) {
|
||||
if ( $tokens == false ) return false;
|
||||
class WC_Eval_Math_Stack {
|
||||
|
||||
$stack = new WC_Eval_Math_Stack;
|
||||
/**
|
||||
* Stack array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $stack = array();
|
||||
|
||||
foreach ( $tokens as $token ) { // nice and easy
|
||||
// if the token is a binary operator, pop two values off the stack, do the operation, and push the result back on
|
||||
if ( in_array( $token, array( '+', '-', '*', '/', '^' ) ) ) {
|
||||
if ( is_null( $op2 = $stack->pop() ) ) return self::trigger( "internal error" );
|
||||
if ( is_null( $op1 = $stack->pop() ) ) return self::trigger( "internal error" );
|
||||
switch ( $token ) {
|
||||
case '+':
|
||||
$stack->push( $op1+$op2 ); break;
|
||||
case '-':
|
||||
$stack->push( $op1-$op2 ); break;
|
||||
case '*':
|
||||
$stack->push( $op1*$op2 ); break;
|
||||
case '/':
|
||||
if ( $op2 == 0 ) return self::trigger( "division by zero" );
|
||||
$stack->push( $op1/$op2 ); break;
|
||||
case '^':
|
||||
$stack->push( pow( $op1, $op2 ) ); break;
|
||||
}
|
||||
// if the token is a unary operator, pop one value off the stack, do the operation, and push it back on
|
||||
} elseif ( $token == "_" ) {
|
||||
$stack->push( -1*$stack->pop() );
|
||||
// if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on
|
||||
} elseif ( ! preg_match( "/^([a-z]\w*)\($/", $token, $matches ) ) {
|
||||
if ( is_numeric( $token ) ) {
|
||||
$stack->push( $token );
|
||||
} elseif ( array_key_exists( $token, self::$v ) ) {
|
||||
$stack->push( self::$v[$token] );
|
||||
} elseif ( array_key_exists( $token, $vars ) ) {
|
||||
$stack->push( $vars[$token] );
|
||||
} else {
|
||||
return self::trigger( "undefined variable '$token'" );
|
||||
}
|
||||
/**
|
||||
* Stack counter.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $count = 0;
|
||||
|
||||
/**
|
||||
* Push value into stack.
|
||||
*
|
||||
* @param mixed $val
|
||||
*/
|
||||
public function push( $val ) {
|
||||
$this->stack[ $this->count ] = $val;
|
||||
$this->count++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop value from stack.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function pop() {
|
||||
if ( $this->count > 0 ) {
|
||||
$this->count--;
|
||||
return $this->stack[ $this->count ];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// when we're out of tokens, the stack should have a single element, the final result
|
||||
if ( $stack->count != 1 ) return self::trigger( "internal error" );
|
||||
return $stack->pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger an error, but nicely, if need be.
|
||||
*
|
||||
* @param string $msg
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function trigger( $msg ) {
|
||||
self::$last_error = $msg;
|
||||
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
||||
echo "\nError found in:";
|
||||
self::debugPrintCallingFunction();
|
||||
trigger_error( $msg, E_USER_WARNING );
|
||||
/**
|
||||
* Get last value from stack.
|
||||
*
|
||||
* @param int $n
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function last( $n=1 ) {
|
||||
$key = $this->count - $n;
|
||||
return array_key_exists( $key, $this->stack ) ? $this->stack[ $key ] : null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the file name, function name, and
|
||||
* line number which called your function
|
||||
* (not this function, then one that called
|
||||
* it to begin with)
|
||||
*/
|
||||
private static function debugPrintCallingFunction() {
|
||||
$file = 'n/a';
|
||||
$func = 'n/a';
|
||||
$line = 'n/a';
|
||||
$debugTrace = debug_backtrace();
|
||||
if ( isset( $debugTrace[1] ) ) {
|
||||
$file = $debugTrace[1]['file'] ? $debugTrace[1]['file'] : 'n/a';
|
||||
$line = $debugTrace[1]['line'] ? $debugTrace[1]['line'] : 'n/a';
|
||||
}
|
||||
if ( isset( $debugTrace[2] ) ) $func = $debugTrace[2]['function'] ? $debugTrace[2]['function'] : 'n/a';
|
||||
echo "\n$file, $func, $line\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class WC_Eval_Math_Stack.
|
||||
*/
|
||||
class WC_Eval_Math_Stack {
|
||||
|
||||
/**
|
||||
* Stack array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $stack = array();
|
||||
|
||||
/**
|
||||
* Stack counter.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $count = 0;
|
||||
|
||||
/**
|
||||
* Push value into stack.
|
||||
*
|
||||
* @param mixed $val
|
||||
*/
|
||||
public function push( $val ) {
|
||||
$this->stack[ $this->count ] = $val;
|
||||
$this->count++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop value from stack.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function pop() {
|
||||
if ( $this->count > 0 ) {
|
||||
$this->count--;
|
||||
return $this->stack[ $this->count ];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last value from stack.
|
||||
*
|
||||
* @param int $n
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function last( $n = 1 ) {
|
||||
$key = $this->count - $n;
|
||||
return array_key_exists( $key, $this->stack ) ? $this->stack[ $key ] : null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ $settings = array(
|
|||
'title' => __( 'Enable/Disable', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Enable this shipping method', 'woocommerce' ),
|
||||
'default' => 'no',
|
||||
'default' => 'yes',
|
||||
),
|
||||
'title' => array(
|
||||
'title' => __( 'Method Title', 'woocommerce' ),
|
||||
|
@ -23,27 +23,6 @@ $settings = array(
|
|||
'default' => __( 'Flat Rate', 'woocommerce' ),
|
||||
'desc_tip' => true
|
||||
),
|
||||
'availability' => array(
|
||||
'title' => __( 'Availability', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'default' => 'all',
|
||||
'class' => 'availability wc-enhanced-select',
|
||||
'options' => array(
|
||||
'all' => __( 'All allowed countries', 'woocommerce' ),
|
||||
'specific' => __( 'Specific Countries', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'countries' => array(
|
||||
'title' => __( 'Specific Countries', 'woocommerce' ),
|
||||
'type' => 'multiselect',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'css' => 'width: 450px;',
|
||||
'default' => '',
|
||||
'options' => WC()->countries->get_shipping_countries(),
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some countries', 'woocommerce' )
|
||||
)
|
||||
),
|
||||
'tax_status' => array(
|
||||
'title' => __( 'Tax Status', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
|
@ -68,9 +47,10 @@ $shipping_classes = WC()->shipping->get_shipping_classes();
|
|||
|
||||
if ( ! empty( $shipping_classes ) ) {
|
||||
$settings[ 'class_costs' ] = array(
|
||||
'title' => __( 'Shipping Class Costs', 'woocommerce' ),
|
||||
'type' => 'title',
|
||||
'description' => sprintf( __( 'These costs can optionally be added based on the %sproduct shipping class%s.', 'woocommerce' ), '<a href="' . admin_url( 'edit-tags.php?taxonomy=product_shipping_class&post_type=product' ) . '">', '</a>' )
|
||||
'title' => __( 'Shipping Class Costs', 'woocommerce' ),
|
||||
'type' => 'title',
|
||||
'default' => '',
|
||||
'description' => sprintf( __( 'These costs can optionally be added based on the %sproduct shipping class%s.', 'woocommerce' ), '<a href="' . admin_url( 'edit-tags.php?taxonomy=product_shipping_class&post_type=product' ) . '">', '</a>' )
|
||||
);
|
||||
foreach ( $shipping_classes as $shipping_class ) {
|
||||
if ( ! isset( $shipping_class->term_id ) ) {
|
||||
|
@ -105,20 +85,4 @@ if ( ! empty( $shipping_classes ) ) {
|
|||
);
|
||||
}
|
||||
|
||||
if ( apply_filters( 'woocommerce_enable_deprecated_additional_flat_rates', $this->get_option( 'options', false ) ) ) {
|
||||
$settings[ 'additional_rates' ] = array(
|
||||
'title' => __( 'Additional Rates', 'woocommerce' ),
|
||||
'type' => 'title',
|
||||
'description' => __( 'These rates are extra shipping options with additional costs (based on the flat rate).', 'woocommerce' ),
|
||||
);
|
||||
$settings['options'] = array(
|
||||
'title' => __( 'Additional Rates', 'woocommerce' ),
|
||||
'type' => 'textarea',
|
||||
'description' => __( 'One per line: Option Name | Additional Cost [+- Percents] | Per Cost Type (order, class, or item) Example: <code>Priority Mail | 6.95 [+ 0.2%] | order</code>.', 'woocommerce' ),
|
||||
'default' => '',
|
||||
'desc_tip' => true,
|
||||
'placeholder' => __( 'Option Name | Additional Cost [+- Percents%] | Per Cost Type (order, class, or item)', 'woocommerce' )
|
||||
);
|
||||
}
|
||||
|
||||
return $settings;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,95 +9,57 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* A simple shipping method for free shipping.
|
||||
*
|
||||
* @class WC_Shipping_Free_Shipping
|
||||
* @version 2.4.0
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce/Classes/Shipping
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Shipping_Free_Shipping extends WC_Shipping_Method {
|
||||
|
||||
/**
|
||||
* Min amount to be valid.
|
||||
*
|
||||
* @var float
|
||||
*/
|
||||
public $min_amount;
|
||||
/** @var float Min amount to be valid */
|
||||
public $min_amount = 0;
|
||||
|
||||
/**
|
||||
* Requires option.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $requires;
|
||||
/** @var string Requires option */
|
||||
public $requires = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'free_shipping';
|
||||
$this->method_title = __( 'Free Shipping', 'woocommerce' );
|
||||
$this->init();
|
||||
}
|
||||
public function __construct( $instance_id = 0 ) {
|
||||
$this->id = 'free_shipping';
|
||||
$this->instance_id = absint( $instance_id );
|
||||
$this->method_title = __( 'Free Shipping', 'woocommerce' );
|
||||
$this->method_description = __( 'Free Shipping is a special method which can be triggered with coupons and minimum spends.', 'woocommerce' );
|
||||
$this->supports = array(
|
||||
'shipping-zones',
|
||||
'instance-settings'
|
||||
);
|
||||
$this->enabled = $this->get_option( 'enabled' );
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->min_amount = $this->get_option( 'min_amount', 0 );
|
||||
$this->requires = $this->get_option( 'requires' );
|
||||
|
||||
/**
|
||||
* Initialize free shipping.
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Load the settings.
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
// Define user set variables
|
||||
$this->enabled = $this->get_option( 'enabled' );
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->min_amount = $this->get_option( 'min_amount', 0 );
|
||||
$this->availability = $this->get_option( 'availability' );
|
||||
$this->countries = $this->get_option( 'countries' );
|
||||
$this->requires = $this->get_option( 'requires' );
|
||||
|
||||
// Actions
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Gateway Settings Form Fields.
|
||||
* Get setting form fields for instances of this shipping method within zones.
|
||||
* @return array
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->form_fields = array(
|
||||
public function get_instance_form_fields() {
|
||||
return array(
|
||||
'enabled' => array(
|
||||
'title' => __( 'Enable/Disable', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Enable Free Shipping', 'woocommerce' ),
|
||||
'default' => 'no'
|
||||
'default' => 'yes'
|
||||
),
|
||||
'title' => array(
|
||||
'title' => __( 'Method Title', 'woocommerce' ),
|
||||
'title' => __( 'Title', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => __( 'Free Shipping', 'woocommerce' ),
|
||||
'default' => $this->method_title,
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'availability' => array(
|
||||
'title' => __( 'Method availability', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'default' => 'all',
|
||||
'class' => 'availability wc-enhanced-select',
|
||||
'options' => array(
|
||||
'all' => __( 'All allowed countries', 'woocommerce' ),
|
||||
'specific' => __( 'Specific Countries', 'woocommerce' )
|
||||
)
|
||||
),
|
||||
'countries' => array(
|
||||
'title' => __( 'Specific Countries', 'woocommerce' ),
|
||||
'type' => 'multiselect',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'css' => 'width: 450px;',
|
||||
'default' => '',
|
||||
'options' => WC()->countries->get_shipping_countries(),
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some countries', 'woocommerce' )
|
||||
)
|
||||
),
|
||||
'requires' => array(
|
||||
'title' => __( 'Free Shipping Requires...', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
|
@ -136,37 +97,21 @@ class WC_Shipping_Free_Shipping extends WC_Shipping_Method {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if free shipping is available.
|
||||
*
|
||||
* See if free shipping is available based on the package and cart.
|
||||
* @param array $package
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available( $package ) {
|
||||
if ( 'no' == $this->enabled ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( 'specific' == $this->availability ) {
|
||||
$ship_to_countries = $this->countries;
|
||||
} else {
|
||||
$ship_to_countries = array_keys( WC()->countries->get_shipping_countries() );
|
||||
}
|
||||
|
||||
if ( is_array( $ship_to_countries ) && ! in_array( $package['destination']['country'], $ship_to_countries ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enabled logic
|
||||
$is_available = false;
|
||||
$has_coupon = false;
|
||||
$has_met_min_amount = false;
|
||||
|
||||
if ( in_array( $this->requires, array( 'coupon', 'either', 'both' ) ) ) {
|
||||
|
||||
if ( $coupons = WC()->cart->get_coupons() ) {
|
||||
foreach ( $coupons as $code => $coupon ) {
|
||||
if ( $coupon->is_valid() && $coupon->enable_free_shipping() ) {
|
||||
$has_coupon = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -186,24 +131,16 @@ class WC_Shipping_Free_Shipping extends WC_Shipping_Method {
|
|||
|
||||
switch ( $this->requires ) {
|
||||
case 'min_amount' :
|
||||
if ( $has_met_min_amount ) {
|
||||
$is_available = true;
|
||||
}
|
||||
$is_available = $has_met_min_amount;
|
||||
break;
|
||||
case 'coupon' :
|
||||
if ( $has_coupon ) {
|
||||
$is_available = true;
|
||||
}
|
||||
$is_available = $has_coupon;
|
||||
break;
|
||||
case 'both' :
|
||||
if ( $has_met_min_amount && $has_coupon ) {
|
||||
$is_available = true;
|
||||
}
|
||||
$is_available = $has_met_min_amount && $has_coupon;
|
||||
break;
|
||||
case 'either' :
|
||||
if ( $has_met_min_amount || $has_coupon ) {
|
||||
$is_available = true;
|
||||
}
|
||||
$is_available = $has_met_min_amount || $has_coupon;
|
||||
break;
|
||||
default :
|
||||
$is_available = true;
|
||||
|
@ -214,17 +151,15 @@ class WC_Shipping_Free_Shipping extends WC_Shipping_Method {
|
|||
}
|
||||
|
||||
/**
|
||||
* Calculate free shipping.
|
||||
*
|
||||
* @return array
|
||||
* Called to calculate shipping rates for this method. Rates can be added using the add_rate() method.
|
||||
* @uses WC_Shipping_Method::add_rate()
|
||||
*/
|
||||
public function calculate_shipping() {
|
||||
$args = array(
|
||||
'id' => $this->id,
|
||||
'label' => $this->title,
|
||||
'cost' => 0,
|
||||
'taxes' => false
|
||||
);
|
||||
$this->add_rate( $args );
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$this->add_rate( array(
|
||||
'id' => $this->id . $this->instance_id,
|
||||
'label' => $this->title,
|
||||
'cost' => 0,
|
||||
'taxes' => false
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,363 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flat Rate Shipping Method.
|
||||
*
|
||||
* This class is here for backwards commpatility for methods existing before zones existed.
|
||||
*
|
||||
* @deprecated 2.6.0
|
||||
* @version 2.4.0
|
||||
* @package WooCommerce/Classes/Shipping
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Shipping_Legacy_Flat_Rate extends WC_Shipping_Method {
|
||||
|
||||
/** @var string cost passed to [fee] shortcode */
|
||||
protected $fee_cost = '';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'legacy_flat_rate';
|
||||
$this->method_title = __( 'Flat Rate (Legacy)', 'woocommerce' );
|
||||
$this->method_description = sprintf( __( '<strong>This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your <a href="%s">Shipping Zones</a>.</strong>', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) );
|
||||
$this->init();
|
||||
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
add_action( 'woocommerce_flat_rate_shipping_add_rate', array( $this, 'calculate_extra_shipping' ), 10, 3 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the option in the WP DB.
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_option_key() {
|
||||
return $this->plugin_id . 'flat_rate' . '_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* init function.
|
||||
*/
|
||||
public function init() {
|
||||
// Load the settings.
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
// Define user set variables
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->availability = $this->get_option( 'availability' );
|
||||
$this->countries = $this->get_option( 'countries' );
|
||||
$this->tax_status = $this->get_option( 'tax_status' );
|
||||
$this->cost = $this->get_option( 'cost' );
|
||||
$this->type = $this->get_option( 'type', 'class' );
|
||||
$this->options = $this->get_option( 'options', false ); // @deprecated in 2.4.0
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise Settings Form Fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->form_fields = include( 'includes/settings-flat-rate.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a cost from a sum/string.
|
||||
* @param string $sum
|
||||
* @param array $args
|
||||
* @return string
|
||||
*/
|
||||
protected function evaluate_cost( $sum, $args = array() ) {
|
||||
include_once( 'includes/class-wc-eval-math.php' );
|
||||
|
||||
$locale = localeconv();
|
||||
$decimals = array( wc_get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'] );
|
||||
|
||||
$this->fee_cost = $args['cost'];
|
||||
|
||||
// Expand shortcodes
|
||||
add_shortcode( 'fee', array( $this, 'fee' ) );
|
||||
|
||||
$sum = do_shortcode( str_replace(
|
||||
array(
|
||||
'[qty]',
|
||||
'[cost]'
|
||||
),
|
||||
array(
|
||||
$args['qty'],
|
||||
$args['cost']
|
||||
),
|
||||
$sum
|
||||
) );
|
||||
|
||||
remove_shortcode( 'fee', array( $this, 'fee' ) );
|
||||
|
||||
// Remove whitespace from string
|
||||
$sum = preg_replace( '/\s+/', '', $sum );
|
||||
|
||||
// Remove locale from string
|
||||
$sum = str_replace( $decimals, '.', $sum );
|
||||
|
||||
// Trim invalid start/end characters
|
||||
$sum = rtrim( ltrim( $sum, "\t\n\r\0\x0B+*/" ), "\t\n\r\0\x0B+-*/" );
|
||||
|
||||
// Do the math
|
||||
return $sum ? WC_Eval_Math::evaluate( $sum ) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out fee (shortcode).
|
||||
* @param array $atts
|
||||
* @return string
|
||||
*/
|
||||
public function fee( $atts ) {
|
||||
$atts = shortcode_atts( array(
|
||||
'percent' => '',
|
||||
'min_fee' => ''
|
||||
), $atts );
|
||||
|
||||
$calculated_fee = 0;
|
||||
|
||||
if ( $atts['percent'] ) {
|
||||
$calculated_fee = $this->fee_cost * ( floatval( $atts['percent'] ) / 100 );
|
||||
}
|
||||
|
||||
if ( $atts['min_fee'] && $calculated_fee < $atts['min_fee'] ) {
|
||||
$calculated_fee = $atts['min_fee'];
|
||||
}
|
||||
|
||||
return $calculated_fee;
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate_shipping function.
|
||||
*
|
||||
* @param array $package (default: array())
|
||||
*/
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$rate = array(
|
||||
'id' => $this->id,
|
||||
'label' => $this->title,
|
||||
'cost' => 0,
|
||||
);
|
||||
|
||||
// Calculate the costs
|
||||
$has_costs = false; // True when a cost is set. False if all costs are blank strings.
|
||||
$cost = $this->get_option( 'cost' );
|
||||
|
||||
if ( $cost !== '' ) {
|
||||
$has_costs = true;
|
||||
$rate['cost'] = $this->evaluate_cost( $cost, array(
|
||||
'qty' => $this->get_package_item_qty( $package ),
|
||||
'cost' => $package['contents_cost']
|
||||
) );
|
||||
}
|
||||
|
||||
// Add shipping class costs
|
||||
$found_shipping_classes = $this->find_shipping_classes( $package );
|
||||
$highest_class_cost = 0;
|
||||
|
||||
foreach ( $found_shipping_classes as $shipping_class => $products ) {
|
||||
// Also handles BW compatibility when slugs were used instead of ids
|
||||
$shipping_class_term = get_term_by( 'slug', $shipping_class, 'product_shipping_class' );
|
||||
$class_cost_string = $shipping_class_term && $shipping_class_term->term_id ? $this->get_option( 'class_cost_' . $shipping_class_term->term_id, $this->get_option( 'class_cost_' . $shipping_class, '' ) ) : $this->get_option( 'no_class_cost', '' );
|
||||
|
||||
if ( $class_cost_string === '' ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$has_costs = true;
|
||||
$class_cost = $this->evaluate_cost( $class_cost_string, array(
|
||||
'qty' => array_sum( wp_list_pluck( $products, 'quantity' ) ),
|
||||
'cost' => array_sum( wp_list_pluck( $products, 'line_total' ) )
|
||||
) );
|
||||
|
||||
if ( $this->type === 'class' ) {
|
||||
$rate['cost'] += $class_cost;
|
||||
} else {
|
||||
$highest_class_cost = $class_cost > $highest_class_cost ? $class_cost : $highest_class_cost;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->type === 'order' && $highest_class_cost ) {
|
||||
$rate['cost'] += $highest_class_cost;
|
||||
}
|
||||
|
||||
// Add the rate
|
||||
if ( $has_costs ) {
|
||||
$this->add_rate( $rate );
|
||||
}
|
||||
|
||||
/**
|
||||
* Developers can add additional flat rates based on this one via this action since @version 2.4.
|
||||
*
|
||||
* Previously there were (overly complex) options to add additional rates however this was not user.
|
||||
* friendly and goes against what Flat Rate Shipping was originally intended for.
|
||||
*
|
||||
* This example shows how you can add an extra rate based on this flat rate via custom function:
|
||||
*
|
||||
* add_action( 'woocommerce_flat_rate_shipping_add_rate', 'add_another_custom_flat_rate', 10, 2 );
|
||||
*
|
||||
* function add_another_custom_flat_rate( $method, $rate ) {
|
||||
* $new_rate = $rate;
|
||||
* $new_rate['id'] .= ':' . 'custom_rate_name'; // Append a custom ID.
|
||||
* $new_rate['label'] = 'Rushed Shipping'; // Rename to 'Rushed Shipping'.
|
||||
* $new_rate['cost'] += 2; // Add $2 to the cost.
|
||||
*
|
||||
* // Add it to WC.
|
||||
* $method->add_rate( $new_rate );
|
||||
* }.
|
||||
*/
|
||||
do_action( 'woocommerce_flat_rate_shipping_add_rate', $this, $rate, $package );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get items in package.
|
||||
* @param array $package
|
||||
* @return int
|
||||
*/
|
||||
public function get_package_item_qty( $package ) {
|
||||
$total_quantity = 0;
|
||||
foreach ( $package['contents'] as $item_id => $values ) {
|
||||
if ( $values['quantity'] > 0 && $values['data']->needs_shipping() ) {
|
||||
$total_quantity += $values['quantity'];
|
||||
}
|
||||
}
|
||||
return $total_quantity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and returns shipping classes and the products with said class.
|
||||
* @param mixed $package
|
||||
* @return array
|
||||
*/
|
||||
public function find_shipping_classes( $package ) {
|
||||
$found_shipping_classes = array();
|
||||
|
||||
foreach ( $package['contents'] as $item_id => $values ) {
|
||||
if ( $values['data']->needs_shipping() ) {
|
||||
$found_class = $values['data']->get_shipping_class();
|
||||
|
||||
if ( ! isset( $found_shipping_classes[ $found_class ] ) ) {
|
||||
$found_shipping_classes[ $found_class ] = array();
|
||||
}
|
||||
|
||||
$found_shipping_classes[ $found_class ][ $item_id ] = $values;
|
||||
}
|
||||
}
|
||||
|
||||
return $found_shipping_classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds extra calculated flat rates.
|
||||
*
|
||||
* @deprecated 2.4.0
|
||||
*
|
||||
* Additonal rates defined like this:
|
||||
* Option Name | Additional Cost [+- Percents%] | Per Cost Type (order, class, or item).
|
||||
*/
|
||||
public function calculate_extra_shipping( $method, $rate, $package ) {
|
||||
if ( $this->options ) {
|
||||
$options = array_filter( (array) explode( "\n", $this->options ) );
|
||||
|
||||
foreach ( $options as $option ) {
|
||||
$this_option = array_map( 'trim', explode( WC_DELIMITER, $option ) );
|
||||
if ( sizeof( $this_option ) !== 3 ) {
|
||||
continue;
|
||||
}
|
||||
$extra_rate = $rate;
|
||||
$extra_rate['id'] = $this->id . ':' . urldecode( sanitize_title( $this_option[0] ) );
|
||||
$extra_rate['label'] = $this_option[0];
|
||||
$extra_cost = $this->get_extra_cost( $this_option[1], $this_option[2], $package );
|
||||
if ( is_array( $extra_rate['cost'] ) ) {
|
||||
$extra_rate['cost']['order'] = $extra_rate['cost']['order'] + $extra_cost;
|
||||
} else {
|
||||
$extra_rate['cost'] += $extra_cost;
|
||||
}
|
||||
$this->add_rate( $extra_rate );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the percentage adjustment for each shipping rate.
|
||||
*
|
||||
* @deprecated 2.4.0
|
||||
* @param float $cost
|
||||
* @param float $percent_adjustment
|
||||
* @param string $percent_operator
|
||||
* @param float $base_price
|
||||
* @return float
|
||||
*/
|
||||
public function calc_percentage_adjustment( $cost, $percent_adjustment, $percent_operator, $base_price ) {
|
||||
if ( '+' == $percent_operator ) {
|
||||
$cost += $percent_adjustment * $base_price;
|
||||
} else {
|
||||
$cost -= $percent_adjustment * $base_price;
|
||||
}
|
||||
return $cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get extra cost.
|
||||
*
|
||||
* @deprecated 2.4.0
|
||||
* @param string $cost_string
|
||||
* @param string $type
|
||||
* @param array $package
|
||||
* @return float
|
||||
*/
|
||||
public function get_extra_cost( $cost_string, $type, $package ) {
|
||||
$cost = $cost_string;
|
||||
$cost_percent = false;
|
||||
$pattern =
|
||||
'/' . // start regex
|
||||
'(\d+\.?\d*)' . // capture digits, optionally capture a `.` and more digits
|
||||
'\s*' . // match whitespace
|
||||
'(\+|-)' . // capture the operand
|
||||
'\s*'. // match whitespace
|
||||
'(\d+\.?\d*)'. // capture digits, optionally capture a `.` and more digits
|
||||
'\%/'; // match the percent sign & end regex
|
||||
if ( preg_match( $pattern, $cost_string, $this_cost_matches ) ) {
|
||||
$cost_operator = $this_cost_matches[2];
|
||||
$cost_percent = $this_cost_matches[3] / 100;
|
||||
$cost = $this_cost_matches[1];
|
||||
}
|
||||
switch ( $type ) {
|
||||
case 'class' :
|
||||
$cost = $cost * sizeof( $this->find_shipping_classes( $package ) );
|
||||
break;
|
||||
case 'item' :
|
||||
$cost = $cost * $this->get_package_item_qty( $package );
|
||||
break;
|
||||
}
|
||||
if ( $cost_percent ) {
|
||||
switch ( $type ) {
|
||||
case 'class' :
|
||||
$shipping_classes = $this->find_shipping_classes( $package );
|
||||
foreach ( $shipping_classes as $shipping_class => $items ){
|
||||
foreach ( $items as $item_id => $values ) {
|
||||
$cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $values['line_total'] );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'item' :
|
||||
foreach ( $package['contents'] as $item_id => $values ) {
|
||||
if ( $values['data']->needs_shipping() ) {
|
||||
$cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $values['line_total'] );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'order' :
|
||||
$cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $package['contents_cost'] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $cost;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,308 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'WC_Eval_Math' ) ) {
|
||||
/**
|
||||
* Class WC_Eval_Math. Supports basic math only (removed eval function).
|
||||
*
|
||||
* Based on EvalMath by Miles Kaufman Copyright (C) 2005 Miles Kaufmann http://www.twmagic.com/.
|
||||
*/
|
||||
class WC_Eval_Math {
|
||||
/** @var string */
|
||||
public static $last_error = null;
|
||||
|
||||
/** @var array */
|
||||
public static $v = array( 'e' => 2.71, 'pi' => 3.14 ); // variables (and constants)
|
||||
|
||||
/** @var array */
|
||||
public static $f = array(); // user-defined functions
|
||||
|
||||
/** @var array */
|
||||
public static $vb = array( 'e', 'pi' ); // constants
|
||||
|
||||
/** @var array */
|
||||
public static $fb = array(); // built-in functions
|
||||
|
||||
/**
|
||||
* Evaluate maths string.
|
||||
*
|
||||
* @param string $expr
|
||||
* @return mixed
|
||||
*/
|
||||
public static function evaluate( $expr ) {
|
||||
self::$last_error = null;
|
||||
$expr = trim( $expr );
|
||||
if ( substr( $expr, -1, 1 ) == ';' ) $expr = substr( $expr, 0, strlen( $expr )-1 ); // strip semicolons at the end
|
||||
//===============
|
||||
// is it a variable assignment?
|
||||
if ( preg_match( '/^\s*([a-z]\w*)\s*=\s*(.+)$/', $expr, $matches ) ) {
|
||||
if ( in_array( $matches[1], self::$vb ) ) { // make sure we're not assigning to a constant
|
||||
return self::trigger( "cannot assign to constant '$matches[1]'" );
|
||||
}
|
||||
if ( ( $tmp = self::pfx( self::nfx( $matches[2] ) ) ) === false ) return false; // get the result and make sure it's good
|
||||
self::$v[$matches[1]] = $tmp; // if so, stick it in the variable array
|
||||
return self::$v[$matches[1]]; // and return the resulting value
|
||||
//===============
|
||||
// is it a function assignment?
|
||||
} elseif ( preg_match( '/^\s*([a-z]\w*)\s*\(\s*([a-z]\w*(?:\s*,\s*[a-z]\w*)*)\s*\)\s*=\s*(.+)$/', $expr, $matches ) ) {
|
||||
$fnn = $matches[1]; // get the function name
|
||||
if ( in_array( $matches[1], self::$fb ) ) { // make sure it isn't built in
|
||||
return self::trigger( "cannot redefine built-in function '$matches[1]()'" );
|
||||
}
|
||||
$args = explode( ",", preg_replace( "/\s+/", "", $matches[2] ) ); // get the arguments
|
||||
if ( ( $stack = self::nfx( $matches[3] ) ) === false ) return false; // see if it can be converted to postfix
|
||||
for ( $i = 0; $i<count( $stack ); $i++ ) { // freeze the state of the non-argument variables
|
||||
$token = $stack[$i];
|
||||
if ( preg_match( '/^[a-z]\w*$/', $token ) and !in_array( $token, $args ) ) {
|
||||
if ( array_key_exists( $token, self::$v ) ) {
|
||||
$stack[$i] = self::$v[$token];
|
||||
} else {
|
||||
return self::trigger( "undefined variable '$token' in function definition" );
|
||||
}
|
||||
}
|
||||
}
|
||||
self::$f[$fnn] = array( 'args'=>$args, 'func'=>$stack );
|
||||
return true;
|
||||
//===============
|
||||
} else {
|
||||
return self::pfx( self::nfx( $expr ) ); // straight up evaluation, woo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert infix to postfix notation.
|
||||
*
|
||||
* @param string $expr
|
||||
* @return string
|
||||
*/
|
||||
private static function nfx( $expr ) {
|
||||
|
||||
$index = 0;
|
||||
$stack = new WC_Eval_Math_Stack;
|
||||
$output = array(); // postfix form of expression, to be passed to pfx()
|
||||
// $expr = trim(strtolower($expr));
|
||||
$expr = trim( $expr );
|
||||
|
||||
$ops = array( '+', '-', '*', '/', '^', '_' );
|
||||
$ops_r = array( '+'=>0, '-'=>0, '*'=>0, '/'=>0, '^'=>1 ); // right-associative operator?
|
||||
$ops_p = array( '+'=>0, '-'=>0, '*'=>1, '/'=>1, '_'=>1, '^'=>2 ); // operator precedence
|
||||
|
||||
$expecting_op = false; // we use this in syntax-checking the expression
|
||||
// and determining when a - is a negation
|
||||
|
||||
if ( preg_match( "/[^\w\s+*^\/()\.,-]/", $expr, $matches ) ) { // make sure the characters are all good
|
||||
return self::trigger( "illegal character '{$matches[0]}'" );
|
||||
}
|
||||
|
||||
while ( 1 ) { // 1 Infinite Loop ;)
|
||||
$op = substr( $expr, $index, 1 ); // get the first character at the current index
|
||||
// find out if we're currently at the beginning of a number/variable/function/parenthesis/operand
|
||||
$ex = preg_match( '/^([A-Za-z]\w*\(?|\d+(?:\.\d*)?|\.\d+|\()/', substr( $expr, $index ), $match );
|
||||
//===============
|
||||
if ( $op == '-' and !$expecting_op ) { // is it a negation instead of a minus?
|
||||
$stack->push( '_' ); // put a negation on the stack
|
||||
$index++;
|
||||
} elseif ( $op == '_' ) { // we have to explicitly deny this, because it's legal on the stack
|
||||
return self::trigger( "illegal character '_'" ); // but not in the input expression
|
||||
//===============
|
||||
} elseif ( ( in_array( $op, $ops ) or $ex ) and $expecting_op ) { // are we putting an operator on the stack?
|
||||
if ( $ex ) { // are we expecting an operator but have a number/variable/function/opening parethesis?
|
||||
$op = '*'; $index--; // it's an implicit multiplication
|
||||
}
|
||||
// heart of the algorithm:
|
||||
while ( $stack->count > 0 and ( $o2 = $stack->last() ) and in_array( $o2, $ops ) and ( $ops_r[$op] ? $ops_p[$op] < $ops_p[$o2] : $ops_p[$op] <= $ops_p[$o2] ) ) {
|
||||
$output[] = $stack->pop(); // pop stuff off the stack into the output
|
||||
}
|
||||
// many thanks: http://en.wikipedia.org/wiki/Reverse_Polish_notation#The_algorithm_in_detail
|
||||
$stack->push( $op ); // finally put OUR operator onto the stack
|
||||
$index++;
|
||||
$expecting_op = false;
|
||||
//===============
|
||||
} elseif ( $op == ')' and $expecting_op ) { // ready to close a parenthesis?
|
||||
while ( ( $o2 = $stack->pop() ) != '(' ) { // pop off the stack back to the last (
|
||||
if ( is_null( $o2 ) ) return self::trigger( "unexpected ')'" );
|
||||
else $output[] = $o2;
|
||||
}
|
||||
if ( preg_match( "/^([A-Za-z]\w*)\($/", $stack->last( 2 ), $matches ) ) { // did we just close a function?
|
||||
$fnn = $matches[1]; // get the function name
|
||||
$arg_count = $stack->pop(); // see how many arguments there were (cleverly stored on the stack, thank you)
|
||||
$output[] = $stack->pop(); // pop the function and push onto the output
|
||||
if ( in_array( $fnn, self::$fb ) ) { // check the argument count
|
||||
if ( $arg_count > 1 )
|
||||
return self::trigger( "too many arguments ($arg_count given, 1 expected)" );
|
||||
} elseif ( array_key_exists( $fnn, self::$f ) ) {
|
||||
if ( $arg_count != count( self::$f[$fnn]['args'] ) )
|
||||
return self::trigger( "wrong number of arguments ($arg_count given, " . count( self::$f[$fnn]['args'] ) . " expected)" );
|
||||
} else { // did we somehow push a non-function on the stack? this should never happen
|
||||
return self::trigger( "internal error" );
|
||||
}
|
||||
}
|
||||
$index++;
|
||||
//===============
|
||||
} elseif ( $op == ',' and $expecting_op ) { // did we just finish a function argument?
|
||||
while ( ( $o2 = $stack->pop() ) != '(' ) {
|
||||
if ( is_null( $o2 ) ) return self::trigger( "unexpected ','" ); // oops, never had a (
|
||||
else $output[] = $o2; // pop the argument expression stuff and push onto the output
|
||||
}
|
||||
// make sure there was a function
|
||||
if ( !preg_match( "/^([A-Za-z]\w*)\($/", $stack->last( 2 ), $matches ) )
|
||||
return self::trigger( "unexpected ','" );
|
||||
$stack->push( $stack->pop()+1 ); // increment the argument count
|
||||
$stack->push( '(' ); // put the ( back on, we'll need to pop back to it again
|
||||
$index++;
|
||||
$expecting_op = false;
|
||||
//===============
|
||||
} elseif ( $op == '(' and !$expecting_op ) {
|
||||
$stack->push( '(' ); // that was easy
|
||||
$index++;
|
||||
//===============
|
||||
} elseif ( $ex and !$expecting_op ) { // do we now have a function/variable/number?
|
||||
$expecting_op = true;
|
||||
$val = $match[1];
|
||||
if ( preg_match( "/^([A-Za-z]\w*)\($/", $val, $matches ) ) { // may be func, or variable w/ implicit multiplication against parentheses...
|
||||
if ( in_array( $matches[1], self::$fb ) or array_key_exists( $matches[1], self::$f ) ) { // it's a func
|
||||
$stack->push( $val );
|
||||
$stack->push( 1 );
|
||||
$stack->push( '(' );
|
||||
$expecting_op = false;
|
||||
} else { // it's a var w/ implicit multiplication
|
||||
$val = $matches[1];
|
||||
$output[] = $val;
|
||||
}
|
||||
} else { // it's a plain old var or num
|
||||
$output[] = $val;
|
||||
}
|
||||
$index += strlen( $val );
|
||||
//===============
|
||||
} elseif ( $op == ')' ) { // miscellaneous error checking
|
||||
return self::trigger( "unexpected ')'" );
|
||||
} elseif ( in_array( $op, $ops ) and !$expecting_op ) {
|
||||
return self::trigger( "unexpected operator '$op'" );
|
||||
} else { // I don't even want to know what you did to get here
|
||||
return self::trigger( "an unexpected error occured" );
|
||||
}
|
||||
if ( $index == strlen( $expr ) ) {
|
||||
if ( in_array( $op, $ops ) ) { // did we end with an operator? bad.
|
||||
return self::trigger( "operator '$op' lacks operand" );
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
while ( substr( $expr, $index, 1 ) == ' ' ) { // step the index past whitespace (pretty much turns whitespace
|
||||
$index++; // into implicit multiplication if no operator is there)
|
||||
}
|
||||
|
||||
}
|
||||
while ( !is_null( $op = $stack->pop() ) ) { // pop everything off the stack and push onto output
|
||||
if ( $op == '(' ) return self::trigger( "expecting ')'" ); // if there are (s on the stack, ()s were unbalanced
|
||||
$output[] = $op;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
// evaluate postfix notation
|
||||
private static function pfx( $tokens, $vars = array() ) {
|
||||
if ( $tokens == false ) return false;
|
||||
|
||||
$stack = new WC_Eval_Math_Stack;
|
||||
|
||||
foreach ( $tokens as $token ) { // nice and easy
|
||||
// if the token is a binary operator, pop two values off the stack, do the operation, and push the result back on
|
||||
if ( in_array( $token, array( '+', '-', '*', '/', '^' ) ) ) {
|
||||
if ( is_null( $op2 = $stack->pop() ) ) return self::trigger( "internal error" );
|
||||
if ( is_null( $op1 = $stack->pop() ) ) return self::trigger( "internal error" );
|
||||
switch ( $token ) {
|
||||
case '+':
|
||||
$stack->push( $op1+$op2 ); break;
|
||||
case '-':
|
||||
$stack->push( $op1-$op2 ); break;
|
||||
case '*':
|
||||
$stack->push( $op1*$op2 ); break;
|
||||
case '/':
|
||||
if ( $op2 == 0 ) return self::trigger( "division by zero" );
|
||||
$stack->push( $op1/$op2 ); break;
|
||||
case '^':
|
||||
$stack->push( pow( $op1, $op2 ) ); break;
|
||||
}
|
||||
// if the token is a unary operator, pop one value off the stack, do the operation, and push it back on
|
||||
} elseif ( $token == "_" ) {
|
||||
$stack->push( -1*$stack->pop() );
|
||||
// if the token is a function, pop arguments off the stack, hand them to the function, and push the result back on
|
||||
} elseif ( ! preg_match( "/^([a-z]\w*)\($/", $token, $matches ) ) {
|
||||
if ( is_numeric( $token ) ) {
|
||||
$stack->push( $token );
|
||||
} elseif ( array_key_exists( $token, self::$v ) ) {
|
||||
$stack->push( self::$v[$token] );
|
||||
} elseif ( array_key_exists( $token, $vars ) ) {
|
||||
$stack->push( $vars[$token] );
|
||||
} else {
|
||||
return self::trigger( "undefined variable '$token'" );
|
||||
}
|
||||
}
|
||||
}
|
||||
// when we're out of tokens, the stack should have a single element, the final result
|
||||
if ( $stack->count != 1 ) return self::trigger( "internal error" );
|
||||
return $stack->pop();
|
||||
}
|
||||
|
||||
// trigger an error, but nicely, if need be
|
||||
private static function trigger( $msg ) {
|
||||
self::$last_error = $msg;
|
||||
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
||||
echo "\nError found in:";
|
||||
self::debugPrintCallingFunction();
|
||||
trigger_error( $msg, E_USER_WARNING );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prints the file name, function name, and
|
||||
// line number which called your function
|
||||
// (not this function, then one that called
|
||||
// it to begin with)
|
||||
private static function debugPrintCallingFunction() {
|
||||
$file = 'n/a';
|
||||
$func = 'n/a';
|
||||
$line = 'n/a';
|
||||
$debugTrace = debug_backtrace();
|
||||
if ( isset( $debugTrace[1] ) ) {
|
||||
$file = $debugTrace[1]['file'] ? $debugTrace[1]['file'] : 'n/a';
|
||||
$line = $debugTrace[1]['line'] ? $debugTrace[1]['line'] : 'n/a';
|
||||
}
|
||||
if ( isset( $debugTrace[2] ) ) $func = $debugTrace[2]['function'] ? $debugTrace[2]['function'] : 'n/a';
|
||||
echo "\n$file, $func, $line\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class WC_Eval_Math_Stack.
|
||||
*/
|
||||
class WC_Eval_Math_Stack {
|
||||
|
||||
/** @var array */
|
||||
public $stack = array();
|
||||
|
||||
/** @var integer */
|
||||
public $count = 0;
|
||||
|
||||
public function push( $val ) {
|
||||
$this->stack[ $this->count ] = $val;
|
||||
$this->count++;
|
||||
}
|
||||
|
||||
public function pop() {
|
||||
if ( $this->count > 0 ) {
|
||||
$this->count--;
|
||||
return $this->stack[ $this->count ];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function last( $n=1 ) {
|
||||
$key = $this->count - $n;
|
||||
return array_key_exists( $key, $this->stack ) ? $this->stack[ $key ] : null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$cost_desc = __( 'Enter a cost (excl. tax) or sum, e.g. <code>10.00 * [qty]</code>.', 'woocommerce' ) . '<br/>' . __( 'Supports the following placeholders: <code>[qty]</code> = number of items, <code>[cost]</code> = cost of items, <code>[fee percent="10" min_fee="20"]</code> = Percentage based fee.', 'woocommerce' );
|
||||
|
||||
/**
|
||||
* Settings for flat rate shipping.
|
||||
*/
|
||||
$settings = array(
|
||||
'enabled' => array(
|
||||
'title' => __( 'Enable/Disable', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Once disabled, this legacy method will no longer be available.', 'woocommerce' ),
|
||||
'default' => 'no',
|
||||
),
|
||||
'title' => array(
|
||||
'title' => __( 'Method Title', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => __( 'Flat Rate', 'woocommerce' ),
|
||||
'desc_tip' => true
|
||||
),
|
||||
'availability' => array(
|
||||
'title' => __( 'Availability', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'default' => 'all',
|
||||
'class' => 'availability wc-enhanced-select',
|
||||
'options' => array(
|
||||
'all' => __( 'All allowed countries', 'woocommerce' ),
|
||||
'specific' => __( 'Specific Countries', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
'countries' => array(
|
||||
'title' => __( 'Specific Countries', 'woocommerce' ),
|
||||
'type' => 'multiselect',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'css' => 'width: 450px;',
|
||||
'default' => '',
|
||||
'options' => WC()->countries->get_shipping_countries(),
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some countries', 'woocommerce' )
|
||||
)
|
||||
),
|
||||
'tax_status' => array(
|
||||
'title' => __( 'Tax Status', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'default' => 'taxable',
|
||||
'options' => array(
|
||||
'taxable' => __( 'Taxable', 'woocommerce' ),
|
||||
'none' => _x( 'None', 'Tax status', 'woocommerce' )
|
||||
)
|
||||
),
|
||||
'cost' => array(
|
||||
'title' => __( 'Cost', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '',
|
||||
'description' => $cost_desc,
|
||||
'default' => '',
|
||||
'desc_tip' => true
|
||||
)
|
||||
);
|
||||
|
||||
$shipping_classes = WC()->shipping->get_shipping_classes();
|
||||
|
||||
if ( ! empty( $shipping_classes ) ) {
|
||||
$settings[ 'class_costs' ] = array(
|
||||
'title' => __( 'Shipping Class Costs', 'woocommerce' ),
|
||||
'type' => 'title',
|
||||
'default' => '',
|
||||
'description' => sprintf( __( 'These costs can optionally be added based on the %sproduct shipping class%s.', 'woocommerce' ), '<a href="' . admin_url( 'edit-tags.php?taxonomy=product_shipping_class&post_type=product' ) . '">', '</a>' )
|
||||
);
|
||||
foreach ( $shipping_classes as $shipping_class ) {
|
||||
if ( ! isset( $shipping_class->term_id ) ) {
|
||||
continue;
|
||||
}
|
||||
$settings[ 'class_cost_' . $shipping_class->term_id ] = array(
|
||||
'title' => sprintf( __( '"%s" Shipping Class Cost', 'woocommerce' ), esc_html( $shipping_class->name ) ),
|
||||
'type' => 'text',
|
||||
'placeholder' => __( 'N/A', 'woocommerce' ),
|
||||
'description' => $cost_desc,
|
||||
'default' => $this->get_option( 'class_cost_' . $shipping_class->slug ), // Before 2.5.0, we used slug here which caused issues with long setting names
|
||||
'desc_tip' => true
|
||||
);
|
||||
}
|
||||
$settings[ 'no_class_cost' ] = array(
|
||||
'title' => __( 'No Shipping Class Cost', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => __( 'N/A', 'woocommerce' ),
|
||||
'description' => $cost_desc,
|
||||
'default' => '',
|
||||
'desc_tip' => true
|
||||
);
|
||||
$settings[ 'type' ] = array(
|
||||
'title' => __( 'Calculation Type', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'default' => 'class',
|
||||
'options' => array(
|
||||
'class' => __( 'Per Class: Charge shipping for each shipping class individually', 'woocommerce' ),
|
||||
'order' => __( 'Per Order: Charge shipping for the most expensive shipping class', 'woocommerce' ),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if ( apply_filters( 'woocommerce_enable_deprecated_additional_flat_rates', $this->get_option( 'options', false ) ) ) {
|
||||
$settings[ 'additional_rates' ] = array(
|
||||
'title' => __( 'Additional Rates', 'woocommerce' ),
|
||||
'type' => 'title',
|
||||
'default' => '',
|
||||
'description' => __( 'These rates are extra shipping options with additional costs (based on the flat rate).', 'woocommerce' ),
|
||||
);
|
||||
$settings['options'] = array(
|
||||
'title' => __( 'Additional Rates', 'woocommerce' ),
|
||||
'type' => 'textarea',
|
||||
'description' => __( 'One per line: Option Name | Additional Cost [+- Percents] | Per Cost Type (order, class, or item) Example: <code>Priority Mail | 6.95 [+ 0.2%] | order</code>.', 'woocommerce' ),
|
||||
'default' => '',
|
||||
'desc_tip' => true,
|
||||
'placeholder' => __( 'Option Name | Additional Cost [+- Percents%] | Per Cost Type (order, class, or item)', 'woocommerce' )
|
||||
);
|
||||
}
|
||||
|
||||
return $settings;
|
|
@ -0,0 +1,218 @@
|
|||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Free Shipping Method.
|
||||
*
|
||||
* This class is here for backwards commpatility for methods existing before zones existed.
|
||||
*
|
||||
* @deprecated 2.6.0
|
||||
* @version 2.4.0
|
||||
* @package WooCommerce/Classes/Shipping
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Shipping_Legacy_Free_Shipping extends WC_Shipping_Method {
|
||||
|
||||
/** @var float Min amount to be valid */
|
||||
public $min_amount;
|
||||
|
||||
/** @var string Requires option */
|
||||
public $requires;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'legacy_free_shipping';
|
||||
$this->method_title = __( 'Free Shipping (Legacy)', 'woocommerce' );
|
||||
$this->method_description = sprintf( __( '<strong>This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your <a href="%s">Shipping Zones</a>.</strong>', 'woocommerce' ), admin_url( 'admin.php?page=wc-shipping' ) );
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the option in the WP DB.
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_option_key() {
|
||||
return $this->plugin_id . 'free_shipping' . '_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* init function.
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Load the settings.
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
// Define user set variables
|
||||
$this->enabled = $this->get_option( 'enabled' );
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->min_amount = $this->get_option( 'min_amount', 0 );
|
||||
$this->availability = $this->get_option( 'availability' );
|
||||
$this->countries = $this->get_option( 'countries' );
|
||||
$this->requires = $this->get_option( 'requires' );
|
||||
|
||||
// Actions
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise Gateway Settings Form Fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->form_fields = array(
|
||||
'enabled' => array(
|
||||
'title' => __( 'Enable/Disable', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Once disabled, this legacy method will no longer be available.', 'woocommerce' ),
|
||||
'default' => 'no'
|
||||
),
|
||||
'title' => array(
|
||||
'title' => __( 'Method Title', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => __( 'Free Shipping', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'availability' => array(
|
||||
'title' => __( 'Method availability', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'default' => 'all',
|
||||
'class' => 'availability wc-enhanced-select',
|
||||
'options' => array(
|
||||
'all' => __( 'All allowed countries', 'woocommerce' ),
|
||||
'specific' => __( 'Specific Countries', 'woocommerce' )
|
||||
)
|
||||
),
|
||||
'countries' => array(
|
||||
'title' => __( 'Specific Countries', 'woocommerce' ),
|
||||
'type' => 'multiselect',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'css' => 'width: 450px;',
|
||||
'default' => '',
|
||||
'options' => WC()->countries->get_shipping_countries(),
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some countries', 'woocommerce' )
|
||||
)
|
||||
),
|
||||
'requires' => array(
|
||||
'title' => __( 'Free Shipping Requires...', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'default' => '',
|
||||
'options' => array(
|
||||
'' => __( 'N/A', 'woocommerce' ),
|
||||
'coupon' => __( 'A valid free shipping coupon', 'woocommerce' ),
|
||||
'min_amount' => __( 'A minimum order amount (defined below)', 'woocommerce' ),
|
||||
'either' => __( 'A minimum order amount OR a coupon', 'woocommerce' ),
|
||||
'both' => __( 'A minimum order amount AND a coupon', 'woocommerce' ),
|
||||
)
|
||||
),
|
||||
'min_amount' => array(
|
||||
'title' => __( 'Minimum Order Amount', 'woocommerce' ),
|
||||
'type' => 'price',
|
||||
'placeholder' => wc_format_localized_price( 0 ),
|
||||
'description' => __( 'Users will need to spend this amount to get free shipping (if enabled above).', 'woocommerce' ),
|
||||
'default' => '0',
|
||||
'desc_tip' => true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* is_available function.
|
||||
* @param array $package
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available( $package ) {
|
||||
if ( 'no' == $this->enabled ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( 'specific' == $this->availability ) {
|
||||
$ship_to_countries = $this->countries;
|
||||
} else {
|
||||
$ship_to_countries = array_keys( WC()->countries->get_shipping_countries() );
|
||||
}
|
||||
|
||||
if ( is_array( $ship_to_countries ) && ! in_array( $package['destination']['country'], $ship_to_countries ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enabled logic
|
||||
$is_available = false;
|
||||
$has_coupon = false;
|
||||
$has_met_min_amount = false;
|
||||
|
||||
if ( in_array( $this->requires, array( 'coupon', 'either', 'both' ) ) ) {
|
||||
|
||||
if ( $coupons = WC()->cart->get_coupons() ) {
|
||||
foreach ( $coupons as $code => $coupon ) {
|
||||
if ( $coupon->is_valid() && $coupon->enable_free_shipping() ) {
|
||||
$has_coupon = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( in_array( $this->requires, array( 'min_amount', 'either', 'both' ) ) && isset( WC()->cart->cart_contents_total ) ) {
|
||||
if ( WC()->cart->prices_include_tax ) {
|
||||
$total = WC()->cart->cart_contents_total + array_sum( WC()->cart->taxes );
|
||||
} else {
|
||||
$total = WC()->cart->cart_contents_total;
|
||||
}
|
||||
|
||||
if ( $total >= $this->min_amount ) {
|
||||
$has_met_min_amount = true;
|
||||
}
|
||||
}
|
||||
|
||||
switch ( $this->requires ) {
|
||||
case 'min_amount' :
|
||||
if ( $has_met_min_amount ) {
|
||||
$is_available = true;
|
||||
}
|
||||
break;
|
||||
case 'coupon' :
|
||||
if ( $has_coupon ) {
|
||||
$is_available = true;
|
||||
}
|
||||
break;
|
||||
case 'both' :
|
||||
if ( $has_met_min_amount && $has_coupon ) {
|
||||
$is_available = true;
|
||||
}
|
||||
break;
|
||||
case 'either' :
|
||||
if ( $has_met_min_amount || $has_coupon ) {
|
||||
$is_available = true;
|
||||
}
|
||||
break;
|
||||
default :
|
||||
$is_available = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $is_available, $package );
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate_shipping function.
|
||||
* @return array
|
||||
*/
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$args = array(
|
||||
'id' => $this->id,
|
||||
'label' => $this->title,
|
||||
'cost' => 0,
|
||||
'taxes' => false
|
||||
);
|
||||
$this->add_rate( $args );
|
||||
}
|
||||
}
|
|
@ -6,27 +6,38 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
/**
|
||||
* International Delivery - Based on the Flat Rate Shipping Method.
|
||||
*
|
||||
* @class WC_Shipping_Flat_Rate
|
||||
* This class is here for backwards commpatility for methods existing before zones existed.
|
||||
*
|
||||
* @deprecated 2.6.0
|
||||
* @version 2.4.0
|
||||
* @package WooCommerce/Classes/Shipping
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Shipping_International_Delivery extends WC_Shipping_Flat_Rate {
|
||||
class WC_Shipping_Legacy_International_Delivery extends WC_Shipping_Legacy_Flat_Rate {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'international_delivery';
|
||||
$this->method_title = __( 'International Flat Rate', 'woocommerce' );
|
||||
$this->method_description = __( 'International Flat Rate Shipping lets you charge a fixed rate for shipping.', 'woocommerce' );
|
||||
$this->id = 'legacy_international_delivery';
|
||||
$this->method_title = __( 'International Flat Rate (Legacy)', 'woocommerce' );
|
||||
$this->method_description = sprintf( __( '<strong>This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your <a href="%s">Shipping Zones</a>.</strong>', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) );
|
||||
$this->init();
|
||||
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize settings form fields.
|
||||
* Return the name of the option in the WP DB.
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_option_key() {
|
||||
return $this->plugin_id . 'international_delivery' . '_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise settings form fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
parent::init_form_fields();
|
||||
|
@ -44,7 +55,7 @@ class WC_Shipping_International_Delivery extends WC_Shipping_Flat_Rate {
|
|||
}
|
||||
|
||||
/**
|
||||
* Check if international delivery is available.
|
||||
* is_available function.
|
||||
*
|
||||
* @param array $package
|
||||
* @return bool
|
|
@ -7,27 +7,36 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
/**
|
||||
* Local Delivery Shipping Method.
|
||||
*
|
||||
* A simple shipping method allowing local delivery as a shipping method.
|
||||
* This class is here for backwards commpatility for methods existing before zones existed.
|
||||
*
|
||||
* @class WC_Shipping_Local_Delivery
|
||||
* @deprecated 2.6.0
|
||||
* @version 2.3.0
|
||||
* @package WooCommerce/Classes/Shipping
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Shipping_Local_Delivery extends WC_Shipping_Local_Pickup {
|
||||
class WC_Shipping_Legacy_Local_Delivery extends WC_Shipping_Local_Pickup {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'local_delivery';
|
||||
$this->method_title = __( 'Local Delivery', 'woocommerce' );
|
||||
$this->method_description = __( 'Local delivery is a simple shipping method for delivering orders locally.', 'woocommerce' );
|
||||
$this->id = 'legacy_local_delivery';
|
||||
$this->method_title = __( 'Local Delivery (Legacy)', 'woocommerce' );
|
||||
$this->method_description = sprintf( __( '<strong>This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your <a href="%s">Shipping Zones</a>.</strong>', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) );
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize local delivery.
|
||||
* Return the name of the option in the WP DB.
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_option_key() {
|
||||
return $this->plugin_id . 'local_delivery' . '_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* init function.
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
|
@ -48,7 +57,7 @@ class WC_Shipping_Local_Delivery extends WC_Shipping_Local_Pickup {
|
|||
}
|
||||
|
||||
/**
|
||||
* Calculate local delivery shipping.
|
||||
* calculate_shipping function.
|
||||
*
|
||||
* @param array $package (default: array())
|
||||
*/
|
||||
|
@ -88,7 +97,7 @@ class WC_Shipping_Local_Delivery extends WC_Shipping_Local_Pickup {
|
|||
'enabled' => array(
|
||||
'title' => __( 'Enable', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Enable local delivery', 'woocommerce' ),
|
||||
'label' => __( 'Once disabled, this legacy method will no longer be available.', 'woocommerce' ),
|
||||
'default' => 'no'
|
||||
),
|
||||
'title' => array(
|
|
@ -0,0 +1,209 @@
|
|||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Pickup Shipping Method.
|
||||
*
|
||||
* This class is here for backwards commpatility for methods existing before zones existed.
|
||||
*
|
||||
* @deprecated 2.6.0
|
||||
* @version 2.3.0
|
||||
* @package WooCommerce/Classes/Shipping
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Shipping_Legacy_Local_Pickup extends WC_Shipping_Method {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'legacy_local_pickup';
|
||||
$this->method_title = __( 'Local Pickup (Legacy)', 'woocommerce' );
|
||||
$this->method_description = sprintf( __( '<strong>This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your <a href="%s">Shipping Zones</a>.</strong>', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) );
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the option in the WP DB.
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
public function get_option_key() {
|
||||
return $this->plugin_id . 'local_pickup' . '_settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* init function.
|
||||
*/
|
||||
public function init() {
|
||||
|
||||
// Load the settings.
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
// Define user set variables
|
||||
$this->enabled = $this->get_option( 'enabled' );
|
||||
$this->title = $this->get_option( 'title' );
|
||||
$this->codes = $this->get_option( 'codes' );
|
||||
$this->availability = $this->get_option( 'availability' );
|
||||
$this->countries = $this->get_option( 'countries' );
|
||||
|
||||
// Actions
|
||||
add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate_shipping function.
|
||||
*/
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$rate = array(
|
||||
'id' => $this->id,
|
||||
'label' => $this->title,
|
||||
);
|
||||
$this->add_rate( $rate );
|
||||
}
|
||||
|
||||
/**
|
||||
* init_form_fields function.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->form_fields = array(
|
||||
'enabled' => array(
|
||||
'title' => __( 'Enable', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Once disabled, this legacy method will no longer be available.', 'woocommerce' ),
|
||||
'default' => 'no'
|
||||
),
|
||||
'title' => array(
|
||||
'title' => __( 'Title', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => __( 'Local Pickup', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'codes' => array(
|
||||
'title' => __( 'Allowed ZIP/Post Codes', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'desc_tip' => __( 'What ZIP/post codes are available for local pickup?', 'woocommerce' ),
|
||||
'default' => '',
|
||||
'description' => __( 'Separate codes with a comma. Accepts wildcards, e.g. <code>P*</code> will match a postcode of PE30. Also accepts a pattern, e.g. <code>NG1___</code> would match NG1 1AA but not NG10 1AA', 'woocommerce' ),
|
||||
'placeholder' => 'e.g. 12345, 56789'
|
||||
),
|
||||
'availability' => array(
|
||||
'title' => __( 'Method availability', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'default' => 'all',
|
||||
'class' => 'availability wc-enhanced-select',
|
||||
'options' => array(
|
||||
'all' => __( 'All allowed countries', 'woocommerce' ),
|
||||
'specific' => __( 'Specific Countries', 'woocommerce' )
|
||||
)
|
||||
),
|
||||
'countries' => array(
|
||||
'title' => __( 'Specific Countries', 'woocommerce' ),
|
||||
'type' => 'multiselect',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'css' => 'width: 450px;',
|
||||
'default' => '',
|
||||
'options' => WC()->countries->get_shipping_countries(),
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some countries', 'woocommerce' )
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get postcodes for this method.
|
||||
* @return array
|
||||
*/
|
||||
public function get_valid_postcodes() {
|
||||
$codes = array();
|
||||
|
||||
if ( $this->codes != '' ) {
|
||||
foreach( explode( ',', $this->codes ) as $code ) {
|
||||
$codes[] = strtoupper( trim( $code ) );
|
||||
}
|
||||
}
|
||||
|
||||
return $codes;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if a given postcode matches valid postcodes.
|
||||
* @param string postcode
|
||||
* @param string country code
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_valid_postcode( $postcode, $country ) {
|
||||
$codes = $this->get_valid_postcodes();
|
||||
$postcode = $this->clean( $postcode );
|
||||
$formatted_postcode = wc_format_postcode( $postcode, $country );
|
||||
|
||||
if ( in_array( $postcode, $codes ) || in_array( $formatted_postcode, $codes ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Pattern matching
|
||||
foreach ( $codes as $c ) {
|
||||
$pattern = '/^' . str_replace( '_', '[0-9a-zA-Z]', preg_quote( $c ) ) . '$/i';
|
||||
if ( preg_match( $pattern, $postcode ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Wildcard search
|
||||
$wildcard_postcode = $formatted_postcode . '*';
|
||||
$postcode_length = strlen( $formatted_postcode );
|
||||
|
||||
for ( $i = 0; $i < $postcode_length; $i++ ) {
|
||||
if ( in_array( $wildcard_postcode, $codes ) ) {
|
||||
return true;
|
||||
}
|
||||
$wildcard_postcode = substr( $wildcard_postcode, 0, -2 ) . '*';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* See if the method is available.
|
||||
*
|
||||
* @param array $package
|
||||
* @return bool
|
||||
*/
|
||||
public function is_available( $package ) {
|
||||
$is_available = "yes" === $this->enabled;
|
||||
|
||||
if ( $is_available && $this->get_valid_postcodes() ) {
|
||||
$is_available = $this->is_valid_postcode( $package['destination']['postcode'], $package['destination']['country'] );
|
||||
}
|
||||
|
||||
if ( $is_available ) {
|
||||
if ( $this->availability === 'specific' ) {
|
||||
$ship_to_countries = $this->countries;
|
||||
} else {
|
||||
$ship_to_countries = array_keys( WC()->countries->get_shipping_countries() );
|
||||
}
|
||||
if ( is_array( $ship_to_countries ) && ! in_array( $package['destination']['country'], $ship_to_countries ) ) {
|
||||
$is_available = false;
|
||||
}
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $is_available, $package );
|
||||
}
|
||||
|
||||
/**
|
||||
* clean function.
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $code
|
||||
* @return string
|
||||
*/
|
||||
public function clean( $code ) {
|
||||
return str_replace( '-', '', sanitize_title( $code ) ) . ( strstr( $code, '*' ) ? '*' : '' );
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,7 +9,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
* A simple shipping method allowing free pickup as a shipping method.
|
||||
*
|
||||
* @class WC_Shipping_Local_Pickup
|
||||
* @version 2.3.0
|
||||
* @version 2.6.0
|
||||
* @package WooCommerce/Classes/Shipping
|
||||
* @author WooThemes
|
||||
*/
|
||||
|
@ -19,10 +18,15 @@ class WC_Shipping_Local_Pickup extends WC_Shipping_Method {
|
|||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'local_pickup';
|
||||
$this->method_title = __( 'Local Pickup', 'woocommerce' );
|
||||
$this->method_description = __( 'Local pickup is a simple method which allows customers to pick up orders themselves.', 'woocommerce' );
|
||||
public function __construct( $instance_id = 0 ) {
|
||||
$this->id = 'local_pickup';
|
||||
$this->instance_id = absint( $instance_id );
|
||||
$this->method_title = __( 'Local Pickup', 'woocommerce' );
|
||||
$this->method_description = __( 'Allow customers to pick up orders themselves. By default, when using local pickup store base taxes will apply regardless of customer address.', 'woocommerce' );
|
||||
$this->supports = array(
|
||||
'shipping-zones',
|
||||
'instance-settings'
|
||||
);
|
||||
$this->init();
|
||||
}
|
||||
|
||||
|
@ -50,24 +54,23 @@ class WC_Shipping_Local_Pickup extends WC_Shipping_Method {
|
|||
* calculate_shipping function.
|
||||
* Calculate local pickup shipping.
|
||||
*/
|
||||
public function calculate_shipping() {
|
||||
$rate = array(
|
||||
'id' => $this->id,
|
||||
public function calculate_shipping( $package = array() ) {
|
||||
$this->add_rate( array(
|
||||
'id' => $this->id . $this->instance_id,
|
||||
'label' => $this->title,
|
||||
);
|
||||
$this->add_rate( $rate );
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Init form fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->form_fields = array(
|
||||
$this->instance_form_fields = array(
|
||||
'enabled' => array(
|
||||
'title' => __( 'Enable', 'woocommerce' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Enable local pickup', 'woocommerce' ),
|
||||
'default' => 'no'
|
||||
'default' => 'yes'
|
||||
),
|
||||
'title' => array(
|
||||
'title' => __( 'Title', 'woocommerce' ),
|
||||
|
@ -75,35 +78,6 @@ class WC_Shipping_Local_Pickup extends WC_Shipping_Method {
|
|||
'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
|
||||
'default' => __( 'Local Pickup', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
'codes' => array(
|
||||
'title' => __( 'Allowed ZIP/Post Codes', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'desc_tip' => __( 'What ZIP/post codes are available for local pickup?', 'woocommerce' ),
|
||||
'default' => '',
|
||||
'description' => __( 'Separate codes with a comma. Accepts wildcards, e.g. <code>P*</code> will match a postcode of PE30. Also accepts a pattern, e.g. <code>NG1___</code> would match NG1 1AA but not NG10 1AA', 'woocommerce' ),
|
||||
'placeholder' => 'e.g. 12345, 56789'
|
||||
),
|
||||
'availability' => array(
|
||||
'title' => __( 'Method availability', 'woocommerce' ),
|
||||
'type' => 'select',
|
||||
'default' => 'all',
|
||||
'class' => 'availability wc-enhanced-select',
|
||||
'options' => array(
|
||||
'all' => __( 'All allowed countries', 'woocommerce' ),
|
||||
'specific' => __( 'Specific Countries', 'woocommerce' )
|
||||
)
|
||||
),
|
||||
'countries' => array(
|
||||
'title' => __( 'Specific Countries', 'woocommerce' ),
|
||||
'type' => 'multiselect',
|
||||
'class' => 'wc-enhanced-select',
|
||||
'css' => 'width: 450px;',
|
||||
'default' => '',
|
||||
'options' => WC()->countries->get_shipping_countries(),
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some countries', 'woocommerce' )
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
/**
|
||||
* Update WC to 2.6.0
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category Admin
|
||||
* @package WooCommerce/Admin/Updates
|
||||
* @version 2.6.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
/**
|
||||
* Old (table rate) shipping zones to new core shipping zones migration.
|
||||
* zone_enabled and zone_type are no longer used, but it's safe to leave them be.
|
||||
*/
|
||||
if ( $wpdb->get_var( "SHOW COLUMNS FROM `{$wpdb->prefix}woocommerce_shipping_zones` LIKE 'zone_enabled';" ) ) {
|
||||
$wpdb->query( "ALTER TABLE {$wpdb->prefix}woocommerce_shipping_zones CHANGE `zone_type` `zone_type` VARCHAR(40) NOT NULL DEFAULT '';" );
|
||||
$wpdb->query( "ALTER TABLE {$wpdb->prefix}woocommerce_shipping_zones CHANGE `zone_enabled` `zone_enabled` INT(1) NOT NULL DEFAULT 1;" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Shipping zones in WC 2.6.0 use a table named woocommerce_shipping_zone_methods.
|
||||
* Migrate the old data out of woocommerce_shipping_zone_shipping_methods into the new table and port over any known options (used by table rates and flat rate boxes).
|
||||
*/
|
||||
if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}woocommerce_shipping_zone_shipping_methods';" ) ) {
|
||||
$old_methods = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods;" );
|
||||
if ( $old_methods ) {
|
||||
$max_new_id = $wpdb->get_var( "SELECT MAX(instance_id) FROM {$wpdb->prefix}woocommerce_shipping_zone_methods" );
|
||||
$max_old_id = $wpdb->get_var( "SELECT MAX(shipping_method_id) FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods" );
|
||||
|
||||
// Avoid ID conflicts
|
||||
$wpdb->query( $wpdb->prepare( "ALTER TABLE {$wpdb->prefix}woocommerce_shipping_zone_methods AUTO_INCREMENT = %d;", max( $max_new_id, $max_old_id ) + 1 ) );
|
||||
|
||||
// Move data
|
||||
foreach ( $old_methods as $old_method ) {
|
||||
$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zone_methods', array(
|
||||
'zone_id' => $old_method->zone_id,
|
||||
'method_id' => $old_method->shipping_method_type,
|
||||
'method_order' => $old_method->shipping_method_order
|
||||
) );
|
||||
|
||||
$new_instance_id = $wpdb->insert_id;
|
||||
|
||||
// Move main settings
|
||||
$older_settings_key = 'woocommerce_' . $old_method->shipping_method_type . '-' . $old_method->shipping_method_id . '_settings';
|
||||
$old_settings_key = 'woocommerce_' . $old_method->shipping_method_type . '_' . $old_method->shipping_method_id . '_settings';
|
||||
add_option( 'woocommerce_' . $old_method->shipping_method_type . '_' . $new_instance_id . '_settings', get_option( $old_settings_key, get_option( $older_settings_key ) ) );
|
||||
|
||||
if ( 'table_rate' === $old_method->shipping_method_type ) {
|
||||
// Move priority settings
|
||||
add_option( 'woocommerce_table_rate_default_priority_' . $new_instance_id, get_option( 'woocommerce_table_rate_default_priority_' . $old_method->shipping_method_id ) );
|
||||
add_option( 'woocommerce_table_rate_priorities_' . $new_instance_id, get_option( 'woocommerce_table_rate_priorities_' . $old_method->shipping_method_id ) );
|
||||
|
||||
// Move rates
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'woocommerce_shipping_table_rates',
|
||||
array(
|
||||
'shipping_method_id' => $new_instance_id
|
||||
),
|
||||
array(
|
||||
'shipping_method_id' => $old_method->shipping_method_id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( 'flat_rate_boxes' === $old_method->shipping_method_type ) {
|
||||
$wpdb->update(
|
||||
$wpdb->prefix . 'woocommerce_shipping_flat_rate_boxes',
|
||||
array(
|
||||
'shipping_method_id' => $new_instance_id
|
||||
),
|
||||
array(
|
||||
'shipping_method_id' => $old_method->shipping_method_id
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* woocommerce_calc_shipping option has been removed in 2.6
|
||||
*/
|
||||
if ( 'no' === get_option( 'woocommerce_calc_shipping' ) ) {
|
||||
update_option( 'woocommerce_ship_to_countries', 'disabled' );
|
||||
}
|
|
@ -308,8 +308,6 @@ function wc_cart_totals_shipping_method_label( $method ) {
|
|||
$label .= ' <small class="tax_label">' . WC()->countries->inc_tax_or_vat() . '</small>';
|
||||
}
|
||||
}
|
||||
} elseif ( $method->id !== 'free_shipping' ) {
|
||||
$label .= ' (' . __( 'Free', 'woocommerce' ) . ')';
|
||||
}
|
||||
|
||||
return apply_filters( 'woocommerce_cart_shipping_method_full_label', $label, $method );
|
||||
|
|
|
@ -308,6 +308,17 @@ if ( ! function_exists( 'wc_tax_enabled' ) ) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'wc_shipping_enabled' ) ) {
|
||||
|
||||
/**
|
||||
* Is shipping enabled?
|
||||
* @return bool
|
||||
*/
|
||||
function wc_shipping_enabled() {
|
||||
return apply_filters( 'wc_shipping_enabled', get_option( 'woocommerce_ship_to_countries' ) !== 'disabled' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'wc_prices_include_tax' ) ) {
|
||||
|
||||
/**
|
||||
|
|
|
@ -912,3 +912,25 @@ function wc_get_checkout_url() {
|
|||
|
||||
return apply_filters( 'woocommerce_get_checkout_url', $checkout_url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a shipping method.
|
||||
*
|
||||
* @since 1.5.7
|
||||
* @param string|object $shipping_method class name (string) or a class object.
|
||||
*/
|
||||
function woocommerce_register_shipping_method( $shipping_method ) {
|
||||
WC()->shipping->register_shipping_method( $shipping_method );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the shipping zone matching a given package from the cart.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @uses WC_Shipping_Zones::get_zone_matching_package
|
||||
* @param array $package
|
||||
* @return WC_Shipping_Zone
|
||||
*/
|
||||
function wc_get_shipping_zone( $package ) {
|
||||
return WC_Shipping_Zones::get_zone_matching_package( $package );
|
||||
}
|
||||
|
|
|
@ -721,3 +721,18 @@ add_action( 'pre_get_posts', 'wc_shop_order_status_backwards_compatibility' );
|
|||
function woocommerce_compile_less_styles() {
|
||||
_deprecated_function( 'woocommerce_compile_less_styles', '2.3' );
|
||||
}
|
||||
|
||||
/**
|
||||
* woocommerce_calc_shipping was an option used to determine if shipping was enabled prior to version 2.6.0. This has since been replaced with wc_shipping_enabled() function and
|
||||
* the woocommerce_ship_to_countries setting.
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
function woocommerce_calc_shipping_backwards_compatibility( $value ) {
|
||||
if ( defined( 'WC_UPDATING' ) ) {
|
||||
return $value;
|
||||
}
|
||||
return 'disabled' === get_option( 'woocommerce_ship_to_countries' ) ? 'no' : 'yes';
|
||||
}
|
||||
|
||||
add_filter( 'pre_option_woocommerce_calc_shipping', 'woocommerce_calc_shipping_backwards_compatibility' );
|
||||
|
|
|
@ -761,3 +761,34 @@ add_filter( 'woocommerce_admin_settings_sanitize_option_woocommerce_hold_stock_m
|
|||
function wc_sanitize_term_text_based( $term ) {
|
||||
return trim( wp_unslash( strip_tags( $term ) ) );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'wc_make_numeric_postcode' ) ) {
|
||||
/**
|
||||
* Make numeric postcode.
|
||||
*
|
||||
* Converts letters to numbers so we can do a simple range check on postcodes.
|
||||
* E.g. PE30 becomes 16050300 (P = 16, E = 05, 3 = 03, 0 = 00)
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param string $postcode Regular postcode
|
||||
* @return string
|
||||
*/
|
||||
function wc_make_numeric_postcode( $postcode ) {
|
||||
$postcode_length = strlen( $postcode );
|
||||
$letters_to_numbers = array_merge( array( 0 ), range( 'A', 'Z' ) );
|
||||
$letters_to_numbers = array_flip( $letters_to_numbers );
|
||||
$numeric_postcode = '';
|
||||
|
||||
for ( $i = 0; $i < $postcode_length; $i ++ ) {
|
||||
if ( is_numeric( $postcode[ $i ] ) ) {
|
||||
$numeric_postcode .= str_pad( $postcode[ $i ], 2, '0', STR_PAD_LEFT );
|
||||
} elseif ( isset( $letters_to_numbers[ $postcode[ $i ] ] ) ) {
|
||||
$numeric_postcode .= str_pad( $letters_to_numbers[ $postcode[ $i ] ], 2, '0', STR_PAD_LEFT );
|
||||
} else {
|
||||
$numeric_postcode .= '00';
|
||||
}
|
||||
}
|
||||
|
||||
return $numeric_postcode;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
|
||||
$customer_id = get_current_user_id();
|
||||
|
||||
if ( ! wc_ship_to_billing_address_only() && get_option( 'woocommerce_calc_shipping' ) !== 'no' ) {
|
||||
if ( ! wc_ship_to_billing_address_only() && wc_shipping_enabled() ) {
|
||||
$page_title = apply_filters( 'woocommerce_my_account_my_address_title', __( 'My Addresses', 'woocommerce' ) );
|
||||
$get_addresses = apply_filters( 'woocommerce_my_account_get_addresses', array(
|
||||
'billing' => __( 'Billing Address', 'woocommerce' ),
|
||||
|
@ -43,7 +43,7 @@ $col = 1;
|
|||
<?php echo apply_filters( 'woocommerce_my_account_my_address_description', __( 'The following addresses will be used on the checkout page by default.', 'woocommerce' ) ); ?>
|
||||
</p>
|
||||
|
||||
<?php if ( ! wc_ship_to_billing_address_only() && get_option( 'woocommerce_calc_shipping' ) !== 'no' ) echo '<div class="col2-set addresses">'; ?>
|
||||
<?php if ( ! wc_ship_to_billing_address_only() && wc_shipping_enabled() ) echo '<div class="col2-set addresses">'; ?>
|
||||
|
||||
<?php foreach ( $get_addresses as $name => $title ) : ?>
|
||||
|
||||
|
@ -78,4 +78,4 @@ $col = 1;
|
|||
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if ( ! wc_ship_to_billing_address_only() && get_option( 'woocommerce_calc_shipping' ) !== 'no' ) echo '</div>'; ?>
|
||||
<?php if ( ! wc_ship_to_billing_address_only() && wc_shipping_enabled() ) echo '</div>'; ?>
|
||||
|
|
|
@ -66,10 +66,10 @@ class WC_Unit_Tests_Bootstrap {
|
|||
|
||||
// clean existing install first
|
||||
define( 'WP_UNINSTALL_PLUGIN', true );
|
||||
update_option( 'woocommerce_status_options', array( 'uninstall_data' => 1 ) );
|
||||
include( $this->plugin_dir . '/uninstall.php' );
|
||||
|
||||
WC_Install::install();
|
||||
update_option( 'woocommerce_calc_shipping', 'yes' ); // Needed for tests cart and shipping methods
|
||||
|
||||
// reload capabilities after install, see https://core.trac.wordpress.org/ticket/28374
|
||||
$GLOBALS['wp_roles']->reinit();
|
||||
|
@ -103,6 +103,7 @@ class WC_Unit_Tests_Bootstrap {
|
|||
require_once( $this->tests_dir . '/framework/helpers/class-wc-helper-shipping.php' );
|
||||
require_once( $this->tests_dir . '/framework/helpers/class-wc-helper-customer.php' );
|
||||
require_once( $this->tests_dir . '/framework/helpers/class-wc-helper-order.php' );
|
||||
require_once( $this->tests_dir . '/framework/helpers/class-wc-helper-shipping-zones.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class WC_Helper_Shipping_Zones.
|
||||
*
|
||||
* This helper class should ONLY be used for unit tests!.
|
||||
*/
|
||||
class WC_Helper_Shipping_Zones {
|
||||
|
||||
/**
|
||||
* Create some mock shipping zones to test against
|
||||
*/
|
||||
public static function create_mock_zones() {
|
||||
self::remove_mock_zones();
|
||||
|
||||
// Local zone
|
||||
$zone = new WC_Shipping_Zone();
|
||||
$zone->set_zone_name( 'Local' );
|
||||
$zone->set_zone_order( 1 );
|
||||
$zone->add_location( 'GB', 'country' );
|
||||
$zone->add_location( 'CB*', 'postcode' );
|
||||
$zone->save();
|
||||
|
||||
// Europe zone
|
||||
$zone = new WC_Shipping_Zone();
|
||||
$zone->set_zone_name( 'Europe' );
|
||||
$zone->set_zone_order( 2 );
|
||||
$zone->add_location( 'EU', 'continent' );
|
||||
$zone->save();
|
||||
|
||||
// US california zone
|
||||
$zone = new WC_Shipping_Zone();
|
||||
$zone->set_zone_name( 'California' );
|
||||
$zone->set_zone_order( 3 );
|
||||
$zone->add_location( 'US:CA', 'state' );
|
||||
$zone->save();
|
||||
|
||||
// US zone
|
||||
$zone = new WC_Shipping_Zone();
|
||||
$zone->set_zone_name( 'US' );
|
||||
$zone->set_zone_order( 4 );
|
||||
$zone->add_location( 'US', 'country' );
|
||||
$zone->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all zones
|
||||
*/
|
||||
public static function remove_mock_zones() {
|
||||
global $wpdb;
|
||||
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}woocommerce_shipping_zone_methods;" );
|
||||
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}woocommerce_shipping_zone_locations;" );
|
||||
$wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}woocommerce_shipping_zones;" );
|
||||
WC_Cache_Helper::incr_cache_prefix( 'shipping_zones' );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,324 @@
|
|||
<?php
|
||||
namespace WooCommerce\Tests\Shipping_Zone;
|
||||
|
||||
/**
|
||||
* Class Shipping_Zone.
|
||||
* @package WooCommerce\Tests\Shipping_Zone
|
||||
*/
|
||||
class Shipping_Zone extends \WC_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zone::get_data
|
||||
*/
|
||||
public function test_get_data() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
$data = $zone->get_data();
|
||||
|
||||
// Assert
|
||||
$this->assertTrue( \is_array( $data ) );
|
||||
$this->assertTrue( 4 === \sizeof( $data ) );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zones::get_zone_id
|
||||
*/
|
||||
public function test_get_zone_id() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_zone_id(), 1 );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zones::get_zone_name
|
||||
*/
|
||||
public function test_get_zone_name() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_zone_name(), 'Local' );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zones::get_zone_order
|
||||
*/
|
||||
public function test_get_zone_order() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_zone_order(), 1 );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zones::get_zone_locations
|
||||
*/
|
||||
public function test_get_zone_locations() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
|
||||
// Assert
|
||||
$this->assertTrue( \is_array( $zone->get_zone_locations() ) );
|
||||
$this->assertTrue( 2 === \sizeof( $zone->get_zone_locations() ) );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zones::get_formatted_location
|
||||
*/
|
||||
public function test_get_formatted_location() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_formatted_location(), 'United Kingdom (UK), CB*' );
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 2 );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_formatted_location(), 'Europe' );
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 3 );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_formatted_location(), 'California' );
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 4 );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_formatted_location(), 'United States (US)' );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zone::get_shipping_methods
|
||||
*/
|
||||
public function test_get_shipping_methods() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
$zone->add_shipping_method( 'flat_rate' );
|
||||
$methods = $zone->get_shipping_methods();
|
||||
|
||||
// Assert
|
||||
$this->assertTrue( 1 === \sizeof( $methods ) );
|
||||
$this->assertInstanceOf( 'WC_Shipping_Method', current( $methods ) );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zone::set_zone_name
|
||||
*/
|
||||
public function test_set_zone_name() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
$zone->set_zone_name( 'I am a fish' );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_zone_name(), 'I am a fish' );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zone::set_zone_order
|
||||
*/
|
||||
public function test_set_zone_order() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
$zone->set_zone_order( 100 );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_zone_order(), 100 );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zone::is_valid_location_type
|
||||
*/
|
||||
public function test_is_valid_location_type() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_zone_order(), 1 );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zone::add_location
|
||||
*/
|
||||
public function test_add_location() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
|
||||
// Assert
|
||||
$this->assertTrue( $zone->is_valid_location_type( 'state' ) );
|
||||
$this->assertTrue( $zone->is_valid_location_type( 'country' ) );
|
||||
$this->assertTrue( $zone->is_valid_location_type( 'continent' ) );
|
||||
$this->assertTrue( $zone->is_valid_location_type( 'postcode' ) );
|
||||
$this->assertFalse( $zone->is_valid_location_type( 'poop' ) );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zone::clear_locations
|
||||
*/
|
||||
public function test_clear_locations() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
$zone->clear_locations();
|
||||
|
||||
// Assert
|
||||
$this->assertTrue( empty( $zone->get_zone_locations() ) );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zone::set_locations
|
||||
*/
|
||||
public function test_set_locations() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
$zone->clear_locations();
|
||||
$zone->set_locations( array(
|
||||
array(
|
||||
'code' => 'US',
|
||||
'type' => 'country'
|
||||
),
|
||||
array(
|
||||
'code' => '90210',
|
||||
'type' => 'postcode'
|
||||
)
|
||||
) );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_zone_locations(), array(
|
||||
2 => (object) array(
|
||||
'code' => 'US',
|
||||
'type' => 'country'
|
||||
),
|
||||
3 => (object) array(
|
||||
'code' => '90210',
|
||||
'type' => 'postcode'
|
||||
)
|
||||
) );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zone::save
|
||||
*/
|
||||
public function test_save() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
$zone->set_zone_name( 'I am a fish' );
|
||||
$zone->save();
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( $zone->get_zone_name(), 'I am a fish' );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zone::add_shipping_method
|
||||
*/
|
||||
public function test_add_shipping_method() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
$zone->add_shipping_method( 'flat_rate' );
|
||||
$zone->add_shipping_method( 'free_shipping' );
|
||||
|
||||
// Assert
|
||||
$methods = $zone->get_shipping_methods();
|
||||
|
||||
// Assert
|
||||
$this->assertTrue( 2 === \sizeof( $methods ) );
|
||||
$this->assertInstanceOf( 'WC_Shipping_Method', current( $methods ) );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
<?php
|
||||
namespace WooCommerce\Tests\Shipping_Zones;
|
||||
|
||||
/**
|
||||
* Class Shipping_Zones.
|
||||
* @package WooCommerce\Tests\Shipping_Zones
|
||||
*/
|
||||
class Shipping_Zones extends \WC_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zones::get_zones
|
||||
*/
|
||||
public function test_get_zones() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zones = \WC_Shipping_Zones::get_zones();
|
||||
|
||||
// Assert
|
||||
$this->assertTrue( \is_array( $zones ) );
|
||||
$this->assertTrue( 4 === \sizeof( $zones ) );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zones::get_zone
|
||||
*/
|
||||
public function test_get_zone() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone( 1 );
|
||||
|
||||
// Assert that the first zone is our local zone
|
||||
$this->assertInstanceOf( 'WC_Shipping_Zone', $zone );
|
||||
$this->assertEquals( $zone->get_zone_name(), 'Local' );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zones::get_zone_by
|
||||
*/
|
||||
public function test_get_zone_by() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone_by( 'zone_id', 2 );
|
||||
|
||||
// Assert
|
||||
$this->assertInstanceOf( 'WC_Shipping_Zone', $zone );
|
||||
$this->assertEquals( $zone->get_zone_name(), 'Europe' );
|
||||
|
||||
// Test instance_id
|
||||
$instance_id = $zone->add_shipping_method( 'flat_rate' );
|
||||
|
||||
$zone = \WC_Shipping_Zones::get_zone_by( 'instance_id', $instance_id );
|
||||
|
||||
// Assert
|
||||
$this->assertInstanceOf( 'WC_Shipping_Zone', $zone );
|
||||
$this->assertEquals( $zone->get_zone_name(), 'Europe' );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zones::get_shipping_method
|
||||
*/
|
||||
public function test_get_shipping_method() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone = \WC_Shipping_Zones::get_zone_by( 'zone_id', 1 );
|
||||
$instance_id = $zone->add_shipping_method( 'flat_rate' );
|
||||
$shipping_method = \WC_Shipping_Zones::get_shipping_method( $instance_id );
|
||||
|
||||
// Assert
|
||||
$this->assertInstanceOf( 'WC_Shipping_Flat_Rate', $shipping_method );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zones::delete_zone
|
||||
*/
|
||||
public function test_delete_zone() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
\WC_Shipping_Zones::delete_zone( 1 );
|
||||
$zones = \WC_Shipping_Zones::get_zones();
|
||||
|
||||
// Assert
|
||||
$this->assertTrue( 3 === \sizeof( $zones ) );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: WC_Shipping_Zones::get_zone_matching_package
|
||||
*/
|
||||
public function test_get_zone_matching_package() {
|
||||
// Setup
|
||||
\WC_Helper_Shipping_Zones::create_mock_zones();
|
||||
|
||||
// Test
|
||||
$zone1 = \WC_Shipping_Zones::get_zone_matching_package( array(
|
||||
'destination' => array(
|
||||
'country' => 'GB',
|
||||
'state' => 'Cambs',
|
||||
'postcode' => 'CB23 1GG',
|
||||
)
|
||||
) );
|
||||
$zone2 = \WC_Shipping_Zones::get_zone_matching_package( array(
|
||||
'destination' => array(
|
||||
'country' => 'GB',
|
||||
'state' => 'Cambs',
|
||||
'postcode' => 'PE12 1BG',
|
||||
)
|
||||
) );
|
||||
$zone3 = \WC_Shipping_Zones::get_zone_matching_package( array(
|
||||
'destination' => array(
|
||||
'country' => 'US',
|
||||
'state' => 'CA',
|
||||
'postcode' => '90210',
|
||||
)
|
||||
) );
|
||||
$zone4 = \WC_Shipping_Zones::get_zone_matching_package( array(
|
||||
'destination' => array(
|
||||
'country' => 'US',
|
||||
'state' => 'AL',
|
||||
'postcode' => '12345',
|
||||
)
|
||||
) );
|
||||
|
||||
// Assert
|
||||
$this->assertEquals( 'Local', $zone1->get_zone_name() );
|
||||
$this->assertEquals( 'Europe', $zone2->get_zone_name() );
|
||||
$this->assertEquals( 'California', $zone3->get_zone_name() );
|
||||
$this->assertEquals( 'US', $zone4->get_zone_name() );
|
||||
|
||||
// Clean
|
||||
\WC_Helper_Shipping_Zones::remove_mock_zones();
|
||||
}
|
||||
}
|
|
@ -34,7 +34,9 @@ class WC_Tests_Install extends \WC_Unit_Test_Case {
|
|||
// clean existing install first
|
||||
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
|
||||
define( 'WP_UNINSTALL_PLUGIN', true );
|
||||
update_option( 'woocommerce_status_options', array( 'uninstall_data' => 1 ) );
|
||||
}
|
||||
|
||||
include( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) . '/uninstall.php' );
|
||||
|
||||
\WC_Install::install();
|
||||
|
@ -86,6 +88,7 @@ class WC_Tests_Install extends \WC_Unit_Test_Case {
|
|||
// Clean existing install first
|
||||
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
|
||||
define( 'WP_UNINSTALL_PLUGIN', true );
|
||||
update_option( 'woocommerce_status_options', array( 'uninstall_data' => 1 ) );
|
||||
}
|
||||
include( dirname( dirname( dirname( dirname( __FILE__ ) ) ) ) . '/uninstall.php' );
|
||||
|
||||
|
|
|
@ -46,6 +46,9 @@ if ( ! empty( $status_options['uninstall_data'] ) ) {
|
|||
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}woocommerce_termmeta" );
|
||||
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}woocommerce_tax_rates" );
|
||||
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}woocommerce_tax_rate_locations" );
|
||||
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}woocommerce_shipping_zone_methods" );
|
||||
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}woocommerce_shipping_zone_locations" );
|
||||
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}woocommerce_shipping_zones" );
|
||||
$wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}woocommerce_sessions" );
|
||||
|
||||
// Delete options.
|
||||
|
|
|
@ -284,6 +284,7 @@ final class WooCommerce {
|
|||
include_once( 'includes/class-wc-form-handler.php' ); // Form Handlers
|
||||
include_once( 'includes/class-wc-cart.php' ); // The main cart class
|
||||
include_once( 'includes/class-wc-tax.php' ); // Tax class
|
||||
include_once( 'includes/class-wc-shipping-zones.php' ); // Shipping Zones class
|
||||
include_once( 'includes/class-wc-customer.php' ); // Customer class
|
||||
include_once( 'includes/class-wc-shortcodes.php' ); // Shortcodes class
|
||||
include_once( 'includes/class-wc-https.php' ); // https Helper
|
||||
|
|
Loading…
Reference in New Issue