PluginProbe
Packeta / 2.0.9
Packeta v2.0.9
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 / Upgrade.php

Upgrade.php in Packeta 2.0.9, at src/Packetery/Module/Upgrade.php

477 lines 14.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class Upgrade.
4 *
5 * @package Packetery\Module
6 */
7
8 declare( strict_types=1 );
9
10 namespace Packetery\Module;
11
12 use Packetery\Core;
13 use Packetery\Core\Log\ILogger;
14 use Packetery\Core\Log\Record;
15 use Packetery\Module\Carrier\EntityRepository;
16 use Packetery\Module\Options\OptionsProvider;
17 use Packetery\Module\Upgrade\Version_1_4_2;
18
19 /**
20 * Class Upgrade.
21 */
22 class Upgrade {
23
24 const POST_TYPE_VALIDATED_ADDRESS = 'packetery_address';
25
26 const META_LENGTH = 'packetery_length';
27 const META_WIDTH = 'packetery_width';
28 const META_HEIGHT = 'packetery_height';
29 const META_PACKET_STATUS = 'packetery_packet_status';
30 const META_WEIGHT = 'packetery_weight';
31 const META_CARRIER_ID = 'packetery_carrier_id';
32 const META_IS_EXPORTED = 'packetery_is_exported';
33 const META_IS_LABEL_PRINTED = 'packetery_is_label_printed';
34 const META_CARRIER_NUMBER = 'packetery_carrier_number';
35 const META_PACKET_ID = 'packetery_packet_id';
36 const META_POINT_ID = 'packetery_point_id';
37 const META_POINT_NAME = 'packetery_point_name';
38 const META_POINT_CITY = 'packetery_point_city';
39 const META_POINT_ZIP = 'packetery_point_zip';
40 const META_POINT_STREET = 'packetery_point_street';
41 const META_POINT_URL = 'packetery_point_url';
42
43 /**
44 * Order repository.
45 *
46 * @var Order\Repository
47 */
48 private $orderRepository;
49
50 /**
51 * Message manager.
52 *
53 * @var MessageManager
54 */
55 private $messageManager;
56
57 /**
58 * Logger.
59 *
60 * @var ILogger
61 */
62 private $logger;
63
64 /**
65 * Log repository.
66 *
67 * @var Log\Repository
68 */
69 private $logRepository;
70
71 /**
72 * Carrier repository.
73 *
74 * @var Carrier\Repository
75 */
76 private $carrierRepository;
77
78 /**
79 * Customs declaration repository.
80 *
81 * @var CustomsDeclaration\Repository
82 */
83 private $customsDeclarationRepository;
84
85 /**
86 * WpdbAdapter.
87 *
88 * @var WpdbAdapter
89 */
90 private $wpdbAdapter;
91
92 /**
93 * Options provider.
94 *
95 * @var OptionsProvider
96 */
97 private $optionsProvider;
98
99 /**
100 * @var EntityRepository
101 */
102 private $carrierEntityRepository;
103
104 public function __construct(
105 Order\Repository $orderRepository,
106 MessageManager $messageManager,
107 ILogger $logger,
108 Log\Repository $logRepository,
109 WpdbAdapter $wpdbAdapter,
110 Carrier\Repository $carrierRepository,
111 CustomsDeclaration\Repository $customsDeclarationRepository,
112 OptionsProvider $optionsProvider,
113 EntityRepository $carrierEntityRepository
114 ) {
115 $this->orderRepository = $orderRepository;
116 $this->messageManager = $messageManager;
117 $this->logger = $logger;
118 $this->logRepository = $logRepository;
119 $this->wpdbAdapter = $wpdbAdapter;
120 $this->carrierRepository = $carrierRepository;
121 $this->customsDeclarationRepository = $customsDeclarationRepository;
122 $this->optionsProvider = $optionsProvider;
123 $this->carrierEntityRepository = $carrierEntityRepository;
124 }
125
126 /**
127 * Checks previous plugin version and runs upgrade if needed.
128 * https://www.sitepoint.com/wordpress-plugin-updates-right-way/
129 *
130 * @return void
131 */
132 public function check(): void {
133 $oldVersion = get_option( 'packetery_version' );
134 if ( $oldVersion === Plugin::VERSION ) {
135 return;
136 }
137
138 $this->createLogTable();
139 $this->createCarrierTable();
140 $this->createOrderTable();
141 $this->createCustomsDeclarationTables();
142
143 // If no previous version detected, no upgrade will be run.
144 if ( $oldVersion !== null && $oldVersion !== false ) {
145 if ( version_compare( $oldVersion, '1.2.0', '<' ) ) {
146 $logEntries = get_posts(
147 [
148 'post_type' => 'packetery_log',
149 'post_status' => 'any',
150 'nopaging' => true,
151 'fields' => 'ids',
152 ]
153 );
154 foreach ( $logEntries as $logEntryId ) {
155 wp_delete_post( $logEntryId, true );
156 }
157
158 unregister_post_type( 'packetery_log' );
159
160 $this->migrateWpOrderMetadata();
161 $addressEntries = get_posts(
162 [
163 'post_type' => self::POST_TYPE_VALIDATED_ADDRESS,
164 'post_status' => 'any',
165 'nopaging' => true,
166 'fields' => 'ids',
167 ]
168 );
169 foreach ( $addressEntries as $addressEntryId ) {
170 wp_delete_post( $addressEntryId, true );
171 }
172
173 unregister_post_type( self::POST_TYPE_VALIDATED_ADDRESS );
174 }
175
176 if ( version_compare( $oldVersion, '1.2.6', '<' ) ) {
177 $this->orderRepository->deleteOrphans();
178 }
179
180 if ( version_compare( $oldVersion, '1.4.2', '<' ) ) {
181 $migration = new Version_1_4_2( $this->wpdbAdapter );
182 $migration->run();
183 }
184
185 if ( version_compare( $oldVersion, '1.5', '<' ) ) {
186 wp_clear_scheduled_hook( CronService::CRON_CARRIERS_HOOK );
187 }
188
189 if ( version_compare( $oldVersion, '1.6.0', '<' ) ) {
190 wp_clear_scheduled_hook( CronService::CRON_LOG_AUTO_DELETION_HOOK );
191 wp_clear_scheduled_hook( CronService::CRON_PACKET_STATUS_SYNC_HOOK );
192 }
193
194 if ( version_compare( $oldVersion, '1.7.0', '<' ) ) {
195 $orderStatusAutoChange = $this->optionsProvider->isOrderStatusAutoChangeEnabled();
196 $autoOrderStatus = $this->optionsProvider->getAutoOrderStatus();
197 $syncSettings = $this->optionsProvider->getOptionsByName( OptionsProvider::OPTION_NAME_PACKETERY_SYNC );
198 if ( $orderStatusAutoChange ) {
199 $syncSettings['allow_order_status_change'] = true;
200 }
201 if ( $autoOrderStatus !== null ) {
202 $syncSettings['order_status_change_packet_statuses'] = [
203 Core\Entity\PacketStatus::RECEIVED_DATA => $autoOrderStatus,
204 ];
205 }
206
207 update_option( OptionsProvider::OPTION_NAME_PACKETERY_SYNC, $syncSettings );
208 }
209
210 if ( version_compare( $oldVersion, '1.7.1', '<' ) ) {
211 $syncSettings = $this->optionsProvider->getOptionsByName( OptionsProvider::OPTION_NAME_PACKETERY_SYNC );
212 if (
213 isset( $syncSettings['order_status_change_packet_statuses'][ Core\Entity\PacketStatus::RECEIVED_DATA ] ) &&
214 $syncSettings['order_status_change_packet_statuses'][ Core\Entity\PacketStatus::RECEIVED_DATA ] === ''
215 ) {
216 unset( $syncSettings['order_status_change_packet_statuses'][ Core\Entity\PacketStatus::RECEIVED_DATA ] );
217 update_option( OptionsProvider::OPTION_NAME_PACKETERY_SYNC, $syncSettings );
218 }
219 }
220
221 if ( version_compare( $oldVersion, '1.8.0', '<' ) ) {
222 $generalSettings = $this->optionsProvider->getOptionsByName( OptionsProvider::OPTION_NAME_PACKETERY );
223 if ( isset( $generalSettings['cod_payment_method'] ) ) {
224 $generalSettings['cod_payment_methods'] = [ $generalSettings['cod_payment_method'] ];
225 unset( $generalSettings['cod_payment_method'] );
226 }
227
228 update_option( OptionsProvider::OPTION_NAME_PACKETERY, $generalSettings );
229 }
230 }
231
232 update_option( 'packetery_version', Plugin::VERSION );
233 }
234
235 /**
236 * Migrates WP order metadata.
237 *
238 * @return void
239 */
240 private function migrateWpOrderMetadata(): void {
241 $this->createOrderTable();
242
243 // Did not work when called from plugins_loaded hook.
244 $orders = wc_get_orders(
245 [
246 'nopaging' => true,
247 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
248 'meta_query' => [
249 [
250 'key' => self::META_CARRIER_ID,
251 'compare' => 'EXISTS',
252 ],
253 [
254 'key' => self::META_CARRIER_ID,
255 'compare' => '!=',
256 'value' => '',
257 ],
258 ],
259 ]
260 );
261
262 foreach ( $orders as $order ) {
263 $orderEntity = new Core\Entity\Order(
264 (string) $order->get_id(),
265 $this->carrierEntityRepository->getAnyById( $this->getMetaAsNullableString( $order, self::META_CARRIER_ID ) )
266 );
267 $order->delete_meta_data( self::META_CARRIER_ID );
268
269 $orderEntity->setWeight( $this->getMetaAsNullableFloat( $order, self::META_WEIGHT ) );
270 $order->delete_meta_data( self::META_WEIGHT );
271
272 $orderEntity->setPacketStatus( $this->getMetaAsNullableString( $order, self::META_PACKET_STATUS ) );
273 $order->delete_meta_data( self::META_PACKET_STATUS );
274
275 $orderEntity->setIsExported( (bool) $this->getMetaAsNullableString( $order, self::META_IS_EXPORTED ) );
276 $order->delete_meta_data( self::META_IS_EXPORTED );
277
278 $orderEntity->setIsLabelPrinted( (bool) $this->getMetaAsNullableString( $order, self::META_IS_LABEL_PRINTED ) );
279 $order->delete_meta_data( self::META_IS_LABEL_PRINTED );
280
281 $orderEntity->setCarrierNumber( $this->getMetaAsNullableString( $order, self::META_CARRIER_NUMBER ) );
282 $order->delete_meta_data( self::META_CARRIER_NUMBER );
283
284 $orderEntity->setPacketId( $this->getMetaAsNullableString( $order, self::META_PACKET_ID ) );
285 $order->delete_meta_data( self::META_PACKET_ID );
286
287 $orderEntity->setSize(
288 new Core\Entity\Size(
289 $this->getMetaAsNullableFloat( $order, self::META_LENGTH ),
290 $this->getMetaAsNullableFloat( $order, self::META_WIDTH ),
291 $this->getMetaAsNullableFloat( $order, self::META_HEIGHT )
292 )
293 );
294 $order->delete_meta_data( self::META_LENGTH );
295 $order->delete_meta_data( self::META_WIDTH );
296 $order->delete_meta_data( self::META_HEIGHT );
297
298 if ( $this->getMetaAsNullableString( $order, self::META_POINT_ID ) !== null ) {
299 $orderEntity->setPickupPoint(
300 new Core\Entity\PickupPoint(
301 $this->getMetaAsNullableString( $order, self::META_POINT_ID ),
302 $this->getMetaAsNullableString( $order, self::META_POINT_NAME ),
303 $this->getMetaAsNullableString( $order, self::META_POINT_CITY ),
304 $this->getMetaAsNullableString( $order, self::META_POINT_ZIP ),
305 $this->getMetaAsNullableString( $order, self::META_POINT_STREET ),
306 $this->getMetaAsNullableString( $order, self::META_POINT_URL )
307 )
308 );
309 }
310 $order->delete_meta_data( self::META_POINT_ID );
311 $order->delete_meta_data( self::META_POINT_NAME );
312 $order->delete_meta_data( self::META_POINT_CITY );
313 $order->delete_meta_data( self::META_POINT_ZIP );
314 $order->delete_meta_data( self::META_POINT_STREET );
315 $order->delete_meta_data( self::META_POINT_URL );
316
317 $validatedAddressId = $this->getValidatedAddressIdByOrderId( (int) $order->get_id() );
318 if ( $validatedAddressId !== null ) {
319 $validatedAddress = $this->createAddressFromPostId( $validatedAddressId );
320 $orderEntity->setAddressValidated( true );
321 $orderEntity->setDeliveryAddress( $validatedAddress );
322 }
323
324 $this->orderRepository->save( $orderEntity );
325 $order->save_meta_data();
326 }
327 }
328
329 /**
330 * Creates active widget address using woocommerce order id.
331 *
332 * @param int $addressId Address ID.
333 *
334 * @return Core\Entity\Address|null
335 */
336 public function createAddressFromPostId( int $addressId ): ?Core\Entity\Address {
337 $address = new Core\Entity\Address(
338 get_post_meta( $addressId, 'street', true ),
339 get_post_meta( $addressId, 'city', true ),
340 get_post_meta( $addressId, 'postCode', true )
341 );
342 $address->setHouseNumber( get_post_meta( $addressId, 'houseNumber', true ) );
343 $address->setCounty( get_post_meta( $addressId, 'county', true ) );
344 $address->setLongitude( get_post_meta( $addressId, 'longitude', true ) );
345 $address->setLatitude( get_post_meta( $addressId, 'latitude', true ) );
346
347 return $address;
348 }
349
350 /**
351 * Gets active address.
352 *
353 * @param int $orderId Order ID.
354 *
355 * @return int|null
356 */
357 public function getValidatedAddressIdByOrderId( int $orderId ): ?int {
358 $postIds = get_posts(
359 [
360 'post_type' => self::POST_TYPE_VALIDATED_ADDRESS,
361 'post_status' => 'any',
362 'nopaging' => true,
363 'numberposts' => 1,
364 'fields' => 'ids',
365 'post_parent' => $orderId,
366 ]
367 );
368
369 if ( count( $postIds ) === 0 ) {
370 return null;
371 }
372
373 return (int) array_shift( $postIds );
374 }
375
376 /**
377 * Gets meta property of order as string.
378 *
379 * @param \WC_Order $order Order.
380 * @param string $key Meta order key.
381 *
382 * @return string|null
383 */
384 private function getMetaAsNullableString( \WC_Order $order, string $key ): ?string {
385 $value = $order->get_meta( $key, true );
386
387 return ( ( $value !== null && $value !== '' ) ? (string) $value : null );
388 }
389
390 /**
391 * Gets meta property of order as float.
392 *
393 * @param \WC_Order $order Order.
394 * @param string $key Meta order key.
395 *
396 * @return float|null
397 */
398 private function getMetaAsNullableFloat( \WC_Order $order, string $key ): ?float {
399 $value = $order->get_meta( $key, true );
400
401 return ( ( $value !== null && $value !== '' ) ? (float) $value : null );
402 }
403
404 /**
405 * Creates log table.
406 *
407 * @return void
408 */
409 private function createLogTable(): void {
410 if ( $this->logRepository->createOrAlterTable() === false ) {
411 $this->messageManager->flash_message(
412 // translators: %s: Short table name.
413 sprintf( __( 'Database %s table could not be created or altered, more information might be found in WooCommerce logs.', 'packeta' ), 'log' ),
414 MessageManager::TYPE_ERROR
415 );
416 }
417 }
418
419 /**
420 * Creates carrier table.
421 *
422 * @return void
423 */
424 private function createCarrierTable(): void {
425 if ( $this->carrierRepository->createOrAlterTable() === false ) {
426 $this->flashAndLog( 'carrier', Record::ACTION_CARRIER_TABLE_NOT_CREATED );
427 }
428 }
429
430 /**
431 * Creates order table.
432 *
433 * @return void
434 */
435 private function createOrderTable(): void {
436 if ( $this->orderRepository->createOrAlterTable() === false ) {
437 $this->flashAndLog( 'order', Record::ACTION_ORDER_TABLE_NOT_CREATED );
438 }
439 }
440
441 /**
442 * Creates order table.
443 *
444 * @return void
445 */
446 private function createCustomsDeclarationTables(): void {
447 if ( $this->customsDeclarationRepository->createOrAlterTable() === false ) {
448 $this->flashAndLog( 'customs_declaration', Record::ACTION_CUSTOMS_DECLARATION_TABLE_NOT_CREATED );
449 }
450
451 if ( $this->customsDeclarationRepository->createOrAlterItemTable() === false ) {
452 $this->flashAndLog( 'customs_declaration_item', Record::ACTION_CUSTOMS_DECLARATION_ITEM_TABLE_NOT_CREATED );
453 }
454 }
455
456 /**
457 * Flashes error and logs to Packeta log.
458 *
459 * @param string $table Short table name.
460 * @param string $action Log action.
461 *
462 * @return void
463 */
464 private function flashAndLog( string $table, string $action ): void {
465 // translators: %s: Short table name.
466 $flashMessage = sprintf( __( 'Database %s table of Packeta plugin could not be created or altered, you can find more information in Packeta log.', 'packeta' ), $table );
467 $this->messageManager->flash_message( $flashMessage, MessageManager::TYPE_ERROR );
468
469 $record = new Record();
470 $record->action = $action;
471 $record->status = Record::STATUS_ERROR;
472 // translators: %s: Short table name.
473 $record->title = sprintf( __( 'Database %s table could not be created or altered, more information might be found in WooCommerce logs.', 'packeta' ), $table );
474 $this->logger->add( $record );
475 }
476 }
477