PluginProbe
Packeta / 1.6.4
Packeta v1.6.4
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 1.6.4, at src/Packetery/Module/Upgrade.php

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