PluginProbe
Packeta / 2.1
Packeta v2.1
2.3.2 2.3.1 trunk 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3.0 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 All 56 releases
packeta / src / Packetery / Module / Carrier / Updater.php

Updater.php in Packeta 2.1, at src/Packetery/Module/Carrier/Updater.php

322 lines 8.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Packeta carrier updater
4 *
5 * @package Packetery
6 */
7
8 declare( strict_types=1 );
9
10 namespace Packetery\Module\Carrier;
11
12 use Packetery\Core\Log\ILogger;
13 use Packetery\Core\Log\Record;
14 use Packetery\Module\Framework\WpAdapter;
15 use Packetery\Module\Transients;
16
17 /**
18 * Class CarrierUpdater.
19 *
20 * @package Packetery
21 */
22 class Updater {
23
24 /**
25 * Log messages.
26 *
27 * @var string[]
28 */
29 private $logMessages = [];
30
31 /**
32 * Carrier repository.
33 *
34 * @var Repository
35 */
36 private $carrierRepository;
37
38 /**
39 * Logger.
40 *
41 * @var ILogger
42 */
43 private $logger;
44
45 /**
46 * @var CarrierOptionsFactory
47 */
48 private $carrierOptionsFactory;
49
50 /**
51 * @var WpAdapter
52 */
53 private $wpAdapter;
54
55 public function __construct(
56 Repository $carrierRepository,
57 ILogger $logger,
58 CarrierOptionsFactory $carrierOptionsFactory,
59 WpAdapter $wpAdapter
60 ) {
61 $this->carrierRepository = $carrierRepository;
62 $this->logger = $logger;
63 $this->carrierOptionsFactory = $carrierOptionsFactory;
64 $this->wpAdapter = $wpAdapter;
65 }
66
67 /**
68 * Validates data from API.
69 *
70 * @param non-empty-array<int, array<string, string>> $carriers
71 *
72 * @return bool
73 */
74 public function validate_carrier_data( array $carriers ): bool {
75 foreach ( $carriers as $carrier ) {
76 if ( ! isset(
77 $carrier['id'],
78 $carrier['name'],
79 $carrier['country'],
80 $carrier['currency'],
81 $carrier['pickupPoints'],
82 $carrier['apiAllowed'],
83 $carrier['separateHouseNumber'],
84 $carrier['customsDeclarations'],
85 $carrier['requiresEmail'],
86 $carrier['requiresPhone'],
87 $carrier['requiresSize'],
88 $carrier['disallowsCod'],
89 $carrier['maxWeight']
90 ) ) {
91 return false;
92 }
93 }
94
95 return true;
96 }
97
98 /**
99 * Maps input data to storage structure.
100 *
101 * @param array<int, array<string, string>> $carriers $carriers Validated data retrieved from API.
102 *
103 * @return array<int, array<string, string|float|bool>> data to store in db
104 */
105 private function carriers_mapper( array $carriers ): array {
106 $mappedData = array();
107
108 $carrierBooleanParams = array(
109 'is_pickup_points' => 'pickupPoints',
110 'has_carrier_direct_label' => 'apiAllowed',
111 'separate_house_number' => 'separateHouseNumber',
112 'customs_declarations' => 'customsDeclarations',
113 'requires_email' => 'requiresEmail',
114 'requires_phone' => 'requiresPhone',
115 'requires_size' => 'requiresSize',
116 'disallows_cod' => 'disallowsCod',
117 'available' => 'available',
118 );
119
120 foreach ( $carriers as $carrier ) {
121 $carrierId = (int) $carrier['id'];
122 $carrierData = array(
123 'name' => $carrier['name'],
124 'country' => $carrier['country'],
125 'currency' => $carrier['currency'],
126 'max_weight' => (float) $carrier['maxWeight'],
127 'deleted' => false,
128 );
129 foreach ( $carrierBooleanParams as $columnName => $paramName ) {
130 $carrierData[ $columnName ] = ( $carrier[ $paramName ] === 'true' );
131 }
132 $mappedData[ $carrierId ] = $carrierData;
133 }
134
135 return $mappedData;
136 }
137
138 /**
139 * Saves carriers.
140 *
141 * @param array<int, array<string, string>> $carriers Validated data retrieved from API.
142 */
143 public function save( array $carriers ): void {
144 $mappedData = $this->carriers_mapper( $carriers );
145 $carriersInDb = $this->carrierRepository->getAllRawIndexed();
146 foreach ( $mappedData as $carrierId => $carrier ) {
147 if ( isset( $carriersInDb[ $carrierId ] ) ) {
148 $this->carrierRepository->update( $carrier, $carrierId );
149 $differences = $this->getArrayDifferences( $carriersInDb[ $carrierId ], $carrier );
150 if ( isset( $differences['available'] ) ) {
151 $carrierOptions = $this->carrierOptionsFactory->createByCarrierId( (string) $carrierId );
152 if ( $carrierOptions->isActive() ) {
153 $this->wpAdapter->updateOption(
154 $carrierOptions->getOptionId(),
155 array_merge( $carrierOptions->toArray(), [ 'active' => false ] )
156 );
157 }
158 }
159
160 if ( count( $differences ) > 0 ) {
161 $this->addLogEntry(
162 // translators: %s is carrier name.
163 sprintf( __( 'Carrier parameters changed for carrier "%s".', 'packeta' ), $carrier['name'] ) . ' ' .
164
165 __( 'New parameters', 'packeta' ) . ': ' . implode( ', ', $differences )
166 );
167 }
168 unset( $carriersInDb[ $carrierId ] );
169 } else {
170 $carrier['id'] = $carrierId;
171 $this->carrierRepository->insert( $carrier );
172 $this->addLogEntry(
173 // translators: %s is carrier name.
174 sprintf( __( 'A new carrier "%s" has been added.', 'packeta' ), $carrier['name'] )
175 );
176 }
177 }
178
179 if ( count( $carriersInDb ) > 0 ) {
180 $this->carrierRepository->set_as_deleted( array_keys( $carriersInDb ) );
181 foreach ( $carriersInDb as $deletedCarrier ) {
182 if ( (bool) $deletedCarrier['deleted'] === true ) {
183 continue;
184 }
185 $this->addLogEntry(
186 // translators: %s is carrier name.
187 sprintf( __( 'Carrier "%s" has been removed.', 'packeta' ), $deletedCarrier['name'] )
188 );
189 }
190 }
191
192 if ( count( $this->logMessages ) > 0 ) {
193 set_transient( Transients::CARRIER_CHANGES, true );
194 } else {
195 delete_transient( Transients::CARRIER_CHANGES );
196 }
197 }
198
199 /**
200 * Gets array changes as array of strings.
201 *
202 * @param array<string, bool|float|string> $oldData Previous version.
203 * @param array<string, bool|float|string> $newData New version.
204 *
205 * @return array<string, string>
206 */
207 private function getArrayDifferences( array $oldData, array $newData ): array {
208 $differences = [];
209 $columnSettings = $this->getColumnSettings();
210
211 foreach ( $oldData as $key => $oldValue ) {
212 if ( $key === 'id' ) {
213 continue;
214 }
215
216 if ( $key === 'deleted' ) {
217 if ( (string) $oldValue === '1' && isset( $newData['name'] ) ) {
218 $differences[ $key ] = __( 'carrier was re-enabled', 'packeta' );
219 }
220
221 continue;
222 }
223
224 $newValue = (string) $newData[ $key ];
225 if ( $columnSettings[ $key ]['isBoolean'] === true ) {
226 $newValue = ( $newValue === '1' ? $newValue : '0' );
227 $oldValue = ( (string) $oldValue === '1' ? (string) $oldValue : '0' );
228 }
229 if ( (string) $oldValue === $newValue ) {
230 continue;
231 }
232 if ( $columnSettings[ $key ]['isBoolean'] === true ) {
233 $newValue = ( $newValue === '1' ? __( 'yes', 'packeta' ) : __( 'no', 'packeta' ) );
234 $oldValue = ( $oldValue === '1' ? __( 'yes', 'packeta' ) : __( 'no', 'packeta' ) );
235 }
236 $differences[ $key ] = $columnSettings[ $key ]['label'] . ': ' . $oldValue . ' => ' . $newValue;
237 }
238
239 return $differences;
240 }
241
242 /**
243 * Adds log entry.
244 *
245 * @param string $message Message.
246 *
247 * @return void
248 */
249 private function addLogEntry( string $message ): void {
250 $this->logMessages[] = $message;
251
252 $record = new Record();
253 $record->action = Record::ACTION_CARRIER_LIST_UPDATE;
254 $record->status = Record::STATUS_SUCCESS;
255 $record->title = $message;
256 $record->params = [];
257 $this->logger->add( $record );
258 }
259
260 /**
261 * Gets translations and isBoolean properties for column names.
262 *
263 * @return array<string, array<string, string|bool>>
264 */
265 private function getColumnSettings(): array {
266 return [
267 'name' => [
268 'label' => __( 'name', 'packeta' ),
269 'isBoolean' => false,
270 ],
271 'is_pickup_points' => [
272 'label' => __( 'offers own pickup points', 'packeta' ),
273 'isBoolean' => true,
274 ],
275 'has_carrier_direct_label' => [
276 'label' => __( 'supports direct labels', 'packeta' ),
277 'isBoolean' => true,
278 ],
279 'separate_house_number' => [
280 'label' => __( 'requires separate house number', 'packeta' ),
281 'isBoolean' => true,
282 ],
283 'customs_declarations' => [
284 'label' => __( 'requires completion of customs declarations', 'packeta' ),
285 'isBoolean' => true,
286 ],
287 'requires_email' => [
288 'label' => __( 'requires email', 'packeta' ),
289 'isBoolean' => true,
290 ],
291 'requires_phone' => [
292 'label' => __( 'requires phone number', 'packeta' ),
293 'isBoolean' => true,
294 ],
295 'requires_size' => [
296 'label' => __( 'requires package size', 'packeta' ),
297 'isBoolean' => true,
298 ],
299 'disallows_cod' => [
300 'label' => __( 'disallows COD', 'packeta' ),
301 'isBoolean' => true,
302 ],
303 'country' => [
304 'label' => __( 'country', 'packeta' ),
305 'isBoolean' => false,
306 ],
307 'currency' => [
308 'label' => __( 'currency', 'packeta' ),
309 'isBoolean' => false,
310 ],
311 'max_weight' => [
312 'label' => __( 'maximum weight (kg)', 'packeta' ),
313 'isBoolean' => false,
314 ],
315 'available' => [
316 'label' => __( 'available', 'packeta' ),
317 'isBoolean' => true,
318 ],
319 ];
320 }
321 }
322