├── assets
├── css
│ └── admin.css
└── js
│ ├── table-rate-rows.js
│ └── table-rate-rows.min.js
├── changelog.txt
├── includes
├── class-wc-shipping-table-rate-privacy.php
├── class-wc-shipping-table-rate.php
├── functions-admin.php
├── functions-ajax.php
└── legacy
│ └── shipping-zones
│ ├── assets
│ ├── css
│ │ ├── shipping_zones.css
│ │ └── shipping_zones.less
│ └── js
│ │ └── shipping-zone-admin.js
│ ├── class-wc-shipping-zones.php
│ └── includes
│ ├── class-wc-shipping-zone-admin.php
│ ├── class-wc-shipping-zone.php
│ ├── class-wc-shipping-zones-admin.php
│ ├── class-wc-shipping-zones-ajax-handler.php
│ ├── list-tables
│ ├── class-wc-shipping-zone-methods-table.php
│ └── class-wc-shipping-zones-table.php
│ ├── views
│ ├── form-add-shipping-zone.php
│ ├── form-edit-shipping-zone.php
│ ├── html-zone-list.php
│ ├── html-zone-method-settings.php
│ └── html-zone-methods.php
│ └── wc-shipping-zone-functions.php
├── installer.php
├── languages
└── woocommerce-table-rate-shipping.pot
├── uninstall.php
└── woocommerce-table-rate-shipping.php
/assets/css/admin.css:
--------------------------------------------------------------------------------
1 | #shipping_class_priorities table input,#shipping_class_priorities table select,table#shipping_rates input,table#shipping_rates select{width:100%}#shipping_class_priorities table input[type=checkbox],table#shipping_rates input[type=checkbox]{width:auto}#shipping_class_priorities table td,table#shipping_rates td{cursor:move}#shipping_class_priorities table a.dupe,#shipping_class_priorities table a.remove,table#shipping_rates a.dupe,table#shipping_rates a.remove{float:right;margin-left:4px}#shipping_class_priorities table td,#shipping_class_priorities table th,table#shipping_rates td,table#shipping_rates th{padding:15px 10px;vertical-align:middle}#shipping_class_priorities table tr:nth-child(even) td,#shipping_class_priorities table tr:nth-child(even) th,table#shipping_rates tr:nth-child(even) td,table#shipping_rates tr:nth-child(even) th{background:#fafafa}#shipping_class_priorities table td.checkbox,#shipping_class_priorities table th.checkbox,table#shipping_rates td.checkbox,table#shipping_rates th.checkbox{text-align:center}#shipping_class_priorities table td .disabled,table#shipping_rates td .disabled{opacity:.5}#shipping_class_priorities table .check-column,table#shipping_rates .check-column{width:24px;min-width:24px!important;text-align:center;padding:15px 10px}#shipping_class_priorities table .check-column input,table#shipping_rates .check-column input{width:auto;vertical-align:middle;margin:0 0 0 8px}
--------------------------------------------------------------------------------
/assets/js/table-rate-rows.js:
--------------------------------------------------------------------------------
1 | /*global $, woocommerce_shipping_table_rate_rows, ajaxurl */
2 | ( function( $, data, wp, ajaxurl ) {
3 |
4 | var wc_table_rate_rows_row_template = wp.template( 'table-rate-shipping-row-template' ),
5 | $settings_form = $( '#mainform' ),
6 | $rates_table = $( '#shipping_rates' ),
7 | $rates = $rates_table.find( 'tbody.table_rates' );
8 |
9 | var wc_table_rate_rows = {
10 | init: function() {
11 | $settings_form
12 | .on( 'change', '#woocommerce_table_rate_calculation_type', this.onCalculationTypeChange );
13 | $rates_table
14 | .on( 'change', 'select[name^="shipping_condition"]', this.onShippingConditionChange )
15 | .on( 'change', 'input[name^="shipping_abort["]', this.onShippingAbortChange )
16 | .on( 'click', 'a.add-rate', this.onAddRate )
17 | .on( 'click', 'a.remove', this.onRemoveRate )
18 | .on( 'click', 'a.dupe', this.onDupeRate );
19 |
20 | var rates_data = $rates.data( 'rates' );
21 |
22 | $( rates_data ).each( function( i ) {
23 | var size = $rates.find( '.table_rate' ).length;
24 | $rates.append( wc_table_rate_rows_row_template( {
25 | rate: rates_data[ i ],
26 | index: size
27 | } ) );
28 | } );
29 |
30 | $( 'label[for="woocommerce_table_rate_handling_fee"], label[for="woocommerce_table_rate_max_cost"], label[for="woocommerce_table_rate_min_cost"]', $settings_form ).each( function( i, el ) {
31 | $(el).data( 'o_label', $(el).text() );
32 | });
33 |
34 | $( '#woocommerce_table_rate_calculation_type, select[name^="shipping_condition"], input[name^="shipping_abort["]', $settings_form ).change();
35 |
36 | $rates.sortable( {
37 | items: 'tr',
38 | cursor: 'move',
39 | axis: 'y',
40 | handle: 'td',
41 | scrollSensitivity: 40,
42 | helper: function(e,ui){
43 | ui.children().each( function() {
44 | $( this ).width( $(this).width() );
45 | });
46 | ui.css( 'left', '0' );
47 | return ui;
48 | },
49 | start: function( event, ui ) {
50 | ui.item.css('background-color','#f6f6f6');
51 | },
52 | stop: function( event, ui ) {
53 | ui.item.removeAttr( 'style' );
54 | wc_table_rate_rows.reindexRows();
55 | }
56 | } );
57 | },
58 | onCalculationTypeChange: function() {
59 | var selected = $( this ).val();
60 |
61 | if ( selected == 'item' ) {
62 | $( 'td.cost_per_item input' ).attr( 'disabled', 'disabled' ).addClass('disabled');
63 | } else {
64 | $( 'td.cost_per_item input' ).removeAttr( 'disabled' ).removeClass('disabled');
65 | }
66 |
67 | if ( selected ) {
68 | $( '#shipping_class_priorities' ).hide();
69 | $( 'td.shipping_label, th.shipping_label' ).hide();
70 | } else {
71 | $( '#shipping_class_priorities' ).show();
72 | $( 'td.shipping_label, th.shipping_label' ).show();
73 | }
74 |
75 | if ( ! selected ) {
76 | $( '#shipping_class_priorities span.description.per_order' ).show();
77 | $( '#shipping_class_priorities span.description.per_class' ).hide();
78 | }
79 |
80 | var label_text = data.i18n.order;
81 |
82 | if ( selected == 'item' ) {
83 | label_text = data.i18n.item;
84 | } else if ( selected == 'line' ) {
85 | label_text = data.i18n.line_item;
86 | } else if ( selected == 'class' ) {
87 | label_text = data.i18n.class;
88 | }
89 |
90 | $('label[for="woocommerce_table_rate_handling_fee"], label[for="woocommerce_table_rate_max_cost"], label[for="woocommerce_table_rate_min_cost"]').each(function( i, el ) {
91 | var text = $(el).data( 'o_label' );
92 | text = text.replace( '[item]', label_text );
93 | $(el).text( text );
94 | });
95 | },
96 | onShippingConditionChange: function() {
97 | var selected = $( this ).val();
98 | var $row = $( this ).closest('tr');
99 |
100 | if ( selected == '' ) {
101 | $row.find('input[name^="shipping_min"], input[name^="shipping_max"]').val( '' ).prop( 'disabled', true ).addClass( 'disabled' );
102 | } else {
103 | $row.find('input[name^="shipping_min"], input[name^="shipping_max"]').prop( 'disabled', false ).removeClass( 'disabled' );
104 | }
105 | },
106 | onShippingAbortChange: function() {
107 | var checked = $( this ).is( ':checked' );
108 | var $row = $( this ).closest( 'tr' );
109 |
110 | if ( checked ) {
111 | $row.find('td.cost').hide();
112 | $row.find('td.abort_reason').show();
113 | $row.find('input[name^="shipping_per_item"], input[name^="shipping_cost_per_weight"], input[name^="shipping_cost_percent"], input[name^="shipping_cost"], input[name^="shipping_label"]').prop( 'disabled', true ).addClass( 'disabled' );
114 | } else {
115 | $row.find('td.cost').show();
116 | $row.find('td.abort_reason').hide();
117 | $row.find('input[name^="shipping_per_item"], input[name^="shipping_cost_per_weight"], input[name^="shipping_cost_percent"], input[name^="shipping_cost"], input[name^="shipping_label"]').prop( 'disabled', false ).removeClass( 'disabled' );
118 | }
119 |
120 | $( '#woocommerce_table_rate_calculation_type' ).change();
121 | },
122 | onAddRate: function( event ) {
123 | event.preventDefault();
124 | var target = $rates;
125 | var size = target.find( '.table_rate' ).length;
126 |
127 | target.append( wc_table_rate_rows_row_template( {
128 | rate: {
129 | rate_id: '',
130 | rate_class: '',
131 | rate_condition: '',
132 | rate_min: '',
133 | rate_max: '',
134 | rate_priority: '',
135 | rate_abort: '',
136 | rate_abort_reason: '',
137 | rate_cost: '',
138 | rate_cost_per_item: '',
139 | rate_cost_per_weight_unit: '',
140 | rate_cost_percent: '',
141 | rate_label: ''
142 | },
143 | index: size
144 | } ) );
145 |
146 | $( '#woocommerce_table_rate_calculation_type, select[name^="shipping_condition"], input[name^="shipping_abort["]', $rates_table ).change();
147 | },
148 | onRemoveRate: function( event ) {
149 | event.preventDefault();
150 | if ( confirm( data.i18n.delete_rates ) ) {
151 | var rate_ids = [];
152 |
153 | $rates.find( 'tr td.check-column input:checked' ).each( function( i, el ) {
154 | var rate_id = $(el).closest( 'tr.table_rate' ).find( '.rate_id' ).val();
155 | rate_ids.push( rate_id );
156 | $(el).closest( 'tr.table_rate' ).addClass( 'deleting' );
157 | });
158 |
159 | var ajax_data = {
160 | action: 'woocommerce_table_rate_delete',
161 | rate_id: rate_ids,
162 | security: data.delete_rates_nonce
163 | };
164 |
165 | $.post( ajaxurl, ajax_data, function(response) {
166 | $( 'tr.deleting').fadeOut( '300', function() {
167 | $( this ).remove();
168 | } );
169 | });
170 | }
171 | },
172 | onDupeRate: function( event ) {
173 | event.preventDefault();
174 | if ( confirm( data.i18n.dupe_rates ) ) {
175 |
176 | $rates.find( 'tr td.check-column input:checked' ).each( function( i, el ) {
177 | var dupe = $(el).closest( 'tr' ).clone();
178 | dupe.find( '.rate_id' ).val( '0' );
179 | $rates.append( dupe );
180 | });
181 |
182 | wc_table_rate_rows.reindexRows();
183 | }
184 | },
185 | reindexRows: function() {
186 | var loop = 0;
187 | $rates.find( 'tr' ).each( function( index, row ) {
188 | $('input.text, input.checkbox, select.select, input[type=hidden]', row ).each( function( i, el ) {
189 | var t = $(el);
190 | t.attr( 'name', t.attr('name').replace(/\[([^[]*)\]/, "[" + loop + "]" ) );
191 | });
192 | loop++;
193 | });
194 | }
195 | };
196 |
197 | wc_table_rate_rows.init();
198 |
199 | })( jQuery, woocommerce_shipping_table_rate_rows, wp, ajaxurl );
200 |
--------------------------------------------------------------------------------
/assets/js/table-rate-rows.min.js:
--------------------------------------------------------------------------------
1 | !function(a,i,e,o){var n=e.template("table-rate-shipping-row-template"),t=a("#mainform"),r=a("#shipping_rates"),s=r.find("tbody.table_rates"),p={init:function(){t.on("change","#woocommerce_table_rate_calculation_type",this.onCalculationTypeChange),r.on("change",'select[name^="shipping_condition"]',this.onShippingConditionChange).on("change",'input[name^="shipping_abort["]',this.onShippingAbortChange).on("click","a.add-rate",this.onAddRate).on("click","a.remove",this.onRemoveRate).on("click","a.dupe",this.onDupeRate);var i=s.data("rates");a(i).each(function(e){var t=s.find(".table_rate").length;s.append(n({rate:i[e],index:t}))}),a('label[for="woocommerce_table_rate_handling_fee"], label[for="woocommerce_table_rate_max_cost"], label[for="woocommerce_table_rate_min_cost"]',t).each(function(e,t){a(t).data("o_label",a(t).text())}),a('#woocommerce_table_rate_calculation_type, select[name^="shipping_condition"], input[name^="shipping_abort["]',t).change(),s.sortable({items:"tr",cursor:"move",axis:"y",handle:"td",scrollSensitivity:40,helper:function(e,t){return t.children().each(function(){a(this).width(a(this).width())}),t.css("left","0"),t},start:function(e,t){t.item.css("background-color","#f6f6f6")},stop:function(e,t){t.item.removeAttr("style"),p.reindexRows()}})},onCalculationTypeChange:function(){var e=a(this).val();"item"==e?a("td.cost_per_item input").attr("disabled","disabled").addClass("disabled"):a("td.cost_per_item input").removeAttr("disabled").removeClass("disabled"),e?(a("#shipping_class_priorities").hide(),a("td.shipping_label, th.shipping_label").hide()):(a("#shipping_class_priorities").show(),a("td.shipping_label, th.shipping_label").show()),e||(a("#shipping_class_priorities span.description.per_order").show(),a("#shipping_class_priorities span.description.per_class").hide());var n=i.i18n.order;"item"==e?n=i.i18n.item:"line"==e?n=i.i18n.line_item:"class"==e&&(n=i.i18n.class),a('label[for="woocommerce_table_rate_handling_fee"], label[for="woocommerce_table_rate_max_cost"], label[for="woocommerce_table_rate_min_cost"]').each(function(e,t){var i=a(t).data("o_label");i=i.replace("[item]",n),a(t).text(i)})},onShippingConditionChange:function(){var e=a(this).val(),t=a(this).closest("tr");""==e?t.find('input[name^="shipping_min"], input[name^="shipping_max"]').val("").prop("disabled",!0).addClass("disabled"):t.find('input[name^="shipping_min"], input[name^="shipping_max"]').prop("disabled",!1).removeClass("disabled")},onShippingAbortChange:function(){var e=a(this).is(":checked"),t=a(this).closest("tr");e?(t.find("td.cost").hide(),t.find("td.abort_reason").show(),t.find('input[name^="shipping_per_item"], input[name^="shipping_cost_per_weight"], input[name^="shipping_cost_percent"], input[name^="shipping_cost"], input[name^="shipping_label"]').prop("disabled",!0).addClass("disabled")):(t.find("td.cost").show(),t.find("td.abort_reason").hide(),t.find('input[name^="shipping_per_item"], input[name^="shipping_cost_per_weight"], input[name^="shipping_cost_percent"], input[name^="shipping_cost"], input[name^="shipping_label"]').prop("disabled",!1).removeClass("disabled")),a("#woocommerce_table_rate_calculation_type").change()},onAddRate:function(e){e.preventDefault();var t=s,i=t.find(".table_rate").length;t.append(n({rate:{rate_id:"",rate_class:"",rate_condition:"",rate_min:"",rate_max:"",rate_priority:"",rate_abort:"",rate_abort_reason:"",rate_cost:"",rate_cost_per_item:"",rate_cost_per_weight_unit:"",rate_cost_percent:"",rate_label:""},index:i})),a('#woocommerce_table_rate_calculation_type, select[name^="shipping_condition"], input[name^="shipping_abort["]',r).change()},onRemoveRate:function(e){if(e.preventDefault(),confirm(i.i18n.delete_rates)){var n=[];s.find("tr td.check-column input:checked").each(function(e,t){var i=a(t).closest("tr.table_rate").find(".rate_id").val();n.push(i),a(t).closest("tr.table_rate").addClass("deleting")});var t={action:"woocommerce_table_rate_delete",rate_id:n,security:i.delete_rates_nonce};a.post(o,t,function(e){a("tr.deleting").fadeOut("300",function(){a(this).remove()})})}},onDupeRate:function(e){e.preventDefault(),confirm(i.i18n.dupe_rates)&&(s.find("tr td.check-column input:checked").each(function(e,t){var i=a(t).closest("tr").clone();i.find(".rate_id").val("0"),s.append(i)}),p.reindexRows())},reindexRows:function(){var n=0;s.find("tr").each(function(e,t){a("input.text, input.checkbox, select.select, input[type=hidden]",t).each(function(e,t){var i=a(t);i.attr("name",i.attr("name").replace(/\[([^[]*)\]/,"["+n+"]"))}),n++})}};p.init()}(jQuery,woocommerce_shipping_table_rate_rows,wp,ajaxurl);
2 |
--------------------------------------------------------------------------------
/changelog.txt:
--------------------------------------------------------------------------------
1 | *** Table Rate Shipping Changelog ***
2 |
3 | 2020-08-19 - version 3.0.29
4 | * Tweak - WordPress 5.5 compatibility.
5 |
6 | 2020-06-05 - version 3.0.28
7 | * Tweak - WC 4.2 compatibility.
8 |
9 | 2020-05-12 - version 3.0.27
10 | * Fix - Use tax rate based on cart items when table rate is set to including taxes.
11 | * Fix - Deduct taxes when user is VAT exempt and table rate is set to including taxes.
12 |
13 | 2020-04-30 - version 3.0.26
14 | * Tweak - WC 4.1 compatibility.
15 |
16 | 2020-04-14 - version 3.0.25
17 | * Fix - Save the abort notice in the session (to display when shipping methods are loaded from cache).
18 |
19 | 2020-04-08 - version 3.0.24
20 | * Fix - Adjust conditions for abort notices to show in cart/checkout pages.
21 | * Tweak - WP 5.4 compatibility.
22 |
23 | 2020-04-01 - version 3.0.23
24 | * Tweak - Add filter to compare price restrictions after discounts and coupons have been applied.
25 | * Tweak - Remove legacy code.
26 |
27 | 2020-03-11 - version 3.0.22
28 | * Fix - Change columns in table based on the chosen calculation type.
29 |
30 | 2020-02-26 - version 3.0.21
31 | * Tweak - WC 4.0 compatibility.
32 | * Tweak - Improve layout for min max fields.
33 |
34 | 2020-02-05 - version 3.0.20
35 | * Fix - Use proper escape for attributes.
36 |
37 | 2020-01-15 - version 3.0.19
38 | * Tweak - Only show abort notices in the cart/checkout page.
39 |
40 | 2019-11-05 - version 3.0.18
41 | * Tweak - WC 3.8 compatibility.
42 |
43 | 2019-08-08 - version 3.0.17
44 | * Tweak - WC 3.7 compatibility.
45 |
46 | 2019-07-02 - version 3.0.16
47 | * Fix - PHP notices.
48 |
49 | 2019-04-14 - version 3.0.15
50 | * Update - Add filter that allows per shipping class intergration with other plugins.
51 | * Tweak - WC 3.6 compatibility.
52 |
53 | 2019-03-04 - version 3.0.14
54 | * Tweak - Order Handling Fee verbiage to not include percentages as not intended.
55 |
56 | 2018-11-28 - version 3.0.13
57 | * Fix - Fatal error with inclusive taxes and calculating rates per item.
58 |
59 | 2018-10-31 - version 3.0.12
60 | * Fix - Default to shipping costs exclusive of taxes for existing methods.
61 |
62 | 2018-10-29 - version 3.0.11
63 | * Fix - Duplicate row would not save changes.
64 | * Update - Allow more than 2 decimals of precision for rule constraints.
65 | * Update - Deleting shipping class deletes related table rate shipping rules.
66 | * Update - Allow table rate prices to be entered inclusive of taxes.
67 | * Fix - Properly determine product's price when inclusive taxes are used and respect the 'woocommerce_adjust_non_base_location_prices' filter.
68 | * Fix - Rounding errors of shipping prices before taxes are added.
69 | * Fix - Multiple abort notices appearing.
70 |
71 | 2018-09-25 - version 3.0.10
72 | * Update - WC 3.5 compatibility.
73 |
74 | 2018-05-30 - version 3.0.9
75 | * Fix - Saving settings not working in WooCommerce 3.4.1
76 |
77 | 2018-05-23 - version 3.0.8
78 | * Update - Privacy policy notification.
79 | * Update - WC 3.4 compatibility.
80 | * Fix - Use correct plugin URL on plugins listview.
81 | * Fix - Weight cost doesn't support different decimal separators.
82 |
83 | 2018-01-26 - version 3.0.7
84 | * Add - Percentage support for Order total Handling Fee.
85 | * Fix - Additional fixes for supporting decimal separator as comma.
86 |
87 | 2018-01-12 - version 3.0.6
88 | * Fix - Decimal separator as comma isn't respected in table rates.
89 |
90 | 2017-12-13 - version 3.0.5
91 | * Update - WC tested up to version.
92 |
93 | 2017-06-20 - version 3.0.4
94 | * Fix - Additional PHP7.1 notice fixes.
95 |
96 | 2017-04-27 - version 3.0.3
97 | * Fix - Additional WC 3.0 compatibility.
98 | * Fix - PHP 7.1 notices.
99 |
100 | 2016-09-19 - version 3.0.2
101 | * Fix - Class type shipping label was not showing.
102 | * Update - Hide unnecessary class priorities depending on calculation type.
103 |
104 | 2016-06-09 - version 3.0.1
105 | * Fix - Undefined method get_field_default which introduced in WC 2.6
106 |
107 | 2016-05-24 - version 3.0.0
108 | * Implemented WC 2.6.0 Support and new data structures.
109 |
110 | 2015-11-20 - version 2.9.2
111 | * Fix - Escape postcodes passed to queries.
112 |
113 | 2015-11-18 - version 2.9.1
114 | * Fix - No matching rates when table rate has 'No Class' rule.
115 | * Fix - Coupons not taken into account when looping through shipping methods.
116 |
117 | 2015-05-12 - version 2.9.0
118 | * Removed legacy notice code.
119 | * Reorganised options
120 | * Added new max cost option.
121 | * Hide shipping classes when unused.
122 |
123 | 2015-04-21 - version 2.8.3
124 | * Fix - Potential XSS with add_query_arg.
125 |
126 | 2015-02-17 - version 2.8.2
127 | * Fix - Postcode save method.
128 |
129 | 2015-02-11 - version 2.8.1
130 | * Fix - Fatal error in cart and checkout when trying to register the shipping methods.
131 |
132 | 2015-01-29 - version 2.8.0
133 | * WC 2.3 Compatibility.
134 | * Refactored shipping zone framework.
135 |
136 | 2014-12-03 - version 2.7.2
137 | * Fixed order type abort. It should abort and offer no rates from the table.
138 |
139 | 2014-10-14 - version 2.7.1
140 | * Fix JS error when abort is selected.
141 |
142 | 2014-10-08 - version 2.7.0
143 | * Row cleanup.
144 | * Additonal logic to 'abort' a table rate if a row matches.
145 | * Show optional message on abort.
146 | * Added option for order handling fee (base cost).
147 | * Added option for max cost.
148 | * Updated text domain.
149 | * Fix display of disabled inputs.
150 |
151 | 2014-01-28 - version 2.6.10
152 | * Only show debugging if set to display
153 |
154 | 2014-01-06 - version 2.6.9
155 | * 2.1 compat
156 |
157 | 2013-12-02 - version 2.6.8
158 | * Hooks for WPML
159 |
160 | 2013-11-21 - version 2.6.7
161 | * Hook when getting product price during calculation
162 |
163 | 2013-08-13 - version 2.6.6
164 | * Fix zone ordering
165 |
166 | 2013-04-25 - version 2.6.5
167 | * sanitize_text_field on state names
168 |
169 | 2013-04-22 - version 2.6.4
170 | * Removed uninstall scripts
171 |
172 | 2013-04-19 - version 2.6.3
173 | * Round weights to 2dp
174 |
175 | 2013-03-15 - version 2.6.2
176 | * Fix numeric ranges
177 |
178 | 2013-03-13 - version 2.6.1
179 | * Localisation for zones
180 |
181 | 2013-01-29 - version 2.6.0
182 | * Shipping Zone interface update
183 |
184 | 2013-01-29 - version 2.5.2
185 | * Correctly cast the shipping class id
186 |
187 | 2013-01-21 - version 2.5.1
188 | * esc_js on class name
189 |
190 | 2013-01-11 - version 2.5.0
191 | * WC 2.0 Compat
192 |
193 | 2012-12-13 - version 2.4.1
194 | * Fix prepare
195 | * Fix class != check
196 |
197 | 2012-11-26 - version 2.4.0
198 | * Previous version class priorities has been removed in favour of running the rates in order of definition.
199 | * Min cost option per table rate.
200 | * New updater
201 |
202 | 2012-11-26 - version 2.3.0
203 | * Fixed method enable/disable setting.
204 | * Choose the order in which classes are evalulated for per-class rates.
205 |
206 | 2012-11-06 - version 2.2.2
207 | * Fix matched rates when using the break option.
208 |
209 | 2012-11-06 - version 2.2.1
210 | * Fix labels
211 |
212 | 2012-11-05 - version 2.2
213 | * For stores with tax inc prices, calculate correct item price with local tax.
214 | * Added debug mode - kicks in when WP_DEBUG is on.
215 | * Fix shipping_condition none.
216 | * Renamed 'priority' to 'break' to make more sense.
217 | * Allow label translation.
218 |
219 | 2012-10-23 - version 2.1.3
220 | * Calculated rate tweak - a row much match or 0 priced rates will be ignored
221 | * Ensure transients are cleared on save
222 |
223 | 2012-10-05 - version 2.1.2
224 | * Fix insert on some systems
225 | * Fix default shipping_method_order in table
226 |
227 | 2012-10-05 - version 2.1.1
228 | * Tweak some text descriptions
229 |
230 | 2012-10-03 - version 2.1.0
231 | * Ability to sort methods within zones to control the order on the frontend
232 |
233 | 2012-08-20 - version 2.0.6
234 | * Fix 'Any Shipping Class'
235 |
236 | 2012-08-14 - version 2.0.5
237 | * Fix priority checkbox for per-class rates
238 |
239 | 2012-07-26 - version 2.0.4
240 | * Set default title for instances - labels are required so this fixes things when title is not set
241 | * Fix get_cart_shipping_class_id function
242 |
243 | 2012-07-19 - version 2.0.3
244 | * First release
245 |
246 | 2012-06-25 - version 2.0.2 Beta
247 | * Fix state detection for zones
248 | * Fix count items in class
249 | * Fix no shipping class query
250 | * Don't hide empty shipping classes
251 | * 'None' condition
252 |
253 | 2012-06-12 - version 2.0.1 Beta
254 | * Fix zone dropdown for states
255 |
256 | 2012-04-19 - version 2.0 Beta
257 | * Re-write based on user feedback. Due to the massive restructure, and new zones functionality it isn't possible to upgrade your old rates - you will need to re-enter them (however, due to the zones and new features this process should be much easier!)
258 | * Re-done the interface for efficiency
259 | * Introduction of shipping zones to simplify data entry
260 | * Allow costs to be defined with 4dp to prevent rounding issues
261 | * items_in_class condition, if you only want to count items of the priority class
262 | * Rates stored in a table rather than serialised for improved reliability
263 | * Calculated rates (add matching rules together)
264 | * Per item, per line, per class rules for calculated rates
265 | * Multiple table rate instances per zone
266 | * Define costs per item, per weight unit, and a percent of the total
267 |
268 | 2012-02-09 - version 1.5.1
269 | * Weights/item count did not consider quantity
270 |
271 | 2012-02-09 - version 1.5
272 | * Mixed carts - when using a shipping class, only count items in said class when using item # rules
273 | * Weight and price and count only for items that need shipping
274 |
275 | 2012-02-09 - version 1.4.4
276 | * Postcode - don't remove spaces
277 |
278 | 2012-02-09 - version 1.4.3
279 | * Postcode case fix
280 |
281 | 2012-02-02 - version 1.4.2
282 | * Empty label fix
283 |
284 | 2012-02-01 - version 1.4.1
285 | * Logic bug with priority rates
286 |
287 | 2012-01-26 - version 1.4
288 | * WC 1.4 Compatibility (shipping rate API)
289 |
290 | 2011-12-15 - version 1.3
291 | * Support for the new 'Product Shipping Classes' in WC 1.3. This means you can have different table rates for different groups of products.
292 | * Drag and drop rates to re-order by priority
293 | * 'Priority' option if you want a rate to be the *only* one used if matched
294 |
295 | 2011-12-01 - version 1.2
296 | * Woo Updater
297 | * Made use of WC 1.3 Settings API
298 | * 'Chosen' input to aid adding rates
299 |
300 | 2011-11-15 - version 1.1.2
301 | * Changed textdomain
302 |
303 | 2011-11-15 - version 1.1.1
304 | * Changed text domain
305 |
306 | 2011-10-27 - version 1.1
307 | * Changed the way countries are defined to improve performance
308 | * Shortcuts for EU countries/US States
309 | * Postcodes can now be comma separated
310 | * Ability to exclude postcodes
311 |
312 | 2011-10-06 - version 1.0.1
313 | * Fixed rates when state is chosen/entered
314 |
315 | 2011-09-27 - version 1.0
316 | * First Release
317 |
--------------------------------------------------------------------------------
/includes/class-wc-shipping-table-rate-privacy.php:
--------------------------------------------------------------------------------
1 | Learn more about how this works, including what you may want to include in your privacy policy.', 'woocommerce-table-rate-shipping' ), 'https://docs.woocommerce.com/document/privacy-shipping/#woocommerce-table-rate-shipping' ) );
21 | }
22 | }
23 |
24 | new WC_Shipping_Table_Rate_Privacy();
25 |
--------------------------------------------------------------------------------
/includes/class-wc-shipping-table-rate.php:
--------------------------------------------------------------------------------
1 | id = 'table_rate';
29 | $this->instance_id = absint( $instance_id );
30 | $this->method_title = __( 'Table rates', 'woocommerce-table-rate-shipping' );
31 | $this->method_description = __( 'Table rates are dynamic rates based on a number of cart conditions.', 'woocommerce-table-rate-shipping' );
32 | $this->title = $this->method_title;
33 | $this->has_settings = false;
34 | $this->supports = array( 'zones', 'shipping-zones', 'instance-settings' );
35 |
36 | // Load the form fields.
37 | $this->init_form_fields();
38 |
39 | // Get settings
40 | $this->enabled = 'yes';
41 | $this->title = $this->get_option( 'title', __( 'Table Rate', 'woocommerce-table-rate-shipping' ) );
42 | $this->fee = $this->get_option( 'handling_fee' );
43 | $this->order_handling_fee = $this->get_option( 'order_handling_fee' );
44 | $this->tax_status = $this->get_option( 'tax_status' );
45 | $this->calculation_type = $this->get_option( 'calculation_type' );
46 | $this->min_cost = $this->get_option( 'min_cost' );
47 | $this->max_cost = $this->get_option( 'max_cost' );
48 | $this->max_shipping_cost = $this->get_option( 'max_shipping_cost' );
49 |
50 | // Table rate specific variables
51 | $this->rates_table = $wpdb->prefix . 'woocommerce_shipping_table_rates';
52 | $this->available_rates = array();
53 |
54 | add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
55 | }
56 |
57 | /**
58 | * get_option function.
59 | *
60 | * Gets and option from the settings API, using defaults if necessary to prevent undefined notices.
61 | *
62 | * @param string $key
63 | * @param mixed $empty_value
64 | * @return mixed The value specified for the option or a default value for the option.
65 | */
66 | public function get_option( $key, $empty_value = null ) {
67 | // Instance options take priority over global options
68 | if ( in_array( $key, array_keys( $this->get_instance_form_fields() ) ) ) {
69 | return $this->get_instance_option( $key, $empty_value );
70 | }
71 |
72 | // Return global option
73 | return parent::get_option( $key, $empty_value );
74 | }
75 |
76 | /**
77 | * Gets an option from the settings API, using defaults if necessary to prevent undefined notices.
78 | *
79 | * @param string $key
80 | * @param mixed $empty_value
81 | * @return mixed The value specified for the option or a default value for the option.
82 | */
83 | public function get_instance_option( $key, $empty_value = null ) {
84 | if ( empty( $this->instance_settings ) ) {
85 | $this->init_instance_settings();
86 | }
87 |
88 | // Get option default if unset.
89 | if ( ! isset( $this->instance_settings[ $key ] ) ) {
90 | $form_fields = $this->get_instance_form_fields();
91 |
92 | if ( is_callable( array( $this, 'get_field_default' ) ) ) {
93 | $this->instance_settings[ $key ] = $this->get_field_default( $form_fields[ $key ] );
94 | } else {
95 | $this->instance_settings[ $key ] = empty( $form_fields[ $key ]['default'] ) ? '' : $form_fields[ $key ]['default'];
96 | }
97 | }
98 |
99 | if ( ! is_null( $empty_value ) && '' === $this->instance_settings[ $key ] ) {
100 | $this->instance_settings[ $key ] = $empty_value;
101 | }
102 |
103 | // For the admin view, make sure we display them with decimal separator.
104 | // Otherwise, use dots for calculation.
105 | if ( is_admin() && in_array( $key, $this->decimal_options ) ) {
106 | $decimal_separator = wc_get_price_decimal_separator();
107 | $this->instance_settings[ $key ] = str_replace( '.', $decimal_separator, $this->instance_settings[ $key ] );
108 | }
109 |
110 | return $this->instance_settings[ $key ];
111 | }
112 |
113 | /**
114 | * Get settings fields for instances of this shipping method (within zones).
115 | * Should be overridden by shipping methods to add options.
116 | * @since 3.0.0
117 | * @return array
118 | */
119 | public function get_instance_form_fields() {
120 | return apply_filters( 'woocommerce_shipping_instance_form_fields_' . $this->id, $this->instance_form_fields );
121 | }
122 |
123 | /**
124 | * Return the name of the option in the WP DB.
125 | * @since 3.0.0
126 | * @return string
127 | */
128 | public function get_instance_option_key() {
129 | return $this->instance_id ? $this->plugin_id . $this->id . '_' . $this->instance_id . '_settings' : '';
130 | }
131 |
132 | /**
133 | * Initialise Settings for instances.
134 | * @since 3.0.0
135 | */
136 | public function init_instance_settings() {
137 | // 2nd option is for BW compat
138 | $this->instance_settings = get_option( $this->get_instance_option_key(), get_option( $this->plugin_id . $this->id . '-' . $this->instance_id . '_settings', null ) );
139 |
140 | /*
141 | * Order handling fee does not handle percentages. So
142 | * we need to remove previously saved % before initializing.
143 | *
144 | * @since 3.0.14 To fix https://github.com/woocommerce/woocommerce-table-rate-shipping/issues/91
145 | */
146 | $this->instance_settings['order_handling_fee'] = str_replace(
147 | '%',
148 | '',
149 | empty( $this->instance_settings['order_handling_fee'] ) ? '' : $this->instance_settings['order_handling_fee']
150 | );
151 |
152 | // If there are no settings defined, use defaults.
153 | if ( ! is_array( $this->instance_settings ) ) {
154 | $form_fields = $this->get_instance_form_fields();
155 | $this->instance_settings = array_merge( array_fill_keys( array_keys( $form_fields ), '' ), wp_list_pluck( $form_fields, 'default' ) );
156 | }
157 | }
158 |
159 | /**
160 | * Initialise Gateway Settings Form Fields
161 | */
162 | public function init_form_fields() {
163 | $this->form_fields = array(); // No global options for table rates
164 | $this->instance_form_fields = array(
165 | 'title' => array(
166 | 'title' => __( 'Method Title', 'woocommerce-table-rate-shipping' ),
167 | 'type' => 'text',
168 | 'desc_tip' => true,
169 | 'description' => __( 'This controls the title which the user sees during checkout.', 'woocommerce-table-rate-shipping' ),
170 | 'default' => __( 'Table Rate', 'woocommerce-table-rate-shipping' )
171 | ),
172 | 'tax_status' => array(
173 | 'title' => __( 'Tax Status', 'woocommerce-table-rate-shipping' ),
174 | 'type' => 'select',
175 | 'description' => '',
176 | 'desc_tip' => true,
177 | 'default' => 'taxable',
178 | 'options' => array(
179 | 'taxable' => __('Taxable', 'woocommerce-table-rate-shipping'),
180 | 'none' => __('None', 'woocommerce-table-rate-shipping'),
181 | )
182 | ),
183 | 'prices_include_tax' => array(
184 | 'title' => __( 'Tax included in shipping costs', 'woocommerce-table-rate-shipping' ),
185 | 'type' => 'select',
186 | 'description' => '',
187 | 'desc_tip' => true,
188 | 'default' => get_option( $this->get_instance_option_key() ) ? 'no' // Shipping method has previously been configured so we default to 'no' to maintain backwards compatibility.
189 | : ( 'yes' === get_option( 'woocommerce_prices_include_tax' ) ? 'yes' : 'no' ), // Otherwise default to the store setting.
190 | 'options' => array(
191 | 'yes' => __( 'Yes, I will enter costs below inclusive of tax', 'woocommerce-table-rate-shipping' ),
192 | 'no' => __( 'No, I will enter costs below exclusive of tax', 'woocommerce-table-rate-shipping' ),
193 | ),
194 | ),
195 | 'order_handling_fee' => array(
196 | 'title' => __( 'Handling Fee', 'woocommerce-table-rate-shipping' ),
197 | 'type' => 'number',
198 | 'desc_tip' => __( 'Enter an amount, e.g. 2.50. Leave blank to disable. This cost is applied once for the order as a whole.', 'woocommerce-table-rate-shipping' ),
199 | 'default' => '',
200 | 'placeholder' => __( 'n/a', 'woocommerce-table-rate-shipping' ),
201 | 'custom_attributes' => array(
202 | 'step' => '0.01',
203 | ),
204 | ),
205 | 'max_shipping_cost' => array(
206 | 'title' => __( 'Maximum Shipping Cost', 'woocommerce-table-rate-shipping' ),
207 | 'type' => 'text',
208 | 'desc_tip' => __( 'Maximum cost that the customer will pay after all the shipping rules have been applied. If the shipping cost calculated is bigger than this value, this cost will be the one shown.', 'woocommerce-table-rate-shipping' ),
209 | 'default' => '',
210 | 'placeholder' => __( 'n/a', 'woocommerce-table-rate-shipping' )
211 | ),
212 | 'rates' => array(
213 | 'title' => __( 'Rates', 'woocommerce-table-rate-shipping' ),
214 | 'type' => 'title',
215 | 'description' => __( 'This is where you define your table rates which are applied to an order.', 'woocommerce-table-rate-shipping'),
216 | 'default' => ''
217 | ),
218 | 'calculation_type' => array(
219 | 'title' => __( 'Calculation Type', 'woocommerce-table-rate-shipping' ),
220 | 'type' => 'select',
221 | 'description' => __( 'Per order rates will offer the customer all matching rates. Calculated rates will sum all matching rates and provide a single total.', 'woocommerce-table-rate-shipping' ),
222 | 'default' => '',
223 | 'desc_tip' => true,
224 | 'options' => array(
225 | '' => __( 'Per order', 'woocommerce-table-rate-shipping' ),
226 | 'item' => __( 'Calculated rates per item', 'woocommerce-table-rate-shipping' ),
227 | 'line' => __( 'Calculated rates per line item', 'woocommerce-table-rate-shipping' ),
228 | 'class' => __( 'Calculated rates per shipping class', 'woocommerce-table-rate-shipping' )
229 | )
230 | ),
231 | 'handling_fee' => array(
232 | 'title' => __( 'Handling Fee Per [item]', 'woocommerce-table-rate-shipping' ),
233 | 'type' => 'text',
234 | 'desc_tip' => __( 'Handling fee. Enter an amount, e.g. 2.50, or a percentage, e.g. 5%. Leave blank to disable. Applied based on the "Calculation Type" chosen below.', 'woocommerce-table-rate-shipping' ),
235 | 'default' => '',
236 | 'placeholder' => __( 'n/a', 'woocommerce-table-rate-shipping' ),
237 | ),
238 | 'min_cost' => array(
239 | 'title' => __( 'Minimum Cost Per [item]', 'woocommerce-table-rate-shipping' ),
240 | 'type' => 'text',
241 | 'desc_tip' => true,
242 | 'description' => __('Minimum cost for this shipping method (optional). If the cost is lower, this minimum cost will be enforced.', 'woocommerce-table-rate-shipping'),
243 | 'default' => '',
244 | 'placeholder' => __( 'n/a', 'woocommerce-table-rate-shipping' )
245 | ),
246 | 'max_cost' => array(
247 | 'title' => __( 'Maximum Cost Per [item]', 'woocommerce-table-rate-shipping' ),
248 | 'type' => 'text',
249 | 'desc_tip' => true,
250 | 'description' => __( 'Maximum cost for this shipping method (optional). If the cost is higher, this maximum cost will be enforced.', 'woocommerce-table-rate-shipping'),
251 | 'default' => '',
252 | 'placeholder' => __( 'n/a', 'woocommerce-table-rate-shipping' )
253 | ),
254 | );
255 |
256 | }
257 |
258 | /**
259 | * Admin options
260 | */
261 | public function admin_options() {
262 | $this->instance_options();
263 | }
264 |
265 | /**
266 | * Return admin options as a html string.
267 | * @return string
268 | */
269 | public function get_admin_options_html() {
270 | ob_start();
271 | $this->instance_options();
272 | return ob_get_clean();
273 | }
274 |
275 | /**
276 | * admin_options function.
277 | */
278 | public function instance_options() {
279 | ?>
280 |
299 | decimal_options as $option ) {
310 | $option = 'woocommerce_table_rate_' . $option;
311 |
312 | if ( ! isset( $_POST[ $option ] ) ) {
313 | continue;
314 | }
315 |
316 | $_POST[ $option ] = str_replace( $decimal_separator, '.', $_POST[ $option ] );
317 | }
318 |
319 | parent::process_admin_options();
320 | wc_table_rate_admin_shipping_rows_process( $this->instance_id );
321 | }
322 |
323 | /**
324 | * is_available function.
325 | *
326 | * @param array $package
327 | * @return bool
328 | */
329 | public function is_available( $package ) {
330 | $available = true;
331 |
332 | if ( ! $this->get_rates( $package ) ) {
333 | $available = false;
334 | }
335 |
336 | return apply_filters( 'woocommerce_shipping_' . $this->id . '_is_available', $available, $package, $this );
337 | }
338 |
339 | /**
340 | * count_items_in_class function.
341 | * @return int
342 | */
343 | public function count_items_in_class( $package, $class_id ) {
344 | $count = 0;
345 |
346 | // Find shipping classes for products in the package
347 | foreach ( $package['contents'] as $item_id => $values ) {
348 | if ( $values['data']->needs_shipping() && $values['data']->get_shipping_class_id() == $class_id ) {
349 | $count += $values['quantity'];
350 | }
351 | }
352 |
353 | return $count;
354 | }
355 |
356 | /**
357 | * get_cart_shipping_class_id function.
358 | * @return int
359 | */
360 | public function get_cart_shipping_class_id( $package ) {
361 | // Find shipping class for cart
362 | $found_shipping_classes = array();
363 | $shipping_class_id = 0;
364 | $shipping_class_slug = '';
365 |
366 | // Find shipping classes for products in the package
367 | if ( sizeof( $package['contents'] ) > 0 ) {
368 | foreach ( $package['contents'] as $item_id => $values ) {
369 | if ( $values['data']->needs_shipping() ) {
370 | $found_shipping_classes[ $values['data']->get_shipping_class_id() ] = $values['data']->get_shipping_class();
371 | }
372 | }
373 | }
374 |
375 | $found_shipping_classes = array_unique( $found_shipping_classes );
376 |
377 | if ( sizeof( $found_shipping_classes ) == 1 ) {
378 | $shipping_class_slug = current( $found_shipping_classes );
379 | } elseif ( $found_shipping_classes > 1 ) {
380 |
381 | // Get class with highest priority
382 | $priority = get_option( 'woocommerce_table_rate_default_priority_' . $this->instance_id );
383 | $priorities = get_option( 'woocommerce_table_rate_priorities_' . $this->instance_id );
384 |
385 | foreach ( $found_shipping_classes as $class ) {
386 | if ( isset( $priorities[ $class ] ) && $priorities[ $class ] < $priority ) {
387 | $priority = $priorities[ $class ];
388 | $shipping_class_slug = $class;
389 | }
390 | }
391 | }
392 |
393 | $found_shipping_classes = array_flip( $found_shipping_classes );
394 |
395 | if ( isset( $found_shipping_classes[ $shipping_class_slug ] ) )
396 | $shipping_class_id = $found_shipping_classes[ $shipping_class_slug ];
397 |
398 | return $shipping_class_id;
399 | }
400 |
401 | /**
402 | * query_rates function.
403 | *
404 | * @param array $args
405 | * @return array
406 | */
407 | public function query_rates( $args ) {
408 | global $wpdb;
409 |
410 | $defaults = array(
411 | 'price' => '',
412 | 'weight' => '',
413 | 'count' => 1,
414 | 'count_in_class' => 1,
415 | 'shipping_class_id' => ''
416 | );
417 |
418 | $args = apply_filters( 'woocommerce_table_rate_query_rates_args', wp_parse_args( $args, $defaults ) );
419 |
420 | extract( $args, EXTR_SKIP );
421 |
422 | if ( $shipping_class_id == "" ) {
423 | $shipping_class_id_in = " AND rate_class IN ( '', '0' )";
424 | } else {
425 | $shipping_class_id_in = " AND rate_class IN ( '', '" . absint( $shipping_class_id ) . "' )";
426 | }
427 |
428 | $rates = $wpdb->get_results(
429 | $wpdb->prepare( "
430 | SELECT rate_id, rate_cost, rate_cost_per_item, rate_cost_per_weight_unit, rate_cost_percent, rate_label, rate_priority, rate_abort, rate_abort_reason
431 | FROM {$this->rates_table}
432 | WHERE shipping_method_id IN ( %s )
433 | {$shipping_class_id_in}
434 | AND
435 | (
436 | rate_condition = ''
437 | OR
438 | (
439 | rate_condition = 'price'
440 | AND
441 | (
442 | ( ( rate_min + 0 ) = '' AND ( rate_max + 0 ) = '' )
443 | OR
444 | ( ( rate_min + 0 ) >= 0 AND ( rate_max + 0 ) >=0 AND '{$price}' >= ( rate_min + 0 ) AND '{$price}' <= ( rate_max + 0 ) )
445 | OR
446 | ( ( rate_min + 0 ) >= 0 AND ( rate_max + 0 ) = '' AND '{$price}' >= ( rate_min + 0 ) )
447 | OR
448 | ( ( rate_min + 0 ) = '' AND ( rate_max + 0 ) >= 0 AND '{$price}' <= ( rate_max + 0 ) )
449 | )
450 | )
451 | OR
452 | (
453 | rate_condition = 'weight'
454 | AND
455 | (
456 | ( ( rate_min + 0 ) = '' AND ( rate_max + 0 ) = '' )
457 | OR
458 | ( ( rate_min + 0 ) >= 0 AND ( rate_max + 0 ) >=0 AND '{$weight}' >= ( rate_min + 0 ) AND '{$weight}' <= ( rate_max + 0 ) )
459 | OR
460 | ( ( rate_min + 0 ) >= 0 AND ( rate_max + 0 ) = '' AND '{$weight}' >= ( rate_min + 0 ) )
461 | OR
462 | ( ( rate_min + 0 ) = '' AND ( rate_max + 0 ) >= 0 AND '{$weight}' <= ( rate_max + 0 ) )
463 | )
464 | )
465 | OR
466 | (
467 | rate_condition = 'items'
468 | AND
469 | (
470 | ( ( rate_min + 0 ) = '' AND ( rate_max + 0 ) = '' )
471 | OR
472 | ( ( rate_min + 0 ) >= 0 AND ( rate_max + 0 ) >=0 AND '{$count}' >= ( rate_min + 0 ) AND '{$count}' <= ( rate_max + 0 ) )
473 | OR
474 | ( ( rate_min + 0 ) >= 0 AND ( rate_max + 0 ) = '' AND '{$count}' >= ( rate_min + 0 ) )
475 | OR
476 | ( ( rate_min + 0 ) = '' AND ( rate_max + 0 ) >= 0 AND '{$count}' <= ( rate_max + 0 ) )
477 | )
478 | )
479 | OR
480 | (
481 | rate_condition = 'items_in_class'
482 | AND
483 | (
484 | ( ( rate_min + 0 ) = '' AND ( rate_max + 0 ) = '' )
485 | OR
486 | ( ( rate_min + 0 ) >= 0 AND ( rate_max + 0 ) >= 0 AND '{$count_in_class}' >= ( rate_min + 0 ) AND '{$count_in_class}' <= ( rate_max + 0 ) )
487 | OR
488 | ( ( rate_min + 0 ) >= 0 AND ( rate_max + 0 ) = '' AND '{$count_in_class}' >= ( rate_min + 0 ) )
489 | OR
490 | ( ( rate_min + 0 ) = '' AND ( rate_max + 0 ) >= 0 AND '{$count_in_class}' <= ( rate_max + 0 ) )
491 | )
492 | )
493 | )
494 | ORDER BY rate_order ASC
495 | ", $this->instance_id )
496 | );
497 |
498 | return apply_filters( 'woocommerce_table_rate_query_rates', $rates );
499 | }
500 |
501 | /**
502 | * get_rates function.
503 | * @return bool
504 | */
505 | public function get_rates( $package ) {
506 | global $wpdb;
507 |
508 | if ( ! $this->instance_id )
509 | return false;
510 |
511 | $rates = array();
512 | $this->unset_abort_message();
513 |
514 | // Get rates, depending on type
515 | if ( $this->calculation_type == 'item' ) {
516 |
517 | // For each ITEM get matching rates
518 | $costs = array();
519 |
520 | $matched = false;
521 |
522 | foreach ( $package['contents'] as $item_id => $values ) {
523 |
524 | $_product = $values['data'];
525 |
526 | if ( $values['quantity'] > 0 && $_product->needs_shipping() ) {
527 |
528 | $product_price = $this->get_product_price( $_product, 1, $values );
529 |
530 | $matching_rates = $this->query_rates( array(
531 | 'price' => $product_price,
532 | 'weight' => (float) $_product->get_weight(),
533 | 'count' => 1,
534 | 'count_in_class' => $this->count_items_in_class( $package, $_product->get_shipping_class_id() ),
535 | 'shipping_class_id' => $_product->get_shipping_class_id()
536 | ) );
537 |
538 | $item_weight = round( (float) $_product->get_weight(), 2 );
539 | $item_fee = (float) $this->get_fee( $this->fee, $product_price );
540 | $item_cost = 0;
541 |
542 | foreach ( $matching_rates as $rate ) {
543 | $item_cost += (float) $rate->rate_cost;
544 | $item_cost += (float) $rate->rate_cost_per_weight_unit * $item_weight;
545 | $item_cost += ( (float) $rate->rate_cost_percent / 100 ) * $product_price;
546 | $matched = true;
547 | if ( $rate->rate_abort ) {
548 | if ( ! empty( $rate->rate_abort_reason ) && ! wc_has_notice( $rate->rate_abort_reason, 'notice' ) ) {
549 | $this->add_notice( $rate->rate_abort_reason, 'notice' );
550 | }
551 | return;
552 | }
553 | if ( $rate->rate_priority )
554 | break;
555 | }
556 |
557 | $cost = ( $item_cost + $item_fee ) * $values['quantity'];
558 |
559 | if ( $this->min_cost && $cost < $this->min_cost ) {
560 | $cost = $this->min_cost;
561 | }
562 | if ( $this->max_cost && $cost > $this->max_cost ) {
563 | $cost = $this->max_cost;
564 | }
565 |
566 | $costs[ $item_id ] = $cost;
567 |
568 | }
569 | }
570 |
571 | if ( $matched ) {
572 | if ( $this->order_handling_fee ) {
573 | $costs['order'] = $this->order_handling_fee;
574 | } else {
575 | $costs['order'] = 0;
576 | }
577 |
578 | if ( $this->max_shipping_cost && ( $costs['order'] + array_sum( $costs ) ) > $this->max_shipping_cost ) {
579 | $rates[] = array(
580 | 'id' => is_callable( array( $this, 'get_rate_id' ) ) ? $this->get_rate_id() : $this->instance_id,
581 | 'label' => __( $this->title, 'woocommerce-table-rate-shipping' ),
582 | 'cost' => $this->max_shipping_cost
583 | );
584 | } else {
585 | $rates[] = array(
586 | 'id' => is_callable( array( $this, 'get_rate_id' ) ) ? $this->get_rate_id() : $this->instance_id,
587 | 'label' => __( $this->title, 'woocommerce-table-rate-shipping' ),
588 | 'cost' => $costs,
589 | 'calc_tax' => 'per_item',
590 | 'package' => $package,
591 | );
592 | }
593 | }
594 |
595 | } elseif ( $this->calculation_type == 'line' ) {
596 |
597 | // For each LINE get matching rates
598 | $costs = array();
599 |
600 | $matched = false;
601 |
602 | foreach ( $package['contents'] as $item_id => $values ) {
603 |
604 | $_product = $values['data'];
605 |
606 | if ( $values['quantity'] > 0 && $_product->needs_shipping() ) {
607 |
608 | $product_price = $this->get_product_price( $_product, $values['quantity'], $values );
609 |
610 | $matching_rates = $this->query_rates( array(
611 | 'price' => $product_price,
612 | 'weight' => (float) $_product->get_weight() * $values['quantity'],
613 | 'count' => $values['quantity'],
614 | 'count_in_class' => $this->count_items_in_class( $package, $_product->get_shipping_class_id() ),
615 | 'shipping_class_id' => $_product->get_shipping_class_id()
616 | ) );
617 |
618 | $item_weight = round( (float) $_product->get_weight() * $values['quantity'], 2 );
619 | $item_fee = (float) $this->get_fee( $this->fee, $product_price );
620 | $item_cost = 0;
621 |
622 | foreach ( $matching_rates as $rate ) {
623 | $item_cost += (float) $rate->rate_cost;
624 | $item_cost += (float) $rate->rate_cost_per_item * $values['quantity'];
625 | $item_cost += (float) $rate->rate_cost_per_weight_unit * $item_weight;
626 | $item_cost += ( (float) $rate->rate_cost_percent / 100 ) * $product_price;
627 | $matched = true;
628 |
629 | if ( $rate->rate_abort ) {
630 | if ( ! empty( $rate->rate_abort_reason ) ) {
631 | $this->add_notice( $rate->rate_abort_reason, 'notice' );
632 | }
633 | return;
634 | }
635 | if ( $rate->rate_priority )
636 | break;
637 | }
638 |
639 | $item_cost = $item_cost + $item_fee;
640 |
641 | if ( $this->min_cost && $item_cost < $this->min_cost ) {
642 | $item_cost = $this->min_cost;
643 | }
644 | if ( $this->max_cost && $item_cost > $this->max_cost ) {
645 | $item_cost = $this->max_cost;
646 | }
647 |
648 | $costs[ $item_id ] = $item_cost;
649 | }
650 |
651 | }
652 |
653 | if ( $matched ) {
654 | if ( $this->order_handling_fee ) {
655 | $costs['order'] = $this->order_handling_fee;
656 | } else {
657 | $costs['order'] = 0;
658 | }
659 |
660 | if ( $this->max_shipping_cost && ( $costs['order'] + array_sum( $costs ) ) > $this->max_shipping_cost ) {
661 | $rates[] = array(
662 | 'id' => is_callable( array( $this, 'get_rate_id' ) ) ? $this->get_rate_id() : $this->instance_id,
663 | 'label' => __( $this->title, 'woocommerce-table-rate-shipping' ),
664 | 'cost' => $this->max_shipping_cost,
665 | 'package' => $package,
666 | );
667 | } else {
668 | $rates[] = array(
669 | 'id' => is_callable( array( $this, 'get_rate_id' ) ) ? $this->get_rate_id() : $this->instance_id,
670 | 'label' => __( $this->title, 'woocommerce-table-rate-shipping' ),
671 | 'cost' => $costs,
672 | 'calc_tax' => 'per_item',
673 | 'package' => $package,
674 | );
675 | }
676 | }
677 |
678 | } elseif ( $this->calculation_type == 'class' ) {
679 |
680 | // For each CLASS get matching rates
681 | $total_cost = 0;
682 |
683 | // First get all the rates in the table
684 | $all_rates = $this->get_shipping_rates();
685 |
686 | // Now go through cart items and group items by class
687 | $classes = array();
688 |
689 | foreach ( $package['contents'] as $item_id => $values ) {
690 |
691 | $_product = $values['data'];
692 |
693 | if ( $values['quantity'] > 0 && $_product->needs_shipping() ) {
694 |
695 | $shipping_class = $_product->get_shipping_class_id();
696 |
697 | if ( ! isset( $classes[ $shipping_class ] ) ) {
698 | $classes[ $shipping_class ] = new stdClass();
699 | $classes[ $shipping_class ]->price = 0;
700 | $classes[ $shipping_class ]->weight = 0;
701 | $classes[ $shipping_class ]->items = 0;
702 | $classes[ $shipping_class ]->items_in_class = 0;
703 | }
704 |
705 | $classes[ $shipping_class ]->price += $this->get_product_price( $_product, $values['quantity'], $values );
706 | $classes[ $shipping_class ]->weight += (float) $_product->get_weight() * $values['quantity'];
707 | $classes[ $shipping_class ]->items += $values['quantity'];
708 | $classes[ $shipping_class ]->items_in_class += $values['quantity'];
709 | }
710 | }
711 |
712 | $matched = false;
713 | $total_cost = 0;
714 | $stop = false;
715 |
716 | // Now we have groups, loop the rates and find matches in order
717 | foreach ( $all_rates as $rate ) {
718 |
719 | foreach ( $classes as $class_id => $class ) {
720 |
721 | if ( $class_id == "" ) {
722 | if ( $rate->rate_class != 0 && $rate->rate_class !== '' )
723 | continue;
724 | } else {
725 | if ( $rate->rate_class != $class_id && $rate->rate_class !== '' )
726 | continue;
727 | }
728 |
729 | $rate_match = false;
730 |
731 | switch ( $rate->rate_condition ) {
732 | case '' :
733 | $rate_match = true;
734 | break;
735 | case 'price' :
736 | case 'weight' :
737 | case 'items_in_class' :
738 | case 'items' :
739 |
740 | $condition = $rate->rate_condition;
741 | $value = $class->$condition;
742 |
743 | if ( $rate->rate_min === '' && $rate->rate_max === '' )
744 | $rate_match = true;
745 |
746 | if ( $value >= $rate->rate_min && $value <= $rate->rate_max )
747 | $rate_match = true;
748 |
749 | if ( $value >= $rate->rate_min && ! $rate->rate_max )
750 | $rate_match = true;
751 |
752 | if ( $value <= $rate->rate_max && ! $rate->rate_min )
753 | $rate_match = true;
754 |
755 | break;
756 | }
757 |
758 | // Rate matched class
759 | if ( $rate_match ) {
760 | $rate_label = ! empty( $rate->rate_label ) ? $rate->rate_label : $this->title;
761 | $class_cost = 0;
762 | $class_cost += (float) $rate->rate_cost;
763 | $class_cost += (float) $rate->rate_cost_per_item * $class->items_in_class;
764 | $class_cost += (float) $rate->rate_cost_per_weight_unit * $class->weight;
765 | $class_cost += ( (float) $rate->rate_cost_percent / 100 ) * $class->price;
766 |
767 | if ( $rate->rate_abort ) {
768 | if ( ! empty( $rate->rate_abort_reason ) ) {
769 | $this->add_notice( $rate->rate_abort_reason, 'notice' );
770 | }
771 | return;
772 | }
773 |
774 | if ( $rate->rate_priority ) {
775 | $stop = true;
776 | }
777 |
778 | $matched = true;
779 |
780 | $class_fee = (float) $this->get_fee( $this->fee, $class->price );
781 | $class_cost += $class_fee;
782 |
783 | if ( $this->min_cost && $class_cost < $this->min_cost ) {
784 | $class_cost = $this->min_cost;
785 | }
786 | if ( $this->max_cost && $class_cost > $this->max_cost ) {
787 | $class_cost = $this->max_cost;
788 | }
789 |
790 | $total_cost += $class_cost;
791 | }
792 | }
793 |
794 | // Breakpoint
795 | if ( $stop ) {
796 | break;
797 | }
798 | }
799 |
800 | if ( $this->order_handling_fee ) {
801 | $total_cost += $this->get_fee( $this->order_handling_fee, $total_cost );
802 | }
803 |
804 | if ( $this->max_shipping_cost && $total_cost > $this->max_shipping_cost ) {
805 | $total_cost = $this->max_shipping_cost;
806 | }
807 |
808 | if ( $matched ) {
809 | $rates[] = array(
810 | 'id' => is_callable( array( $this, 'get_rate_id' ) ) ? $this->get_rate_id() : $this->instance_id,
811 | 'label' => __( $rate_label, 'woocommerce-table-rate-shipping' ),
812 | 'cost' => $total_cost,
813 | 'package' => $package,
814 | );
815 | }
816 |
817 | } else {
818 |
819 | // For the ORDER get matching rates
820 | $shipping_class = $this->get_cart_shipping_class_id( $package );
821 | $price = 0;
822 | $weight = 0;
823 | $count = 0;
824 | $count_in_class = 0;
825 |
826 | foreach ( $package['contents'] as $item_id => $values ) {
827 |
828 | $_product = $values['data'];
829 |
830 | if ( $values['quantity'] > 0 && $_product->needs_shipping() ) {
831 | $price += $this->get_product_price( $_product, $values['quantity'], $values );
832 | $weight += (float) $_product->get_weight() * (float) $values['quantity'];
833 | $count += $values['quantity'];
834 |
835 | if ( $_product->get_shipping_class_id() == $shipping_class )
836 | $count_in_class += $values['quantity'];
837 |
838 | }
839 | }
840 |
841 | $matching_rates = $this->query_rates( array(
842 | 'price' => $price,
843 | 'weight' => $weight,
844 | 'count' => $count,
845 | 'count_in_class' => $count_in_class,
846 | 'shipping_class_id' => $shipping_class
847 | ) );
848 |
849 | foreach ( $matching_rates as $rate ) {
850 | $label = $rate->rate_label;
851 | if ( ! $label )
852 | $label = $this->title;
853 |
854 | if ( $rate->rate_abort ) {
855 | if ( ! empty( $rate->rate_abort_reason ) ) {
856 | $this->add_notice( $rate->rate_abort_reason, 'notice' );
857 | }
858 | $rates = array(); // Clear rates
859 | break;
860 | }
861 |
862 | if ( $rate->rate_priority )
863 | $rates = array();
864 |
865 | $cost = (float) $rate->rate_cost;
866 | $cost += (float) $rate->rate_cost_per_item * $count;
867 | $cost += (float) $this->get_fee( $this->fee, $price );
868 | $cost += (float) $rate->rate_cost_per_weight_unit * $weight;
869 | $cost += ( (float) $rate->rate_cost_percent / 100 ) * $price;
870 |
871 | if ( $this->order_handling_fee ) {
872 | $cost += $this->order_handling_fee;
873 | }
874 |
875 | if ( $this->min_cost && $cost < $this->min_cost ) {
876 | $cost = $this->min_cost;
877 | }
878 |
879 | if ( $this->max_cost && $cost > $this->max_cost ) {
880 | $cost = $this->max_cost;
881 | }
882 |
883 | if ( $this->max_shipping_cost && $cost > $this->max_shipping_cost ) {
884 | $cost = $this->max_shipping_cost;
885 | }
886 |
887 | $rates[] = array(
888 | 'id' => is_callable( array( $this, 'get_rate_id' ) ) ? $this->get_rate_id( $rate->rate_id ) : $this->instance_id . ' : ' . $rate->rate_id,
889 | 'label' => __( $label, 'woocommerce-table-rate-shipping' ),
890 | 'cost' => $cost,
891 | 'package' => $package,
892 | );
893 |
894 | if ( $rate->rate_priority ) {
895 | break;
896 | }
897 | }
898 |
899 | }
900 |
901 | $is_customer_vat_exempt = WC()->cart->get_customer()->get_is_vat_exempt();
902 |
903 | if ( 'yes' === $this->get_instance_option( 'prices_include_tax' ) && ( $this->is_taxable() || $is_customer_vat_exempt ) ) {
904 | // We allow the table rate to be entered inclusive of taxes just like product prices.
905 | foreach ( $rates as $key => $rate ) {
906 |
907 | $tax_rates = WC_Tax::get_shipping_tax_rates();
908 |
909 | // Temporarily override setting since our shipping rate will always include taxes here.
910 | add_filter( 'woocommerce_prices_include_tax', array( $this, 'override_prices_include_tax_setting' ) );
911 | $base_tax_rates = WC_Tax::get_shipping_tax_rates( null, false );
912 | remove_filter( 'woocommerce_prices_include_tax', array( $this, 'override_prices_include_tax_setting' ) );
913 |
914 | $total_cost = is_array( $rate['cost'] ) ? array_sum( $rate['cost'] ) : $rate['cost'];
915 |
916 | if ( apply_filters( 'woocommerce_adjust_non_base_location_prices', true ) ) {
917 | $taxes = WC_Tax::calc_tax( $total_cost, $base_tax_rates, true );
918 | } else {
919 | $taxes = WC_Tax::calc_tax( $total_cost, $tax_rates, true );
920 | }
921 |
922 | $rates[ $key ]['cost'] = $total_cost - array_sum( $taxes );
923 |
924 | $rates[ $key ]['taxes'] = $is_customer_vat_exempt ? array() : WC_Tax::calc_shipping_tax( $rates[ $key ]['cost'], $tax_rates );
925 |
926 | $rates[ $key ]['price_decimals'] = '4'; // Prevent the cost from being rounded before the tax is added.
927 | }
928 | }
929 |
930 | // None found?
931 | if ( sizeof( $rates ) == 0 ) {
932 | return false;
933 | }
934 |
935 | // Set available
936 | $this->available_rates = $rates;
937 |
938 | return true;
939 | }
940 |
941 | /**
942 | * Unique function for overriding the prices including tax setting in WooCommerce.
943 | *
944 | * @since 3.0.27
945 | *
946 | * @return bool
947 | */
948 | public function override_prices_include_tax_setting() {
949 | return true;
950 | }
951 |
952 | /**
953 | * calculate_shipping function.
954 | * @param array $package
955 | */
956 | public function calculate_shipping( $package = array() ) {
957 | if ( $this->available_rates ) {
958 | foreach ( $this->available_rates as $rate ) {
959 | $this->add_rate( $rate );
960 | }
961 | }
962 | }
963 |
964 | /**
965 | * Get raw shipping rates from the DB.
966 | *
967 | * Optional filter helper for integration with other plugins.
968 | *
969 | * @param string $output Output format.
970 | * @return mixed
971 | */
972 | public function get_shipping_rates( $output = OBJECT ) {
973 | global $wpdb;
974 |
975 | $rates = $wpdb->get_results( "
976 | SELECT * FROM {$this->rates_table}
977 | WHERE shipping_method_id = {$this->instance_id}
978 | ORDER BY rate_order ASC;
979 | ", $output );
980 |
981 | return apply_filters( 'woocommerce_table_rate_get_shipping_rates', $rates );
982 | }
983 |
984 | /**
985 | * Get shipping rates with normalized values (respect decimal separator
986 | * settings), for display.
987 | *
988 | * @return array
989 | */
990 | public function get_normalized_shipping_rates() {
991 | $shipping_rates = $this->get_shipping_rates( ARRAY_A );
992 | $decimal_separator = wc_get_price_decimal_separator();
993 | $normalize_keys = array(
994 | 'rate_cost',
995 | 'rate_cost_per_item',
996 | 'rate_cost_per_weight_unit',
997 | 'rate_cost_percent',
998 | 'rate_max',
999 | 'rate_min',
1000 | );
1001 |
1002 | foreach ( $shipping_rates as $index => $shipping_rate ) {
1003 | foreach ( $normalize_keys as $key ) {
1004 | if ( ! isset( $shipping_rate[ $key ] ) ) {
1005 | continue;
1006 | }
1007 |
1008 | $shipping_rates[ $index ][ $key ] = str_replace( '.', $decimal_separator, $shipping_rates[ $index ][ $key ] );
1009 | }
1010 | }
1011 |
1012 | return $shipping_rates;
1013 | }
1014 |
1015 | /**
1016 | * Retrieve the product price from a line item.
1017 | *
1018 | * @param object $_product Product object.
1019 | * @param int $qty Line item quantity.
1020 | * @param array $item Array of line item data.
1021 | * @return float
1022 | */
1023 | public function get_product_price( $_product, $qty = 1, $item = array() ) {
1024 |
1025 | // Use the product price based on the line item totals (including coupons and discounts).
1026 | // This is not enabled by default (since it can be interpreted differently).
1027 | if ( apply_filters( 'woocommerce_table_rate_compare_price_limits_after_discounts', false, $item ) && isset( $item['line_total'] ) ) {
1028 | return $item['line_total'] + ( ! empty( $item['line_tax'] ) ? $item['line_tax'] : 0 );
1029 | }
1030 |
1031 | $row_base_price = $_product->get_price() * $qty;
1032 | $row_base_price = apply_filters( 'woocommerce_table_rate_package_row_base_price', $row_base_price, $_product, $qty );
1033 |
1034 | if ( $_product->is_taxable() && wc_prices_include_tax() ) {
1035 |
1036 | $base_tax_rates = WC_Tax::get_base_tax_rates( $_product->get_tax_class() );
1037 |
1038 | $tax_rates = WC_Tax::get_rates( $_product->get_tax_class() );
1039 |
1040 | if ( $tax_rates !== $base_tax_rates && apply_filters( 'woocommerce_adjust_non_base_location_prices', true )) {
1041 | $base_taxes = WC_Tax::calc_tax( $row_base_price, $base_tax_rates, true, true );
1042 | $modded_taxes = WC_Tax::calc_tax( $row_base_price - array_sum( $base_taxes ), $tax_rates, false );
1043 | $row_base_price = ( $row_base_price - array_sum( $base_taxes ) ) + array_sum( $modded_taxes );
1044 | }
1045 | }
1046 |
1047 | return $row_base_price;
1048 | }
1049 |
1050 | /**
1051 | * Admin Panel Options Processing
1052 | * - Saves the options to the DB
1053 | *
1054 | * @since 1.0.0
1055 | * @deprecated 3.0.0
1056 | */
1057 | public function process_instance_options() {
1058 | $this->validate_settings_fields( $this->get_instance_form_fields() );
1059 |
1060 | if ( count( $this->errors ) > 0 ) {
1061 | $this->display_errors();
1062 | return false;
1063 | } else {
1064 | wc_table_rate_admin_shipping_rows_process( $this->instance_id );
1065 | update_option( $this->get_instance_option_key(), $this->sanitized_fields );
1066 | return true;
1067 | }
1068 | }
1069 |
1070 | /**
1071 | * Adds a notice to the cart/checkout header.
1072 | *
1073 | * @since 3.0.19
1074 | * @param string $message Message to show
1075 | * @return void
1076 | */
1077 | private function add_notice( $message ) {
1078 | $this->save_abort_message( $message );
1079 |
1080 | // Only display shipping notices in cart/checkout.
1081 | if ( ! is_cart() && ! is_checkout() ) {
1082 | return;
1083 | }
1084 |
1085 | if ( ! wc_has_notice( $message ) ) {
1086 | wc_add_notice( $message );
1087 | }
1088 | }
1089 |
1090 | /**
1091 | * Save the abort notice in the session (to display when shipping methods are loaded from cache).
1092 | *
1093 | * @since 3.0.25
1094 | * @param string $message Abort message.
1095 | */
1096 | private function save_abort_message( $message ) {
1097 | $abort = WC()->session->get( WC_Table_Rate_Shipping::$abort_key );
1098 | if ( empty( $abort ) ) {
1099 | $abort = array();
1100 | }
1101 |
1102 | $abort[ $this->instance_id ] = $message;
1103 | WC()->session->set( WC_Table_Rate_Shipping::$abort_key, $abort );
1104 | }
1105 |
1106 | /**
1107 | * Unset the abort notice in the session.
1108 | *
1109 | * @since 3.0.25
1110 | */
1111 | private function unset_abort_message() {
1112 | $abort = WC()->session->get( WC_Table_Rate_Shipping::$abort_key );
1113 | unset( $abort[ $this->instance_id ] );
1114 | WC()->session->set( WC_Table_Rate_Shipping::$abort_key, $abort );
1115 | }
1116 |
1117 | }
1118 |
--------------------------------------------------------------------------------
/includes/functions-admin.php:
--------------------------------------------------------------------------------
1 |
17 |
75 |
128 | shipping->get_shipping_classes();
140 | if ( ! $classes ) :
141 | echo '' . __( 'No shipping classes exist - you can ignore this option :)', 'woocommerce-table-rate-shipping' ) . '
';
142 | else :
143 | $priority = get_option( 'woocommerce_table_rate_default_priority_' . $shipping_method_id ) != '' ? get_option( 'woocommerce_table_rate_default_priority_' . $shipping_method_id ) : 10;
144 | ?>
145 |
174 | query( "DELETE FROM `$wpdb->options` WHERE `option_name` LIKE ('_transient_wc_ship_%')" );
189 |
190 | // Save class priorities
191 | if ( empty( $_POST['woocommerce_table_rate_calculation_type'] ) ) {
192 |
193 | if ( isset( $_POST['woocommerce_table_rate_priorities'] ) ) {
194 | $priorities = array_map( 'intval', (array) $_POST['woocommerce_table_rate_priorities'] );
195 | update_option( 'woocommerce_table_rate_priorities_' . $shipping_method_id, $priorities );
196 | }
197 |
198 | if ( isset( $_POST['woocommerce_table_rate_default_priority'] ) ) {
199 | update_option( 'woocommerce_table_rate_default_priority_' . $shipping_method_id, (int) esc_attr( $_POST['woocommerce_table_rate_default_priority'] ) );
200 | }
201 | } else {
202 | delete_option( 'woocommerce_table_rate_priorities_' . $shipping_method_id );
203 | delete_option( 'woocommerce_table_rate_default_priority_' . $shipping_method_id );
204 | }
205 |
206 | if ( function_exists( 'wc_get_rounding_precision' ) ) {
207 | $precision = wc_get_rounding_precision();
208 | } else {
209 | $precision = 4;
210 | }
211 |
212 | // Save rates
213 | $rate_ids = isset( $_POST['rate_id'] ) ? array_map( 'intval', $_POST['rate_id'] ) : array();
214 | $shipping_class = isset( $_POST['shipping_class'] ) ? array_map( 'wc_clean', $_POST['shipping_class'] ) : array();
215 | $shipping_condition = isset( $_POST['shipping_condition'] ) ? array_map( 'wc_clean', $_POST['shipping_condition'] ) : array();
216 | $shipping_min = isset( $_POST['shipping_min'] ) ? array_map( 'wc_clean', $_POST['shipping_min'] ) : array();
217 | $shipping_max = isset( $_POST['shipping_max'] ) ? array_map( 'wc_clean', $_POST['shipping_max'] ) : array();
218 | $shipping_cost = isset( $_POST['shipping_cost'] ) ? array_map( 'wc_clean', $_POST['shipping_cost'] ) : array();
219 | $shipping_per_item = isset( $_POST['shipping_per_item'] ) ? array_map( 'wc_clean', $_POST['shipping_per_item'] ) : array();
220 | $shipping_cost_per_weight = isset( $_POST['shipping_cost_per_weight'] ) ? array_map( 'wc_clean', $_POST['shipping_cost_per_weight'] ) : array();
221 | $cost_percent = isset( $_POST['shipping_cost_percent'] ) ? array_map( 'wc_clean', $_POST['shipping_cost_percent'] ) : array();
222 | $shipping_label = isset( $_POST['shipping_label'] ) ? array_map( 'wc_clean', $_POST['shipping_label'] ) : array();
223 | $shipping_priority = isset( $_POST['shipping_priority'] ) ? array_map( 'wc_clean', $_POST['shipping_priority'] ) : array();
224 | $shipping_abort = isset( $_POST['shipping_abort'] ) ? array_map( 'wc_clean', $_POST['shipping_abort'] ) : array();
225 | $shipping_abort_reason = isset( $_POST['shipping_abort_reason'] ) ? array_map( 'wc_clean', $_POST['shipping_abort_reason'] ) : array();
226 |
227 | // Get max key
228 | $max_key = ( $rate_ids ) ? max( array_keys( $rate_ids ) ) : 0;
229 |
230 | for ( $i = 0; $i <= $max_key; $i++ ) {
231 |
232 | if ( ! isset( $rate_ids[ $i ] ) ) {
233 | continue;
234 | }
235 |
236 | $rate_id = $rate_ids[ $i ];
237 | $rate_class = isset( $shipping_class[ $i ] ) ? $shipping_class[ $i ] : '';
238 | $rate_condition = $shipping_condition[ $i ];
239 | $rate_min = isset( $shipping_min[ $i ] ) ? $shipping_min[ $i ] : '';
240 | $rate_max = isset( $shipping_max[ $i ] ) ? $shipping_max[ $i ] : '';
241 | $rate_cost = isset( $shipping_cost[ $i ] ) ? wc_format_decimal( $shipping_cost[ $i ], $precision, true ) : '';
242 | $rate_cost_per_item = isset( $shipping_per_item[ $i ] ) ? wc_format_decimal( $shipping_per_item[ $i ], $precision, true ) : '';
243 | $rate_cost_per_weight_unit = isset( $shipping_cost_per_weight[ $i ] ) ? wc_format_decimal( $shipping_cost_per_weight[ $i ], $precision, true ) : '';
244 | $rate_cost_percent = isset( $cost_percent[ $i ] ) ? wc_format_decimal( str_replace( '%', '', $cost_percent[ $i ] ), $precision, true ) : '';
245 | $rate_label = isset( $shipping_label[ $i ] ) ? $shipping_label[ $i ] : '';
246 | $rate_priority = isset( $shipping_priority[ $i ] ) ? 1 : 0;
247 | $rate_abort = isset( $shipping_abort[ $i ] ) ? 1 : 0;
248 | $rate_abort_reason = isset( $shipping_abort_reason[ $i ] ) ? $shipping_abort_reason[ $i ] : '';
249 |
250 | // Format min and max
251 | switch ( $rate_condition ) {
252 | case 'weight':
253 | case 'price':
254 | if ( $rate_min ) {
255 | $rate_min = wc_format_decimal( $rate_min, $precision, true );
256 | }
257 | if ( $rate_max ) {
258 | $rate_max = wc_format_decimal( $rate_max, $precision, true );
259 | }
260 | break;
261 | case 'items':
262 | case 'items_in_class':
263 | if ( $rate_min ) {
264 | $rate_min = round( $rate_min );
265 | }
266 | if ( $rate_max ) {
267 | $rate_max = round( $rate_max );
268 | }
269 | break;
270 | default:
271 | $rate_min = '';
272 | $rate_max = '';
273 | break;
274 | }
275 |
276 | if ( $rate_id > 0 ) {
277 |
278 | // Update row
279 | $wpdb->update(
280 | $wpdb->prefix . 'woocommerce_shipping_table_rates',
281 | array(
282 | 'rate_class' => $rate_class,
283 | 'rate_condition' => sanitize_title( $rate_condition ),
284 | 'rate_min' => $rate_min,
285 | 'rate_max' => $rate_max,
286 | 'rate_cost' => $rate_cost,
287 | 'rate_cost_per_item' => $rate_cost_per_item,
288 | 'rate_cost_per_weight_unit' => $rate_cost_per_weight_unit,
289 | 'rate_cost_percent' => $rate_cost_percent,
290 | 'rate_label' => $rate_label,
291 | 'rate_priority' => $rate_priority,
292 | 'rate_order' => $i,
293 | 'shipping_method_id' => $shipping_method_id,
294 | 'rate_abort' => $rate_abort,
295 | 'rate_abort_reason' => $rate_abort_reason,
296 | ),
297 | array(
298 | 'rate_id' => $rate_id,
299 | ),
300 | array(
301 | '%s',
302 | '%s',
303 | '%s',
304 | '%s',
305 | '%s',
306 | '%s',
307 | '%s',
308 | '%s',
309 | '%s',
310 | '%s',
311 | '%d',
312 | '%d',
313 | '%d',
314 | '%s',
315 | ),
316 | array(
317 | '%d',
318 | )
319 | );
320 |
321 | } else {
322 |
323 | // Insert row
324 | $result = $wpdb->insert(
325 | $wpdb->prefix . 'woocommerce_shipping_table_rates',
326 | array(
327 | 'rate_class' => $rate_class,
328 | 'rate_condition' => sanitize_title( $rate_condition ),
329 | 'rate_min' => $rate_min,
330 | 'rate_max' => $rate_max,
331 | 'rate_cost' => $rate_cost,
332 | 'rate_cost_per_item' => $rate_cost_per_item,
333 | 'rate_cost_per_weight_unit' => $rate_cost_per_weight_unit,
334 | 'rate_cost_percent' => $rate_cost_percent,
335 | 'rate_label' => $rate_label,
336 | 'rate_priority' => $rate_priority,
337 | 'rate_order' => $i,
338 | 'shipping_method_id' => $shipping_method_id,
339 | 'rate_abort' => $rate_abort,
340 | 'rate_abort_reason' => $rate_abort_reason,
341 | ),
342 | array(
343 | '%s',
344 | '%s',
345 | '%s',
346 | '%s',
347 | '%s',
348 | '%s',
349 | '%s',
350 | '%s',
351 | '%s',
352 | '%s',
353 | '%d',
354 | '%d',
355 | '%d',
356 | '%s',
357 | )
358 | );
359 | }
360 | }
361 | }
362 |
--------------------------------------------------------------------------------
/includes/functions-ajax.php:
--------------------------------------------------------------------------------
1 | query( "DELETE FROM {$wpdb->prefix}woocommerce_shipping_table_rates WHERE rate_id IN (" . implode( ',', $rate_ids ) . ")" );
23 | }
24 |
25 | die();
26 | }
27 |
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/assets/css/shipping_zones.css:
--------------------------------------------------------------------------------
1 | .method_type_selector{display:inline-block;top:-2px;position:relative}.method_type_selector select{font-size:13px!important;margin:0 0 0 1em;vertical-align:middle;font-family:sans-serif;display:inline-block}.method_type_selector .add-new-h2{vertical-align:middle;margin-left:0;top:0;color:#21759b;cursor:pointer}#add-zone #zone_name{width:95%}#add-zone input{width:auto}#add-zone p{margin-top:0}#add-zone div{margin-bottom:.5em}#add-zone div label{margin-top:.5em}#add-zone label img.help_tip{margin:0 0 0 5px;position:relative;line-height:12px;vertical-align:top}#add-zone .chzn-container{width:95%!important;margin:9px 0 0}#add-zone .chzn-container .chzn-drop{width:100%!important;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#add-zone .chzn-container .search-field input{width:150px!important}#add-zone .button{margin-right:4px}table.shippingzones{position:relative}table.shippingzones td{vertical-align:top;padding:7px;line-height:1.4em;overflow:hidden;cursor:move}table.shippingzones tr:last-child td{cursor:default}table.shippingzones #zone_name{width:30%}table.shippingzones .column-enabled{width:80px}table.shippingzones .column-zone_type{width:30%}table.shippingzones .column-enabled{text-align:center}table.shippingzones th.check-column{padding-top:8px;padding-bottom:0}.woocommerce .form-wrap p{font-style:normal}.zone_type_options{padding-left:26px}.wc-col-container{padding:0;margin:0}.wc-col-container .wc-col-right{float:right;clear:right;width:65%;padding:0;margin:0}.wc-col-container .wc-col-left{width:35%;padding:0;margin:0}.wc-col-container .wc-col-wrap{padding:0 7px}.wc-col-container .wc-col-wrap p{width:95%}.wc-col-container:after{content:".";display:block;height:0;clear:both;visibility:hidden}
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/assets/css/shipping_zones.less:
--------------------------------------------------------------------------------
1 |
2 | .method_type_selector {
3 | display: inline-block;
4 | top: -2px;
5 | position: relative;
6 | select {
7 | font-size: 13px !important;
8 | margin: 0 0 0 1em;
9 | vertical-align: middle;
10 | font-family: sans-serif;
11 | display: inline-block;
12 | }
13 | .add-new-h2 {
14 | vertical-align: middle;
15 | margin-left: 0;
16 | top:0;
17 | color: #21759b;
18 | cursor: pointer;
19 | }
20 | }
21 | #add-zone {
22 | #zone_name {
23 | width: 95%;
24 | }
25 | input {
26 | width: auto;
27 | }
28 | p {
29 | margin-top: 0;
30 | }
31 | div {
32 | margin-bottom: .5em;
33 |
34 | label {
35 | margin-top: .5em;
36 | }
37 | }
38 | label {
39 | img.help_tip {
40 | margin: 0 0 0 5px;
41 | position: relative;
42 | line-height: 12px;
43 | vertical-align: top;
44 | }
45 | }
46 | .chzn-container {
47 | width: 95% !important;
48 | margin: 9px 0 0;
49 | .chzn-drop {
50 | width: 100% !important;
51 | -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
52 | -moz-box-sizing: border-box; /* Firefox, other Gecko */
53 | box-sizing: border-box; /* Opera/IE 8+ */
54 | }
55 | .search-field input {
56 | width: 150px !important;
57 | }
58 | }
59 | .button {
60 | margin-right: 4px;
61 | }
62 | }
63 | table.shippingzones {
64 | position: relative;
65 | td {
66 | vertical-align: top;
67 | padding: 7px 7px;
68 | line-height: 1.4em;
69 | overflow: hidden;
70 | cursor: move;
71 | }
72 | tr:last-child {
73 | td {
74 | cursor:default;
75 | }
76 | }
77 | #zone_name {
78 | width: 30%;
79 | }
80 | .column-enabled {
81 | width: 80px;
82 | }
83 | .column-zone_type {
84 | width: 30%;
85 | }
86 | .column-enabled {
87 | text-align: center;
88 | }
89 | th.check-column {
90 | padding-top: 8px;
91 | padding-bottom: 0;
92 | }
93 | }
94 | .woocommerce {
95 | .form-wrap {
96 | p {
97 | font-style: normal;
98 | }
99 | }
100 | }
101 | .zone_type_options {
102 | padding-left: 26px;
103 | }
104 | .wc-col-container {
105 | padding: 0;
106 | margin: 0;
107 |
108 | .wc-col-right {
109 | float: right;
110 | clear: right;
111 | width: 65%;
112 | padding: 0;
113 | margin: 0;
114 | }
115 | .wc-col-left {
116 | width: 35%;
117 | padding: 0;
118 | margin: 0;
119 | }
120 | .wc-col-wrap {
121 | padding: 0 7px;
122 | p {
123 | width: 95%;
124 | }
125 | }
126 | }
127 | .wc-col-container:after {
128 | content: ".";
129 | display: block;
130 | height: 0;
131 | clear: both;
132 | visibility: hidden;
133 | }
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/assets/js/shipping-zone-admin.js:
--------------------------------------------------------------------------------
1 | jQuery(function($) {
2 |
3 | if ( ! wc_shipping_zones_params.supports_select2 ) {
4 | $("select.chosen_select").chosen();
5 | }
6 |
7 | $('body')
8 |
9 | .on( 'click', 'a.shipping-zone-delete', function(){
10 | var answer = confirm( $(this).data('message') );
11 | if ( answer ) {
12 | return true;
13 | } else {
14 | return false;
15 | }
16 | })
17 |
18 | .on( 'change', 'input[name=zone_type]', function() {
19 | if ( $(this).is(':checked') ) {
20 | var value = $(this).val();
21 | $( '.zone_type_options' ).slideUp();
22 | $( '.zone_type_' + value ).slideDown();
23 | }
24 | })
25 |
26 | .on( 'click', '.select_us_states', function(){
27 | $(this).closest('div').find('option[value="US:AK"], option[value="US:AL"], option[value="US:AZ"], option[value="US:AR"], option[value="US:CA"], option[value="US:CO"], option[value="US:CT"], option[value="US:DE"], option[value="US:DC"], option[value="US:FL"], option[value="US:GA"], option[value="US:HI"], option[value="US:ID"], option[value="US:IL"], option[value="US:IN"], option[value="US:IA"], option[value="US:KS"], option[value="US:KY"], option[value="US:LA"], option[value="US:ME"], option[value="US:MD"], option[value="US:MA"], option[value="US:MI"], option[value="US:MN"], option[value="US:MS"], option[value="US:MO"], option[value="US:MT"], option[value="US:NE"], option[value="US:NV"], option[value="US:NH"], option[value="US:NJ"], option[value="US:NM"], option[value="US:NY"], option[value="US:NC"], option[value="US:ND"], option[value="US:OH"], option[value="US:OK"], option[value="US:OR"], option[value="US:PA"], option[value="US:RI"], option[value="US:SC"], option[value="US:SD"], option[value="US:TN"], option[value="US:TX"], option[value="US:UT"], option[value="US:VT"], option[value="US:VA"], option[value="US:WA"], option[value="US:WV"], option[value="US:WI"], option[value="US:WY"]').attr("selected","selected");
28 | $(this).closest('div').find('select').trigger('chosen:updated').change();
29 | return false;
30 | })
31 |
32 | .on( 'click', '.select_europe', function(){
33 | $(this).closest('div').find('option[value="AL"], option[value="AD"], option[value="AM"], option[value="AT"], option[value="BY"], option[value="BE"], option[value="BA"], option[value="BG"], option[value="CH"], option[value="CY"], option[value="CZ"], option[value="DE"], option[value="DK"], option[value="EE"], option[value="ES"], option[value="FO"], option[value="FI"], option[value="FR"], option[value="GB"], option[value="GE"], option[value="GI"], option[value="GR"], option[value="HU"], option[value="HR"], option[value="IE"], option[value="IS"], option[value="IT"], option[value="LT"], option[value="LU"], option[value="LV"], option[value="MC"], option[value="MK"], option[value="MT"], option[value="NO"], option[value="NL"], option[value="PO"], option[value="PT"], option[value="RO"], option[value="RU"], option[value="SE"], option[value="SI"], option[value="SK"], option[value="SM"], option[value="TR"], option[value="UA"], option[value="VA"]').attr("selected","selected");
34 | $(this).closest('div').find('select').trigger('chosen:updated').change();
35 | return false;
36 | })
37 |
38 | .on( 'click', '.select_none', function(){
39 | $(this).closest('div').find('select option').removeAttr("selected");
40 | $(this).closest('div').find('select').trigger('chosen:updated').change();
41 | return false;
42 | })
43 |
44 | .on( 'click', '.select_all', function(){
45 | $(this).closest('div').find('select option').attr("selected","selected");
46 | $(this).closest('div').find('select').trigger('chosen:updated').change();
47 | return false;
48 | });
49 |
50 | // Sorting
51 | $('table.shippingzones tbody').sortable({
52 | items:'tr:not(:last-child)',
53 | cursor:'move',
54 | axis:'y',
55 | handle: 'td',
56 | scrollSensitivity:40,
57 | helper:function(e,ui){
58 | ui.children().each(function(){
59 | $(this).width($(this).width());
60 | });
61 | ui.css('left', '0');
62 | return ui;
63 | },
64 | start:function(event,ui){
65 | ui.item.css('background-color','#f6f6f6');
66 | },
67 | stop:function(event,ui){
68 | ui.item.removeAttr('style');
69 | },
70 | update: function(event, ui) {
71 | $('table.shippingzones tbody td').css('cursor','default');
72 | $('table.shippingzones tbody').sortable('disable');
73 |
74 | // show spinner
75 | ui.item.find('.check-column input').hide();
76 | ui.item.find('.check-column').append(' ');
77 |
78 | // Parent
79 | var zone_ids = [];
80 |
81 | $(this).closest('form').find('input.zone_id').each(function(){
82 | var zone_id = $(this).val();
83 | zone_ids.push(zone_id);
84 | });
85 |
86 | // go do the sorting stuff via ajax
87 | $.post( ajaxurl, { action: 'woocommerce_zone_ordering', security: wc_shipping_zones_params.shipping_zones_nonce, zone_ids: zone_ids }, function(response) {
88 | ui.item.find('.check-column input').show();
89 | ui.item.find('.check-column').find('img').remove();
90 | $('table.shippingzones tbody td').css('cursor','move');
91 | $('table.shippingzones tbody').sortable('enable');
92 |
93 | });
94 |
95 | // fix cell colors
96 | $('table.shippingzones tbody tr').each(function(){
97 | var i = $('table.shippingzones tbody tr').index(this);
98 | if ( i%2 == 0 ) $(this).addClass('alternate');
99 | else $(this).removeClass('alternate');
100 | });
101 | }
102 | });
103 |
104 | $('.zone_type_options').hide();
105 | $('input[name=zone_type]').change();
106 | });
107 |
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/class-wc-shipping-zones.php:
--------------------------------------------------------------------------------
1 | wp_create_nonce( 'shipping-zones' ),
60 | 'supports_select2' => version_compare( WC_VERSION, '2.3', '>' ) ? 1 : 0
61 | )
62 | );
63 |
64 | if ( version_compare( WC_VERSION, '2.3', '<' ) ) {
65 | wp_enqueue_script( 'woocommerce_admin' );
66 | wp_enqueue_script( 'jquery-ui-sortable' );
67 | wp_enqueue_script( 'chosen' );
68 | }
69 |
70 | do_action( 'woocommerce_shipping_zones_css' );
71 | }
72 | }
73 |
74 | WC_Shipping_Zones::init();
75 |
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/class-wc-shipping-zone-admin.php:
--------------------------------------------------------------------------------
1 | exists() ) {
21 | echo '' . sprintf( __( 'Invalid shipping zone. Back to zones. ', SHIPPING_ZONES_TEXTDOMAIN ), esc_url( remove_query_arg( 'zone' ) ) ) . '
';
22 | return;
23 | }
24 |
25 | self::add_method( $zone );
26 | self::delete_method( $zone );
27 |
28 | if ( ! empty( $_GET['method'] )) {
29 | self::method_settings( $zone, absint( $_GET['method'] ) );
30 | return;
31 | } else {
32 | include( 'views/html-zone-methods.php' );
33 | }
34 | }
35 |
36 | /**
37 | * Add shipping method to zone
38 | */
39 | public static function add_method( $zone ) {
40 | if ( ! empty( $_GET['add_method'] ) && ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'woocommerce_add_method' ) ) {
41 | $type = wc_clean( $_GET['method_type'] );
42 |
43 | if ( $type && ( $method_id = $zone->add_shipping_method( $type ) ) ) {
44 | echo '' . sprintf( __( 'Shipping method successfully created. View method. ', SHIPPING_ZONES_TEXTDOMAIN ), esc_url( add_query_arg( 'method', $method_id, add_query_arg( 'zone', $zone->zone_id, admin_url( 'admin.php?page=shipping_zones' ) ) ) ) ) . '
';
45 | } else {
46 | echo '' . __( 'Invalid shipping method', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
47 | }
48 | }
49 | }
50 |
51 | /**
52 | * Delete shipping method from zone.
53 | */
54 | public static function delete_method( $zone ) {
55 | if ( ! empty( $_GET['delete_method'] ) && ! empty( $_GET['_wpnonce'] ) && wp_verify_nonce( $_GET['_wpnonce'], 'woocommerce_delete_method' ) ) {
56 | $method_id = absint( $_GET['delete_method'] );
57 |
58 | if ( $zone->delete_shipping_method( $method_id ) ) {
59 | echo '' . __( 'Shipping method successfully deleted', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
60 | }
61 | }
62 | }
63 |
64 | /**
65 | * list_shipping_zone_methods function.
66 | */
67 | public static function list_shipping_zone_methods() {
68 | if ( ! class_exists( 'WC_Shipping_Zone_Methods_Table' ) ) {
69 | require_once( 'list-tables/class-wc-shipping-zone-methods-table.php' );
70 | }
71 | echo '';
76 | }
77 |
78 | /**
79 | * Show settings for a method
80 | */
81 | public static function method_settings( $zone, $method_id ) {
82 | global $wpdb;
83 |
84 | // Get method
85 | $method = $wpdb->get_row( $wpdb->prepare( "
86 | SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods WHERE shipping_method_id = %s
87 | ", $method_id ) );
88 |
89 | $callback = 'woocommerce_get_shipping_method_' . $method->shipping_method_type;
90 |
91 | if ( ! function_exists( $callback ) ) {
92 | return;
93 | }
94 |
95 | // Construct method instance
96 | $shipping_method = $callback( $method_id );
97 |
98 | if ( ! empty( $_POST['save_method'] ) ) {
99 |
100 | if ( empty( $_POST['woocommerce_save_method_nonce'] ) || ! wp_verify_nonce( $_POST['woocommerce_save_method_nonce'], 'woocommerce_save_method' )) {
101 | echo '' . __( 'Edit failed. Please try again.', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
102 |
103 | } elseif ( $shipping_method->process_instance_options() ) {
104 |
105 | // re-init so we re-load settings
106 | unset( $shipping_method );
107 | $shipping_method = $callback( $method_id );
108 |
109 | echo '' . __( 'Shipping method saved successfully.', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
110 | }
111 | }
112 |
113 | include( 'views/html-zone-method-settings.php' );
114 | }
115 | }
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/class-wc-shipping-zone.php:
--------------------------------------------------------------------------------
1 | zone_id = $zone_id;
27 | $this->init();
28 | $this->find_shipping_methods();
29 | }
30 |
31 | /**
32 | * Does this zone exist?
33 | * @return bool
34 | */
35 | public function exists() {
36 | return $this->exists;
37 | }
38 |
39 | /**
40 | * Register zone shipping methods for use.
41 | */
42 | public function register_shipping_methods() {
43 | foreach ( $this->shipping_methods as $shipping_method ) {
44 | if ( is_callable( $shipping_method['callback'] ) ) {
45 | $method = call_user_func( $shipping_method['callback'], $shipping_method['number'] );
46 |
47 | if ( $method->enabled == 'yes' ) {
48 | WC()->shipping->register_shipping_method( $method );
49 | }
50 | }
51 | }
52 | }
53 |
54 | /**
55 | * Add a shipping method to this zone.
56 | * @param string $type
57 | * @return int
58 | */
59 | public function add_shipping_method( $type ) {
60 | global $wpdb;
61 |
62 | if ( ! $type ) {
63 | return 0;
64 | }
65 |
66 | $wpdb->insert(
67 | $wpdb->prefix . 'woocommerce_shipping_zone_shipping_methods',
68 | array(
69 | 'shipping_method_type' => $type,
70 | 'zone_id' => $this->zone_id,
71 | 'shipping_method_order' => 0
72 | ),
73 | array(
74 | '%s',
75 | '%d',
76 | '%d'
77 | )
78 | );
79 |
80 | return $wpdb->insert_id;
81 | }
82 |
83 |
84 | /**
85 | * Delete a shipping method belonging to this zone.
86 | * @param int $id
87 | */
88 | public function delete_shipping_method( $id ) {
89 | global $wpdb;
90 |
91 | $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_shipping_methods', array( 'shipping_method_id' => $id ) );
92 | $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_table_rates', array( 'shipping_method_id' => $id ) );
93 |
94 | delete_option( 'woocommerce_table_rate_priorities_' . $id );
95 | delete_option( 'woocommerce_table_rate_default_priority_' . $id );
96 | }
97 |
98 | /**
99 | * Init the zone data
100 | */
101 | private function init() {
102 | if ( $this->zone_id > 0 ) {
103 | global $wpdb;
104 |
105 | $zone = $wpdb->get_row( $wpdb->prepare( "
106 | SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zones
107 | WHERE zone_id = %d LIMIT 1
108 | ", $this->zone_id ) );
109 |
110 | if ( $zone ) {
111 | $this->zone_name = $zone->zone_name;
112 | $this->zone_enabled = $zone->zone_enabled;
113 | $this->zone_type = $zone->zone_type;
114 | $this->zone_order = $zone->zone_order;
115 | $this->exists = true;
116 | }
117 | } else {
118 | $this->zone_name = __( 'Everywhere else', SHIPPING_ZONES_TEXTDOMAIN );
119 | $this->zone_enabled = 1;
120 | $this->zone_type = '';
121 | $this->zone_order = '';
122 | $this->exists = true;
123 | }
124 | }
125 |
126 | /**
127 | * Find shipping methods for this zone.
128 | */
129 | private function find_shipping_methods() {
130 | global $wpdb;
131 |
132 | $zone_methods = $wpdb->get_results( $wpdb->prepare( "
133 | SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods
134 | WHERE zone_id = %s
135 | ORDER BY shipping_method_order ASC
136 | ", $this->zone_id ) );
137 |
138 | foreach ( $zone_methods as $method ) {
139 | $this->shipping_methods[] = array(
140 | 'number' => $method->shipping_method_id, // Instance number for the method
141 | 'callback' => 'woocommerce_get_shipping_method_' . $method->shipping_method_type // Callback function to init the method class
142 | );
143 | }
144 | }
145 | }
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/class-wc-shipping-zones-admin.php:
--------------------------------------------------------------------------------
1 | shipping();
17 | }
18 | if ( ! empty( $_GET['edit_zone'] ) ) {
19 | self::edit_zone_screen();
20 | } elseif ( isset( $_GET['zone'] ) ) {
21 | include_once( 'class-wc-shipping-zone-admin.php' );
22 | WC_Shipping_Zone_Admin::view_zone_screen();
23 | } else {
24 | self::list_zones_screen();
25 | }
26 | }
27 |
28 | /**
29 | * Save zone after editing
30 | */
31 | private static function save_zone( $zone_id = 0 ) {
32 | global $wpdb;
33 |
34 | $editing = ! empty( $zone_id );
35 |
36 | if ( ! empty( $_POST['add_zone'] ) || ! empty( $_POST['edit_zone'] ) ) {
37 |
38 | if ( empty( $_POST['woocommerce_save_zone_nonce'] ) || ! wp_verify_nonce( $_POST['woocommerce_save_zone_nonce'], 'woocommerce_save_zone' ) ) {
39 | echo '' . __( 'Could not save zone. Please try again.', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
40 | return;
41 | }
42 |
43 | $fields = array(
44 | 'zone_name',
45 | 'zone_type',
46 | 'zone_enabled',
47 | 'zone_type_countries',
48 | 'zone_type_states',
49 | 'zone_type_postcodes',
50 | 'postcodes'
51 | );
52 |
53 | $zone_count = $wpdb->get_var( "SELECT COUNT( zone_id ) FROM {$wpdb->prefix}woocommerce_shipping_zones" );
54 | $data = array();
55 |
56 | foreach ( $fields as $field ) {
57 | $data[ $field ] = empty( $_POST[ $field ] ) ? '' : $_POST[ $field ];
58 |
59 | if ( 'postcodes' === $field ) {
60 | $data[ $field ] = array_map( 'strtoupper', array_map( 'wc_clean', explode( "\n", $data[ $field ] ) ) );
61 | } else {
62 | $data[ $field ] = is_array( $data[ $field ] ) ? array_map( 'wc_clean', $data[ $field ] ) : wc_clean( $data[ $field ] );
63 | }
64 | }
65 |
66 | // If name is left blank...
67 | if ( empty( $data['zone_name'] ) ) {
68 | if ( $editing ) {
69 | echo '' . __( 'Zone name is required', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
70 | return;
71 | } else {
72 | $data['zone_name'] = __( 'Zone', SHIPPING_ZONES_TEXTDOMAIN ) . ' ' . ( $zone_count + 1 );
73 | }
74 | }
75 |
76 | // Check required fields
77 | if ( empty( $data['zone_type'] ) ) {
78 | echo '' . __(' Zone type is required', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
79 | return;
80 | }
81 |
82 | $data['zone_enabled'] = ( $data['zone_enabled'] || ! $editing ) ? 1 : 0;
83 |
84 | // Determine field we are saving
85 | $locations_field = 'zone_type_' . $data['zone_type'];
86 |
87 | // Get the countries into a nicely formatted array
88 | if ( ! $data[ $locations_field ] ) {
89 | $data[ $locations_field ] = array();
90 | }
91 |
92 | if ( is_array( $data[ $locations_field ] ) ) {
93 | $data[ $locations_field ] = array_filter( array_map( 'strtoupper', array_map( 'sanitize_text_field', $data[ $locations_field ] ) ) );
94 | } else {
95 | $data[ $locations_field ] = array( strtoupper( sanitize_text_field( $data[ $locations_field ] ) ) );
96 | }
97 |
98 | // Any set?
99 | if ( sizeof( $data[ $locations_field ] ) == 0 ) {
100 | echo '' . __('You must choose at least 1 country to add a zone.', SHIPPING_ZONES_TEXTDOMAIN) . '
';
101 | return;
102 | }
103 |
104 | // If dealing with a postcode, grab that field too
105 | if ( $data['zone_type'] == 'postcodes' ) {
106 |
107 | $data['postcodes'] = array_filter( array_unique( $data['postcodes'] ) );
108 |
109 | if ( sizeof( $data['postcodes'] ) == 0 ) {
110 | echo '' . __('You must choose at least 1 postcode to add postcode zone.', SHIPPING_ZONES_TEXTDOMAIN) . '
';
111 | return;
112 | }
113 |
114 | } else {
115 | $data['postcodes'] = array();
116 | }
117 |
118 | if ( $editing ) {
119 | $wpdb->update(
120 | $wpdb->prefix . 'woocommerce_shipping_zones',
121 | array(
122 | 'zone_name' => $data['zone_name'],
123 | 'zone_enabled' => $data['zone_enabled'],
124 | 'zone_type' => $data['zone_type'],
125 | ),
126 | array(
127 | 'zone_id' => $zone_id
128 | )
129 | );
130 | } else {
131 | $wpdb->insert(
132 | $wpdb->prefix . 'woocommerce_shipping_zones',
133 | array(
134 | 'zone_name' => $data['zone_name'],
135 | 'zone_enabled' => $data['zone_enabled'],
136 | 'zone_type' => $data['zone_type'],
137 | 'zone_order' => $zone_count + 1
138 | ),
139 | array(
140 | '%s',
141 | '%d',
142 | '%s',
143 | '%d'
144 | )
145 | );
146 | $zone_id = $wpdb->insert_id;
147 | }
148 |
149 | $update_locations = true;
150 |
151 | if ( $editing ) {
152 | $locations = $wpdb->get_col( $wpdb->prepare( "
153 | SELECT location_code FROM {$wpdb->prefix}woocommerce_shipping_zone_locations
154 | WHERE zone_id = %d
155 | ", $zone_id ) );
156 |
157 | $new_locations = array_merge( $data[ $locations_field ], $data['postcodes'] );
158 |
159 | if ( array_diff( $locations, $new_locations ) || array_diff( $new_locations, $locations ) ) {
160 | $update_locations = true;
161 | } else {
162 | $update_locations = false;
163 | }
164 | }
165 |
166 | if ( $update_locations ) {
167 | if ( $zone_id > 0 ) {
168 |
169 | // Remove locations
170 | $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE zone_id = %s", $zone_id ) );
171 |
172 | // Insert locations which apply to this zone
173 | foreach ( $data[ $locations_field ] as $code ) {
174 | if ( $code ) {
175 | $wpdb->insert(
176 | $wpdb->prefix . 'woocommerce_shipping_zone_locations',
177 | array(
178 | 'location_code' => $code,
179 | 'location_type' => strstr( $code, ':' ) ? 'state' : 'country',
180 | 'zone_id' => $zone_id,
181 | ),
182 | array(
183 | '%s',
184 | '%s',
185 | '%d'
186 | )
187 | );
188 | }
189 | }
190 |
191 | // Save postcodes
192 | if ( $data['zone_type'] == 'postcodes' ) {
193 | foreach ( $data['postcodes'] as $code ) {
194 | if ( $code ) {
195 | $wpdb->insert(
196 | $wpdb->prefix . 'woocommerce_shipping_zone_locations',
197 | array(
198 | 'location_code' => $code,
199 | 'location_type' => 'postcode',
200 | 'zone_id' => $zone_id,
201 | ),
202 | array(
203 | '%s',
204 | '%s',
205 | '%d'
206 | )
207 | );
208 | }
209 | }
210 | }
211 |
212 | } else {
213 | echo '' . __( 'Error saving zone.', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
214 | return;
215 | }
216 | }
217 |
218 | if ( $editing ) {
219 | echo '' . sprintf( __( 'Shipping zone saved. Back to zones. ', SHIPPING_ZONES_TEXTDOMAIN ), esc_url( remove_query_arg( 'edit_zone' ) ) ) . '
';
220 | } else {
221 | echo '' . __( 'Shipping zone saved.', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
222 | }
223 | }
224 | }
225 |
226 | /**
227 | * Edit Zone Screen
228 | */
229 | public static function edit_zone_screen() {
230 | $zone_id = absint( $_GET['edit_zone'] );
231 | self::save_zone( $zone_id );
232 | self::edit_zone( $zone_id );
233 | }
234 |
235 | /**
236 | * list_zone_page function.
237 | */
238 | public static function list_zones_screen() {
239 | self::save_zone();
240 | include( 'views/html-zone-list.php' );
241 | }
242 |
243 | /**
244 | * Edit zone form
245 | */
246 | private static function edit_zone( $zone_id ) {
247 | global $wpdb;
248 |
249 | $countries = WC()->countries->get_allowed_countries();
250 | $base = WC()->countries->get_base_country();
251 |
252 | // Load details to edit
253 | $zone = $wpdb->get_row( $wpdb->prepare( "
254 | SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zones
255 | WHERE zone_id = %d LIMIT 1
256 | ", $zone_id ) );
257 |
258 | $location_counties = $wpdb->get_col( $wpdb->prepare( "
259 | SELECT location_code FROM {$wpdb->prefix}woocommerce_shipping_zone_locations
260 | WHERE zone_id = %d AND location_type = 'country'
261 | ", $zone_id ) );
262 |
263 | $location_states = $wpdb->get_col( $wpdb->prepare( "
264 | SELECT location_code FROM {$wpdb->prefix}woocommerce_shipping_zone_locations
265 | WHERE zone_id = %d AND location_type = 'state'
266 | ", $zone_id ) );
267 |
268 | $location_postcodes = $wpdb->get_col( $wpdb->prepare( "
269 | SELECT location_code FROM {$wpdb->prefix}woocommerce_shipping_zone_locations
270 | WHERE zone_id = %d AND location_type = 'postcode'
271 | ", $zone_id ) );
272 |
273 | $selected_states = array_merge( $location_states, $location_counties );
274 |
275 | include( 'views/form-edit-shipping-zone.php' );
276 | }
277 |
278 | /**
279 | * list_shipping_zones function.
280 | *
281 | * @access public
282 | * @return void
283 | */
284 | public static function list_shipping_zones() {
285 | if ( ! class_exists( 'WC_Shipping_Zones_Table' ) ) {
286 | require_once( 'list-tables/class-wc-shipping-zones-table.php' );
287 | }
288 |
289 | echo '';
294 | }
295 |
296 | /**
297 | * add_shipping_zone_form function.
298 | */
299 | public static function add_shipping_zone_form() {
300 | global $wpdb;
301 |
302 | $countries = WC()->countries->get_allowed_countries();
303 | $base = WC()->countries->get_base_country();
304 | $zone_count = $wpdb->get_var( "SELECT COUNT( zone_id ) FROM {$wpdb->prefix}woocommerce_shipping_zones;" );
305 |
306 | include( 'views/form-add-shipping-zone.php' );
307 | }
308 | }
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/class-wc-shipping-zones-ajax-handler.php:
--------------------------------------------------------------------------------
1 | $zone ) {
29 |
30 | if ( $zone > 0 ) {
31 |
32 | $wpdb->update(
33 | $wpdb->prefix . 'woocommerce_shipping_zones',
34 | array(
35 | 'zone_order' => $i,
36 | ),
37 | array( 'zone_id' => $zone ),
38 | array( '%d' ),
39 | array( '%d' )
40 | );
41 | }
42 | }
43 |
44 | die();
45 | }
46 |
47 | public static function shipping_method_ordering() {
48 | check_ajax_referer( 'shipping-zones', 'security' );
49 |
50 | global $wpdb;
51 |
52 | $shipping_method_id = isset( $_POST['shipping_method_id'] ) ? absint( $_POST['shipping_method_id'] ) : false;
53 | $prev_shipping_method_id = isset( $_POST['prev_shipping_method_id'] ) ? absint( $_POST['prev_shipping_method_id'] ) : false;
54 | $next_shipping_method_id = isset( $_POST['next_shipping_method_id'] ) ? absint( $_POST['next_shipping_method_id'] ) : false;
55 |
56 | if ( ! $shipping_method_id )
57 | die( -1 );
58 |
59 | $zone_id = absint( $wpdb->get_var( "SELECT zone_id FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods WHERE shipping_method_id = " . $shipping_method_id ) );
60 |
61 | $siblings = $wpdb->get_results("
62 | SELECT shipping_method_id, shipping_method_order FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods
63 | WHERE zone_id = " . $zone_id . "
64 | AND shipping_method_id NOT IN (" . $shipping_method_id . ")
65 | ORDER BY shipping_method_order ASC
66 | ");
67 |
68 | $new_positions = array(); // store new positions for ajax
69 | $menu_order = 0;
70 |
71 | foreach( $siblings as $sibling ) {
72 |
73 | // if this is the post that comes after our repositioned post, set our repositioned post position and increment menu order
74 | if ( $next_shipping_method_id && $next_shipping_method_id == $sibling->shipping_method_id ) {
75 | $wpdb->update(
76 | $wpdb->prefix . "woocommerce_shipping_zone_shipping_methods",
77 | array(
78 | 'shipping_method_order' => $menu_order
79 | ),
80 | array( 'shipping_method_id' => $shipping_method_id ),
81 | array( '%d' ),
82 | array( '%d' )
83 | );
84 | $new_positions[ $shipping_method_id ] = $menu_order;
85 | $menu_order++;
86 | }
87 |
88 | // if repositioned post has been set, and new items are already in the right order, we can stop
89 | if ( isset( $new_positions[ $shipping_method_id ] ) && $sibling->shipping_method_order >= $menu_order )
90 | break;
91 |
92 | // set the menu order of the current sibling and increment the menu order
93 | $wpdb->update(
94 | $wpdb->prefix . "woocommerce_shipping_zone_shipping_methods",
95 | array(
96 | 'shipping_method_order' => $menu_order
97 | ),
98 | array( 'shipping_method_id' => $sibling->shipping_method_id ),
99 | array( '%d' ),
100 | array( '%d' )
101 | );
102 | $new_positions[ $sibling->shipping_method_id ] = $menu_order;
103 | $menu_order++;
104 |
105 | if ( ! $next_shipping_method_id && $prev_shipping_method_id == $sibling->shipping_method_id ) {
106 | $wpdb->update(
107 | $wpdb->prefix . "woocommerce_shipping_zone_shipping_methods",
108 | array(
109 | 'shipping_method_order' => $menu_order
110 | ),
111 | array( 'shipping_method_id' => $shipping_method_id ),
112 | array( '%d' ),
113 | array( '%d' )
114 | );
115 | $new_positions[ $shipping_method_id ] = $menu_order;
116 | $menu_order++;
117 | }
118 | }
119 |
120 | die();
121 | }
122 | }
123 |
124 | WC_Shipping_Zones_Ajax_Handler::init();
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zone-methods-table.php:
--------------------------------------------------------------------------------
1 | zone_id = (int) $_GET['zone'];
27 | $this->index = 0;
28 |
29 | //Set parent defaults
30 | parent::__construct( array(
31 | 'singular' => 'Shipping Method', //singular name of the listed records
32 | 'plural' => 'Shipping Methods', //plural name of the listed records
33 | 'ajax' => false //does this table support ajax?
34 | ) );
35 |
36 | wc_enqueue_js( "
37 | jQuery('table.shippingmethods tbody th, table.shippingmethods tbody td').css('cursor','move');
38 |
39 | jQuery('table.shippingmethods tbody').sortable({
40 | items: 'tr:not(.inline-edit-row)',
41 | cursor: 'move',
42 | axis: 'y',
43 | containment: 'table.shippingmethods',
44 | scrollSensitivity: 40,
45 | helper: function(e, ui) {
46 | ui.children().each(function() { jQuery(this).width(jQuery(this).width()); });
47 | return ui;
48 | },
49 | start: function(event, ui) {
50 | if ( ! ui.item.hasClass('alternate') ) ui.item.css( 'background-color', '#ffffff' );
51 | ui.item.children('td,th').css('border-bottom-width','0');
52 | ui.item.css( 'outline', '1px solid #dfdfdf' );
53 | },
54 | stop: function(event, ui) {
55 | ui.item.removeAttr('style');
56 | ui.item.children('td,th').css('border-bottom-width','1px');
57 | },
58 | update: function(event, ui) {
59 | jQuery('table.shippingmethods tbody th, table.shippingmethods tbody td').css('cursor','default');
60 | jQuery('table.shippingmethods tbody').sortable('disable');
61 |
62 | var shipping_method_id = ui.item.find('.check-column input').val();
63 | var prev_shipping_method_id = ui.item.prev().find('.check-column input').val();
64 | var next_shipping_method_id = ui.item.next().find('.check-column input').val();
65 |
66 | // show spinner
67 | ui.item.find('.check-column input').hide().after(' ');
68 |
69 | // go do the sorting stuff via ajax
70 | jQuery.post( ajaxurl, { action: 'woocommerce_shipping_method_ordering', security: '" . wp_create_nonce( 'shipping-zones' ) . "', shipping_method_id: shipping_method_id, prev_shipping_method_id: prev_shipping_method_id, next_shipping_method_id: next_shipping_method_id }, function(response) {
71 | ui.item.find('.check-column input').show().siblings('img').remove();
72 | jQuery('table.shippingmethods tbody th, table.shippingmethods tbody td').css('cursor','move');
73 | jQuery('table.shippingmethods tbody').sortable('enable');
74 | });
75 |
76 | // fix cell colors
77 | jQuery( 'table.shippingmethods tbody tr' ).each(function(){
78 | var i = jQuery('table.shippingmethods tbody tr').index(this);
79 | if ( i%2 == 0 ) jQuery(this).addClass('alternate');
80 | else jQuery(this).removeClass('alternate');
81 | });
82 | }
83 | });
84 |
85 | " );
86 | }
87 |
88 | /**
89 | * Checkbox column
90 | * @param string
91 | */
92 | public function column_cb( $item ){
93 | return sprintf(
94 | ' ',
95 | 'shipping_method_id',
96 | $item->instance_id
97 | );
98 | }
99 |
100 | /**
101 | * Output the title column.
102 | * @param object $item
103 | * @return string
104 | */
105 | public function column_title( $item ) {
106 | $title = $item->title;
107 |
108 | if ( ! $title ) {
109 | $title = ucwords( $item->method_title );
110 | }
111 |
112 | return '
113 | ' . esc_html( $title ) . '
114 | ';
117 | }
118 |
119 | /**
120 | * Output the type column.
121 | * @param object $item
122 | * @return string
123 | */
124 | public function column_type( $item ) {
125 | return esc_html( $item->method_title );
126 | }
127 |
128 | /**
129 | * Output the enabled column.
130 | * @param object $item
131 | * @return string
132 | */
133 | public function column_enabled( $item ) {
134 | return 'yes' === $item->enabled ? '✔' : '–';
135 | }
136 |
137 | /**
138 | * get_columns function.
139 | * @return array
140 | */
141 | public function get_columns(){
142 | $columns = array(
143 | 'cb' => ' ',
144 | 'title' => __( 'Method Title', SHIPPING_ZONES_TEXTDOMAIN ),
145 | 'type' => __( 'Method Type', SHIPPING_ZONES_TEXTDOMAIN ),
146 | 'enabled' => __( 'Enabled', SHIPPING_ZONES_TEXTDOMAIN ),
147 | );
148 | return $columns;
149 | }
150 |
151 | /**
152 | * Get bulk actions
153 | */
154 | public function get_bulk_actions() {
155 | $actions = array(
156 | 'delete' => __('Delete', SHIPPING_ZONES_TEXTDOMAIN)
157 | );
158 | return $actions;
159 | }
160 |
161 | /**
162 | * Process bulk actions
163 | */
164 | public function process_bulk_action() {
165 | global $wpdb;
166 |
167 | if ( ! isset( $_POST['shipping_method_id'] ) ) {
168 | return;
169 | }
170 |
171 | $items = array_filter( array_map( 'absint', $_POST['shipping_method_id'] ) );
172 |
173 | if ( ! $items ) {
174 | return;
175 | }
176 |
177 | if ( 'delete' === $this->current_action() ) {
178 | foreach ( $items as $id ) {
179 | $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_shipping_methods', array( 'shipping_method_id' => $id ) );
180 | $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_table_rates', array( 'shipping_method_id' => $id ) );
181 | delete_option( 'woocommerce_table_rate_priorities_' . $id );
182 | delete_option( 'woocommerce_table_rate_default_priority_' . $id );
183 | }
184 |
185 | echo '' . __( 'Shipping methods deleted', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
186 | }
187 | }
188 |
189 | /**
190 | * Message to be displayed when there are no items
191 | */
192 | public function no_items() {
193 | echo '' . __( 'No shipping methods found.', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
194 | }
195 |
196 | /**
197 | * Get shipping methods to display for this zone.
198 | */
199 | public function prepare_items() {
200 | global $wpdb;
201 |
202 | $this->_column_headers = array( $this->get_columns(), array(), array() );
203 | $this->process_bulk_action();
204 |
205 | $shipping_methods = $wpdb->get_results( $wpdb->prepare( "
206 | SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods
207 | WHERE zone_id = %s
208 | ORDER BY `shipping_method_order` ASC
209 | ", $this->zone_id ) );
210 |
211 | foreach ( $shipping_methods as $method ) {
212 | $class_callback = 'woocommerce_get_shipping_method_' . $method->shipping_method_type;
213 |
214 | if ( function_exists( $class_callback ) ) {
215 | $this->items[] = call_user_func( $class_callback, $method->shipping_method_id );
216 | }
217 | }
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:
--------------------------------------------------------------------------------
1 | 'Shipping Zone',
25 | 'plural' => 'Shipping Zones',
26 | 'ajax' => false
27 | ) );
28 | }
29 |
30 | /**
31 | * Output the zone name column.
32 | * @param object $item
33 | * @return string
34 | */
35 | public function column_zone_name( $item ) {
36 | $zone_name = '
37 |
38 | ' . esc_html( $item->zone_name ) . '
39 |
40 |
41 | ';
49 | return $zone_name;
50 | }
51 |
52 | /**
53 | * Output the zone type column.
54 | * @param object $item
55 | * @return string
56 | */
57 | public function column_zone_type( $item ) {
58 | global $wpdb;
59 |
60 | if ( $item->zone_id == 0 ) {
61 | return __( 'Everywhere', SHIPPING_ZONES_TEXTDOMAIN );
62 | }
63 |
64 | $locations = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE zone_id = %s;", $item->zone_id ) );
65 |
66 | $count = sizeof( $locations );
67 |
68 | if ( 'postcodes' === $item->zone_type ) {
69 | $count = $count - 1;
70 | }
71 |
72 | $locations_prepend = "";
73 | $locations_append = "";
74 | $locations_list = array();
75 |
76 | foreach ( $locations as $location ) {
77 | if ( sizeof( $locations_list ) >= 8 ) {
78 | $locations_append = ' ' . sprintf( __( 'and %s others', SHIPPING_ZONES_TEXTDOMAIN ), ( $count - 8 ) );
79 | break;
80 | }
81 | switch ( $location->location_type ) {
82 | case "country" :
83 | case "state" :
84 |
85 | if ( strstr( $location->location_code, ':' ) ) {
86 | $split_code = explode( ':', $location->location_code );
87 | if ( ! isset( WC()->countries->states[ $split_code[0] ][ $split_code[1] ] ) ) {
88 | continue;
89 | }
90 | $location_name = WC()->countries->states[ $split_code[0] ][ $split_code[1] ];
91 | } else {
92 | if ( ! isset( WC()->countries->countries[ $location->location_code ] ) ) {
93 | continue;
94 | }
95 | $location_name = WC()->countries->countries[ $location->location_code ];
96 | }
97 |
98 | if ( $item->zone_type == 'postcodes' ) {
99 | $locations_prepend = sprintf( __( 'Within %s:', SHIPPING_ZONES_TEXTDOMAIN ), $location_name ) . ' ';
100 | } else {
101 | $locations_list[] = $location_name;
102 | }
103 | break;
104 | case "postcode" :
105 | $locations_list[] = $location->location_code;
106 | }
107 | }
108 |
109 | switch ( $item->zone_type ) {
110 | case "countries" :
111 | return '' . __( 'Countries', SHIPPING_ZONES_TEXTDOMAIN ) . ' ' . $locations_prepend . implode( ', ', $locations_list ) . $locations_append;
112 | case "states" :
113 | return '' . __( 'Countries and states', SHIPPING_ZONES_TEXTDOMAIN ) . ' ' . $locations_prepend . implode( ', ', $locations_list ) . $locations_append;
114 | case "postcodes" :
115 | return '' . __( 'Postcodes', SHIPPING_ZONES_TEXTDOMAIN ) . ' ' . $locations_prepend . implode( ', ', $locations_list ) . $locations_append;
116 | }
117 | }
118 |
119 | /**
120 | * Output the zone enabled column.
121 | * @param object $item
122 | * @return string
123 | */
124 | public function column_enabled( $item ) {
125 | return $item->zone_enabled ? '✔' : '–';
126 | }
127 |
128 | /**
129 | * Output the zone methods column.
130 | * @param object $item
131 | * @return string
132 | */
133 | public function column_methods( $item ) {
134 | global $wpdb;
135 |
136 | $output_methods = array();
137 |
138 | $shipping_methods = $wpdb->get_results( $wpdb->prepare( "
139 | SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods
140 | WHERE zone_id = %s
141 | ORDER BY `shipping_method_order` ASC
142 | ", $item->zone_id ) );
143 |
144 | if ( $shipping_methods ) {
145 | foreach ( $shipping_methods as $method ) {
146 | $class_callback = 'woocommerce_get_shipping_method_' . $method->shipping_method_type;
147 |
148 | if ( function_exists( $class_callback ) ) {
149 | $this_method = call_user_func( $class_callback, $method->shipping_method_id );
150 | $output_methods[] = '' . esc_html( $this_method->title ? $this_method->title : $this_method->id ) . ' ';
151 | }
152 | }
153 |
154 | return implode( ', ', $output_methods );
155 | } else {
156 | return __( 'None', SHIPPING_ZONES_TEXTDOMAIN );
157 | }
158 | }
159 |
160 | /**
161 | * Checkbox column
162 | * @param string
163 | */
164 | public function column_cb( $item ) {
165 | if ( ! $item->zone_id ) {
166 | return;
167 | }
168 | return sprintf(
169 | ' ',
170 | 'zone_id_cb',
171 | $item->zone_id
172 | );
173 | }
174 |
175 | /**
176 | * get_columns function.
177 | * @return array
178 | */
179 | public function get_columns(){
180 | return array(
181 | 'cb' => ' ',
182 | 'zone_name' => __( 'Zone name', SHIPPING_ZONES_TEXTDOMAIN ),
183 | 'zone_type' => __( 'Zone type', SHIPPING_ZONES_TEXTDOMAIN ),
184 | 'enabled' => __( 'Enabled', SHIPPING_ZONES_TEXTDOMAIN ),
185 | 'methods' => __( 'Shipping Methods', SHIPPING_ZONES_TEXTDOMAIN )
186 | );
187 | }
188 |
189 | /**
190 | * Get bulk actions
191 | */
192 | public function get_bulk_actions() {
193 | $actions = array(
194 | 'disable' => __('Disable', SHIPPING_ZONES_TEXTDOMAIN),
195 | 'enable' => __('Enable', SHIPPING_ZONES_TEXTDOMAIN),
196 | '' => '------',
197 | 'delete' => __('Delete', SHIPPING_ZONES_TEXTDOMAIN)
198 | );
199 | return $actions;
200 | }
201 |
202 | /**
203 | * Process bulk actions
204 | */
205 | public function process_bulk_action() {
206 | global $wpdb;
207 |
208 | if ( ! isset( $_POST['zone_id_cb'] ) ) {
209 | return;
210 | }
211 |
212 | $items = array_filter( array_map( 'absint', $_POST['zone_id_cb'] ) );
213 |
214 | if ( ! $items ) {
215 | return;
216 | }
217 |
218 | if ( 'delete' === $this->current_action() ) {
219 |
220 | foreach ( $items as $id ) {
221 | $methods = $wpdb->get_col( $wpdb->prepare( "SELECT shipping_method_id FROM {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods WHERE zone_id = %d", $id ) );
222 |
223 | $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_locations', array( 'zone_id' => $id ) );
224 | $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zones', array( 'zone_id' => $id ) );
225 | $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_zone_shipping_methods', array( 'zone_id' => $id ) );
226 |
227 | foreach ( $methods as $method ) {
228 | $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_table_rates', array( 'shipping_method_id' => $method ) );
229 | delete_option( 'woocommerce_table_rate_priorities_' . $method );
230 | delete_option( 'woocommerce_table_rate_default_priority_' . $method );
231 | }
232 | }
233 |
234 | echo '' . __( 'Shipping zones deleted', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
235 |
236 | } elseif ( 'enable' === $this->current_action() ) {
237 |
238 | foreach ( $items as $id ) {
239 | $wpdb->update(
240 | $wpdb->prefix . 'woocommerce_shipping_zones',
241 | array(
242 | 'zone_enabled' => 1
243 | ),
244 | array( 'zone_id' => $id ),
245 | array( '%d' ),
246 | array( '%d' )
247 | );
248 | }
249 |
250 | echo '' . __( 'Shipping zones enabled', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
251 |
252 | } elseif ( 'disable' === $this->current_action() ) {
253 |
254 | foreach ( $items as $id ) {
255 | $wpdb->update(
256 | $wpdb->prefix . 'woocommerce_shipping_zones',
257 | array(
258 | 'zone_enabled' => 0
259 | ),
260 | array( 'zone_id' => $id ),
261 | array( '%d' ),
262 | array( '%d' )
263 | );
264 | }
265 |
266 | echo '' . __( 'Shipping zones disabled', SHIPPING_ZONES_TEXTDOMAIN ) . '
';
267 | }
268 |
269 | }
270 |
271 | /**
272 | * Get Zones to display
273 | */
274 | public function prepare_items() {
275 | global $wpdb;
276 |
277 | $this->_column_headers = array( $this->get_columns(), array(), array() );
278 | $this->process_bulk_action();
279 |
280 | $this->items = $wpdb->get_results( "
281 | SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zones
282 | ORDER BY zone_order ASC
283 | " );
284 |
285 | $default = new stdClass();
286 | $default->zone_id = 0;
287 | $default->zone_name = __( 'Default Zone (everywhere else)', SHIPPING_ZONES_TEXTDOMAIN );
288 | $default->zone_type = __( 'All countries', SHIPPING_ZONES_TEXTDOMAIN );
289 | $default->zone_enabled = 1;
290 | $this->items[] = $default;
291 | }
292 | }
293 |
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
78 |
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:
--------------------------------------------------------------------------------
1 |
2 |
— zone_name ) ?>
3 |
100 |
101 |
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/views/html-zone-list.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/views/html-zone-method-settings.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | instance_options(); ?>
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/views/html-zone-methods.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/includes/legacy/shipping-zones/includes/wc-shipping-zone-functions.php:
--------------------------------------------------------------------------------
1 | get_results( "
28 | SELECT * FROM {$wpdb->prefix}woocommerce_shipping_zone_locations
29 | WHERE location_type = 'postcode' AND location_code LIKE '%-%'
30 | " );
31 |
32 | if ( $postcode_ranges ) {
33 | $encoded_postcode = wc_make_numeric_postcode( $postcode );
34 | $encoded_postcode_len = strlen( $encoded_postcode );
35 |
36 | foreach ( $postcode_ranges as $postcode_range ) {
37 | $range = array_map( 'trim', explode( '-', $postcode_range->location_code ) );
38 |
39 | if ( sizeof( $range ) != 2 ) {
40 | continue;
41 | }
42 |
43 | if ( is_numeric( $range[0] ) && is_numeric( $range[1] ) ) {
44 | $encoded_postcode = $postcode;
45 | $min = $range[0];
46 | $max = $range[1];
47 | } else {
48 | $min = wc_make_numeric_postcode( $range[0] );
49 | $max = wc_make_numeric_postcode( $range[1] );
50 | $min = str_pad( $min, $encoded_postcode_len, '0' );
51 | $max = str_pad( $max, $encoded_postcode_len, '9' );
52 | }
53 |
54 | if ( $encoded_postcode >= $min && $encoded_postcode <= $max ) {
55 | $valid_zone_ids[] = $postcode_range->zone_id;
56 | }
57 | }
58 | }
59 | }
60 |
61 | // Escape
62 | $country = esc_sql( $package['destination']['country'] );
63 | $state = esc_sql( $country . ':' . $package['destination']['state'] );
64 | $valid_postcodes = array_map( 'esc_sql', $valid_postcodes );
65 | $valid_zone_ids = array_map( 'esc_sql', $valid_zone_ids );
66 |
67 | // Get matching zones
68 | $matching_zone_sql = "
69 | SELECT zones.zone_id FROM {$wpdb->prefix}woocommerce_shipping_zones as zones
70 | LEFT JOIN {$wpdb->prefix}woocommerce_shipping_zone_locations as locations ON zones.zone_id = locations.zone_id
71 | WHERE
72 | (
73 | (
74 | zone_type = 'countries'
75 | AND location_type = 'country'
76 | AND location_code = '{$country}'
77 | )
78 | OR
79 | (
80 | zone_type = 'states'
81 | AND
82 | (
83 | ( location_type = 'state' AND location_code = '{$state}' )
84 | OR
85 | ( location_type = 'country' AND location_code = '{$country}' )
86 | )
87 | )
88 | OR
89 | (
90 | zone_type = 'postcodes'
91 | AND
92 | (
93 | ( location_type = 'state' AND location_code = '{$state}' )
94 | OR
95 | ( location_type = 'country' AND location_code = '{$country}' )
96 | )
97 | AND
98 | (
99 | zones.zone_id IN (
100 | SELECT zone_id FROM {$wpdb->prefix}woocommerce_shipping_zone_locations
101 | WHERE location_type = 'postcode'
102 | AND location_code IN ('" . implode( "','", $valid_postcodes ) . "')
103 | )
104 | OR zones.zone_id IN ('" . implode( "','", $valid_zone_ids ) . "')
105 | )
106 | )
107 | )
108 | AND zone_enabled = 1
109 | ORDER BY zone_order ASC
110 | LIMIT 1
111 | ";
112 |
113 | $matching_zone = $wpdb->get_var( $matching_zone_sql );
114 |
115 | return new WC_Shipping_Zone( $matching_zone ? $matching_zone : 0 );
116 | }
117 |
118 | /**
119 | * make_numeric_postcode function.
120 | *
121 | * Converts letters to numbers so we can do a simple range check on postcodes.
122 | *
123 | * E.g. PE30 becomes 16050300 (P = 16, E = 05, 3 = 03, 0 = 00)
124 | *
125 | * @access public
126 | * @param mixed $postcode
127 | * @return void
128 | */
129 | function wc_make_numeric_postcode( $postcode ) {
130 | $postcode_length = strlen( $postcode );
131 | $letters_to_numbers = array_merge( array( 0 ), range( 'A', 'Z' ) );
132 | $letters_to_numbers = array_flip( $letters_to_numbers );
133 | $numeric_postcode = '';
134 |
135 | for ( $i = 0; $i < $postcode_length; $i ++ ) {
136 | if ( is_numeric( $postcode[ $i ] ) ) {
137 | $numeric_postcode .= str_pad( $postcode[ $i ], 2, '0', STR_PAD_LEFT );
138 | } elseif ( isset( $letters_to_numbers[ $postcode[ $i ] ] ) ) {
139 | $numeric_postcode .= str_pad( $letters_to_numbers[ $postcode[ $i ] ], 2, '0', STR_PAD_LEFT );
140 | } else {
141 | $numeric_postcode .= '00';
142 | }
143 | }
144 |
145 | return $numeric_postcode;
146 | }
147 |
148 | /**
149 | * Alias for wc_get_shipping_zone
150 | */
151 | function woocommerce_make_numeric_postcode( $postcode ) {
152 | return wc_make_numeric_postcode( $postcode );
153 | }
154 |
155 | /**
156 | * Alias for wc_get_shipping_zone
157 | */
158 | function woocommerce_get_shipping_zone( $package ) {
159 | return wc_get_shipping_zone( $package );
160 | }
161 |
--------------------------------------------------------------------------------
/installer.php:
--------------------------------------------------------------------------------
1 | hide_errors();
9 |
10 | $collate = '';
11 |
12 | if ( $wpdb->has_cap( 'collation' ) ) {
13 | $collate = $wpdb->get_charset_collate();
14 | }
15 |
16 | require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
17 |
18 | // Table for storing table rates themselves. shipping_method_id is an individual table of rates applied to a zone
19 | $sql = "
20 | CREATE TABLE {$wpdb->prefix}woocommerce_shipping_table_rates (
21 | rate_id bigint(20) NOT NULL auto_increment,
22 | rate_class varchar(200) NOT NULL,
23 | rate_condition varchar(200) NOT NULL,
24 | rate_min varchar(200) NOT NULL,
25 | rate_max varchar(200) NOT NULL,
26 | rate_cost varchar(200) NOT NULL,
27 | rate_cost_per_item varchar(200) NOT NULL,
28 | rate_cost_per_weight_unit varchar(200) NOT NULL,
29 | rate_cost_percent varchar(200) NOT NULL,
30 | rate_label longtext NULL,
31 | rate_priority int(1) NOT NULL,
32 | rate_order bigint(20) NOT NULL,
33 | shipping_method_id bigint(20) NOT NULL,
34 | rate_abort int(1) NOT NULL,
35 | rate_abort_reason longtext NULL,
36 | PRIMARY KEY (rate_id)
37 | ) $collate;
38 | ";
39 | dbDelta( $sql );
40 |
41 | if ( version_compare( WC_VERSION, '2.6.0', '<' ) ) {
42 | // Table for storing shipping zones
43 | $sql = "
44 | CREATE TABLE {$wpdb->prefix}woocommerce_shipping_zones (
45 | zone_id bigint(20) NOT NULL auto_increment,
46 | zone_name varchar(255) NOT NULL,
47 | zone_enabled int(1) NOT NULL DEFAULT 1,
48 | zone_type varchar(40) NOT NULL DEFAULT '',
49 | zone_order bigint(20) NOT NULL,
50 | PRIMARY KEY (zone_id)
51 | ) $collate;
52 | ";
53 | dbDelta( $sql );
54 |
55 | // Table for storing a shipping zones locations which it applies to. Type can be postcode, state, or country.
56 | $sql = "
57 | CREATE TABLE {$wpdb->prefix}woocommerce_shipping_zone_locations (
58 | location_id bigint(20) NOT NULL auto_increment,
59 | location_code varchar(255) NOT NULL,
60 | zone_id bigint(20) NOT NULL,
61 | location_type varchar(40) NOT NULL,
62 | PRIMARY KEY (location_id)
63 | ) $collate;
64 | ";
65 | dbDelta( $sql );
66 |
67 | // Table for storing shipping zones individial shipping methods and their options
68 | $sql = "
69 | CREATE TABLE {$wpdb->prefix}woocommerce_shipping_zone_shipping_methods (
70 | shipping_method_id bigint(20) NOT NULL auto_increment,
71 | shipping_method_type varchar(255) NOT NULL,
72 | zone_id bigint(20) NOT NULL,
73 | shipping_method_order bigint(20) NOT NULL default 0,
74 | PRIMARY KEY (shipping_method_id)
75 | ) $collate;
76 | ";
77 | dbDelta( $sql );
78 | }
79 |
80 | update_option( 'hide_table_rate_welcome_notice', '' );
81 |
--------------------------------------------------------------------------------
/languages/woocommerce-table-rate-shipping.pot:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2020 WooCommerce
2 | # This file is distributed under the GNU General Public License v3.0.
3 | msgid ""
4 | msgstr ""
5 | "Project-Id-Version: WooCommerce Table Rate Shipping 3.0.29\n"
6 | "Report-Msgid-Bugs-To: "
7 | "https://wordpress.org/support/plugin/woocommerce-table-rate-shipping\n"
8 | "POT-Creation-Date: 2020-08-19 17:32:21+00:00\n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=utf-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "PO-Revision-Date: 2020-MO-DA HO:MI+ZONE\n"
13 | "Last-Translator: FULL NAME \n"
14 | "Language-Team: LANGUAGE \n"
15 | "X-Generator: node-wp-i18n 1.2.3\n"
16 |
17 | #: includes/functions-admin.php:112 includes/functions-admin.php:115
18 | #: includes/functions-admin.php:118 includes/functions-admin.php:121
19 | msgid "0"
20 | msgstr ""
21 |
22 | #: includes/class-wc-shipping-table-rate-privacy.php:12
23 | #: includes/class-wc-shipping-table-rate.php:30
24 | msgid "Table rates"
25 | msgstr ""
26 |
27 | #: includes/class-wc-shipping-table-rate-privacy.php:20
28 | msgid ""
29 | "By using this extension, you may be storing personal data or sharing data "
30 | "with an external service. Learn more about "
31 | "how this works, including what you may want to include in your privacy "
32 | "policy. "
33 | msgstr ""
34 |
35 | #: includes/class-wc-shipping-table-rate.php:31
36 | msgid "Table rates are dynamic rates based on a number of cart conditions."
37 | msgstr ""
38 |
39 | #: includes/class-wc-shipping-table-rate.php:41
40 | #: includes/class-wc-shipping-table-rate.php:170
41 | msgid "Table Rate"
42 | msgstr ""
43 |
44 | #: includes/class-wc-shipping-table-rate.php:166
45 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zone-methods-table.php:144
46 | msgid "Method Title"
47 | msgstr ""
48 |
49 | #: includes/class-wc-shipping-table-rate.php:169
50 | msgid "This controls the title which the user sees during checkout."
51 | msgstr ""
52 |
53 | #: includes/class-wc-shipping-table-rate.php:173
54 | msgid "Tax Status"
55 | msgstr ""
56 |
57 | #: includes/class-wc-shipping-table-rate.php:179
58 | msgid "Taxable"
59 | msgstr ""
60 |
61 | #: includes/class-wc-shipping-table-rate.php:180
62 | #: includes/functions-admin.php:94
63 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:156
64 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:28
65 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:47
66 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:40
67 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:59
68 | msgid "None"
69 | msgstr ""
70 |
71 | #: includes/class-wc-shipping-table-rate.php:184
72 | msgid "Tax included in shipping costs"
73 | msgstr ""
74 |
75 | #: includes/class-wc-shipping-table-rate.php:191
76 | msgid "Yes, I will enter costs below inclusive of tax"
77 | msgstr ""
78 |
79 | #: includes/class-wc-shipping-table-rate.php:192
80 | msgid "No, I will enter costs below exclusive of tax"
81 | msgstr ""
82 |
83 | #: includes/class-wc-shipping-table-rate.php:196
84 | msgid "Handling Fee"
85 | msgstr ""
86 |
87 | #: includes/class-wc-shipping-table-rate.php:198
88 | msgid ""
89 | "Enter an amount, e.g. 2.50. Leave blank to disable. This cost is applied "
90 | "once for the order as a whole."
91 | msgstr ""
92 |
93 | #: includes/class-wc-shipping-table-rate.php:200
94 | #: includes/class-wc-shipping-table-rate.php:210
95 | #: includes/class-wc-shipping-table-rate.php:236
96 | #: includes/class-wc-shipping-table-rate.php:244
97 | #: includes/class-wc-shipping-table-rate.php:252
98 | #: includes/functions-admin.php:104
99 | msgid "n/a"
100 | msgstr ""
101 |
102 | #: includes/class-wc-shipping-table-rate.php:206
103 | msgid "Maximum Shipping Cost"
104 | msgstr ""
105 |
106 | #: includes/class-wc-shipping-table-rate.php:208
107 | msgid ""
108 | "Maximum cost that the customer will pay after all the shipping rules have "
109 | "been applied. If the shipping cost calculated is bigger than this value, "
110 | "this cost will be the one shown."
111 | msgstr ""
112 |
113 | #: includes/class-wc-shipping-table-rate.php:213
114 | msgid "Rates"
115 | msgstr ""
116 |
117 | #: includes/class-wc-shipping-table-rate.php:215
118 | msgid "This is where you define your table rates which are applied to an order."
119 | msgstr ""
120 |
121 | #: includes/class-wc-shipping-table-rate.php:219
122 | msgid "Calculation Type"
123 | msgstr ""
124 |
125 | #: includes/class-wc-shipping-table-rate.php:221
126 | msgid ""
127 | "Per order rates will offer the customer all matching rates. Calculated "
128 | "rates will sum all matching rates and provide a single total."
129 | msgstr ""
130 |
131 | #: includes/class-wc-shipping-table-rate.php:225
132 | msgid "Per order"
133 | msgstr ""
134 |
135 | #: includes/class-wc-shipping-table-rate.php:226
136 | msgid "Calculated rates per item"
137 | msgstr ""
138 |
139 | #: includes/class-wc-shipping-table-rate.php:227
140 | msgid "Calculated rates per line item"
141 | msgstr ""
142 |
143 | #: includes/class-wc-shipping-table-rate.php:228
144 | msgid "Calculated rates per shipping class"
145 | msgstr ""
146 |
147 | #: includes/class-wc-shipping-table-rate.php:232
148 | msgid "Handling Fee Per [item]"
149 | msgstr ""
150 |
151 | #: includes/class-wc-shipping-table-rate.php:234
152 | msgid ""
153 | "Handling fee. Enter an amount, e.g. 2.50, or a percentage, e.g. 5%. Leave "
154 | "blank to disable. Applied based on the \"Calculation Type\" chosen below."
155 | msgstr ""
156 |
157 | #: includes/class-wc-shipping-table-rate.php:239
158 | msgid "Minimum Cost Per [item]"
159 | msgstr ""
160 |
161 | #: includes/class-wc-shipping-table-rate.php:242
162 | msgid ""
163 | "Minimum cost for this shipping method (optional). If the cost is lower, "
164 | "this minimum cost will be enforced."
165 | msgstr ""
166 |
167 | #: includes/class-wc-shipping-table-rate.php:247
168 | msgid "Maximum Cost Per [item]"
169 | msgstr ""
170 |
171 | #: includes/class-wc-shipping-table-rate.php:250
172 | msgid ""
173 | "Maximum cost for this shipping method (optional). If the cost is higher, "
174 | "this maximum cost will be enforced."
175 | msgstr ""
176 |
177 | #: includes/class-wc-shipping-table-rate.php:285
178 | msgid "Table Rates"
179 | msgstr ""
180 |
181 | #: includes/class-wc-shipping-table-rate.php:292
182 | msgid "Class Priorities"
183 | msgstr ""
184 |
185 | #: includes/functions-admin.php:23
186 | msgid "Shipping Class"
187 | msgstr ""
188 |
189 | #: includes/functions-admin.php:24
190 | msgid "Shipping class this rate applies to."
191 | msgstr ""
192 |
193 | #: includes/functions-admin.php:28
194 | msgid "Condition"
195 | msgstr ""
196 |
197 | #: includes/functions-admin.php:29
198 | msgid "Condition vs. destination"
199 | msgstr ""
200 |
201 | #: includes/functions-admin.php:32
202 | msgid "Min–Max"
203 | msgstr ""
204 |
205 | #: includes/functions-admin.php:33
206 | msgid "Bottom and top range for the selected condition. "
207 | msgstr ""
208 |
209 | #: includes/functions-admin.php:36
210 | msgid "Break"
211 | msgstr ""
212 |
213 | #: includes/functions-admin.php:37
214 | msgid ""
215 | "Break at this point. For per-order rates, no rates other than this will be "
216 | "offered. For calculated rates, this will stop any further rates being "
217 | "matched."
218 | msgstr ""
219 |
220 | #: includes/functions-admin.php:40
221 | msgid "Abort"
222 | msgstr ""
223 |
224 | #: includes/functions-admin.php:41
225 | msgid ""
226 | "Enable this option to disable all rates/this shipping method if this row "
227 | "matches any item/line/class being quoted."
228 | msgstr ""
229 |
230 | #: includes/functions-admin.php:44
231 | msgid "Row cost"
232 | msgstr ""
233 |
234 | #: includes/functions-admin.php:45
235 | msgid "Cost for shipping the order, including tax."
236 | msgstr ""
237 |
238 | #: includes/functions-admin.php:48
239 | msgid "Item cost"
240 | msgstr ""
241 |
242 | #: includes/functions-admin.php:49
243 | msgid "Cost per item, including tax."
244 | msgstr ""
245 |
246 | #: includes/functions-admin.php:52
247 | msgid "cost"
248 | msgstr ""
249 |
250 | #: includes/functions-admin.php:53
251 | msgid "Cost per weight unit."
252 | msgstr ""
253 |
254 | #: includes/functions-admin.php:56
255 | msgid "% cost"
256 | msgstr ""
257 |
258 | #: includes/functions-admin.php:57
259 | msgid "Percentage of total to charge."
260 | msgstr ""
261 |
262 | #: includes/functions-admin.php:59
263 | msgid "Label"
264 | msgstr ""
265 |
266 | #: includes/functions-admin.php:60
267 | msgid "Label for the shipping method which the user will be presented. "
268 | msgstr ""
269 |
270 | #: includes/functions-admin.php:66
271 | msgid "Add Shipping Rate"
272 | msgstr ""
273 |
274 | #: includes/functions-admin.php:67
275 | msgid "Define your table rates here in order of priority."
276 | msgstr ""
277 |
278 | #: includes/functions-admin.php:67
279 | msgid "Duplicate selected rows"
280 | msgstr ""
281 |
282 | #: includes/functions-admin.php:67
283 | msgid "Delete selected rows"
284 | msgstr ""
285 |
286 | #: includes/functions-admin.php:84
287 | msgid "Any class"
288 | msgstr ""
289 |
290 | #: includes/functions-admin.php:85
291 | msgid "No class"
292 | msgstr ""
293 |
294 | #: includes/functions-admin.php:95
295 | msgid "Price"
296 | msgstr ""
297 |
298 | #: includes/functions-admin.php:96
299 | msgid "Weight"
300 | msgstr ""
301 |
302 | #: includes/functions-admin.php:97
303 | msgid "Item count"
304 | msgstr ""
305 |
306 | #: includes/functions-admin.php:99
307 | msgid "Item count (same class)"
308 | msgstr ""
309 |
310 | #: includes/functions-admin.php:109
311 | msgid "Optional abort reason text"
312 | msgstr ""
313 |
314 | #: includes/functions-admin.php:141
315 | msgid "No shipping classes exist - you can ignore this option :)"
316 | msgstr ""
317 |
318 | #: includes/functions-admin.php:148 woocommerce-table-rate-shipping.php:189
319 | msgid "Class"
320 | msgstr ""
321 |
322 | #: includes/functions-admin.php:149
323 | msgid "Priority"
324 | msgstr ""
325 |
326 | #: includes/functions-admin.php:155
327 | msgid ""
328 | "When calculating shipping, the cart contents will be searched for "
329 | "all shipping classes . If all product shipping classes are "
330 | "identical , the corresponding class will be "
331 | "used.If there are a mix of classes then the class "
332 | "with the lowest number priority (defined above) will be "
333 | "used."
334 | msgstr ""
335 |
336 | #: includes/functions-admin.php:161
337 | msgid "Default"
338 | msgstr ""
339 |
340 | #: includes/legacy/shipping-zones/class-wc-shipping-zones.php:35
341 | #: includes/legacy/shipping-zones/includes/views/html-zone-list.php:2
342 | #: includes/legacy/shipping-zones/includes/views/html-zone-method-settings.php:3
343 | #: includes/legacy/shipping-zones/includes/views/html-zone-methods.php:3
344 | msgid "Shipping Zones"
345 | msgstr ""
346 |
347 | #. Author of the plugin/theme
348 | msgid "WooCommerce"
349 | msgstr ""
350 |
351 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zone-admin.php:21
352 | msgid "Invalid shipping zone. Back to zones. "
353 | msgstr ""
354 |
355 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zone-admin.php:44
356 | msgid "Shipping method successfully created. View method. "
357 | msgstr ""
358 |
359 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zone-admin.php:46
360 | msgid "Invalid shipping method"
361 | msgstr ""
362 |
363 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zone-admin.php:59
364 | msgid "Shipping method successfully deleted"
365 | msgstr ""
366 |
367 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zone-admin.php:101
368 | msgid "Edit failed. Please try again."
369 | msgstr ""
370 |
371 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zone-admin.php:109
372 | msgid "Shipping method saved successfully."
373 | msgstr ""
374 |
375 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zone.php:118
376 | msgid "Everywhere else"
377 | msgstr ""
378 |
379 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zones-admin.php:39
380 | msgid "Could not save zone. Please try again."
381 | msgstr ""
382 |
383 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zones-admin.php:69
384 | msgid "Zone name is required"
385 | msgstr ""
386 |
387 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zones-admin.php:72
388 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:11
389 | msgid "Zone"
390 | msgstr ""
391 |
392 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zones-admin.php:78
393 | msgid " Zone type is required"
394 | msgstr ""
395 |
396 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zones-admin.php:100
397 | msgid "You must choose at least 1 country to add a zone."
398 | msgstr ""
399 |
400 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zones-admin.php:110
401 | msgid "You must choose at least 1 postcode to add postcode zone."
402 | msgstr ""
403 |
404 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zones-admin.php:213
405 | msgid "Error saving zone."
406 | msgstr ""
407 |
408 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zones-admin.php:219
409 | msgid "Shipping zone saved. Back to zones. "
410 | msgstr ""
411 |
412 | #: includes/legacy/shipping-zones/includes/class-wc-shipping-zones-admin.php:221
413 | msgid "Shipping zone saved."
414 | msgstr ""
415 |
416 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zone-methods-table.php:115
417 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:44
418 | msgid "Edit"
419 | msgstr ""
420 |
421 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zone-methods-table.php:115
422 | msgid "Are you sure you want to delete this method?"
423 | msgstr ""
424 |
425 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zone-methods-table.php:115
426 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zone-methods-table.php:156
427 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:197
428 | msgid "Delete"
429 | msgstr ""
430 |
431 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zone-methods-table.php:145
432 | msgid "Method Type"
433 | msgstr ""
434 |
435 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zone-methods-table.php:146
436 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:184
437 | msgid "Enabled"
438 | msgstr ""
439 |
440 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zone-methods-table.php:185
441 | msgid "Shipping methods deleted"
442 | msgstr ""
443 |
444 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zone-methods-table.php:193
445 | msgid "No shipping methods found."
446 | msgstr ""
447 |
448 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:44
449 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:46
450 | msgid "Configure shipping methods"
451 | msgstr ""
452 |
453 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:61
454 | msgid "Everywhere"
455 | msgstr ""
456 |
457 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:78
458 | msgid "and %s others"
459 | msgstr ""
460 |
461 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:99
462 | msgid "Within %s:"
463 | msgstr ""
464 |
465 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:111
466 | msgid "Countries"
467 | msgstr ""
468 |
469 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:113
470 | msgid "Countries and states"
471 | msgstr ""
472 |
473 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:115
474 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:67
475 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:81
476 | msgid "Postcodes"
477 | msgstr ""
478 |
479 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:182
480 | msgid "Zone name"
481 | msgstr ""
482 |
483 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:183
484 | msgid "Zone type"
485 | msgstr ""
486 |
487 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:185
488 | msgid "Shipping Methods"
489 | msgstr ""
490 |
491 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:194
492 | msgid "Disable"
493 | msgstr ""
494 |
495 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:195
496 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:16
497 | msgid "Enable"
498 | msgstr ""
499 |
500 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:234
501 | msgid "Shipping zones deleted"
502 | msgstr ""
503 |
504 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:250
505 | msgid "Shipping zones enabled"
506 | msgstr ""
507 |
508 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:266
509 | msgid "Shipping zones disabled"
510 | msgstr ""
511 |
512 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:287
513 | msgid "Default Zone (everywhere else)"
514 | msgstr ""
515 |
516 | #: includes/legacy/shipping-zones/includes/list-tables/class-wc-shipping-zones-table.php:288
517 | msgid "All countries"
518 | msgstr ""
519 |
520 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:1
521 | msgid "Add Shipping Zone"
522 | msgstr ""
523 |
524 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:3
525 | msgid ""
526 | "Zones cover multiple countries (and states) and can have shipping methods "
527 | "assigned to them. Each customer will be assigned a single matching shipping "
528 | "zone in order of priority, and if no zones apply the \"default zone\" will "
529 | "be used."
530 | msgstr ""
531 |
532 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:5
533 | msgid ""
534 | "If you wish to disable shipping for a location, add a zone and assign no "
535 | "shipping methods to it."
536 | msgstr ""
537 |
538 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:10
539 | msgid "Zone Name"
540 | msgstr ""
541 |
542 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:14
543 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:16
544 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:24
545 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:28
546 | msgid "Zone Type"
547 | msgstr ""
548 |
549 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:18
550 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:30
551 | msgid "This shipping zone is based on one or more countries"
552 | msgstr ""
553 |
554 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:21
555 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:53
556 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:33
557 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:65
558 | msgid "Choose countries…"
559 | msgstr ""
560 |
561 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:28
562 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:47
563 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:40
564 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:59
565 | msgid "All"
566 | msgstr ""
567 |
568 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:28
569 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:47
570 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:40
571 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:59
572 | msgid "EU States"
573 | msgstr ""
574 |
575 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:31
576 | msgid "This shipping zone is based on one or more states and counties"
577 | msgstr ""
578 |
579 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:34
580 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:46
581 | msgid "Choose states/counties…"
582 | msgstr ""
583 |
584 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:47
585 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:59
586 | msgid "US States"
587 | msgstr ""
588 |
589 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:50
590 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:62
591 | msgid "This shipping zone is based on one or more postcodes/zips"
592 | msgstr ""
593 |
594 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:67
595 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:81
596 | msgid ""
597 | "List 1 postcode per line. Wildcards (*) and ranges (for numeric postcodes) "
598 | "are supported."
599 | msgstr ""
600 |
601 | #: includes/legacy/shipping-zones/includes/views/form-add-shipping-zone.php:74
602 | msgid "Add shipping zone"
603 | msgstr ""
604 |
605 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:2
606 | msgid "Edit Shipping Zone"
607 | msgstr ""
608 |
609 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:8
610 | msgid "Name"
611 | msgstr ""
612 |
613 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:11
614 | msgid "Enter a name which describes this zone"
615 | msgstr ""
616 |
617 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:19
618 | msgid "Enable this zone"
619 | msgstr ""
620 |
621 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:43
622 | msgid "This shipping zone is based on one or more states/counties"
623 | msgstr ""
624 |
625 | #: includes/legacy/shipping-zones/includes/views/form-edit-shipping-zone.php:95
626 | msgid "Save changes"
627 | msgstr ""
628 |
629 | #: includes/legacy/shipping-zones/includes/views/html-zone-method-settings.php:6
630 | msgid "Save shipping method"
631 | msgstr ""
632 |
633 | #: includes/legacy/shipping-zones/includes/views/html-zone-methods.php:6
634 | msgid "Choose a shipping method…"
635 | msgstr ""
636 |
637 | #: includes/legacy/shipping-zones/includes/views/html-zone-methods.php:22
638 | msgid "Add To Zone"
639 | msgstr ""
640 |
641 | #: woocommerce-table-rate-shipping.php:146
642 | msgid "View Documentation"
643 | msgstr ""
644 |
645 | #: woocommerce-table-rate-shipping.php:146
646 | msgid "Docs"
647 | msgstr ""
648 |
649 | #: woocommerce-table-rate-shipping.php:147
650 | msgid "Visit Premium Customer Support Forum"
651 | msgstr ""
652 |
653 | #: woocommerce-table-rate-shipping.php:147
654 | msgid "Premium Support"
655 | msgstr ""
656 |
657 | #: woocommerce-table-rate-shipping.php:166
658 | msgid "Setup Zones"
659 | msgstr ""
660 |
661 | #: woocommerce-table-rate-shipping.php:166
662 | msgid "Documentation"
663 | msgstr ""
664 |
665 | #: woocommerce-table-rate-shipping.php:186
666 | msgid "Order"
667 | msgstr ""
668 |
669 | #: woocommerce-table-rate-shipping.php:187
670 | msgid "Item"
671 | msgstr ""
672 |
673 | #: woocommerce-table-rate-shipping.php:188
674 | msgid "Line Item"
675 | msgstr ""
676 |
677 | #: woocommerce-table-rate-shipping.php:190
678 | msgid "Delete the selected rates?"
679 | msgstr ""
680 |
681 | #: woocommerce-table-rate-shipping.php:191
682 | msgid "Duplicate the selected rates?"
683 | msgstr ""
684 |
685 | #: woocommerce-table-rate-shipping.php:260
686 | #. translators: %s: WooCommerce link
687 | msgid "WooCommerce Table Rate Shipping requires %s to be installed and active."
688 | msgstr ""
689 |
690 | #. Plugin Name of the plugin/theme
691 | msgid "WooCommerce Table Rate Shipping"
692 | msgstr ""
693 |
694 | #. Plugin URI of the plugin/theme
695 | msgid "https://woocommerce.com/products/table-rate-shipping/"
696 | msgstr ""
697 |
698 | #. Description of the plugin/theme
699 | msgid ""
700 | "Table rate shipping lets you define rates depending on location vs shipping "
701 | "class, price, weight, or item count."
702 | msgstr ""
703 |
704 | #. Author URI of the plugin/theme
705 | msgid "https://woocommerce.com/"
706 | msgstr ""
--------------------------------------------------------------------------------
/uninstall.php:
--------------------------------------------------------------------------------
1 | query( "DROP TABLE IF EXISTS {$wpdb->prefix}woocommerce_shipping_table_rates" );
9 | }
10 |
--------------------------------------------------------------------------------
/woocommerce-table-rate-shipping.php:
--------------------------------------------------------------------------------
1 | no_update[ $plugin_base ] ) ) {
69 | unset( $value->no_update[ $plugin_base ] );
70 | }
71 |
72 | return $value;
73 | }
74 |
75 | /**
76 | * Register method for usage.
77 | *
78 | * @param array $shipping_methods List of shipping methods.
79 | * @return array
80 | */
81 | public function woocommerce_shipping_methods( $shipping_methods ) {
82 | $shipping_methods['table_rate'] = 'WC_Shipping_Table_Rate';
83 | return $shipping_methods;
84 | }
85 |
86 | /**
87 | * Init TRS.
88 | */
89 | public function init() {
90 | if ( ! class_exists( 'WooCommerce' ) ) {
91 | add_action( 'admin_notices', array( $this, 'woocommerce_deactivated' ) );
92 | return;
93 | }
94 |
95 | include_once __DIR__ . '/includes/functions-ajax.php';
96 | include_once __DIR__ . '/includes/functions-admin.php';
97 |
98 | /**
99 | * Install check (for updates).
100 | */
101 | if ( get_option( 'table_rate_shipping_version' ) < TABLE_RATE_SHIPPING_VERSION ) {
102 | $this->install();
103 | }
104 |
105 | // 2.6.0+ supports zones and instances.
106 | if ( version_compare( WC_VERSION, '2.6.0', '>=' ) ) {
107 | add_filter( 'woocommerce_shipping_methods', array( $this, 'woocommerce_shipping_methods' ) );
108 | } else {
109 | if ( ! defined( 'SHIPPING_ZONES_TEXTDOMAIN' ) ) {
110 | define( 'SHIPPING_ZONES_TEXTDOMAIN', 'woocommerce-table-rate-shipping' );
111 | }
112 | if ( ! class_exists( 'WC_Shipping_zone' ) ) {
113 | include_once __DIR__ . '/includes/legacy/shipping-zones/class-wc-shipping-zones.php';
114 | }
115 | add_action( 'woocommerce_load_shipping_methods', array( $this, 'load_shipping_methods' ) );
116 | add_action( 'admin_notices', array( $this, 'welcome_notice' ) );
117 | }
118 |
119 | // Hooks.
120 | add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
121 | add_action( 'init', array( $this, 'load_plugin_textdomain' ) );
122 | add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 2 );
123 | add_action( 'woocommerce_shipping_init', array( $this, 'shipping_init' ) );
124 | add_action( 'delete_product_shipping_class', array( $this, 'update_deleted_shipping_class' ) );
125 | add_action( 'woocommerce_before_cart', array( $this, 'maybe_show_abort' ), 1 );
126 | add_action( 'woocommerce_before_checkout_form_cart_notices', array( $this, 'maybe_show_abort' ), 20 );
127 | }
128 |
129 | /**
130 | * Localisation.
131 | */
132 | public function load_plugin_textdomain() {
133 | load_plugin_textdomain( 'woocommerce-table-rate-shipping', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
134 | }
135 |
136 | /**
137 | * Row meta.
138 | *
139 | * @param array $links List of plugin links.
140 | * @param string $file Current file.
141 | * @return array
142 | */
143 | public function plugin_row_meta( $links, $file ) {
144 | if ( plugin_basename( __FILE__ ) === $file ) {
145 | $row_meta = array(
146 | 'docs' => '' . __( 'Docs', 'woocommerce-table-rate-shipping' ) . ' ',
147 | 'support' => '' . __( 'Premium Support', 'woocommerce-table-rate-shipping' ) . ' ',
148 | );
149 | return array_merge( $links, $row_meta );
150 | }
151 | return (array) $links;
152 | }
153 |
154 | /**
155 | * Admin welcome notice.
156 | */
157 | public function welcome_notice() {
158 | if ( get_option( 'hide_table_rate_welcome_notice' ) ) {
159 | return;
160 | }
161 | wp_enqueue_style( 'woocommerce-activation', WC()->plugin_url() . '/assets/css/activation.css', array(), TABLE_RATE_SHIPPING_VERSION );
162 | ?>
163 |
164 |
165 |
Table Rates is installed – Add some shipping zones to get started :)', 'woocommerce-table-rate-shipping' ); ?>
166 |
167 |
168 |
169 | array(
186 | 'order' => __( 'Order', 'woocommerce-table-rate-shipping' ),
187 | 'item' => __( 'Item', 'woocommerce-table-rate-shipping' ),
188 | 'line_item' => __( 'Line Item', 'woocommerce-table-rate-shipping' ),
189 | 'class' => __( 'Class', 'woocommerce-table-rate-shipping' ),
190 | 'delete_rates' => __( 'Delete the selected rates?', 'woocommerce-table-rate-shipping' ),
191 | 'dupe_rates' => __( 'Duplicate the selected rates?', 'woocommerce-table-rate-shipping' ),
192 | ),
193 | 'delete_rates_nonce' => wp_create_nonce( 'delete-rate' ),
194 | )
195 | );
196 | }
197 |
198 | /**
199 | * Load shipping class.
200 | */
201 | public function shipping_init() {
202 | include_once __DIR__ . '/includes/class-wc-shipping-table-rate.php';
203 | include_once __DIR__ . '/includes/class-wc-shipping-table-rate-privacy.php';
204 | }
205 |
206 | /**
207 | * Load shipping methods.
208 | *
209 | * @param array $package Shipping package.
210 | */
211 | public function load_shipping_methods( $package ) {
212 | // Register the main class.
213 | woocommerce_register_shipping_method( 'WC_Shipping_Table_Rate' );
214 |
215 | if ( ! $package ) {
216 | return;
217 | }
218 |
219 | // Get zone for package.
220 | $zone = woocommerce_get_shipping_zone( $package );
221 |
222 | if ( TABLE_RATE_SHIPPING_DEBUG ) {
223 | $notice_text = 'Customer matched shipping zone ' . $zone->zone_name . ' (#' . $zone->zone_id . ')';
224 |
225 | if ( ! wc_has_notice( $notice_text, 'notice' ) ) {
226 | wc_add_notice( $notice_text, 'notice' );
227 | }
228 | }
229 |
230 | if ( $zone->exists() ) {
231 | // Register zone methods.
232 | $zone->register_shipping_methods();
233 | }
234 | }
235 |
236 | /**
237 | * Installer.
238 | */
239 | public function install() {
240 | include_once __DIR__ . '/installer.php';
241 | update_option( 'table_rate_shipping_version', TABLE_RATE_SHIPPING_VERSION );
242 | }
243 |
244 | /**
245 | * Delete table rates when deleting shipping class.
246 | *
247 | * @param int $term_id Term ID.
248 | */
249 | public function update_deleted_shipping_class( $term_id ) {
250 | global $wpdb;
251 |
252 | $wpdb->delete( $wpdb->prefix . 'woocommerce_shipping_table_rates', array( 'rate_class' => $term_id ) );
253 | }
254 |
255 | /**
256 | * WooCommerce Deactivated Notice.
257 | */
258 | public function woocommerce_deactivated() {
259 | /* translators: %s: WooCommerce link */
260 | echo '' . sprintf( esc_html__( 'WooCommerce Table Rate Shipping requires %s to be installed and active.', 'woocommerce-table-rate-shipping' ), 'WooCommerce ' ) . '
';
261 | }
262 |
263 | /**
264 | * Show abort message when shipping methods are loaded from cache.
265 | *
266 | * @since 3.0.25
267 | * @return void
268 | */
269 | public function maybe_show_abort() {
270 | $abort = WC()->session->get( self::$abort_key );
271 |
272 | if ( ! is_array( $abort ) ) {
273 | return;
274 | }
275 |
276 | foreach ( $abort as $message ) {
277 | if ( ! wc_has_notice( $message ) ) {
278 | wc_add_notice( $message );
279 | }
280 | }
281 | }
282 |
283 | }
284 |
285 | new WC_Table_Rate_Shipping();
286 |
287 | /**
288 | * Callback function for loading an instance of this method.
289 | *
290 | * @param mixed $instance Table Rate instance.
291 | * @return WC_Shipping_Table_Rate
292 | */
293 | function woocommerce_get_shipping_method_table_rate( $instance = false ) {
294 | return new WC_Shipping_Table_Rate( $instance );
295 | }
296 |
--------------------------------------------------------------------------------