Zones first draft with backbone saving of zone names
This commit is contained in:
parent
56f274b68b
commit
14eeb9f936
File diff suppressed because one or more lines are too long
|
@ -2117,8 +2117,16 @@ table.wc_shipping_zones {
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
padding: 1em 1em;
|
padding: 1em 1em;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
background: #fff;
|
||||||
}
|
}
|
||||||
tbody tr:nth-child(odd) {
|
tbody.wc-shipping-zone-rows {
|
||||||
|
tr:nth-child(odd) {
|
||||||
|
td {
|
||||||
|
background: #f9f9f9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tr.odd {
|
||||||
td {
|
td {
|
||||||
background: #f9f9f9;
|
background: #f9f9f9;
|
||||||
}
|
}
|
||||||
|
@ -2173,8 +2181,30 @@ table.wc_shipping_zones {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
a.delete {
|
.wc-shipping-zone-actions {
|
||||||
|
width: 3em;
|
||||||
|
|
||||||
|
a.wc-shipping-zone-edit {
|
||||||
@include ir();
|
@include ir();
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
@include icon;
|
||||||
|
content: "\e603";
|
||||||
|
color: #999;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
&:before {
|
||||||
|
color: $red;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a.wc-shipping-zone-delete {
|
||||||
|
@include ir();
|
||||||
|
float: right;
|
||||||
|
margin-left: 1em;
|
||||||
|
|
||||||
&:before {
|
&:before {
|
||||||
@include icon;
|
@include icon;
|
||||||
|
@ -2189,6 +2219,7 @@ table.wc_shipping_zones {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
tfoot {
|
tfoot {
|
||||||
input {
|
input {
|
||||||
float:right;
|
float:right;
|
||||||
|
|
|
@ -0,0 +1,248 @@
|
||||||
|
/* global shippingZonesLocalizeScript, ajaxurl */
|
||||||
|
( function( $, data, wp, ajaxurl ) {
|
||||||
|
$( function() {
|
||||||
|
|
||||||
|
var $table = $( '.wc_shipping_zones' ),
|
||||||
|
$tbody = $( '.wc-shipping-zone-rows' ),
|
||||||
|
$save_button = $( 'input[name="save"]' ),
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
alert( data.strings.save_failed );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ),
|
||||||
|
|
||||||
|
// Backbone view
|
||||||
|
ShippingZoneView = Backbone.View.extend({
|
||||||
|
rowTemplate: wp.template( 'wc-shipping-zone-row' ),
|
||||||
|
initialize: function() {
|
||||||
|
this.listenTo( this.model, 'change:zones', this.setUnloadConfirmation );
|
||||||
|
this.listenTo( this.model, 'saved:zones', this.clearUnloadConfirmation );
|
||||||
|
$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 );
|
||||||
|
$save_button.attr( 'disabled','disabled' );
|
||||||
|
$table.find( '.wc-shipping-zone-add' ).on( 'click', { view: this }, this.onAddNewRow );
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
var zones = _.indexBy( this.model.get( 'zones' ), 'zone_id' ),
|
||||||
|
view = this;
|
||||||
|
|
||||||
|
// Blank out the contents.
|
||||||
|
this.$el.empty();
|
||||||
|
|
||||||
|
if ( _.size( zones ) ) {
|
||||||
|
// Populate $tbody with the current zones
|
||||||
|
$.each( zones, function( id, rowData ) {
|
||||||
|
view.$el.append( view.rowTemplate( rowData ) );
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Make the rows functiothis.$el.find( '.wc-shipping-zone-delete' ).on( 'click', { view: this }, this.onDeleteRow );
|
||||||
|
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 );
|
||||||
|
|
||||||
|
// Stripe
|
||||||
|
if ( _.size(zones) % 2 == 0 ) {
|
||||||
|
$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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSubmit: function( event ) {
|
||||||
|
event.data.view.model.save();
|
||||||
|
event.data.view.render()
|
||||||
|
event.preventDefault();
|
||||||
|
},
|
||||||
|
onAddNewRow: function( event ) {
|
||||||
|
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(),
|
||||||
|
newRow: 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();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
onEditRow: function( event ) {
|
||||||
|
event.preventDefault();
|
||||||
|
$( this ).closest('tr').find('.view, .wc-shipping-zone-edit').hide();
|
||||||
|
$( this ).closest('tr').find('.edit').show();
|
||||||
|
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();
|
||||||
|
|
||||||
|
/*if ( 'city' === attribute || 'postcode' === attribute ) {
|
||||||
|
val = val.split( ';' );
|
||||||
|
val = $.map( val, function( thing ) {
|
||||||
|
return thing.trim();
|
||||||
|
});
|
||||||
|
}*/
|
||||||
|
|
||||||
|
var 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, ui ) {
|
||||||
|
var view = event.data.view,
|
||||||
|
model = view.model,
|
||||||
|
$tr = ui.item,
|
||||||
|
zone_id = $tr.data( 'id' ),
|
||||||
|
zones = _.indexBy( model.get( 'zones' ), 'zone_id' ),
|
||||||
|
old_position = zones[ zone_id ].zone_order,
|
||||||
|
new_position = $tr.index() + ( ( view.page - 1 ) * view.per_page ),
|
||||||
|
which_way = ( new_position > old_position ) ? 'higher' : 'lower',
|
||||||
|
changes = {},
|
||||||
|
zones_to_reorder, reordered_zones;
|
||||||
|
|
||||||
|
zones_to_reorder = _.filter( zones, function( rate ) {
|
||||||
|
var order = parseInt( rate.zone_order, 10 ),
|
||||||
|
limits = [ old_position, new_position ];
|
||||||
|
|
||||||
|
if ( parseInt( rate.zone_id, 10 ) === parseInt( zone_id, 10 ) ) {
|
||||||
|
return true;
|
||||||
|
} else if ( order > _.min( limits ) && order < _.max( limits ) ) {
|
||||||
|
return true;
|
||||||
|
} else if ( 'higher' === which_way && order === _.max( limits ) ) {
|
||||||
|
return true;
|
||||||
|
} else if ( 'lower' === which_way && order === _.min( limits ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} );
|
||||||
|
|
||||||
|
reordered_zones = _.map( zones_to_reorder, function( rate ) {
|
||||||
|
var order = parseInt( rate.zone_order, 10 );
|
||||||
|
|
||||||
|
if ( parseInt( rate.zone_id, 10 ) === parseInt( zone_id, 10 ) ) {
|
||||||
|
rate.zone_order = new_position;
|
||||||
|
} else if ( 'higher' === which_way ) {
|
||||||
|
rate.zone_order = order - 1;
|
||||||
|
} else if ( 'lower' === which_way ) {
|
||||||
|
rate.zone_order = order + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
changes[ rate.zone_id ] = _.extend( changes[ rate.zone_id ] || {}, { zone_order : rate.zone_order } );
|
||||||
|
|
||||||
|
return rate;
|
||||||
|
} );
|
||||||
|
|
||||||
|
if ( reordered_zones.length ) {
|
||||||
|
model.logChanges( changes );
|
||||||
|
view.render(); // temporary, probably should get yanked.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ),
|
||||||
|
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
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})( jQuery, shippingZonesLocalizeScript, wp, ajaxurl );
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -102,6 +102,7 @@ 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-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( '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' ), 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' ), 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_VERSION );
|
||||||
|
|
||||||
// Chosen is @deprecated (2.3) in favour of select2, but is registered for backwards compat
|
// Chosen is @deprecated (2.3) in favour of select2, but is registered for backwards compat
|
||||||
wp_register_script( 'ajax-chosen', WC()->plugin_url() . '/assets/js/chosen/ajax-chosen.jquery' . $suffix . '.js', array( 'jquery', 'chosen' ), WC_VERSION );
|
wp_register_script( 'ajax-chosen', WC()->plugin_url() . '/assets/js/chosen/ajax-chosen.jquery' . $suffix . '.js', array( 'jquery', 'chosen' ), WC_VERSION );
|
||||||
|
|
|
@ -23,6 +23,23 @@ class WC_Admin_Shipping_Zones {
|
||||||
public static function output() {
|
public static function output() {
|
||||||
$allowed_countries = WC()->countries->get_allowed_countries();
|
$allowed_countries = WC()->countries->get_allowed_countries();
|
||||||
$continents = WC()->countries->get_continents();
|
$continents = WC()->countries->get_continents();
|
||||||
|
|
||||||
|
// Localize and enqueue our js.
|
||||||
|
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' )
|
||||||
|
),
|
||||||
|
) );
|
||||||
|
wp_enqueue_script( 'wc-shipping-zones' );
|
||||||
|
|
||||||
include_once( 'views/html-admin-page-shipping-zones.php' );
|
include_once( 'views/html-admin-page-shipping-zones.php' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,31 +10,18 @@
|
||||||
<th class="wc-shipping-zone-name">Zone Name</th>
|
<th class="wc-shipping-zone-name">Zone Name</th>
|
||||||
<th class="wc-shipping-zone-region">Region(s)</th>
|
<th class="wc-shipping-zone-region">Region(s)</th>
|
||||||
<th class="wc-shipping-zone-methods">Shipping Method(s)</th>
|
<th class="wc-shipping-zone-methods">Shipping Method(s)</th>
|
||||||
<th class="wc-shipping-zone-remove"> </th>
|
<th class="wc-shipping-zone-actions"> </th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="5">
|
<td colspan="5">
|
||||||
<a class="button button-secondary" href="#"><?php esc_html_e( 'Add shipping zone', 'woocommerce' ); ?></a>
|
<a class="button button-secondary wc-shipping-zone-add" href="#"><?php esc_html_e( 'Add shipping zone', 'woocommerce' ); ?></a>
|
||||||
<input type="submit" class="button button-primary" value="Save shipping zones" />
|
<input type="submit" name="save" class="button button-primary" value="Save shipping zones" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
<tbody>
|
<tbody class="wc-shipping-zone-rows">
|
||||||
<tr>
|
|
||||||
<td width="1%" class="wc-shipping-zone-sort">
|
|
||||||
<input type="hidden" name="zone_order[]" value="">
|
|
||||||
</td>
|
|
||||||
<td class="wc-shipping-zone-name">
|
|
||||||
UK and Eire
|
|
||||||
</td>
|
|
||||||
<td>UK, Ireland</td>
|
|
||||||
<td>
|
|
||||||
<a href="#"><?php esc_html_e( 'Add a shipping method', 'woocommerce' ); ?></a>
|
|
||||||
</td>
|
|
||||||
<td width="1%"><a class="delete" href="#"><?php _e( 'Delete', 'woocommerce' ); ?></a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td width="1%" class="wc-shipping-zone-sort">
|
<td width="1%" class="wc-shipping-zone-sort">
|
||||||
<input type="hidden" name="zone_order[]" value="">
|
<input type="hidden" name="zone_order[]" value="">
|
||||||
|
@ -61,7 +48,7 @@
|
||||||
<a href="">Limit to specific states</a> | <a href="">Limit to specific zip codes</a>
|
<a href="">Limit to specific states</a> | <a href="">Limit to specific zip codes</a>
|
||||||
</td>
|
</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td width="1%"><a class="delete" href="#"><?php _e( 'Delete', 'woocommerce' ); ?></a></td>
|
<td class="wc-shipping-zone-actions"><a class="delete" href="#"><?php _e( 'Delete', 'woocommerce' ); ?></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -72,11 +59,28 @@
|
||||||
</td>
|
</td>
|
||||||
<td class="wc-shipping-zone-region"><?php esc_html_e( 'Shipping methods added here apply to all regions without a zone.', 'woocommerce' ); ?></td>
|
<td class="wc-shipping-zone-region"><?php esc_html_e( 'Shipping methods added here apply to all regions without a zone.', 'woocommerce' ); ?></td>
|
||||||
<td>
|
<td>
|
||||||
<a href="#"><?php esc_html_e( 'Add a shipping method', 'woocommerce' ); ?></a>
|
<a href="#" class="wc-shipping-zone-add-method button"><?php esc_html_e( 'Add a shipping method', 'woocommerce' ); ?></a>
|
||||||
|
</td>
|
||||||
|
<td class="wc-shipping-zone-actions">
|
||||||
|
<a class="wc-shipping-zone-delete" href="#"><?php _e( 'Delete', 'woocommerce' ); ?></a>
|
||||||
</td>
|
</td>
|
||||||
<td width="1%"><a class="delete" href="#"><?php _e( 'Delete', 'woocommerce' ); ?></a></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<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">{{ data.zone_name }}</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></td>
|
||||||
|
<td><a class="wc-shipping-zone-add-method button" href="#"><?php esc_html_e( 'Add a shipping method', 'woocommerce' ); ?></a></td>
|
||||||
|
<td class="wc-shipping-zone-actions">
|
||||||
|
<a class="wc-shipping-zone-delete" href="#"><?php _e( 'Delete', 'woocommerce' ); ?></a><a class="wc-shipping-zone-edit" href="#"><?php _e( 'Edit', 'woocommerce' ); ?></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</script>
|
||||||
|
|
|
@ -141,6 +141,7 @@ class WC_AJAX {
|
||||||
'save_variations' => false,
|
'save_variations' => false,
|
||||||
'bulk_edit_variations' => false,
|
'bulk_edit_variations' => false,
|
||||||
'tax_rates_save_changes' => false,
|
'tax_rates_save_changes' => false,
|
||||||
|
'shipping_zones_save_changes' => false,
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ( $ajax_events as $ajax_event => $nopriv ) {
|
foreach ( $ajax_events as $ajax_event => $nopriv ) {
|
||||||
|
@ -3019,6 +3020,55 @@ class WC_AJAX {
|
||||||
'rates' => WC_Tax::get_rates_for_tax_class( $current_class ),
|
'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' . (isset( $_POST['wc_shipping_zones_nonce'] ) ? 1 : 0). (isset( $_POST['changes'] ) ? 1 : 0) );
|
||||||
|
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 = new WC_Shipping_Zone( $zone_data['zone_id'] );
|
||||||
|
$zone->set_zone_name( $zone_data['zone_name'] );
|
||||||
|
$zone->set_zone_order( isset( $zone_data['zone_order'] ) ? $zone_data['zone_order'] : 0 );
|
||||||
|
$zone->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_send_json_success( array(
|
||||||
|
'zones' => WC_Shipping_Zones::get_zones(),
|
||||||
|
) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WC_AJAX::init();
|
WC_AJAX::init();
|
||||||
|
|
|
@ -462,6 +462,22 @@ CREATE TABLE {$wpdb->prefix}woocommerce_tax_rate_locations (
|
||||||
KEY tax_rate_id (tax_rate_id),
|
KEY tax_rate_id (tax_rate_id),
|
||||||
KEY location_type (location_type),
|
KEY location_type (location_type),
|
||||||
KEY location_type_code (location_type(40),location_code(90))
|
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 (tax_rate_id),
|
||||||
|
KEY location_type (location_type),
|
||||||
|
KEY location_type_code (location_type(40),location_code(90))
|
||||||
) $collate;
|
) $collate;
|
||||||
";
|
";
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,244 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a single shipping zone
|
||||||
|
*
|
||||||
|
* @class WC_Shipping_Zone
|
||||||
|
* @version 2.5.0
|
||||||
|
* @package WooCommerce/Classes
|
||||||
|
* @category Class
|
||||||
|
* @author WooThemes
|
||||||
|
*/
|
||||||
|
class WC_Shipping_Zone {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get class data array
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_data() {
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert zone into the database
|
||||||
|
* @access private
|
||||||
|
* @param int Read zone data from DB
|
||||||
|
*/
|
||||||
|
private function read( $zone_id ) {
|
||||||
|
global $wpdb;
|
||||||
|
|
||||||
|
if ( $zone_data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zones WHERE zone_id = %d LIMIT 1;", $zone_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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is passed location type valid?
|
||||||
|
* @param string $type
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function is_valid_location_type( $type ) {
|
||||||
|
return in_array( $type, array( 'postcode', 'state' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add location (state or postcode) to a zone.
|
||||||
|
* @param string $code
|
||||||
|
* @param string $type state or postcode
|
||||||
|
*/
|
||||||
|
public function add_location( $code, $type ) {
|
||||||
|
if ( 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set locations
|
||||||
|
* @param array $locations Array of locations
|
||||||
|
*/
|
||||||
|
public function set_locations( $locations = array() ) {
|
||||||
|
$this->data['zone_locations'] = array();
|
||||||
|
|
||||||
|
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 LIMIT 1;", $zone_id ) ) ) {
|
||||||
|
foreach ( $locations as $location ) {
|
||||||
|
$this->add_location( $location->location_code, $location->location_type );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->_locations_changed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save zone data to the database
|
||||||
|
* @param array data to save for this zone
|
||||||
|
*/
|
||||||
|
public function save() {
|
||||||
|
$data = array(
|
||||||
|
'zone_name' => $this->get_zone_name(),
|
||||||
|
'zone_order' => $this->get_zone_order(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! $this->get_zone_id() ) {
|
||||||
|
$this->create( $data );
|
||||||
|
} else {
|
||||||
|
$this->update( $data );
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->save_locations();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
$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
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert zone into the database
|
||||||
|
* @access private
|
||||||
|
* @param array $zone_data data to save for this zone
|
||||||
|
*/
|
||||||
|
private function create( $zone_data ) {
|
||||||
|
global $wpdb;
|
||||||
|
$wpdb->insert( $wpdb->prefix . 'woocommerce_shipping_zones', $zone_data );
|
||||||
|
$this->set_zone_id( $wpdb->insert_id );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update zone in the database
|
||||||
|
* @access private
|
||||||
|
* @param array $zone_data data to save for this zone
|
||||||
|
*/
|
||||||
|
public function update( $zone_data ) {
|
||||||
|
global $wpdb;
|
||||||
|
$wpdb->update( $wpdb->prefix . 'woocommerce_shipping_zones', $zone_data, array( 'zone_id' => $this->get_zone_id() ) );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles storage and retrieval of shipping zones
|
||||||
|
*
|
||||||
|
* @class WC_Shipping_Zones
|
||||||
|
* @version 2.5.0
|
||||||
|
* @package WooCommerce/Classes
|
||||||
|
* @category Class
|
||||||
|
* @author WooThemes
|
||||||
|
*/
|
||||||
|
class WC_Shipping_Zones {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get shipping zones from the database
|
||||||
|
* @return [type] [description]
|
||||||
|
*/
|
||||||
|
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;" );
|
||||||
|
$zones = array();
|
||||||
|
|
||||||
|
foreach ( $raw_zones as $raw_zone ) {
|
||||||
|
$zone = new WC_Shipping_Zone( $raw_zone );
|
||||||
|
$zones[] = $zone->get_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $zones;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function delete_zone( $zone_id ) {
|
||||||
|
global $wpdb;
|
||||||
|
$wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array( 'zone_id' => $zone_id ) );
|
||||||
|
$wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zones', array( 'zone_id' => $zone_id ) );
|
||||||
|
}
|
||||||
|
}
|
|
@ -263,6 +263,7 @@ final class WooCommerce {
|
||||||
include_once( 'includes/class-wc-form-handler.php' ); // Form Handlers
|
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-cart.php' ); // The main cart class
|
||||||
include_once( 'includes/class-wc-tax.php' ); // Tax 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-customer.php' ); // Customer class
|
||||||
include_once( 'includes/class-wc-shortcodes.php' ); // Shortcodes class
|
include_once( 'includes/class-wc-shortcodes.php' ); // Shortcodes class
|
||||||
include_once( 'includes/class-wc-https.php' ); // https Helper
|
include_once( 'includes/class-wc-https.php' ); // https Helper
|
||||||
|
|
Loading…
Reference in New Issue