Completed
Pull Request — develop (#1347)
by David
04:57 queued 01:46
created

Shipping_Zone::add_cutoff_time()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 1
dl 0
loc 18
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
4
namespace Wordlift\Shipping_Data;
5
6
7
use DateTime;
8
use DateTimeZone;
9
use WC_Shipping_Zone;
10
11
class Shipping_Zone {
12
13
	/**
14
	 * @var WC_Shipping_Zone
15
	 */
16
	private $wc_shipping_zone;
17
18
	/**
19
	 * @var Shipping_Method[]
20
	 */
21
	private $methods;
22
23
	/**
24
	 * @var string
25
	 */
26
	private $country_code;
27
28
	/**
29
	 * @var string[]
30
	 */
31
	private $regions = array();
32
33
	/**
34
	 * @var string[]
35
	 */
36
	private $postal_codes = array();
37
38
	/**
39
	 * @var string[]
40
	 */
41
	private $postal_code_prefixes = array();
42
43
	/**
44
	 * @var string[]
45
	 */
46
	private $postal_code_ranges = array();
47
48
	/**
49
	 * Shipping_Zone constructor.
50
	 *
51
	 * @param WC_Shipping_Zone $wc_shipping_zone
52
	 * @param string $country_code
53
	 */
54
	public function __construct( $wc_shipping_zone, $country_code ) {
55
56
		$this->wc_shipping_zone = $wc_shipping_zone;
57
		$this->country_code     = $country_code;
58
59
		$this->load_zone_locations();
60
61
	}
62
63
	private function load_zone_locations() {
64
65
		$this->regions              = array();
66
		$this->postal_codes         = array();
67
		$this->postal_code_prefixes = array();
68
		$this->postal_code_ranges   = array();
69
70
		// Bail out if country code isn't set.
71
		if ( ! isset( $this->country_code ) ) {
72
			return;
73
		}
74
75
		foreach ( $this->wc_shipping_zone->get_zone_locations() as $zone_location ) {
76
			switch ( $zone_location->type ) {
77
				case 'state':
78
					if ( 0 === strpos( $zone_location->code, "$this->country_code:" ) ) {
79
						$this->regions[] = substr( $zone_location->code, 3 );
80
					}
81
82
					break;
83
84
				case 'postcode':
85
					if ( '*' === substr( $zone_location->code, - 1 ) ) {
86
						$this->postal_code_prefixes[] = $zone_location->code;
87
					} else if ( - 1 < strpos( $zone_location->code, '...' ) ) {
88
						$this->postal_code_ranges[] = $zone_location->code;
89
					} else {
90
						$this->postal_codes[] = $zone_location->code;
91
					}
92
93
					break;
94
95
				default:
96
			}
97
		}
98
99
	}
100
101
	private function load_methods() {
102
103
		$this->methods = array_map( 'Wordlift\Shipping_Data\Shipping_Method::from_wc_shipping_method',
104
			$this->wc_shipping_zone->get_shipping_methods( true ) );
105
106
	}
107
108
	public function add_available_delivery_method( &$jsonld ) {
109
110
		$this->load_methods();
111
112
		foreach ( $this->methods as $method ) {
113
			$method->add_available_delivery_method( $jsonld );
114
		}
115
116
	}
117
118
	/**
119
	 * @param array $jsonld
120
	 * @param Product $product
121
	 */
122
	public function add_offer_shipping_details( &$jsonld, $product ) {
123
124
		$this->load_methods();
125
126
		// Ignore the default zone if no methods are configured.
127
		if ( 0 === $this->wc_shipping_zone->get_id() && 0 === count( $this->methods ) ) {
128
			return;
129
		}
130
131
		$this->make_sure_shipping_details_exists_and_it_is_an_array( $jsonld );
132
133
		if ( empty( $this->methods ) ) {
134
			$this->add_shipping_details_with_shipping_method( $jsonld, $product );
135
		} else {
136
			foreach ( $this->methods as $method ) {
137
				$this->add_shipping_details_with_shipping_method( $jsonld, $product, $method );
138
			}
139
		}
140
141
	}
142
143
	/**
144
	 * @param array $jsonld
145
	 * @param Product $product
146
	 */
147
//	private function add_shipping_details_when_no_shipping_methods( &$jsonld, $product ) {
148
//
149
//		$offer_shipping_details = array( '@type' => 'OfferShippingDetails', );
150
//
151
//		$this->add_shipping_destination( $offer_shipping_details );
152
//
153
//		/*
154
//		 * Use Case UC004
155
//		 */
156
//		$shipping_delivery_time = array( '@type' => 'ShippingDeliveryTime', );
157
//		$product->add_handling_time( $offer_shipping_details['deliveryTime'] );
158
//
159
//		$this->add_cutoff_time( $shipping_delivery_time );
160
//
161
//		if ( 1 < count( $shipping_delivery_time ) ) {
162
//			$offer_shipping_details['shippingDeliveryTime'] = $shipping_delivery_time;
163
//		}
164
//
165
//		$jsonld['shippingDetails'][] = $offer_shipping_details;
166
//
167
//	}
168
169
	/**
170
	 * @param array $jsonld
171
	 * @param Product $product
172
	 * @param Shipping_Method $method
173
	 */
174
	private function add_shipping_details_with_shipping_method( &$jsonld, $product, $method = null ) {
175
176
		$offer_shipping_details = array( '@type' => 'OfferShippingDetails', );
177
		$shipping_delivery_time = array( '@type' => 'ShippingDeliveryTime', );
178
179
		$this->add_shipping_destination( $offer_shipping_details );
180
181
		/*
182
		 * Use Case UC003
183
		 * 1.4.3
184
		 */
185
		if ( isset( $method ) ) {
186
			$method->add_shipping_rate( $offer_shipping_details );
187
			$method->add_transit_time( $shipping_delivery_time );
188
		}
189
190
		/*
191
		 * Use Case UC004
192
		 */
193
		$product->add_handling_time( $shipping_delivery_time );
194
195
		$this->add_cutoff_time( $shipping_delivery_time );
196
		$this->add_business_days( $shipping_delivery_time );
197
198
		if ( 1 < count( $shipping_delivery_time ) ) {
199
			$offer_shipping_details['shippingDeliveryTime'] = $shipping_delivery_time;
200
		}
201
202
		$jsonld['shippingDetails'][] = $offer_shipping_details;
203
204
	}
205
206
	private function make_sure_shipping_details_exists_and_it_is_an_array( &$jsonld ) {
207
208
		if ( ! isset( $jsonld['shippingDetails'] ) ) {
209
			$jsonld['shippingDetails'] = array();
210
		}
211
212 View Code Duplication
		if ( ! is_array( $jsonld['shippingDetails'] ) ||
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
213
		     ( ! empty( $jsonld['shippingDetails'] ) && ! is_numeric( key( $jsonld['shippingDetails'] ) ) ) ) {
214
			$jsonld['shippingDetails'] = array( $jsonld['shippingDetails'] );
215
		}
216
217
	}
218
219
	private function add_shipping_destination( &$shipping_details ) {
220
221
		if ( ! isset( $this->country_code ) ) {
222
			return;
223
		}
224
225
		$shipping_destination = array(
226
			'@type'          => 'DefinedRegion',
227
			'addressCountry' => $this->country_code,
228
		);
229
230
		$this->add_address_region( $shipping_destination );
231
		$this->add_postal_code( $shipping_destination );
232
		$this->add_postal_code_prefix( $shipping_destination );
233
		$this->add_postal_code_range( $shipping_destination );
234
235
		$shipping_details['shippingDestination'] = $shipping_destination;
236
237
238
	}
239
240
	private function add_address_region( &$shipping_destination ) {
241
242
		if ( empty( $this->regions ) ) {
243
			return;
244
		}
245
246
		$shipping_destination['addressRegion'] = $this->regions;
247
248
	}
249
250
	private function add_postal_code( &$shipping_destination ) {
251
252
		if ( empty( $this->postal_codes ) ) {
253
			return;
254
		}
255
256
		$shipping_destination['postalCode'] = $this->postal_codes;
257
258
	}
259
260
	private function add_postal_code_prefix( &$shipping_destination ) {
261
262
		if ( empty( $this->postal_code_prefixes ) ) {
263
			return;
264
		}
265
266
		foreach ( $this->postal_code_prefixes as $postal_code_prefix ) {
267
			$shipping_destination['postalCodePrefix'][] = substr( $postal_code_prefix, 0, - 1 );
268
		}
269
270
	}
271
272
	private function add_postal_code_range( &$shipping_destination ) {
273
274
		if ( empty( $this->postal_code_ranges ) ) {
275
			return;
276
		}
277
278
		$shipping_destination['postalCodeRanges'] = array();
279
		foreach ( $this->postal_code_ranges as $post_code_range ) {
280
			$range = explode( '...', $post_code_range );
281
282
			$shipping_destination['postalCodeRanges'][] = array(
283
				'postalCodeBegin' => $range[0],
284
				'postalCodeEnd'   => $range[1],
285
			);
286
		}
287
288
	}
289
290
	public static function from_wc_shipping_zone( $wc_shipping_zone, $country_code = null ) {
291
292
		return new self( $wc_shipping_zone, $country_code );
293
	}
294
295
	private function add_cutoff_time( &$shipping_delivery_time ) {
296
297
		$wpsso_options = get_option( 'wpsso_options' );
298
299
		if ( empty( $wpsso_options['wcsdt_shipdept_cutoff'] )
300
		     || empty( $wpsso_options['wcsdt_shipdept_timezone'] ) ) {
301
			return;
302
		}
303
304
		$cutoff_time = $wpsso_options['wcsdt_shipdept_cutoff'];
305
		$timezone    = $wpsso_options['wcsdt_shipdept_timezone'];
306
307
		$time   = new DateTime( 'now', new DateTimeZone( $timezone ) );
308
		$offset = $time->format( 'P' );
309
310
		$shipping_delivery_time['cutOffTime'] = "{$cutoff_time}{$offset}";
311
312
	}
313
314
	private function add_business_days( &$shipping_delivery_time ) {
315
316
		$wpsso_options = get_option( 'wpsso_options' );
317
318
		$day_of_week = array();
319
		$prefix      = 'wcsdt_shipdept_day_';
320
		foreach ( array( 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ) as $day ) {
321
			$key = $prefix . strtolower( $day );
322
323
			if (
324
				( empty( $wpsso_options["{$key}_open"] ) && empty( $wpsso_options["{$key}_close"] ) )
325
				|| ( 'none' === $wpsso_options["{$key}_open"] && 'none' === $wpsso_options["{$key}_close"] )
326
			) {
327
				continue;
328
			}
329
330
			$day_of_week[] = "https://schema.org/$day";
331
		}
332
333
		if ( ! empty( $day_of_week ) ) {
334
			$shipping_delivery_time['businessDays'] = array(
335
				'@type'     => 'OpeningHoursSpecification',
336
				'dayOfWeek' => $day_of_week,
337
			);
338
		}
339
340
	}
341
342
}