| 1 |
<?php |
| 2 |
/** |
| 3 |
* Shipping zone repository. |
| 4 |
* |
| 5 |
* @package Packetery |
| 6 |
*/ |
| 7 |
|
| 8 |
declare( strict_types=1 ); |
| 9 |
|
| 10 |
namespace Packetery\Module; |
| 11 |
|
| 12 |
use Packetery\Module\Framework\WcAdapter; |
| 13 |
use stdClass; |
| 14 |
use WC_Data_Store; |
| 15 |
use WC_Shipping_Zone; |
| 16 |
use WC_Shipping_Zone_Data_Store_Interface; |
| 17 |
|
| 18 |
/** |
| 19 |
* Shipping zone repository. |
| 20 |
*/ |
| 21 |
class ShippingZoneRepository { |
| 22 |
|
| 23 |
/** |
| 24 |
* @var WC_Shipping_Zone_Data_Store_Interface|WC_Data_Store|null |
| 25 |
*/ |
| 26 |
private $dataStore = null; |
| 27 |
|
| 28 |
/** |
| 29 |
* @var WcAdapter |
| 30 |
*/ |
| 31 |
private $wcAdapter; |
| 32 |
|
| 33 |
public function __construct( WcAdapter $wcAdapter ) { |
| 34 |
$this->wcAdapter = $wcAdapter; |
| 35 |
} |
| 36 |
|
| 37 |
/** |
| 38 |
* Lazy data store getter. |
| 39 |
*/ |
| 40 |
public function getDataStore(): WC_Shipping_Zone_Data_Store_Interface { |
| 41 |
if ( $this->dataStore === null ) { |
| 42 |
$this->dataStore = $this->wcAdapter->dataStoreLoad( 'shipping-zone' ); |
| 43 |
} |
| 44 |
|
| 45 |
return $this->dataStore; |
| 46 |
} |
| 47 |
|
| 48 |
/** |
| 49 |
* Gets all zones. |
| 50 |
* |
| 51 |
* @return WC_Shipping_Zone[] |
| 52 |
*/ |
| 53 |
private function getAllShippingZones(): array { |
| 54 |
$rawZones = $this->getDataStore()->get_zones(); |
| 55 |
$zones = []; |
| 56 |
foreach ( $rawZones as $rawZone ) { |
| 57 |
$zones[] = new WC_Shipping_Zone( $rawZone ); |
| 58 |
} |
| 59 |
// Add zone '0' manually. |
| 60 |
$zones[] = new WC_Shipping_Zone( 0 ); |
| 61 |
|
| 62 |
return $zones; |
| 63 |
} |
| 64 |
|
| 65 |
/** |
| 66 |
* Gets locations for shipping rate. |
| 67 |
* |
| 68 |
* @param string $methodRateId Method rate id. |
| 69 |
* |
| 70 |
* @return stdClass[]|null |
| 71 |
*/ |
| 72 |
private function getLocationsForShippingRate( string $methodRateId ): ?array { |
| 73 |
foreach ( $this->getAllShippingZones() as $zone ) { |
| 74 |
$enabledOnly = true; |
| 75 |
// Can't use get_shipping_methods because of infinite recursion. |
| 76 |
$rawMethods = $this->getDataStore()->get_methods( $zone->get_id(), $enabledOnly ); |
| 77 |
|
| 78 |
/** |
| 79 |
* Raw method. |
| 80 |
* |
| 81 |
* @var stdClass $rawMethod |
| 82 |
*/ |
| 83 |
foreach ( $rawMethods as $rawMethod ) { |
| 84 |
// phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps |
| 85 |
$rawMethodId = sprintf( '%s:%s', $rawMethod->method_id, $rawMethod->instance_id ); |
| 86 |
if ( $methodRateId === $rawMethodId ) { |
| 87 |
return $zone->get_zone_locations(); |
| 88 |
} |
| 89 |
} |
| 90 |
} |
| 91 |
|
| 92 |
return null; |
| 93 |
} |
| 94 |
|
| 95 |
/** |
| 96 |
* Gets country codes for shipping rate. |
| 97 |
* |
| 98 |
* @param string $rateId Rate id. |
| 99 |
* |
| 100 |
* @return string[] |
| 101 |
*/ |
| 102 |
public function getCountryCodesForShippingRate( string $rateId ): array { |
| 103 |
return $this->getCountryCodesFromZoneLocations( $this->getLocationsForShippingRate( $rateId ) ); |
| 104 |
} |
| 105 |
|
| 106 |
private function getCountryCodesFromZoneLocations( ?array $zoneLocations ): array { |
| 107 |
if ( $zoneLocations === null ) { |
| 108 |
return []; |
| 109 |
} |
| 110 |
|
| 111 |
$countries = []; |
| 112 |
$continents = $this->wcAdapter->countriesGetContinents(); |
| 113 |
|
| 114 |
/** |
| 115 |
* @var stdClass $zoneLocation |
| 116 |
*/ |
| 117 |
foreach ( $zoneLocations as $zoneLocation ) { |
| 118 |
if ( $zoneLocation->type === 'country' ) { |
| 119 |
$countries[] = strtolower( $zoneLocation->code ); |
| 120 |
} |
| 121 |
|
| 122 |
if ( $zoneLocation->type === 'continent' && isset( $continents[ $zoneLocation->code ]['countries'] ) ) { |
| 123 |
foreach ( $continents[ $zoneLocation->code ]['countries'] as $countryCode ) { |
| 124 |
$countries[] = strtolower( $countryCode ); |
| 125 |
} |
| 126 |
} |
| 127 |
} |
| 128 |
|
| 129 |
return $countries; |
| 130 |
} |
| 131 |
|
| 132 |
public function getCountryCodesForShippingZone( int $zoneId ): array { |
| 133 |
$zone = new WC_Shipping_Zone( $zoneId ); |
| 134 |
|
| 135 |
return $this->getCountryCodesFromZoneLocations( $zone->get_zone_locations() ); |
| 136 |
} |
| 137 |
} |
| 138 |
|