PluginProbe
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More / 2.1.0
StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More v2.1.0
2.3.0 2.2.0 2.1.1 2.1.0 2.0.0 1.10.0 1.9.1 1.9.0 1.2.1 1.2.2 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.6.0 All 59 releases
storeengine / includes / api / shipping.php

shipping.php in StoreEngine — Complete eCommerce Solution with Memberships, Licensing, Affiliates & More 2.1.0, at includes/api/shipping.php

662 lines 22.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace StoreEngine\API;
4
5 use StoreEngine\Classes\Countries;
6 use StoreEngine\Classes\Exceptions\StoreEngineException;
7 use StoreEngine\Shipping\Methods\ShippingMethod;
8 use StoreEngine\Shipping\Shipping as ShippingObj;
9 use StoreEngine\Shipping\ShippingZone;
10 use StoreEngine\Shipping\ShippingZones;
11 use StoreEngine\Utils\Formatting;
12 use StoreEngine\Utils\Helper;
13 use StoreEngine\Utils\ShippingUtils;
14 use WP_Error;
15 use WP_REST_Request;
16 use WP_REST_Server;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit;
20 }
21
22 class Shipping extends AbstractRestApiController {
23
24 public static function init() {
25 $self = new self();
26 $self->namespace = STOREENGINE_PLUGIN_SLUG . '/v1';
27 $self->rest_base = 'shipping';
28 add_action( 'rest_api_init', [ $self, 'register_routes' ] );
29 }
30
31 public function register_routes() {
32 register_rest_route( $this->namespace, '/' . $this->rest_base . '/zones', [
33 [
34 'methods' => WP_REST_Server::READABLE,
35 'callback' => [ $this, 'get_shipping_zones' ],
36 'permission_callback' => [ $this, 'permissions_check' ],
37 'args' => [],
38 ],
39 [
40 'methods' => WP_REST_Server::CREATABLE,
41 'callback' => [ $this, 'create_shipping_zone' ],
42 'permission_callback' => [ $this, 'permissions_check' ],
43 'args' => [
44 'zone_name' => [
45 'type' => 'string',
46 'required' => true,
47 'sanitize_callback' => 'sanitize_text_field',
48 'validate_callback' => 'rest_validate_request_arg',
49 ],
50 'zone_locations' => [
51 'required' => false,
52 'type' => 'array',
53 'items' => [
54 'type' => 'string',
55 ],
56 'sanitize_callback' => [ $this, 'sanitize_zone_locations' ],
57 ],
58 'zone_postcodes' => [
59 'required' => false,
60 'type' => 'string',
61 'sanitize_callback' => 'sanitize_textarea_field',
62 ],
63 ],
64 ],
65 ] );
66 register_rest_route( $this->namespace, '/' . $this->rest_base . '/zones/(?P<zone_id>[\d]+)', [
67 'args' => [
68 'zone_id' => [
69 'description' => __( 'Unique identifier for the resource.', 'storeengine' ),
70 'type' => 'integer',
71 ],
72 ],
73 [
74 'methods' => WP_REST_Server::READABLE,
75 'callback' => [ $this, 'get_single_shipping_zone' ],
76 'permission_callback' => [ $this, 'permissions_check' ],
77 ],
78 [
79 'methods' => WP_REST_Server::EDITABLE,
80 'callback' => [ $this, 'update_shipping_zone' ],
81 'permission_callback' => [ $this, 'permissions_check' ],
82 'args' => [
83 'zone_name' => [
84 'type' => 'string',
85 'required' => true,
86 'sanitize_callback' => 'sanitize_text_field',
87 'validate_callback' => 'rest_validate_request_arg',
88 ],
89 'zone_locations' => [
90 'required' => false,
91 'type' => 'array',
92 'items' => [
93 'type' => 'string',
94 ],
95 'sanitize_callback' => [ $this, 'sanitize_zone_locations' ],
96 ],
97 'zone_postcodes' => [
98 'required' => false,
99 'type' => 'string',
100 'sanitize_callback' => 'sanitize_textarea_field',
101 ],
102 ],
103 ],
104 [
105 'methods' => WP_REST_Server::DELETABLE,
106 'callback' => [ $this, 'delete_shipping_zone' ],
107 'permission_callback' => [ $this, 'permissions_check' ],
108 ],
109 ] );
110 register_rest_route( $this->namespace, '/' . $this->rest_base . '/zones/(?P<zone_id>[\d]+)/methods', [
111 'args' => [
112 'zone_id' => [
113 'description' => __( 'Unique identifier for the resource.', 'storeengine' ),
114 'type' => 'integer',
115 ],
116 ],
117 [
118 'methods' => WP_REST_Server::READABLE,
119 'callback' => [ $this, 'get_shipping_methods_from_zone' ],
120 'permission_callback' => [ $this, 'permissions_check' ],
121 ],
122 [
123 'methods' => WP_REST_Server::CREATABLE,
124 'callback' => [ $this, 'create_shipping_method' ],
125 'permission_callback' => [ $this, 'permissions_check' ],
126 'args' => $this->get_endpoint_args_for_item_schema(),
127 ],
128 'schema' => [ $this, 'get_public_item_schema' ],
129 ] );
130
131 register_rest_route( $this->namespace, '/' . $this->rest_base . '/methods', [
132 [
133 'methods' => WP_REST_Server::READABLE,
134 'callback' => [ $this, 'get_shipping_methods' ],
135 'permission_callback' => [ $this, 'permissions_check' ],
136 ],
137 ] );
138 register_rest_route( $this->namespace, '/' . $this->rest_base . '/methods/(?P<method_id>[a-zA-Z0-9_-]+)/(?P<instance_id>[\d]+)', [
139 'args' => [
140 'method_id' => [
141 'description' => __( 'Shipping method Id.', 'storeengine' ),
142 'type' => 'string',
143 ],
144 'instance_id' => [
145 'description' => __( 'Shipping method\'s instance id.', 'storeengine' ),
146 'type' => 'integer',
147 ],
148 ],
149 [
150 'methods' => WP_REST_Server::READABLE,
151 'callback' => [ $this, 'get_single_shipping_method' ],
152 'permission_callback' => [ $this, 'permissions_check' ],
153 ],
154 [
155 'methods' => WP_REST_Server::EDITABLE,
156 'callback' => [ $this, 'update_shipping_method' ],
157 'permission_callback' => [ $this, 'permissions_check' ],
158 'args' => [
159 'name' => [
160 'required' => true,
161 'type' => 'string',
162 'sanitize_callback' => 'sanitize_text_field',
163 'validate_callback' => 'rest_validate_request_arg',
164 ],
165 'zone_id' => [
166 'required' => true,
167 'type' => 'integer',
168 'sanitize_callback' => 'absint',
169 'validate_callback' => 'rest_validate_request_arg',
170 ],
171 ],
172 ],
173 [
174 'methods' => WP_REST_Server::DELETABLE,
175 'callback' => [ $this, 'delete_shipping_method' ],
176 'permission_callback' => [ $this, 'permissions_check' ],
177 ],
178 ] );
179
180 register_rest_route( $this->namespace, '/' . $this->rest_base . '/regions', [
181 [
182 'methods' => WP_REST_Server::READABLE,
183 'callback' => [ $this, 'get_regions' ],
184 'permission_callback' => [ $this, 'permissions_check' ],
185 ],
186 ] );
187 }
188
189 public function get_shipping_zones( $request ) {
190 $zones = ShippingZones::get_zones();
191
192 $response = [];
193
194 foreach ( $zones as $zone ) {
195 $response[] = $this->prepare_response_for_collection( $this->prepare_item_for_response( $zone, $request ) );
196 }
197
198 return rest_ensure_response( $response );
199 }
200
201 public function create_shipping_zone( WP_REST_Request $request ) {
202 $shipping_zone = new ShippingZone();
203 $this->prepare_item_for_save( $shipping_zone, $request );
204 $shipping_zone->save();
205
206 return rest_ensure_response( $this->prepare_item_for_response( $shipping_zone, $request ) );
207 }
208
209 public function get_shipping_methods_from_zone( WP_REST_Request $request ) {
210 $zone = $this->get_zone( $request );
211 if ( is_wp_error( $zone ) ) {
212 return $zone;
213 }
214
215 return rest_ensure_response( array_values( array_map( fn( $method ) => array_merge(
216 $method->get_data(), [
217 'instance_id' => $method->get_instance_id(),
218 'method_title' => $method->get_method_title(),
219 'method_description' => $method->get_method_description(),
220 'fields' => $method->get_admin_fields(),
221 ]
222 ), $zone->get_shipping_methods() ) ) );
223 }
224
225 /**
226 * @throws StoreEngineException
227 */
228 public function create_shipping_method( WP_REST_Request $request ) {
229 if ( empty( $request->get_param( 'method_id' ) ) ) {
230 return new WP_Error( 'missing-required-params', __( 'Shipping method ID is required.', 'storeengine' ) );
231 }
232
233 if ( empty( $request->get_param( 'name' ) ) ) {
234 return new WP_Error( 'missing-required-params', __( 'Shipping method name is required.', 'storeengine' ) );
235 }
236
237 $shipping_methods = ShippingObj::init()->get_shipping_method_class_names();
238 $method_id = sanitize_text_field( $request->get_param( 'method_id' ) );
239 if ( ! array_key_exists( $method_id, $shipping_methods ) ) {
240 return new WP_Error( 'invalid-value', __( 'Invalid shipping method Id provided.', 'storeengine' ) );
241 }
242 if ( ! class_exists( $shipping_methods[ $method_id ] ) ) {
243 return new WP_Error( 'invalid-value', __( 'Class not found for shipping method Id!', 'storeengine' ) );
244 }
245
246 $zone_id = $request->get_param( 'zone_id' ) ? absint( $request->get_param( 'zone_id' ) ) : 0;
247 try {
248 $zone = new ShippingZone( $zone_id );
249 } catch ( StoreEngineException $e ) {
250 return new WP_Error( 'invalid-value', $e->getMessage() );
251 }
252 /** @var ShippingMethod $shipping_method */
253 $shipping_method = new $shipping_methods[ $method_id ]();
254
255 if ( 0 === $zone_id && Formatting::string_to_bool( $request->get_param( 'create_zone' ) ) ) {
256 $zone_name = $request->get_param( 'zone_name' ) ? sanitize_text_field( $request->get_param( 'zone_name' ) ) : 'Everywhere';
257 $zone->set_zone_name( $zone_name );
258 $zone->save();
259 $zone_id = $zone->get_id();
260 }
261
262 try {
263 $shipping_method->handle_save_request( array_merge( $request->get_params(), [
264 'zone_id' => $zone_id,
265 ] ) );
266 } catch ( StoreEngineException $e ) {
267 return new WP_Error( 'error-on-save', $e->getMessage(), [
268 'zone_id' => $zone_id,
269 ] );
270 }
271
272 return rest_ensure_response( array_merge(
273 $shipping_method->get_data(), [
274 'instance_id' => $shipping_method->get_instance_id(),
275 'zone_id' => $zone_id,
276 'zone_name' => $zone->get_zone_name(),
277 'method_title' => $shipping_method->get_method_title(),
278 'method_description' => $shipping_method->get_method_description(),
279 'fields' => $shipping_method->get_admin_fields(),
280 ]
281 ) );
282 }
283
284 public function get_single_shipping_zone( WP_REST_Request $request ) {
285 $shipping_zone = $this->get_zone( $request );
286
287 if ( is_wp_error( $shipping_zone ) ) {
288 return $shipping_zone;
289 }
290
291 return rest_ensure_response( $this->prepare_item_for_response( $shipping_zone, $request ) );
292 }
293
294 public function update_shipping_zone( WP_REST_Request $request ) {
295 $shipping_zone = $this->get_zone( $request );
296 if ( is_wp_error( $shipping_zone ) ) {
297 return $shipping_zone;
298 }
299
300 $this->prepare_item_for_save( $shipping_zone, $request );
301 $shipping_zone->save();
302
303 return rest_ensure_response( $this->prepare_item_for_response( $shipping_zone, $request ) );
304 }
305
306 /**
307 * @param array|ShippingZone $item
308 * @param $request
309 *
310 * @return WP_Error|\WP_HTTP_Response|\WP_REST_Response
311 */
312 public function prepare_item_for_response( $item, $request ) {
313 if ( is_array( $item ) ) {
314 $id = $item['zone_id'];
315 $data = array_merge( $item, [
316 'shipping_methods' => array_values( array_map( fn( $method ) => array_merge(
317 $method->get_data(),
318 [
319 'instance_id' => $method->get_instance_id(),
320 'method_title' => $method->get_method_title(),
321 'method_description' => $method->get_method_description(),
322 ]
323 ), $item['shipping_methods'] ) ),
324 'zone_locations' => array_values( array_map( [ $this, 'add_location_label' ], array_filter( $item['zone_locations'], fn( $item ) => 'postcode' !== $item->type ) ) ),
325 'zone_postcode' => implode( "\n", array_map( fn( $item ) => $item->code, array_filter( $item['zone_locations'], fn( $item ) => 'postcode' === $item->type ) ) ),
326 ] );
327 } else {
328 $id = $item->get_id();
329 $data = array_merge( $item->get_data(), [
330 'zone_id' => $item->get_id(),
331 'shipping_methods' => array_values( array_map( fn( $method ) => array_merge(
332 $method->get_data(),
333 [
334 'instance_id' => $method->get_instance_id(),
335 'method_title' => $method->get_method_title(),
336 'method_description' => $method->get_method_description(),
337 ]
338 ), $item->get_shipping_methods() ) ),
339 'zone_locations' => array_values( array_map( [ $this, 'add_location_label' ], array_filter( $item->get_zone_locations(), fn( $item ) => 'postcode' !== $item->type ) ) ),
340 'zone_postcode' => implode( "\n", array_map( fn( $item ) => $item->code, array_filter( $item->get_zone_locations(), fn( $item ) => 'postcode' === $item->type ) ) ),
341 'formatted_zone_location' => $item->get_formatted_location( 6 ),
342 ] );
343 }
344
345 $response = rest_ensure_response( $data );
346 $links = [];
347
348 if ( $id ) {
349 $links['self'] = [
350 'href' => rest_url( sprintf( '/%s/%s/zones/%d', $this->namespace, $this->rest_base, $id ) ),
351 ];
352 }
353
354 $links['collection'] = [
355 'href' => rest_url( sprintf( '/%s/%s/zones', $this->namespace, $this->rest_base ) ),
356 ];
357
358 $response->add_links( $links );
359
360 return $response;
361 }
362
363 /**
364 * Prepares one item for create or update operation.
365 *
366 * @param ShippingZone $shipping_zone
367 * @param WP_REST_Request $request Request object.
368 *
369 * @see self::prepare_item_for_database
370 */
371 protected function prepare_item_for_save( ShippingZone $shipping_zone, WP_REST_Request $request ) {
372 $shipping_zone->set_zone_name( sanitize_text_field( $request->get_param( 'zone_name' ) ) );
373 $shipping_zone->save();
374
375 $zone_name = $request->get_param( 'zone_name' );
376 if ( ! empty( $zone_name ) ) {
377 $shipping_zone->set_zone_name( $zone_name );
378 }
379
380 $zone_locations = $request->get_param( 'zone_locations' );
381 if ( is_array( $zone_locations ) && ! empty( $zone_locations ) ) {
382 // Defense-in-depth: drop any location whose country isn't in
383 // the current shipping allow-list. The React picker already
384 // hides restricted countries via `GET /shipping/regions`, but
385 // a stale client (or a direct REST submission) could still
386 // try to bind a now-restricted country to a zone. Filter here
387 // so the zone storage never disagrees with the General →
388 // Shipping locations setting.
389 $allowed_country_codes = array_keys( Countries::init()->get_shipping_countries() );
390 $allowed_continent_codes = array_keys( Countries::init()->get_shipping_continents() );
391
392 $shipping_zone->clear_locations( [ 'state', 'country', 'continent' ] );
393 foreach ( $zone_locations as $zone_location ) {
394 $location = explode( ':', $zone_location );
395 if ( ! $location || ! is_array( $location ) || count( $location ) < 2 ) {
396 continue;
397 }
398 $type = $location[0];
399 array_shift( $location );
400 $code = implode( ':', $location );
401
402 // For `country:XX`, `state:XX:YY`, and `continent:ZZ`,
403 // the first token is the country/continent code we
404 // gate against. Anything outside the allow-list is
405 // silently dropped — same behavior Woo uses when the
406 // merchant tightens selling locations.
407 if ( 'country' === $type && ! in_array( $code, $allowed_country_codes, true ) ) {
408 continue;
409 }
410 if ( 'state' === $type ) {
411 $state_country = (string) ( $location[0] ?? '' );
412 if ( $state_country && ! in_array( $state_country, $allowed_country_codes, true ) ) {
413 continue;
414 }
415 }
416 if ( 'continent' === $type && ! in_array( $code, $allowed_continent_codes, true ) ) {
417 continue;
418 }
419
420 $shipping_zone->add_location( $code, $type );
421 }
422 }
423
424 $zone_postcodes = $request->get_param( 'zone_postcodes' );
425
426 if ( ! empty( $zone_postcodes ) ) {
427 $shipping_zone->clear_locations( 'postcode' );
428
429 // Allow user to input postcodes comma & semicolon as separator and normalize.
430 // Don't normalize hyphen or other characters, as zip code can contain different characters too.
431 $postcodes = str_replace( [ ';', ',' ], "\n", $zone_postcodes );
432 $postcodes = array_filter( array_map( 'strtoupper', array_map( [
433 Formatting::class,
434 'clean',
435 ], explode( "\n", $postcodes ) ) ) );
436
437 foreach ( $postcodes as $postcode ) {
438 $shipping_zone->add_location( $postcode, 'postcode' );
439 }
440 }
441 }
442
443 public function delete_shipping_zone( WP_REST_Request $request ) {
444 $zone = $this->get_zone( $request );
445 if ( is_wp_error( $zone ) ) {
446 return $zone;
447 }
448
449 try {
450 $zone->clear_locations();
451
452 global $wpdb;
453
454 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
455 $result = $wpdb->delete( $wpdb->prefix . 'storeengine_shipping_zone_methods', [ 'zone_id' => $zone->get_id() ] );
456 // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
457
458 if ( ! $result && ! empty( $wpdb->last_error ) ) {
459 return new WP_Error( 'invalid-value', __( 'Error deleting shipping zone methods.', 'storeengine' ) );
460 }
461
462 $zone->save();
463 $zone->delete();
464 } catch ( StoreEngineException $e ) {
465 return new WP_Error( 'invalid-value', $e->getMessage() );
466 }
467
468 return rest_ensure_response( [ 'success' => true ] );
469 }
470
471 public function get_shipping_methods() {
472 $shipping_methods = ShippingObj::init()->get_shipping_method_class_names();
473 $shipping_methods_data = [];
474
475 foreach ( $shipping_methods as $method_id => $class_name ) {
476 if ( ! class_exists( $class_name ) ) {
477 continue;
478 }
479 $shipping_method = new $class_name();
480 $shipping_methods_data[] = [
481 'method' => $method_id,
482 'title' => $shipping_method->get_method_title(),
483 'description' => $shipping_method->get_method_description(),
484 'fields' => $shipping_method->get_admin_fields(),
485 ];
486 }
487
488 return rest_ensure_response( $shipping_methods_data );
489 }
490
491 public function get_single_shipping_method( WP_REST_Request $request ) {
492 $method = $this->get_method( $request );
493 if ( is_wp_error( $method ) ) {
494 return $method;
495 }
496
497 return rest_ensure_response( array_merge(
498 $method->get_data(), [
499 'instance_id' => $method->get_instance_id(),
500 'method_title' => $method->get_method_title(),
501 'method_description' => $method->get_method_description(),
502 'fields' => $method->get_admin_fields(),
503 ]
504 ) );
505 }
506
507 public function update_shipping_method( WP_REST_Request $request ) {
508 $method = $this->get_method( $request );
509 if ( is_wp_error( $method ) ) {
510 return $method;
511 }
512
513 try {
514 $method->handle_save_request( $request->get_params() );
515 } catch ( StoreEngineException $e ) {
516 return new WP_Error( 'error-on-save', $e->getMessage() );
517 }
518
519 return rest_ensure_response( array_merge(
520 $method->get_data(), [
521 'instance_id' => $method->get_instance_id(),
522 'method_title' => $method->get_method_title(),
523 'method_description' => $method->get_method_description(),
524 'fields' => $method->get_admin_fields(),
525 ]
526 ) );
527 }
528
529 public function delete_shipping_method( WP_REST_Request $request ) {
530 $method = $this->get_method( $request );
531 if ( is_wp_error( $method ) ) {
532 return $method;
533 }
534
535 try {
536 $method->delete();
537 } catch ( StoreEngineException $e ) {
538 return new WP_Error( 'invalid-value', $e->getMessage() );
539 }
540
541 return rest_ensure_response( [
542 'success' => true,
543 ] );
544 }
545
546 public function get_regions() {
547 $allowed_countries = Countries::init()->get_shipping_countries();
548 $shipping_continents = Countries::init()->get_shipping_continents();
549
550 return rest_ensure_response( $this->get_region_options( $allowed_countries, $shipping_continents ) );
551 }
552
553 public function sanitize_zone_locations( $value ): array {
554 return array_map( 'sanitize_text_field', $value );
555 }
556
557 public function permissions_check() {
558 return Helper::check_rest_user_cap( 'manage_options' );
559 }
560
561 public function add_location_label( $shipping_zone ): array {
562 $codes = explode( ':', $shipping_zone->code );
563 $country = $codes[0];
564 $state = '';
565
566 if ( count( $codes ) > 1 ) {
567 $state = $codes[1];
568 }
569
570 $label = null;
571 switch ( $shipping_zone->type ) {
572 case 'country':
573 $label = Countries::init()->get_countries()[ $country ];
574 break;
575 case 'state':
576 $label = Countries::init()->get_states()[ $country ][ $state ];
577 break;
578 case 'continent':
579 $label = Countries::init()->get_continents()[ $country ]['name'];
580 break;
581 }
582
583 $shipping_zone = (array) $shipping_zone;
584
585 return array_merge( $shipping_zone, [ 'label' => $label ] );
586 }
587
588 /**
589 * Get all available regions.
590 *
591 * @param array $allowed_countries Zone ID.
592 * @param array $shipping_continents Zone ID.
593 */
594 private function get_region_options( array $allowed_countries, array $shipping_continents ): array {
595 $options = [];
596 foreach ( $shipping_continents as $continent_code => $continent ) {
597 $continent_data = [
598 'value' => 'continent:' . esc_attr( $continent_code ),
599 'label' => esc_html( $continent['name'] ),
600 'children' => [],
601 ];
602
603 $countries = array_intersect( array_keys( $allowed_countries ), $continent['countries'] );
604
605 foreach ( $countries as $country_code ) {
606 $country_data = [
607 'value' => 'country:' . esc_attr( $country_code ),
608 'label' => esc_html( $allowed_countries[ $country_code ] ),
609 'children' => [],
610 ];
611
612 $states = Countries::init()->get_states( $country_code );
613
614 if ( $states ) {
615 foreach ( $states as $state_code => $state_name ) {
616 $country_data['children'][] = [
617 'value' => 'state:' . esc_attr( $country_code . ':' . $state_code ),
618 'label' => esc_html( $state_name . ', ' . $allowed_countries[ $country_code ] ),
619 ];
620 }
621 }
622 $continent_data['children'][] = $country_data;
623 }
624 $options[] = $continent_data;
625 }
626
627 return $options;
628 }
629
630 /**
631 * @param WP_REST_Request $request
632 *
633 * @return ShippingMethod|WP_Error
634 */
635 private function get_method( WP_REST_Request $request ) {
636 $method_id = sanitize_text_field( $request->get_param( 'method_id' ) );
637 $instance_id = absint( $request->get_param( 'instance_id' ) );
638 if ( ! $method_id ) {
639 return new WP_Error( 'missing-required-params', __( 'Shipping method Id is required.', 'storeengine' ) );
640 }
641 if ( ! $instance_id ) {
642 return new WP_Error( 'missing-required-params', __( 'Shipping method instance id is required.', 'storeengine' ) );
643 }
644
645 return ShippingUtils::get_shipping_method( $method_id, $instance_id );
646 }
647
648 private function get_zone( WP_REST_Request $request ) {
649 $zone_id = absint( $request->get_param( 'zone_id' ) );
650 if ( ! $zone_id ) {
651 return new WP_Error( 'missing-required-params', __( 'Zone Id is required.', 'storeengine' ) );
652 }
653
654 try {
655 return new ShippingZone( $zone_id );
656 } catch ( StoreEngineException $e ) {
657 return new WP_Error( 'invalid-value', __( 'Invalid zone Id provided.', 'storeengine' ) );
658 }
659 }
660
661 }
662