PluginProbe
Packeta / trunk
Packeta vtrunk
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 trunk, at src/Packetery/Module/Carrier/Updater.php

336 lines 9.1 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 $updatedRowCount = $this->carrierRepository->insert( $carrier );
172 if ( $updatedRowCount === false ) {
173 // translators: %s is a carrier name.
174 $message = sprintf( (string) $this->wpAdapter->__( 'An error occurred while saving carrier "%s". More details in WC log.', 'packeta' ), $carrier['name'] );
175
176 $this->logMessages[] = $message;
177
178 $record = new Record();
179 $record->action = Record::ACTION_CARRIER_LIST_UPDATE;
180 $record->status = Record::STATUS_ERROR;
181 $record->title = $message;
182 $record->params = [];
183 $this->logger->add( $record );
184 } else {
185 $this->addLogEntry(
186 // translators: %s is a carrier name.
187 sprintf( (string) $this->wpAdapter->__( 'A new carrier "%s" has been added.', 'packeta' ), $carrier['name'] )
188 );
189 }
190 }
191 }
192
193 if ( count( $carriersInDb ) > 0 ) {
194 $this->carrierRepository->set_as_deleted( array_keys( $carriersInDb ) );
195 foreach ( $carriersInDb as $deletedCarrier ) {
196 if ( (bool) $deletedCarrier['deleted'] === true ) {
197 continue;
198 }
199 $this->addLogEntry(
200 // translators: %s is carrier name.
201 sprintf( __( 'Carrier "%s" has been removed.', 'packeta' ), $deletedCarrier['name'] )
202 );
203 }
204 }
205
206 if ( count( $this->logMessages ) > 0 ) {
207 set_transient( Transients::CARRIER_CHANGES, true );
208 } else {
209 delete_transient( Transients::CARRIER_CHANGES );
210 }
211 }
212
213 /**
214 * Gets array changes as array of strings.
215 *
216 * @param array<string, bool|float|string> $oldData Previous version.
217 * @param array<string, bool|float|string> $newData New version.
218 *
219 * @return array<string, string>
220 */
221 private function getArrayDifferences( array $oldData, array $newData ): array {
222 $differences = [];
223 $columnSettings = $this->getColumnSettings();
224
225 foreach ( $oldData as $key => $oldValue ) {
226 if ( $key === 'id' ) {
227 continue;
228 }
229
230 if ( $key === 'deleted' ) {
231 if ( (string) $oldValue === '1' && isset( $newData['name'] ) ) {
232 $differences[ $key ] = __( 'carrier was re-enabled', 'packeta' );
233 }
234
235 continue;
236 }
237
238 $newValue = (string) $newData[ $key ];
239 if ( $columnSettings[ $key ]['isBoolean'] === true ) {
240 $newValue = ( $newValue === '1' ? $newValue : '0' );
241 $oldValue = ( (string) $oldValue === '1' ? (string) $oldValue : '0' );
242 }
243 if ( (string) $oldValue === $newValue ) {
244 continue;
245 }
246 if ( $columnSettings[ $key ]['isBoolean'] === true ) {
247 $newValue = ( $newValue === '1' ? __( 'yes', 'packeta' ) : __( 'no', 'packeta' ) );
248 $oldValue = ( $oldValue === '1' ? __( 'yes', 'packeta' ) : __( 'no', 'packeta' ) );
249 }
250 $differences[ $key ] = $columnSettings[ $key ]['label'] . ': ' . $oldValue . ' => ' . $newValue;
251 }
252
253 return $differences;
254 }
255
256 /**
257 * Adds log entry.
258 *
259 * @param string $message Message.
260 *
261 * @return void
262 */
263 private function addLogEntry( string $message ): void {
264 $this->logMessages[] = $message;
265
266 $record = new Record();
267 $record->action = Record::ACTION_CARRIER_LIST_UPDATE;
268 $record->status = Record::STATUS_SUCCESS;
269 $record->title = $message;
270 $record->params = [];
271 $this->logger->add( $record );
272 }
273
274 /**
275 * Gets translations and isBoolean properties for column names.
276 *
277 * @return array<string, array<string, string|bool>>
278 */
279 private function getColumnSettings(): array {
280 return [
281 'name' => [
282 'label' => __( 'name', 'packeta' ),
283 'isBoolean' => false,
284 ],
285 'is_pickup_points' => [
286 'label' => __( 'offers own pickup points', 'packeta' ),
287 'isBoolean' => true,
288 ],
289 'has_carrier_direct_label' => [
290 'label' => __( 'supports direct labels', 'packeta' ),
291 'isBoolean' => true,
292 ],
293 'separate_house_number' => [
294 'label' => __( 'requires separate house number', 'packeta' ),
295 'isBoolean' => true,
296 ],
297 'customs_declarations' => [
298 'label' => __( 'requires completion of customs declarations', 'packeta' ),
299 'isBoolean' => true,
300 ],
301 'requires_email' => [
302 'label' => __( 'requires email', 'packeta' ),
303 'isBoolean' => true,
304 ],
305 'requires_phone' => [
306 'label' => __( 'requires phone number', 'packeta' ),
307 'isBoolean' => true,
308 ],
309 'requires_size' => [
310 'label' => __( 'requires package size', 'packeta' ),
311 'isBoolean' => true,
312 ],
313 'disallows_cod' => [
314 'label' => __( 'disallows COD', 'packeta' ),
315 'isBoolean' => true,
316 ],
317 'country' => [
318 'label' => __( 'country', 'packeta' ),
319 'isBoolean' => false,
320 ],
321 'currency' => [
322 'label' => __( 'currency', 'packeta' ),
323 'isBoolean' => false,
324 ],
325 'max_weight' => [
326 'label' => __( 'maximum weight (kg)', 'packeta' ),
327 'isBoolean' => false,
328 ],
329 'available' => [
330 'label' => __( 'available', 'packeta' ),
331 'isBoolean' => true,
332 ],
333 ];
334 }
335 }
336