Version Description
- 2022-10-13 =
- Add - High-Performance Order Storage compatibility.
Download this release
Release Info
Developer | harriswong |
Plugin | WooCommerce ShipStation Gateway |
Version | 4.3.0 |
Comparing to | |
See all releases |
Code changes from version 4.2.0 to 4.3.0
- changelog.txt +3 -0
- includes/api-requests/class-wc-shipstation-api-export.php +127 -139
- includes/api-requests/class-wc-shipstation-api-shipnotify.php +27 -43
- includes/class-wc-shipstation-privacy.php +15 -15
- includes/trait-woocommerce-order-util.php +131 -0
- readme.txt +5 -2
- woocommerce-shipstation.php +7 -5
changelog.txt
CHANGED
@@ -1,5 +1,8 @@
|
|
1 |
*** ShipStation for WooCommerce ***
|
2 |
|
|
|
|
|
|
|
3 |
= 4.2.0 - 2022-09-07 =
|
4 |
* Add - Filter for manipulating address export data.
|
5 |
* Fix - Remove unnecessary files from plugin zip file.
|
1 |
*** ShipStation for WooCommerce ***
|
2 |
|
3 |
+
= 4.3.0 - 2022-10-13 =
|
4 |
+
* Add - High-Performance Order Storage compatibility.
|
5 |
+
|
6 |
= 4.2.0 - 2022-09-07 =
|
7 |
* Add - Filter for manipulating address export data.
|
8 |
* Fix - Remove unnecessary files from plugin zip file.
|
includes/api-requests/class-wc-shipstation-api-export.php
CHANGED
@@ -1,14 +1,17 @@
|
|
1 |
<?php
|
2 |
|
3 |
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly
|
5 |
}
|
6 |
|
|
|
|
|
|
|
7 |
/**
|
8 |
* WC_Shipstation_API_Export Class
|
9 |
*/
|
10 |
class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
11 |
-
|
12 |
/**
|
13 |
* Constructor
|
14 |
*/
|
@@ -18,6 +21,21 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
18 |
}
|
19 |
}
|
20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
/**
|
22 |
* Do the request
|
23 |
*/
|
@@ -34,9 +52,9 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
34 |
$tz_offset = get_option( 'gmt_offset' ) * 3600;
|
35 |
$raw_start_date = wc_clean( urldecode( $_GET['start_date'] ) );
|
36 |
$raw_end_date = wc_clean( urldecode( $_GET['end_date'] ) );
|
37 |
-
$store_weight_unit = get_option('woocommerce_weight_unit');
|
38 |
|
39 |
-
// Parse start and end date
|
40 |
if ( $raw_start_date && false === strtotime( $raw_start_date ) ) {
|
41 |
$month = substr( $raw_start_date, 0, 2 );
|
42 |
$day = substr( $raw_start_date, 2, 2 );
|
@@ -48,17 +66,17 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
48 |
}
|
49 |
|
50 |
if ( $raw_end_date && false === strtotime( $raw_end_date ) ) {
|
51 |
-
$month
|
52 |
-
$day
|
53 |
-
$year
|
54 |
-
$time
|
55 |
-
$end_date
|
56 |
} else {
|
57 |
-
$end_date
|
58 |
}
|
59 |
|
60 |
-
|
61 |
-
|
62 |
'date_modified' => strtotime( $start_date ) . '...' . strtotime( $end_date ),
|
63 |
'type' => 'shop_order',
|
64 |
'status' => WC_ShipStation_Integration::$export_statuses,
|
@@ -67,72 +85,57 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
67 |
'order' => 'DESC',
|
68 |
'paged' => $page,
|
69 |
'limit' => WC_SHIPSTATION_EXPORT_LIMIT,
|
70 |
-
)
|
71 |
-
|
72 |
-
return is_a( $order_or_id, 'WC_Order' ) ? $order_or_id->get_id() : $order_or_id;
|
73 |
-
}, $order_ids );
|
74 |
-
} else {
|
75 |
-
$order_ids = $wpdb->get_col(
|
76 |
-
$wpdb->prepare( "
|
77 |
-
SELECT ID FROM {$wpdb->posts}
|
78 |
-
WHERE post_type = 'shop_order'
|
79 |
-
AND post_status IN ( '" . implode( "','", WC_ShipStation_Integration::$export_statuses ) . "' )
|
80 |
-
AND %s <= post_modified_gmt
|
81 |
-
AND post_modified_gmt <= %s
|
82 |
-
ORDER BY post_modified_gmt DESC
|
83 |
-
LIMIT %d, %d
|
84 |
-
",
|
85 |
-
$start_date,
|
86 |
-
$end_date,
|
87 |
-
WC_SHIPSTATION_EXPORT_LIMIT * ( $page - 1 ),
|
88 |
-
WC_SHIPSTATION_EXPORT_LIMIT
|
89 |
-
)
|
90 |
-
);
|
91 |
-
}
|
92 |
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
AND post_modified_gmt <= %s
|
101 |
-
",
|
102 |
-
$start_date,
|
103 |
-
$end_date
|
104 |
)
|
105 |
);
|
106 |
|
|
|
|
|
107 |
$orders_xml = $xml->createElement( 'Orders' );
|
108 |
|
109 |
-
foreach ( $
|
110 |
if ( ! apply_filters( 'woocommerce_shipstation_export_order', true, $order_id ) ) {
|
111 |
continue;
|
112 |
}
|
113 |
|
114 |
-
|
115 |
-
|
116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
$formatted_order_number = ltrim( $order->get_order_number(), '#' );
|
118 |
$this->xml_append( $order_xml, 'OrderNumber', $formatted_order_number );
|
119 |
$this->xml_append( $order_xml, 'OrderID', $order_id );
|
120 |
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
$order_timestamp = $order_timestamp->getOffsetTimestamp();
|
125 |
-
} else {
|
126 |
-
$order_timestamp = $order->order_date;
|
127 |
-
}
|
128 |
|
129 |
-
$order_timestamp
|
130 |
-
$order_status
|
131 |
$this->xml_append( $order_xml, 'OrderDate', gmdate( 'm/d/Y H:i', $order_timestamp ), false );
|
132 |
$this->xml_append( $order_xml, 'OrderStatus', $order_status );
|
133 |
-
$this->xml_append( $order_xml, 'PaymentMethod', $
|
134 |
-
$this->xml_append( $order_xml, 'OrderPaymentMethodTitle', $
|
135 |
-
$last_modified = strtotime( $
|
136 |
$this->xml_append( $order_xml, 'LastModified', gmdate( 'm/d/Y H:i', $last_modified ), false );
|
137 |
$this->xml_append( $order_xml, 'ShippingMethod', implode( ' | ', $this->get_shipping_methods( $order ) ) );
|
138 |
|
@@ -144,33 +147,33 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
144 |
$this->xml_append( $order_xml, 'CostOfGoods', wc_format_decimal( $order->get_meta( '_wc_cog_order_total_cost', true ) ), false );
|
145 |
}
|
146 |
|
147 |
-
$this->xml_append( $order_xml, 'ShippingAmount', $
|
148 |
-
$this->xml_append( $order_xml, 'CustomerNotes', $
|
149 |
$this->xml_append( $order_xml, 'InternalNotes', implode( ' | ', $this->get_order_notes( $order ) ) );
|
150 |
|
151 |
-
// Custom fields - 1 is used for coupon codes
|
152 |
$this->xml_append( $order_xml, 'CustomField1', implode( ' | ', version_compare( WC_VERSION, '3.7', 'ge' ) ? $order->get_coupon_codes() : $order->get_used_coupons() ) );
|
153 |
|
154 |
-
// Custom fields 2 and 3 can be mapped to a custom field via the following filters
|
155 |
$meta_key = apply_filters( 'woocommerce_shipstation_export_custom_field_2', '' );
|
156 |
if ( $meta_key ) {
|
157 |
-
$this->xml_append( $order_xml, 'CustomField2', apply_filters( 'woocommerce_shipstation_export_custom_field_2_value',
|
158 |
}
|
159 |
|
160 |
$meta_key = apply_filters( 'woocommerce_shipstation_export_custom_field_3', '' );
|
161 |
if ( $meta_key ) {
|
162 |
-
$this->xml_append( $order_xml, 'CustomField3', apply_filters( 'woocommerce_shipstation_export_custom_field_3_value',
|
163 |
}
|
164 |
|
165 |
// Customer data.
|
166 |
$customer_xml = $xml->createElement( 'Customer' );
|
167 |
-
$this->xml_append( $customer_xml, 'CustomerCode', $
|
168 |
|
169 |
$billto_xml = $xml->createElement( 'BillTo' );
|
170 |
-
$this->xml_append( $billto_xml, 'Name',
|
171 |
-
$this->xml_append( $billto_xml, 'Company', $
|
172 |
-
$this->xml_append( $billto_xml, 'Phone', $
|
173 |
-
$this->xml_append( $billto_xml, 'Email', $
|
174 |
$customer_xml->appendChild( $billto_xml );
|
175 |
|
176 |
$shipto_xml = $xml->createElement( 'ShipTo' );
|
@@ -190,17 +193,13 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
190 |
|
191 |
$order_xml->appendChild( $customer_xml );
|
192 |
|
193 |
-
// Item data
|
194 |
$found_item = false;
|
195 |
$items_xml = $xml->createElement( 'Items' );
|
196 |
// Merge arrays without loosing indexes.
|
197 |
$order_items = $order->get_items() + $order->get_items( 'fee' );
|
198 |
foreach ( $order_items as $item_id => $item ) {
|
199 |
-
|
200 |
-
$product = is_callable( array( $item, 'get_product' ) ) ? $item->get_product() : false;
|
201 |
-
} else {
|
202 |
-
$product = $order->get_product_from_item( $item );
|
203 |
-
}
|
204 |
$item_needs_no_shipping = ! $product || ! $product->needs_shipping();
|
205 |
$item_not_a_fee = 'fee' !== $item['type'];
|
206 |
if ( apply_filters( 'woocommerce_shipstation_no_shipping_item', $item_needs_no_shipping && $item_not_a_fee, $product, $item ) ) {
|
@@ -212,57 +211,45 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
212 |
$this->xml_append( $item_xml, 'LineItemID', $item_id );
|
213 |
|
214 |
if ( 'fee' === $item['type'] ) {
|
215 |
-
$this->xml_append( $item_xml, 'Name', $
|
216 |
$this->xml_append( $item_xml, 'Quantity', 1, false );
|
217 |
$this->xml_append( $item_xml, 'UnitPrice', $order->get_item_total( $item, false, true ), false );
|
218 |
}
|
219 |
|
220 |
-
// handle product specific data
|
221 |
if ( $product && $product->needs_shipping() ) {
|
222 |
$this->xml_append( $item_xml, 'SKU', $product->get_sku() );
|
223 |
$this->xml_append( $item_xml, 'Name', $product->get_title() );
|
224 |
-
// image data
|
225 |
-
$image_id
|
226 |
$image_url = $image_id ? current( wp_get_attachment_image_src( $image_id, 'woocommerce_gallery_thumbnail' ) ) : '';
|
227 |
$this->xml_append( $item_xml, 'ImageUrl', $image_url );
|
228 |
|
229 |
if ( 'kg' === $store_weight_unit ) {
|
230 |
$this->xml_append( $item_xml, 'Weight', wc_get_weight( $product->get_weight(), 'g' ), false );
|
231 |
-
$this->xml_append( $item_xml, 'WeightUnits', 'Grams', false );
|
232 |
} else {
|
233 |
$this->xml_append( $item_xml, 'Weight', $product->get_weight(), false );
|
234 |
$this->xml_append( $item_xml, 'WeightUnits', $this->get_shipstation_weight_units( $store_weight_unit ), false );
|
235 |
}
|
236 |
|
237 |
-
// current item quantity - refunded quantity
|
238 |
$item_qty = $item['qty'] - abs( $order->get_qty_refunded_for_item( $item_id ) );
|
239 |
$this->xml_append( $item_xml, 'Quantity', $item_qty, false );
|
240 |
$this->xml_append( $item_xml, 'UnitPrice', $order->get_item_subtotal( $item, false, true ), false );
|
241 |
}
|
242 |
|
243 |
if ( $item['item_meta'] ) {
|
244 |
-
|
245 |
-
|
246 |
-
$formatted_meta = $item_meta->get_formatted( '_' );
|
247 |
-
} else {
|
248 |
-
add_filter( 'woocommerce_is_attribute_in_product_name', '__return_false' );
|
249 |
-
$formatted_meta = $item->get_formatted_meta_data();
|
250 |
-
}
|
251 |
|
252 |
if ( ! empty( $formatted_meta ) ) {
|
253 |
$options_xml = $xml->createElement( 'Options' );
|
254 |
|
255 |
foreach ( $formatted_meta as $meta_key => $meta ) {
|
256 |
-
$option_xml
|
257 |
-
|
258 |
-
|
259 |
-
$this->xml_append( $option_xml, 'Name', $meta['label'] );
|
260 |
-
$this->xml_append( $option_xml, 'Value', $meta['value'] );
|
261 |
-
} else {
|
262 |
-
$this->xml_append( $option_xml, 'Name', $meta->display_key );
|
263 |
-
$this->xml_append( $option_xml, 'Value', wp_strip_all_tags( $meta->display_value ) );
|
264 |
-
}
|
265 |
-
|
266 |
$options_xml->appendChild( $option_xml );
|
267 |
}
|
268 |
|
@@ -277,9 +264,9 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
277 |
continue;
|
278 |
}
|
279 |
|
280 |
-
// Append cart level discount line
|
281 |
if ( $order->get_total_discount() ) {
|
282 |
-
$item_xml
|
283 |
$this->xml_append( $item_xml, 'SKU', 'total-discount' );
|
284 |
$this->xml_append( $item_xml, 'Name', __( 'Total Discount', 'woocommerce-shipstation-integration' ) );
|
285 |
$this->xml_append( $item_xml, 'Adjustment', 'true', false );
|
@@ -288,16 +275,17 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
288 |
$items_xml->appendChild( $item_xml );
|
289 |
}
|
290 |
|
291 |
-
// Append items XML
|
292 |
$order_xml->appendChild( $items_xml );
|
293 |
$orders_xml->appendChild( apply_filters( 'woocommerce_shipstation_export_order_xml', $order_xml ) );
|
294 |
|
295 |
$exported ++;
|
296 |
|
297 |
// Add order note to indicate it has been exported to Shipstation.
|
298 |
-
if ( 'yes' !==
|
299 |
$order->add_order_note( __( 'Order has been exported to Shipstation', 'woocommerce-shipstation-integration' ) );
|
300 |
-
|
|
|
301 |
}
|
302 |
}
|
303 |
|
@@ -318,53 +306,54 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
318 |
* @result array.
|
319 |
*/
|
320 |
public function get_address_data( $order ) {
|
321 |
-
$
|
322 |
-
$
|
323 |
-
$shipping_address = $wc_gte_30 ? $order->get_shipping_address_1() : $order->shipping_address_1;
|
324 |
|
325 |
$address = array();
|
326 |
|
327 |
if ( empty( $shipping_country ) && empty( $shipping_address ) ) {
|
328 |
-
$name =
|
329 |
|
330 |
$address['name'] = $name;
|
331 |
-
$address['company'] = $
|
332 |
-
$address['address1'] = $
|
333 |
-
$address['address2'] = $
|
334 |
-
$address['city'] = $
|
335 |
-
$address['state'] = $
|
336 |
-
$address['postcode'] = $
|
337 |
-
$address['country'] = $
|
338 |
-
$address['phone'] = $
|
339 |
} else {
|
340 |
-
$name =
|
341 |
|
342 |
$address['name'] = $name;
|
343 |
-
$address['company'] = $
|
344 |
-
$address['address1'] = $
|
345 |
-
$address['address2'] = $
|
346 |
-
$address['city'] = $
|
347 |
-
$address['state'] = $
|
348 |
-
$address['postcode'] = $
|
349 |
-
$address['country'] = $
|
350 |
-
$address['phone'] = $
|
351 |
}
|
352 |
|
353 |
-
return apply_filters( 'woocommerce_shipstation_export_address_data', $address, $order,
|
354 |
}
|
355 |
|
356 |
/**
|
357 |
* Get shipping method names
|
358 |
-
*
|
|
|
|
|
359 |
* @return array
|
360 |
*/
|
361 |
private function get_shipping_methods( $order ) {
|
362 |
-
$shipping_methods
|
363 |
$shipping_method_names = array();
|
364 |
|
365 |
foreach ( $shipping_methods as $shipping_method ) {
|
366 |
-
// Replace non-AlNum characters with space
|
367 |
-
$method_name
|
368 |
$shipping_method_names[] = $method_name;
|
369 |
}
|
370 |
|
@@ -373,20 +362,19 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
373 |
|
374 |
/**
|
375 |
* Get Order Notes
|
376 |
-
*
|
|
|
377 |
* @return array
|
378 |
*/
|
379 |
private function get_order_notes( $order ) {
|
380 |
$args = array(
|
381 |
-
'post_id' =>
|
382 |
'approve' => 'approve',
|
383 |
'type' => 'order_note',
|
384 |
);
|
385 |
|
386 |
remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
|
387 |
-
|
388 |
$notes = get_comments( $args );
|
389 |
-
|
390 |
add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
|
391 |
|
392 |
$order_notes = array();
|
@@ -405,13 +393,13 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
405 |
*/
|
406 |
private function xml_append( $append_to, $name, $value, $cdata = true ) {
|
407 |
$data = $append_to->appendChild( $append_to->ownerDocument->createElement( $name ) );
|
408 |
-
|
409 |
if ( $cdata ) {
|
410 |
$child_node = empty( $append_to->ownerDocument->createCDATASection( $value ) ) ? $append_to->ownerDocument->createCDATASection( '' ) : $append_to->ownerDocument->createCDATASection( $value );
|
411 |
} else {
|
412 |
$child_node = empty( $append_to->ownerDocument->createTextNode( $value ) ) ? $append_to->ownerDocument->createTextNode( '' ) : $append_to->ownerDocument->createTextNode( $value );
|
413 |
}
|
414 |
-
|
415 |
$data->appendChild( $child_node );
|
416 |
}
|
417 |
|
@@ -419,7 +407,7 @@ class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
|
419 |
* Convert weight unit abbreviation to Shipstation enum (Pounds, Ounces, Grams)
|
420 |
*/
|
421 |
private function get_shipstation_weight_units( $unit_abbreviation ) {
|
422 |
-
switch( $unit_abbreviation ) {
|
423 |
case 'lbs':
|
424 |
return 'Pounds';
|
425 |
case 'oz':
|
1 |
<?php
|
2 |
|
3 |
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
+
exit; // Exit if accessed directly.
|
5 |
}
|
6 |
|
7 |
+
use WooCommerce\ShipStation\Order_Util;
|
8 |
+
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
|
9 |
+
|
10 |
/**
|
11 |
* WC_Shipstation_API_Export Class
|
12 |
*/
|
13 |
class WC_Shipstation_API_Export extends WC_Shipstation_API_Request {
|
14 |
+
use Order_Util;
|
15 |
/**
|
16 |
* Constructor
|
17 |
*/
|
21 |
}
|
22 |
}
|
23 |
|
24 |
+
private static function prepare_in( $values ) {
|
25 |
+
return implode(
|
26 |
+
',',
|
27 |
+
array_map(
|
28 |
+
function ( $value ) {
|
29 |
+
global $wpdb;
|
30 |
+
|
31 |
+
// Use the official prepare() function to sanitize the value.
|
32 |
+
return $wpdb->prepare( '%s', $value );
|
33 |
+
},
|
34 |
+
$values
|
35 |
+
)
|
36 |
+
);
|
37 |
+
}
|
38 |
+
|
39 |
/**
|
40 |
* Do the request
|
41 |
*/
|
52 |
$tz_offset = get_option( 'gmt_offset' ) * 3600;
|
53 |
$raw_start_date = wc_clean( urldecode( $_GET['start_date'] ) );
|
54 |
$raw_end_date = wc_clean( urldecode( $_GET['end_date'] ) );
|
55 |
+
$store_weight_unit = get_option( 'woocommerce_weight_unit' );
|
56 |
|
57 |
+
// Parse start and end date.
|
58 |
if ( $raw_start_date && false === strtotime( $raw_start_date ) ) {
|
59 |
$month = substr( $raw_start_date, 0, 2 );
|
60 |
$day = substr( $raw_start_date, 2, 2 );
|
66 |
}
|
67 |
|
68 |
if ( $raw_end_date && false === strtotime( $raw_end_date ) ) {
|
69 |
+
$month = substr( $raw_end_date, 0, 2 );
|
70 |
+
$day = substr( $raw_end_date, 2, 2 );
|
71 |
+
$year = substr( $raw_end_date, 4, 4 );
|
72 |
+
$time = substr( $raw_end_date, 9, 4 );
|
73 |
+
$end_date = gmdate( 'Y-m-d H:i:s', strtotime( $year . '-' . $month . '-' . $day . ' ' . $time ) );
|
74 |
} else {
|
75 |
+
$end_date = gmdate( 'Y-m-d H:i:s', strtotime( $raw_end_date ) );
|
76 |
}
|
77 |
|
78 |
+
$orders_to_export = wc_get_orders(
|
79 |
+
array(
|
80 |
'date_modified' => strtotime( $start_date ) . '...' . strtotime( $end_date ),
|
81 |
'type' => 'shop_order',
|
82 |
'status' => WC_ShipStation_Integration::$export_statuses,
|
85 |
'order' => 'DESC',
|
86 |
'paged' => $page,
|
87 |
'limit' => WC_SHIPSTATION_EXPORT_LIMIT,
|
88 |
+
)
|
89 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
+
$total_orders_to_export = wc_get_orders(
|
92 |
+
array(
|
93 |
+
'type' => 'shop_order',
|
94 |
+
'date_modified' => strtotime( $start_date ) . '...' . strtotime( $end_date ),
|
95 |
+
'status' => WC_ShipStation_Integration::$export_statuses,
|
96 |
+
'paginate' => true,
|
97 |
+
'return' => 'ids',
|
|
|
|
|
|
|
|
|
98 |
)
|
99 |
);
|
100 |
|
101 |
+
$max_results = $total_orders_to_export->total;
|
102 |
+
|
103 |
$orders_xml = $xml->createElement( 'Orders' );
|
104 |
|
105 |
+
foreach ( $orders_to_export as $order_id ) {
|
106 |
if ( ! apply_filters( 'woocommerce_shipstation_export_order', true, $order_id ) ) {
|
107 |
continue;
|
108 |
}
|
109 |
|
110 |
+
/**
|
111 |
+
* WooCommerce Order.
|
112 |
+
*
|
113 |
+
* @var WC_Order $order
|
114 |
+
*/
|
115 |
+
$order = apply_filters( 'woocommerce_shipstation_export_get_order', wc_get_order( $order_id ) );
|
116 |
+
|
117 |
+
if ( ! self::is_wc_order( $order ) ) {
|
118 |
+
/* translators: 1: order id */
|
119 |
+
$this->log( sprintf( __( 'Order %s can not be found.', 'woocommerce-shipstation-integration' ), $order_id ) );
|
120 |
+
continue;
|
121 |
+
}
|
122 |
+
|
123 |
+
$order_xml = $xml->createElement( 'Order' );
|
124 |
$formatted_order_number = ltrim( $order->get_order_number(), '#' );
|
125 |
$this->xml_append( $order_xml, 'OrderNumber', $formatted_order_number );
|
126 |
$this->xml_append( $order_xml, 'OrderID', $order_id );
|
127 |
|
128 |
+
// Sequence of date ordering: date paid > date completed > date created.
|
129 |
+
$order_timestamp = $order->get_date_paid() ?: $order->get_date_completed() ?: $order->get_date_created();
|
130 |
+
$order_timestamp = $order_timestamp->getOffsetTimestamp();
|
|
|
|
|
|
|
|
|
131 |
|
132 |
+
$order_timestamp -= $tz_offset;
|
133 |
+
$order_status = ( 'refunded' === $order->get_status() ) ? 'cancelled' : $order->get_status();
|
134 |
$this->xml_append( $order_xml, 'OrderDate', gmdate( 'm/d/Y H:i', $order_timestamp ), false );
|
135 |
$this->xml_append( $order_xml, 'OrderStatus', $order_status );
|
136 |
+
$this->xml_append( $order_xml, 'PaymentMethod', $order->get_payment_method() );
|
137 |
+
$this->xml_append( $order_xml, 'OrderPaymentMethodTitle', $order->get_payment_method_title() );
|
138 |
+
$last_modified = strtotime( $order->get_date_modified()->date( 'm/d/Y H:i' ) ) - $tz_offset;
|
139 |
$this->xml_append( $order_xml, 'LastModified', gmdate( 'm/d/Y H:i', $last_modified ), false );
|
140 |
$this->xml_append( $order_xml, 'ShippingMethod', implode( ' | ', $this->get_shipping_methods( $order ) ) );
|
141 |
|
147 |
$this->xml_append( $order_xml, 'CostOfGoods', wc_format_decimal( $order->get_meta( '_wc_cog_order_total_cost', true ) ), false );
|
148 |
}
|
149 |
|
150 |
+
$this->xml_append( $order_xml, 'ShippingAmount', $order->get_shipping_total(), false );
|
151 |
+
$this->xml_append( $order_xml, 'CustomerNotes', $order->get_customer_note() );
|
152 |
$this->xml_append( $order_xml, 'InternalNotes', implode( ' | ', $this->get_order_notes( $order ) ) );
|
153 |
|
154 |
+
// Custom fields - 1 is used for coupon codes.
|
155 |
$this->xml_append( $order_xml, 'CustomField1', implode( ' | ', version_compare( WC_VERSION, '3.7', 'ge' ) ? $order->get_coupon_codes() : $order->get_used_coupons() ) );
|
156 |
|
157 |
+
// Custom fields 2 and 3 can be mapped to a custom field via the following filters.
|
158 |
$meta_key = apply_filters( 'woocommerce_shipstation_export_custom_field_2', '' );
|
159 |
if ( $meta_key ) {
|
160 |
+
$this->xml_append( $order_xml, 'CustomField2', apply_filters( 'woocommerce_shipstation_export_custom_field_2_value', $order->get_meta( $meta_key, true ), $order_id ) );
|
161 |
}
|
162 |
|
163 |
$meta_key = apply_filters( 'woocommerce_shipstation_export_custom_field_3', '' );
|
164 |
if ( $meta_key ) {
|
165 |
+
$this->xml_append( $order_xml, 'CustomField3', apply_filters( 'woocommerce_shipstation_export_custom_field_3_value', $order->get_meta( $meta_key, true ), $order_id ) );
|
166 |
}
|
167 |
|
168 |
// Customer data.
|
169 |
$customer_xml = $xml->createElement( 'Customer' );
|
170 |
+
$this->xml_append( $customer_xml, 'CustomerCode', $order->get_billing_email() );
|
171 |
|
172 |
$billto_xml = $xml->createElement( 'BillTo' );
|
173 |
+
$this->xml_append( $billto_xml, 'Name', $order->get_billing_first_name() . ' ' . $order->get_billing_last_name() );
|
174 |
+
$this->xml_append( $billto_xml, 'Company', $order->get_billing_company() );
|
175 |
+
$this->xml_append( $billto_xml, 'Phone', $order->get_billing_phone() );
|
176 |
+
$this->xml_append( $billto_xml, 'Email', $order->get_billing_email() );
|
177 |
$customer_xml->appendChild( $billto_xml );
|
178 |
|
179 |
$shipto_xml = $xml->createElement( 'ShipTo' );
|
193 |
|
194 |
$order_xml->appendChild( $customer_xml );
|
195 |
|
196 |
+
// Item data.
|
197 |
$found_item = false;
|
198 |
$items_xml = $xml->createElement( 'Items' );
|
199 |
// Merge arrays without loosing indexes.
|
200 |
$order_items = $order->get_items() + $order->get_items( 'fee' );
|
201 |
foreach ( $order_items as $item_id => $item ) {
|
202 |
+
$product = is_callable( array( $item, 'get_product' ) ) ? $item->get_product() : false;
|
|
|
|
|
|
|
|
|
203 |
$item_needs_no_shipping = ! $product || ! $product->needs_shipping();
|
204 |
$item_not_a_fee = 'fee' !== $item['type'];
|
205 |
if ( apply_filters( 'woocommerce_shipstation_no_shipping_item', $item_needs_no_shipping && $item_not_a_fee, $product, $item ) ) {
|
211 |
$this->xml_append( $item_xml, 'LineItemID', $item_id );
|
212 |
|
213 |
if ( 'fee' === $item['type'] ) {
|
214 |
+
$this->xml_append( $item_xml, 'Name', $item->get_name() );
|
215 |
$this->xml_append( $item_xml, 'Quantity', 1, false );
|
216 |
$this->xml_append( $item_xml, 'UnitPrice', $order->get_item_total( $item, false, true ), false );
|
217 |
}
|
218 |
|
219 |
+
// handle product specific data.
|
220 |
if ( $product && $product->needs_shipping() ) {
|
221 |
$this->xml_append( $item_xml, 'SKU', $product->get_sku() );
|
222 |
$this->xml_append( $item_xml, 'Name', $product->get_title() );
|
223 |
+
// image data.
|
224 |
+
$image_id = $product->get_image_id();
|
225 |
$image_url = $image_id ? current( wp_get_attachment_image_src( $image_id, 'woocommerce_gallery_thumbnail' ) ) : '';
|
226 |
$this->xml_append( $item_xml, 'ImageUrl', $image_url );
|
227 |
|
228 |
if ( 'kg' === $store_weight_unit ) {
|
229 |
$this->xml_append( $item_xml, 'Weight', wc_get_weight( $product->get_weight(), 'g' ), false );
|
230 |
+
$this->xml_append( $item_xml, 'WeightUnits', 'Grams', false );
|
231 |
} else {
|
232 |
$this->xml_append( $item_xml, 'Weight', $product->get_weight(), false );
|
233 |
$this->xml_append( $item_xml, 'WeightUnits', $this->get_shipstation_weight_units( $store_weight_unit ), false );
|
234 |
}
|
235 |
|
236 |
+
// current item quantity - refunded quantity.
|
237 |
$item_qty = $item['qty'] - abs( $order->get_qty_refunded_for_item( $item_id ) );
|
238 |
$this->xml_append( $item_xml, 'Quantity', $item_qty, false );
|
239 |
$this->xml_append( $item_xml, 'UnitPrice', $order->get_item_subtotal( $item, false, true ), false );
|
240 |
}
|
241 |
|
242 |
if ( $item['item_meta'] ) {
|
243 |
+
add_filter( 'woocommerce_is_attribute_in_product_name', '__return_false' );
|
244 |
+
$formatted_meta = $item->get_formatted_meta_data();
|
|
|
|
|
|
|
|
|
|
|
245 |
|
246 |
if ( ! empty( $formatted_meta ) ) {
|
247 |
$options_xml = $xml->createElement( 'Options' );
|
248 |
|
249 |
foreach ( $formatted_meta as $meta_key => $meta ) {
|
250 |
+
$option_xml = $xml->createElement( 'Option' );
|
251 |
+
$this->xml_append( $option_xml, 'Name', $meta->display_key );
|
252 |
+
$this->xml_append( $option_xml, 'Value', wp_strip_all_tags( $meta->display_value ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
$options_xml->appendChild( $option_xml );
|
254 |
}
|
255 |
|
264 |
continue;
|
265 |
}
|
266 |
|
267 |
+
// Append cart level discount line.
|
268 |
if ( $order->get_total_discount() ) {
|
269 |
+
$item_xml = $xml->createElement( 'Item' );
|
270 |
$this->xml_append( $item_xml, 'SKU', 'total-discount' );
|
271 |
$this->xml_append( $item_xml, 'Name', __( 'Total Discount', 'woocommerce-shipstation-integration' ) );
|
272 |
$this->xml_append( $item_xml, 'Adjustment', 'true', false );
|
275 |
$items_xml->appendChild( $item_xml );
|
276 |
}
|
277 |
|
278 |
+
// Append items XML.
|
279 |
$order_xml->appendChild( $items_xml );
|
280 |
$orders_xml->appendChild( apply_filters( 'woocommerce_shipstation_export_order_xml', $order_xml ) );
|
281 |
|
282 |
$exported ++;
|
283 |
|
284 |
// Add order note to indicate it has been exported to Shipstation.
|
285 |
+
if ( 'yes' !== $order->get_meta( '_shipstation_exported', true ) ) {
|
286 |
$order->add_order_note( __( 'Order has been exported to Shipstation', 'woocommerce-shipstation-integration' ) );
|
287 |
+
$order->update_meta_data( '_shipstation_exported', 'yes' );
|
288 |
+
$order->save();
|
289 |
}
|
290 |
}
|
291 |
|
306 |
* @result array.
|
307 |
*/
|
308 |
public function get_address_data( $order ) {
|
309 |
+
$shipping_country = $order->get_shipping_country();
|
310 |
+
$shipping_address = $order->get_shipping_address_1();
|
|
|
311 |
|
312 |
$address = array();
|
313 |
|
314 |
if ( empty( $shipping_country ) && empty( $shipping_address ) ) {
|
315 |
+
$name = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
|
316 |
|
317 |
$address['name'] = $name;
|
318 |
+
$address['company'] = $order->get_billing_company();
|
319 |
+
$address['address1'] = $order->get_billing_address_1();
|
320 |
+
$address['address2'] = $order->get_billing_address_2();
|
321 |
+
$address['city'] = $order->get_billing_city();
|
322 |
+
$address['state'] = $order->get_billing_state();
|
323 |
+
$address['postcode'] = $order->get_billing_postcode();
|
324 |
+
$address['country'] = $order->get_billing_country();
|
325 |
+
$address['phone'] = $order->get_billing_phone();
|
326 |
} else {
|
327 |
+
$name = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
|
328 |
|
329 |
$address['name'] = $name;
|
330 |
+
$address['company'] = $order->get_shipping_company();
|
331 |
+
$address['address1'] = $order->get_shipping_address_1();
|
332 |
+
$address['address2'] = $order->get_shipping_address_2();
|
333 |
+
$address['city'] = $order->get_shipping_city();
|
334 |
+
$address['state'] = $order->get_shipping_state();
|
335 |
+
$address['postcode'] = $order->get_shipping_postcode();
|
336 |
+
$address['country'] = $order->get_shipping_country();
|
337 |
+
$address['phone'] = $order->get_billing_phone();
|
338 |
}
|
339 |
|
340 |
+
return apply_filters( 'woocommerce_shipstation_export_address_data', $address, $order, true );
|
341 |
}
|
342 |
|
343 |
/**
|
344 |
* Get shipping method names
|
345 |
+
*
|
346 |
+
* @param WC_Order $order Order object.
|
347 |
+
*
|
348 |
* @return array
|
349 |
*/
|
350 |
private function get_shipping_methods( $order ) {
|
351 |
+
$shipping_methods = $order->get_shipping_methods();
|
352 |
$shipping_method_names = array();
|
353 |
|
354 |
foreach ( $shipping_methods as $shipping_method ) {
|
355 |
+
// Replace non-AlNum characters with space.
|
356 |
+
$method_name = preg_replace( '/[^A-Za-z0-9 \-\.\_,]/', '', $shipping_method['name'] );
|
357 |
$shipping_method_names[] = $method_name;
|
358 |
}
|
359 |
|
362 |
|
363 |
/**
|
364 |
* Get Order Notes
|
365 |
+
*
|
366 |
+
* @param WC_Order $order Order object.
|
367 |
* @return array
|
368 |
*/
|
369 |
private function get_order_notes( $order ) {
|
370 |
$args = array(
|
371 |
+
'post_id' => $order->get_id(),
|
372 |
'approve' => 'approve',
|
373 |
'type' => 'order_note',
|
374 |
);
|
375 |
|
376 |
remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
|
|
|
377 |
$notes = get_comments( $args );
|
|
|
378 |
add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
|
379 |
|
380 |
$order_notes = array();
|
393 |
*/
|
394 |
private function xml_append( $append_to, $name, $value, $cdata = true ) {
|
395 |
$data = $append_to->appendChild( $append_to->ownerDocument->createElement( $name ) );
|
396 |
+
|
397 |
if ( $cdata ) {
|
398 |
$child_node = empty( $append_to->ownerDocument->createCDATASection( $value ) ) ? $append_to->ownerDocument->createCDATASection( '' ) : $append_to->ownerDocument->createCDATASection( $value );
|
399 |
} else {
|
400 |
$child_node = empty( $append_to->ownerDocument->createTextNode( $value ) ) ? $append_to->ownerDocument->createTextNode( '' ) : $append_to->ownerDocument->createTextNode( $value );
|
401 |
}
|
402 |
+
|
403 |
$data->appendChild( $child_node );
|
404 |
}
|
405 |
|
407 |
* Convert weight unit abbreviation to Shipstation enum (Pounds, Ounces, Grams)
|
408 |
*/
|
409 |
private function get_shipstation_weight_units( $unit_abbreviation ) {
|
410 |
+
switch ( $unit_abbreviation ) {
|
411 |
case 'lbs':
|
412 |
return 'Pounds';
|
413 |
case 'oz':
|
includes/api-requests/class-wc-shipstation-api-shipnotify.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php
|
2 |
|
3 |
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Exit if accessed directly
|
5 |
}
|
6 |
|
7 |
/**
|
@@ -30,11 +30,7 @@ class WC_Shipstation_API_Shipnotify extends WC_Shipstation_API_Request {
|
|
30 |
|
31 |
foreach ( $order->get_items() as $item_id => $item ) {
|
32 |
|
33 |
-
|
34 |
-
$product = is_callable( array( $item, 'get_product' ) ) ? $item->get_product() : false;
|
35 |
-
} else {
|
36 |
-
$product = $order->get_product_from_item( $item );
|
37 |
-
}
|
38 |
|
39 |
if ( is_a( $product, 'WC_Product' ) && $product->needs_shipping() ) {
|
40 |
$needs_shipping += ( $item['qty'] - abs( $order->get_qty_refunded_for_item( $item_id ) ) );
|
@@ -56,27 +52,10 @@ class WC_Shipstation_API_Shipnotify extends WC_Shipstation_API_Request {
|
|
56 |
* @return bool Returns true if item is shippable product.
|
57 |
*/
|
58 |
private function is_shippable_item( $order, $item_id ) {
|
59 |
-
|
60 |
-
|
61 |
-
if ( ! is_callable( array( $item, 'get_product' ) ) ) {
|
62 |
-
return false;
|
63 |
-
}
|
64 |
-
|
65 |
-
$product = $item->get_product();
|
66 |
-
} else {
|
67 |
-
$items = $order->get_items();
|
68 |
-
if ( ! isset( $items[ $item_id ] ) ) {
|
69 |
-
return false;
|
70 |
-
}
|
71 |
|
72 |
-
|
73 |
-
}
|
74 |
-
|
75 |
-
if ( ! $product ) {
|
76 |
-
return false;
|
77 |
-
}
|
78 |
-
|
79 |
-
return $product->needs_shipping();
|
80 |
}
|
81 |
|
82 |
/**
|
@@ -115,16 +94,16 @@ class WC_Shipstation_API_Shipnotify extends WC_Shipstation_API_Request {
|
|
115 |
* Get Parsed XML response.
|
116 |
*
|
117 |
* @param string $xml XML.
|
118 |
-
* @return
|
119 |
*/
|
120 |
private function get_parsed_xml( $xml ) {
|
121 |
if ( ! class_exists( 'WC_Safe_DOMDocument' ) ) {
|
122 |
-
include_once
|
123 |
}
|
124 |
|
125 |
libxml_use_internal_errors( true );
|
126 |
|
127 |
-
$dom = new WC_Safe_DOMDocument;
|
128 |
$success = $dom->loadXML( $xml );
|
129 |
|
130 |
if ( ! $success ) {
|
@@ -217,7 +196,7 @@ class WC_Shipstation_API_Shipnotify extends WC_Shipstation_API_Request {
|
|
217 |
}
|
218 |
|
219 |
// Get real order ID from order object.
|
220 |
-
$order_id =
|
221 |
if ( empty( $order_id ) ) {
|
222 |
/* translators: 1: order id */
|
223 |
$this->log( sprintf( __( 'Invalid order ID: %s', 'woocommerce-shipstation-integration' ), $order_id ) );
|
@@ -247,7 +226,7 @@ class WC_Shipstation_API_Shipnotify extends WC_Shipstation_API_Request {
|
|
247 |
}
|
248 |
|
249 |
$shipped_item_count += $qty_shipped;
|
250 |
-
$shipped_items[]
|
251 |
}
|
252 |
}
|
253 |
}
|
@@ -267,7 +246,7 @@ class WC_Shipstation_API_Shipnotify extends WC_Shipstation_API_Request {
|
|
267 |
$tracking_number
|
268 |
);
|
269 |
|
270 |
-
$current_shipped_items = max( (int)
|
271 |
|
272 |
if ( ( $current_shipped_items + $shipped_item_count ) >= $total_item_count ) {
|
273 |
$order_shipped = true;
|
@@ -283,8 +262,8 @@ class WC_Shipstation_API_Shipnotify extends WC_Shipstation_API_Request {
|
|
283 |
)
|
284 |
);
|
285 |
|
286 |
-
|
287 |
-
|
288 |
} else {
|
289 |
// If we don't have items from SS and order items in WC, or cannot parse
|
290 |
// the XML, just complete the order as a whole.
|
@@ -308,9 +287,10 @@ class WC_Shipstation_API_Shipnotify extends WC_Shipstation_API_Request {
|
|
308 |
wc_st_add_tracking_number( $order_id, $tracking_number, strtolower( $carrier ), $timestamp );
|
309 |
} else {
|
310 |
// You're using Shipment Tracking < 1.4.0. Please update!
|
311 |
-
|
312 |
-
|
313 |
-
|
|
|
314 |
}
|
315 |
|
316 |
$is_customer_note = 0;
|
@@ -329,12 +309,16 @@ class WC_Shipstation_API_Shipnotify extends WC_Shipstation_API_Request {
|
|
329 |
}
|
330 |
|
331 |
// Trigger action for other integrations.
|
332 |
-
do_action(
|
333 |
-
'
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
|
|
|
|
|
|
|
|
338 |
|
339 |
status_header( 200 );
|
340 |
}
|
1 |
<?php
|
2 |
|
3 |
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
+
exit; // Exit if accessed directly.
|
5 |
}
|
6 |
|
7 |
/**
|
30 |
|
31 |
foreach ( $order->get_items() as $item_id => $item ) {
|
32 |
|
33 |
+
$product = is_callable( array( $item, 'get_product' ) ) ? $item->get_product() : false;
|
|
|
|
|
|
|
|
|
34 |
|
35 |
if ( is_a( $product, 'WC_Product' ) && $product->needs_shipping() ) {
|
36 |
$needs_shipping += ( $item['qty'] - abs( $order->get_qty_refunded_for_item( $item_id ) ) );
|
52 |
* @return bool Returns true if item is shippable product.
|
53 |
*/
|
54 |
private function is_shippable_item( $order, $item_id ) {
|
55 |
+
$item = $order->get_item( $item_id );
|
56 |
+
$product = is_callable( array( $item, 'get_product' ) ) ? $item->get_product() : false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
|
58 |
+
return $product ? $product->needs_shipping() : false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
}
|
60 |
|
61 |
/**
|
94 |
* Get Parsed XML response.
|
95 |
*
|
96 |
* @param string $xml XML.
|
97 |
+
* @return SimpleXMLElement|false
|
98 |
*/
|
99 |
private function get_parsed_xml( $xml ) {
|
100 |
if ( ! class_exists( 'WC_Safe_DOMDocument' ) ) {
|
101 |
+
include_once 'class-wc-safe-domdocument.php';
|
102 |
}
|
103 |
|
104 |
libxml_use_internal_errors( true );
|
105 |
|
106 |
+
$dom = new WC_Safe_DOMDocument();
|
107 |
$success = $dom->loadXML( $xml );
|
108 |
|
109 |
if ( ! $success ) {
|
196 |
}
|
197 |
|
198 |
// Get real order ID from order object.
|
199 |
+
$order_id = $order->get_id();
|
200 |
if ( empty( $order_id ) ) {
|
201 |
/* translators: 1: order id */
|
202 |
$this->log( sprintf( __( 'Invalid order ID: %s', 'woocommerce-shipstation-integration' ), $order_id ) );
|
226 |
}
|
227 |
|
228 |
$shipped_item_count += $qty_shipped;
|
229 |
+
$shipped_items[] = $item_name . $item_sku . ' x ' . $qty_shipped;
|
230 |
}
|
231 |
}
|
232 |
}
|
246 |
$tracking_number
|
247 |
);
|
248 |
|
249 |
+
$current_shipped_items = max( (int) $order->get_meta( '_shipstation_shipped_item_count', true ), 0 );
|
250 |
|
251 |
if ( ( $current_shipped_items + $shipped_item_count ) >= $total_item_count ) {
|
252 |
$order_shipped = true;
|
262 |
)
|
263 |
);
|
264 |
|
265 |
+
$order->update_meta_data( '_shipstation_shipped_item_count', $current_shipped_items + $shipped_item_count );
|
266 |
+
$order->save();
|
267 |
} else {
|
268 |
// If we don't have items from SS and order items in WC, or cannot parse
|
269 |
// the XML, just complete the order as a whole.
|
287 |
wc_st_add_tracking_number( $order_id, $tracking_number, strtolower( $carrier ), $timestamp );
|
288 |
} else {
|
289 |
// You're using Shipment Tracking < 1.4.0. Please update!
|
290 |
+
$order->update_meta_data( '_tracking_provider', strtolower( $carrier ) );
|
291 |
+
$order->update_meta_data( '_tracking_number', $tracking_number );
|
292 |
+
$order->update_meta_data( '_date_shipped', $timestamp );
|
293 |
+
$order->save();
|
294 |
}
|
295 |
|
296 |
$is_customer_note = 0;
|
309 |
}
|
310 |
|
311 |
// Trigger action for other integrations.
|
312 |
+
do_action(
|
313 |
+
'woocommerce_shipstation_shipnotify',
|
314 |
+
$order,
|
315 |
+
array(
|
316 |
+
'tracking_number' => $tracking_number,
|
317 |
+
'carrier' => $carrier,
|
318 |
+
'ship_date' => $timestamp,
|
319 |
+
'xml' => $shipstation_xml,
|
320 |
+
)
|
321 |
+
);
|
322 |
|
323 |
status_header( 200 );
|
324 |
}
|
includes/class-wc-shipstation-privacy.php
CHANGED
@@ -22,7 +22,7 @@ class WC_ShipStation_Privacy extends WC_Abstract_Privacy {
|
|
22 |
* @param string $email_address
|
23 |
* @param int $page
|
24 |
*
|
25 |
-
* @return
|
26 |
*/
|
27 |
protected function get_orders( $email_address, $page ) {
|
28 |
$user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
|
@@ -75,15 +75,15 @@ class WC_ShipStation_Privacy extends WC_Abstract_Privacy {
|
|
75 |
'data' => array(
|
76 |
array(
|
77 |
'name' => __( 'ShipStation tracking provider', 'woocommerce-shipstation-integration' ),
|
78 |
-
'value' =>
|
79 |
),
|
80 |
array(
|
81 |
'name' => __( 'ShipStation tracking number', 'woocommerce-shipstation-integration' ),
|
82 |
-
'value' =>
|
83 |
),
|
84 |
array(
|
85 |
'name' => __( 'ShipStation date shipped', 'woocommerce-shipstation-integration' ),
|
86 |
-
'value' =>
|
87 |
),
|
88 |
),
|
89 |
);
|
@@ -140,23 +140,23 @@ class WC_ShipStation_Privacy extends WC_Abstract_Privacy {
|
|
140 |
* @return array
|
141 |
*/
|
142 |
protected function maybe_handle_order( $order ) {
|
143 |
-
$
|
144 |
-
$
|
145 |
-
$
|
146 |
-
$
|
147 |
-
$
|
148 |
-
$shipstation_exported = get_post_meta( $order->get_id(), '_shipstation_exported', true );
|
149 |
|
150 |
if ( empty( $item_count ) && empty( $tracking_provider ) && empty( $tracking_number )
|
151 |
&& empty( $date_shipped ) && empty( $shipstation_exported ) ) {
|
152 |
return array( false, false, array() );
|
153 |
}
|
154 |
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
|
|
160 |
|
161 |
return array( true, false, array( __( 'ShipStation Order Data Erased.', 'woocommerce-shipstation-integration' ) ) );
|
162 |
}
|
22 |
* @param string $email_address
|
23 |
* @param int $page
|
24 |
*
|
25 |
+
* @return WC_Order[]
|
26 |
*/
|
27 |
protected function get_orders( $email_address, $page ) {
|
28 |
$user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
|
75 |
'data' => array(
|
76 |
array(
|
77 |
'name' => __( 'ShipStation tracking provider', 'woocommerce-shipstation-integration' ),
|
78 |
+
'value' => $order->get_meta( '_tracking_provider', true ),
|
79 |
),
|
80 |
array(
|
81 |
'name' => __( 'ShipStation tracking number', 'woocommerce-shipstation-integration' ),
|
82 |
+
'value' => $order->get_meta( '_tracking_number', true ),
|
83 |
),
|
84 |
array(
|
85 |
'name' => __( 'ShipStation date shipped', 'woocommerce-shipstation-integration' ),
|
86 |
+
'value' => $order->get_meta( '_date_shipped', true ) ? date( 'Y-m-d H:i:s', $order->get_meta( '_date_shipped', true ) ) : '',
|
87 |
),
|
88 |
),
|
89 |
);
|
140 |
* @return array
|
141 |
*/
|
142 |
protected function maybe_handle_order( $order ) {
|
143 |
+
$item_count = $order->get_meta( '_shipstation_shipped_item_count', true );
|
144 |
+
$tracking_provider = $order->get_meta( '_tracking_provider', true );
|
145 |
+
$tracking_number = $order->get_meta( '_tracking_number', true );
|
146 |
+
$date_shipped = $order->get_meta( '_date_shipped', true );
|
147 |
+
$shipstation_exported = $order->get_meta( '_shipstation_exported', true );
|
|
|
148 |
|
149 |
if ( empty( $item_count ) && empty( $tracking_provider ) && empty( $tracking_number )
|
150 |
&& empty( $date_shipped ) && empty( $shipstation_exported ) ) {
|
151 |
return array( false, false, array() );
|
152 |
}
|
153 |
|
154 |
+
$order->delete_meta_data( '_shipstation_shipped_item_count' );
|
155 |
+
$order->delete_meta_data( '_tracking_provider' );
|
156 |
+
$order->delete_meta_data( '_tracking_number' );
|
157 |
+
$order->delete_meta_data( '_date_shipped' );
|
158 |
+
$order->delete_meta_data( '_shipstation_exported' );
|
159 |
+
$order->save();
|
160 |
|
161 |
return array( true, false, array( __( 'ShipStation Order Data Erased.', 'woocommerce-shipstation-integration' ) ) );
|
162 |
}
|
includes/trait-woocommerce-order-util.php
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class WooCommerce\OrderBarcodes\Order_Util file.
|
4 |
+
*
|
5 |
+
* @package WooCommerce\OrderBarcodes
|
6 |
+
*/
|
7 |
+
|
8 |
+
namespace WooCommerce\ShipStation;
|
9 |
+
|
10 |
+
use Automattic\WooCommerce\Utilities\OrderUtil;
|
11 |
+
|
12 |
+
defined( 'ABSPATH' ) || exit;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Trait Order_Util
|
16 |
+
*
|
17 |
+
* A proxy-style trait that will help keep our code more stable and cleaner during the
|
18 |
+
* transition to WC Custom Order Tables.
|
19 |
+
*/
|
20 |
+
trait Order_Util {
|
21 |
+
/**
|
22 |
+
* Constant variable for admin screen name.
|
23 |
+
*
|
24 |
+
* @var legacy_order_admin_screen.
|
25 |
+
*/
|
26 |
+
public static $legacy_order_admin_screen = 'shop_order';
|
27 |
+
|
28 |
+
/**
|
29 |
+
* Checks whether the OrderUtil class exists
|
30 |
+
*
|
31 |
+
* @return bool
|
32 |
+
*/
|
33 |
+
public static function wc_order_util_class_exists() {
|
34 |
+
return class_exists( 'Automattic\WooCommerce\Utilities\OrderUtil' );
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Checks whether the OrderUtil class and the given method exist
|
39 |
+
*
|
40 |
+
* @param String $method_name Class method name.
|
41 |
+
*
|
42 |
+
* @return bool
|
43 |
+
*/
|
44 |
+
public static function wc_order_util_method_exists( $method_name ) {
|
45 |
+
if ( ! self::wc_order_util_class_exists() ) {
|
46 |
+
return false;
|
47 |
+
}
|
48 |
+
|
49 |
+
if ( ! method_exists( 'Automattic\WooCommerce\Utilities\OrderUtil', $method_name ) ) {
|
50 |
+
return false;
|
51 |
+
}
|
52 |
+
|
53 |
+
return true;
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Checks whether we are using custom order tables.
|
58 |
+
*
|
59 |
+
* @return bool
|
60 |
+
*/
|
61 |
+
public static function custom_orders_table_usage_is_enabled() {
|
62 |
+
if ( ! self::wc_order_util_method_exists( 'custom_orders_table_usage_is_enabled' ) ) {
|
63 |
+
return false;
|
64 |
+
}
|
65 |
+
|
66 |
+
return OrderUtil::custom_orders_table_usage_is_enabled();
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Returns the relevant order screen depending on whether
|
71 |
+
* custom order tables are being used.
|
72 |
+
*
|
73 |
+
* @return string
|
74 |
+
*/
|
75 |
+
public static function get_order_admin_screen() {
|
76 |
+
if ( ! self::wc_order_util_method_exists( 'get_order_admin_screen' ) ) {
|
77 |
+
return self::$legacy_order_admin_screen;
|
78 |
+
}
|
79 |
+
|
80 |
+
return OrderUtil::get_order_admin_screen();
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Check if the object is WP_Post object.
|
85 |
+
*
|
86 |
+
* @param Mixed $object Either Post object or Order object.
|
87 |
+
*
|
88 |
+
* @return Boolean
|
89 |
+
*/
|
90 |
+
public static function is_wp_post( $object ) {
|
91 |
+
return is_a( $object, 'WP_Post' );
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Check if the object is WC_Order object.
|
96 |
+
*
|
97 |
+
* @param Mixed $object Either Post object or Order object.
|
98 |
+
*
|
99 |
+
* @return Boolean
|
100 |
+
*/
|
101 |
+
public static function is_wc_order( $object ) {
|
102 |
+
return is_a( $object, 'WC_Order' );
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Check if the object is either WP_Post or WC_Order object.
|
107 |
+
*
|
108 |
+
* @param Mixed $object Either Post object or Order object.
|
109 |
+
*
|
110 |
+
* @return Boolean
|
111 |
+
*/
|
112 |
+
public static function is_order_or_post( $object ) {
|
113 |
+
return self::is_wp_post( $object ) || self::is_wc_order( $object );
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Returns the WC_Order object from the object passed to
|
118 |
+
* the add_meta_box callback function.
|
119 |
+
*
|
120 |
+
* @param WC_Order|WP_Post $post_or_order_object Either Post object or Order object.
|
121 |
+
*
|
122 |
+
* @return \WC_Order
|
123 |
+
*/
|
124 |
+
public static function init_theorder_object( $post_or_order_object ) {
|
125 |
+
if ( ! self::wc_order_util_method_exists( 'init_theorder_object' ) ) {
|
126 |
+
return wc_get_order( $post_or_order_object->ID );
|
127 |
+
}
|
128 |
+
|
129 |
+
return OrderUtil::init_theorder_object( $post_or_order_object );
|
130 |
+
}
|
131 |
+
}
|
readme.txt
CHANGED
@@ -2,9 +2,9 @@
|
|
2 |
Contributors: woocommerce, automattic, royho, akeda, mattyza, bor0, woothemes, dwainm, laurendavissmith001
|
3 |
Tags: shipping, woocommerce, automattic
|
4 |
Requires at least: 4.4
|
5 |
-
Tested up to:
|
6 |
Requires PHP: 5.6
|
7 |
-
Stable tag: 4.
|
8 |
License: GPLv3
|
9 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
@@ -46,6 +46,9 @@ If you get stuck, you can ask for help in the Plugin Forum.
|
|
46 |
|
47 |
== Changelog ==
|
48 |
|
|
|
|
|
|
|
49 |
= 4.2.0 - 2022-09-07 =
|
50 |
* Add - Filter for manipulating address export data.
|
51 |
* Fix - Remove unnecessary files from plugin zip file.
|
2 |
Contributors: woocommerce, automattic, royho, akeda, mattyza, bor0, woothemes, dwainm, laurendavissmith001
|
3 |
Tags: shipping, woocommerce, automattic
|
4 |
Requires at least: 4.4
|
5 |
+
Tested up to: 6.0
|
6 |
Requires PHP: 5.6
|
7 |
+
Stable tag: 4.3.0
|
8 |
License: GPLv3
|
9 |
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
10 |
|
46 |
|
47 |
== Changelog ==
|
48 |
|
49 |
+
= 4.3.0 - 2022-10-13 =
|
50 |
+
* Add - High-Performance Order Storage compatibility.
|
51 |
+
|
52 |
= 4.2.0 - 2022-09-07 =
|
53 |
* Add - Filter for manipulating address export data.
|
54 |
* Fix - Remove unnecessary files from plugin zip file.
|
woocommerce-shipstation.php
CHANGED
@@ -2,14 +2,14 @@
|
|
2 |
/**
|
3 |
* Plugin Name: WooCommerce - ShipStation Integration
|
4 |
* Plugin URI: https://woocommerce.com/products/shipstation-integration/
|
5 |
-
* Version: 4.
|
6 |
* Description: Adds ShipStation label printing support to WooCommerce. Requires server DomDocument support.
|
7 |
* Author: WooCommerce
|
8 |
* Author URI: https://woocommerce.com/
|
9 |
* Text Domain: woocommerce-shipstation-integration
|
10 |
* Domain Path: /languages
|
11 |
* Tested up to: 6.0
|
12 |
-
* WC tested up to: 6.
|
13 |
* WC requires at least: 3.4
|
14 |
*/
|
15 |
|
@@ -41,15 +41,17 @@ function woocommerce_shipstation_init() {
|
|
41 |
return;
|
42 |
}
|
43 |
|
44 |
-
define( 'WC_SHIPSTATION_VERSION', '4.
|
45 |
define( 'WC_SHIPSTATION_FILE', __FILE__ );
|
46 |
|
47 |
if ( ! defined( 'WC_SHIPSTATION_EXPORT_LIMIT' ) ) {
|
48 |
define( 'WC_SHIPSTATION_EXPORT_LIMIT', 100 );
|
49 |
}
|
50 |
|
51 |
-
|
52 |
-
|
|
|
|
|
53 |
}
|
54 |
|
55 |
add_action( 'plugins_loaded', 'woocommerce_shipstation_init' );
|
2 |
/**
|
3 |
* Plugin Name: WooCommerce - ShipStation Integration
|
4 |
* Plugin URI: https://woocommerce.com/products/shipstation-integration/
|
5 |
+
* Version: 4.3.0
|
6 |
* Description: Adds ShipStation label printing support to WooCommerce. Requires server DomDocument support.
|
7 |
* Author: WooCommerce
|
8 |
* Author URI: https://woocommerce.com/
|
9 |
* Text Domain: woocommerce-shipstation-integration
|
10 |
* Domain Path: /languages
|
11 |
* Tested up to: 6.0
|
12 |
+
* WC tested up to: 6.9
|
13 |
* WC requires at least: 3.4
|
14 |
*/
|
15 |
|
41 |
return;
|
42 |
}
|
43 |
|
44 |
+
define( 'WC_SHIPSTATION_VERSION', '4.3.0' ); // WRCS: DEFINED_VERSION.
|
45 |
define( 'WC_SHIPSTATION_FILE', __FILE__ );
|
46 |
|
47 |
if ( ! defined( 'WC_SHIPSTATION_EXPORT_LIMIT' ) ) {
|
48 |
define( 'WC_SHIPSTATION_EXPORT_LIMIT', 100 );
|
49 |
}
|
50 |
|
51 |
+
// Include order util trait class file.
|
52 |
+
require_once 'includes/trait-woocommerce-order-util.php';
|
53 |
+
include_once 'includes/class-wc-shipstation-integration.php';
|
54 |
+
include_once 'includes/class-wc-shipstation-privacy.php';
|
55 |
}
|
56 |
|
57 |
add_action( 'plugins_loaded', 'woocommerce_shipstation_init' );
|