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
← All changes | src/Packetery/Module/Order/Repository.php +376 -251 1.5.42.1 View file →
@@ -8,16 +8,20 @@
8 8 declare( strict_types=1 );
9 9
10 10 namespace Packetery\Module\Order;
11 11
12 -use Packetery\Core\Helper;
12 +use DateTimeImmutable;
13 +use Exception;
14 +use Packetery\Core\CoreHelper;
15 +use Packetery\Core\Entity;
13 16 use Packetery\Core\Entity\Order;
14 17 use Packetery\Core\Entity\PickupPoint;
15 -use Packetery\Core\Entity\Size;
16 -use Packetery\Core\Entity\Address;
17 18 use Packetery\Module\Carrier;
18 19 use Packetery\Module\Carrier\PacketaPickupPointsConfig;
19 -use Packetery\Module\ShippingMethod;
20 +use Packetery\Module\CustomsDeclaration;
21 +use Packetery\Module\Exception\InvalidCarrierException;
22 +use Packetery\Module\ModuleHelper;
23 +use Packetery\Module\Shipping\ShippingProvider;
20 24 use Packetery\Module\WpdbAdapter;
21 25 use WC_Order;
22 26 use WP_Post;
23 27
@@ -42,13 +46,13 @@
42 46 */
43 47 private $builder;
44 48
45 49 /**
46 - * Helper.
50 + * CoreHelper.
47 51 *
48 - * @var Helper
52 + * @var CoreHelper
49 53 */
50 - private $helper;
54 + private $coreHelper;
51 55
52 56 /**
53 57 * Internal pickup points config.
54 58 *
@@ -56,37 +60,57 @@
56 60 */
57 61 private $pickupPointsConfig;
58 62
59 63 /**
64 + * Carrier repository.
65 + *
66 + * @var Carrier\EntityRepository
67 + */
68 + private $carrierRepository;
69 +
70 + /**
71 + * Customs declaration repository.
72 + *
73 + * @var CustomsDeclaration\Repository
74 + */
75 + private $customsDeclarationRepository;
76 +
77 + /**
60 78 * Repository constructor.
61 79 *
62 - * @param WpdbAdapter $wpdbAdapter WpdbAdapter.
63 - * @param Builder $orderFactory Order factory.
64 - * @param Helper $helper Helper.
65 - * @param PacketaPickupPointsConfig $pickupPointsConfig Internal pickup points config.
80 + * @param WpdbAdapter $wpdbAdapter WpdbAdapter.
81 + * @param Builder $orderFactory Order factory.
82 + * @param CoreHelper $coreHelper CoreHelper.
83 + * @param PacketaPickupPointsConfig $pickupPointsConfig Internal pickup points config.
84 + * @param Carrier\EntityRepository $carrierRepository Carrier repository.
85 + * @param CustomsDeclaration\Repository $customsDeclarationRepository Customs declaration repository.
66 86 */
67 87 public function __construct(
68 88 WpdbAdapter $wpdbAdapter,
69 89 Builder $orderFactory,
70 - Helper $helper,
71 - PacketaPickupPointsConfig $pickupPointsConfig
90 + CoreHelper $coreHelper,
91 + PacketaPickupPointsConfig $pickupPointsConfig,
92 + Carrier\EntityRepository $carrierRepository,
93 + CustomsDeclaration\Repository $customsDeclarationRepository
72 94 ) {
73 - $this->wpdbAdapter = $wpdbAdapter;
74 - $this->builder = $orderFactory;
75 - $this->helper = $helper;
76 - $this->pickupPointsConfig = $pickupPointsConfig;
95 + $this->wpdbAdapter = $wpdbAdapter;
96 + $this->builder = $orderFactory;
97 + $this->coreHelper = $coreHelper;
98 + $this->pickupPointsConfig = $pickupPointsConfig;
99 + $this->carrierRepository = $carrierRepository;
100 + $this->customsDeclarationRepository = $customsDeclarationRepository;
77 101 }
78 102
79 103 /**
80 104 * Applies custom order status filter.
81 105 *
82 - * @param array $clauses Query clauses.
83 - * @param \WP_Query $queryObject WP Query.
84 - * @param array $paramValues Param values.
106 + * @param array<string, string|null> $clauses Query clauses.
107 + * @param \WP_Query|null $queryObject WP Query.
108 + * @param array<string, string|null> $paramValues Param values.
85 109 *
86 110 * @return void
87 111 */
88 - private function applyCustomFilters( array &$clauses, \WP_Query $queryObject, array $paramValues ): void {
112 + private function applyCustomFilters( array &$clauses, ?\WP_Query $queryObject, array $paramValues ): void {
89 113 /**
90 114 * Filters order statuses to exclude in Packeta order list filtering.
91 115 *
92 116 * @since 1.4
@@ -91,65 +115,71 @@
91 115 *
92 116 * @since 1.4
93 117 *
94 118 * @param array $orderStatusesToExclude Order statuses to exclude.
95 - * @param \WP_Query $queryObject WP Query.
119 + * @param \WP_Query|null $queryObject WP Query.
96 120 * @param array $paramValues Param values.
97 121 */
98 122 $orderStatusesToExclude = (array) apply_filters( 'packetery_exclude_orders_with_status', [], $queryObject, $paramValues );
99 - if ( ! $orderStatusesToExclude ) {
123 + if ( count( $orderStatusesToExclude ) === 0 ) {
100 124 return;
101 125 }
102 126
103 - $clauses['where'] .= sprintf( ' AND `%s`.`post_status` NOT IN (%s)', $this->wpdbAdapter->posts, $this->wpdbAdapter->prepareInClause( $orderStatusesToExclude ) );
127 + if ( ModuleHelper::isHposEnabled() ) {
128 + $clauses['where'] .= sprintf( ' AND `%s`.`status` NOT IN (%s)', $this->wpdbAdapter->wcOrders, $this->wpdbAdapter->prepareInClause( $orderStatusesToExclude ) );
129 + } else {
130 + $clauses['where'] .= sprintf( ' AND `%s`.`post_status` NOT IN (%s)', $this->wpdbAdapter->posts, $this->wpdbAdapter->prepareInClause( $orderStatusesToExclude ) );
131 + }
104 132 }
105 133
106 134 /**
107 - * Extends WP_Query to include custom table.
135 + * Extends SQL query clauses.
108 136 *
109 - * @link https://wordpress.stackexchange.com/questions/50305/how-to-extend-wp-query-to-include-custom-table-in-query
137 + * @param array<string, string> $clauses Clauses.
138 + * @param \WP_Query|null $queryObject Query object.
139 + * @param array<string, string|null> $paramValues Param values.
110 140 *
111 - * @param array $clauses Clauses.
112 - * @param \WP_Query $queryObject WP_Query.
113 - * @param array $paramValues Param values.
114 - *
115 - * @return array
141 + * @return array<string, string>
116 142 */
117 - public function processPostClauses( array $clauses, \WP_Query $queryObject, array $paramValues ): array {
118 - if ( isset( $queryObject->query['post_type'] ) &&
119 - (
120 - 'shop_order' === $queryObject->query['post_type'] ||
121 - ( is_array( $queryObject->query['post_type'] ) && in_array( 'shop_order', $queryObject->query['post_type'], true ) )
122 - )
123 - ) {
124 - // TODO: Introduce variable.
125 - $clauses['join'] .= ' LEFT JOIN `' . $this->wpdbAdapter->packetery_order . '` ON `' . $this->wpdbAdapter->packetery_order . '`.`id` = `' . $this->wpdbAdapter->posts . '`.`id`';
143 + public function processClauses( array $clauses, ?\WP_Query $queryObject, array $paramValues ): array {
144 + if ( ModuleHelper::isHposEnabled() ) {
145 + $clauses['join'] .= ' LEFT JOIN `' . $this->wpdbAdapter->packeteryOrder . '` ON `' . $this->wpdbAdapter->packeteryOrder . '`.`id` = `' . $this->wpdbAdapter->wcOrders . '`.`id`';
146 + } else {
147 + $clauses['join'] .= ' LEFT JOIN `' . $this->wpdbAdapter->packeteryOrder . '` ON `' . $this->wpdbAdapter->packeteryOrder . '`.`id` = `' . $this->wpdbAdapter->posts . '`.`id`';
148 + }
126 149
127 - if ( $paramValues['packetery_carrier_id'] ) {
128 - $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packetery_order . '`.`carrier_id` = "' . esc_sql( $paramValues['packetery_carrier_id'] ) . '"';
129 - $this->applyCustomFilters( $clauses, $queryObject, $paramValues );
150 + if ( isset( $paramValues['packetery_carrier_id'] ) && $paramValues['packetery_carrier_id'] !== '' ) {
151 + $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packeteryOrder . '`.`carrier_id` = "' . esc_sql( $paramValues['packetery_carrier_id'] ) . '"';
152 + $this->applyCustomFilters( $clauses, $queryObject, $paramValues );
153 + }
154 + if ( isset( $paramValues['packetery_to_submit'] ) && $paramValues['packetery_to_submit'] !== '' ) {
155 + $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packeteryOrder . '`.`carrier_id` IS NOT NULL ';
156 + $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packeteryOrder . '`.`is_exported` = false ';
157 + $this->applyCustomFilters( $clauses, $queryObject, $paramValues );
158 + }
159 + if ( isset( $paramValues['packetery_to_print'] ) && $paramValues['packetery_to_print'] !== '' ) {
160 + $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packeteryOrder . '`.`packet_id` IS NOT NULL ';
161 + $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packeteryOrder . '`.`is_label_printed` = false ';
162 + $this->applyCustomFilters( $clauses, $queryObject, $paramValues );
163 + }
164 + if ( isset( $paramValues['packetery_order_type'] ) && $paramValues['packetery_order_type'] !== '' ) {
165 + if ( $paramValues['packetery_order_type'] === Entity\Carrier::INTERNAL_PICKUP_POINTS_ID ) {
166 + $comparison = 'IN';
167 + } else {
168 + $comparison = 'NOT IN';
130 169 }
131 - if ( $paramValues['packetery_to_submit'] ) {
132 - $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packetery_order . '`.`carrier_id` IS NOT NULL ';
133 - $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packetery_order . '`.`is_exported` = false ';
134 - $this->applyCustomFilters( $clauses, $queryObject, $paramValues );
170 + $internalCarriers = array_keys( $this->carrierRepository->getNonFeedCarriers() );
171 + $internalCarriers[] = Entity\Carrier::INTERNAL_PICKUP_POINTS_ID;
172 + $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packeteryOrder . '`.`carrier_id` ' . $comparison . ' (' . $this->wpdbAdapter->prepareInClause( $internalCarriers ) . ')';
173 + $this->applyCustomFilters( $clauses, $queryObject, $paramValues );
174 + }
175 + if ( isset( $paramValues['orderby'] ) && $paramValues['orderby'] === 'packetery_packet_stored_until' ) {
176 + if ( $paramValues['order'] === 'asc' ) {
177 + $clauses['orderby'] = '`' . $this->wpdbAdapter->packeteryOrder . '`.`stored_until` ASC';
135 178 }
136 - if ( $paramValues['packetery_to_print'] ) {
137 - $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packetery_order . '`.`packet_id` IS NOT NULL ';
138 - $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packetery_order . '`.`is_label_printed` = false ';
139 - $this->applyCustomFilters( $clauses, $queryObject, $paramValues );
179 + if ( $paramValues['order'] === 'desc' ) {
180 + $clauses['orderby'] = '`' . $this->wpdbAdapter->packeteryOrder . '`.`stored_until` DESC';
140 181 }
141 - if ( $paramValues['packetery_order_type'] ) {
142 - if ( Carrier\Repository::INTERNAL_PICKUP_POINTS_ID === $paramValues['packetery_order_type'] ) {
143 - $comparison = 'IN';
144 - } else {
145 - $comparison = 'NOT IN';
146 - }
147 - $internalCarriers = array_keys( $this->pickupPointsConfig->getVendorCarriers() );
148 - $internalCarriers[] = Carrier\Repository::INTERNAL_PICKUP_POINTS_ID;
149 - $clauses['where'] .= ' AND `' . $this->wpdbAdapter->packetery_order . '`.`carrier_id` ' . $comparison . ' (' . $this->wpdbAdapter->prepareInClause( $internalCarriers ) . ')';
150 - $this->applyCustomFilters( $clauses, $queryObject, $paramValues );
151 - }
152 182 }
153 183
154 184 return $clauses;
155 185 }
@@ -159,20 +189,22 @@
159 189 *
160 190 * @return bool
161 191 */
162 192 public function createOrAlterTable(): bool {
163 - $createTableQuery = 'CREATE TABLE ' . $this->wpdbAdapter->packetery_order . ' (
193 + $createTableQuery = 'CREATE TABLE ' . $this->wpdbAdapter->packeteryOrder . ' (
164 194 `id` bigint(20) unsigned NOT NULL,
165 - `carrier_id` varchar(255) NOT NULL,
195 + `carrier_id` varchar(15) NOT NULL,
166 196 `is_exported` tinyint(1) NOT NULL,
167 - `packet_id` varchar(255) NULL,
197 + `packet_id` varchar(15) NULL,
198 + `packet_claim_id` varchar(15) NULL,
199 + `packet_claim_password` varchar(10) NULL,
168 200 `is_label_printed` tinyint(1) NOT NULL,
169 - `point_id` varchar(255) NULL,
170 - `point_name` varchar(255) NULL,
201 + `point_id` varchar(50) NULL,
202 + `point_name` varchar(150) NULL,
171 203 `point_url` varchar(255) NULL,
172 - `point_street` varchar(255) NULL,
173 - `point_zip` varchar(255) NULL,
174 - `point_city` varchar(255) NULL,
204 + `point_street` varchar(120) NULL,
205 + `point_zip` varchar(10) NULL,
206 + `point_city` varchar(70) NULL,
175 207 `address_validated` tinyint(1) NOT NULL,
176 208 `delivery_address` text NULL,
177 209 `weight` float NULL,
178 210 `length` float NULL,
@@ -182,169 +214,126 @@
182 214 `value` double NULL,
183 215 `cod` double NULL,
184 216 `api_error_message` text NULL,
185 217 `api_error_date` datetime NULL,
186 - `carrier_number` varchar(255) NULL,
187 - `packet_status` varchar(255) NULL,
218 + `carrier_number` varchar(50) NULL,
219 + `packet_status` varchar(30) NULL,
220 + `stored_until` date NULL,
188 221 `deliver_on` date NULL,
222 + `car_delivery_id` varchar(15) NULL,
189 223 PRIMARY KEY (`id`)
190 224 ) ' . $this->wpdbAdapter->get_charset_collate();
191 225
192 - return $this->wpdbAdapter->dbDelta( $createTableQuery, $this->wpdbAdapter->packetery_order );
226 + return $this->wpdbAdapter->dbDelta( $createTableQuery, $this->wpdbAdapter->packeteryOrder );
193 227 }
194 228
195 229 /**
196 - * Drop table used to store orders.
230 + * @throws InvalidCarrierException InvalidCarrierException.
197 231 */
198 - public function drop(): void {
199 - $this->wpdbAdapter->query( 'DROP TABLE IF EXISTS `' . $this->wpdbAdapter->packetery_order . '`' );
232 + public function getById( int $id ): ?Order {
233 + $wcOrder = $this->getWcOrderById( $id );
234 + if ( $wcOrder === null ) {
235 + return null;
236 + }
237 +
238 + return $this->getByWcOrder( $wcOrder );
200 239 }
201 240
202 241 /**
203 - * Gets order data.
204 - *
205 - * @param int $id Order id.
206 - *
207 - * @return Order|null
242 + * Ignores InvalidCarrierException.
208 243 */
209 - public function getById( int $id ): ?Order {
244 + public function getByIdWithValidCarrier( int $id ): ?Order {
210 245 $wcOrder = $this->getWcOrderById( $id );
211 - if ( null === $wcOrder ) {
246 + if ( $wcOrder === null ) {
212 247 return null;
213 248 }
214 249
215 - return $this->getByWcOrder( $wcOrder );
250 + return $this->getByWcOrderWithValidCarrier( $wcOrder );
216 251 }
217 252
218 253 /**
219 - * Gets order by wc order.
254 + * Returns Packeta order, or null.
220 255 *
221 - * @param WC_Order $wcOrder WC Order.
256 + * @param int $id Order ID.
222 257 *
223 258 * @return Order|null
224 259 */
225 - public function getByWcOrder( WC_Order $wcOrder ): ?Order {
226 - if ( ! $wcOrder->has_shipping_method( ShippingMethod::PACKETERY_METHOD_ID ) ) {
260 + public function findById( int $id ): ?Order {
261 + $wcOrder = $this->getWcOrderById( $id );
262 + if ( $wcOrder === null ) {
227 263 return null;
228 264 }
229 265
230 - $result = $this->wpdbAdapter->get_row(
231 - $this->wpdbAdapter->prepare(
232 - '
233 - SELECT o.* FROM `' . $this->wpdbAdapter->packetery_order . '` o
234 - JOIN `' . $this->wpdbAdapter->posts . '` as wp_p ON wp_p.ID = o.id
235 - WHERE o.`id` = %d',
236 - $wcOrder->get_id()
237 - )
238 - );
266 + $result = $this->getDataById( $wcOrder->get_id() );
267 + if ( $result === null ) {
268 + return null;
269 + }
239 270
240 - if ( ! $result ) {
271 + try {
272 + return $this->builder->build( $wcOrder, $result );
273 + } catch ( InvalidCarrierException $invalidCarrierException ) {
241 274 return null;
242 275 }
243 -
244 - $partialOrder = $this->createPartialOrder( $result );
245 - return $this->builder->finalize( $wcOrder, $partialOrder );
246 276 }
247 277
248 278 /**
249 - * Creates partial order.
279 + * Gets Packeta order data by id.
250 280 *
251 - * @param \stdClass $result DB result.
281 + * @param int $id Order id.
252 282 *
253 - * @return Order
283 + * @return object|null
254 284 */
255 - private function createPartialOrder( \stdClass $result ): Order {
256 - $partialOrder = new Order(
257 - $result->id,
258 - $result->carrier_id
285 + public function getDataById( int $id ): ?object {
286 + return $this->wpdbAdapter->get_row(
287 + $this->wpdbAdapter->prepare(
288 + '
289 + SELECT `o`.* FROM `' . $this->wpdbAdapter->packeteryOrder . '` `o`
290 + ' . $this->getWcOrderJoinClause() . '
291 + WHERE `o`.`id` = %d',
292 + $id
293 + )
259 294 );
295 + }
260 296
261 - $orderWeight = $this->parseFloat( $result->weight );
262 - if ( null !== $orderWeight ) {
263 - $partialOrder->setWeight( $orderWeight );
297 + private function getDataByWcOrder( WC_Order $wcOrder ): ?object {
298 + if ( ! ShippingProvider::wcOrderHasOurMethod( $wcOrder ) ) {
299 + return null;
264 300 }
265 - $partialOrder->setPacketId( $result->packet_id );
266 - $partialOrder->setSize( new Size( $this->parseFloat( $result->length ), $this->parseFloat( $result->width ), $this->parseFloat( $result->height ) ) );
267 - $partialOrder->setIsExported( (bool) $result->is_exported );
268 - $partialOrder->setIsLabelPrinted( (bool) $result->is_label_printed );
269 - $partialOrder->setCarrierNumber( $result->carrier_number );
270 - $partialOrder->setPacketStatus( $result->packet_status );
271 - $partialOrder->setAddressValidated( (bool) $result->address_validated );
272 - $partialOrder->setAdultContent( $this->parseBool( $result->adult_content ) );
273 - $partialOrder->setValue( $this->parseFloat( $result->value ) );
274 - $partialOrder->setCod( $this->parseFloat( $result->cod ) );
275 - $partialOrder->setDeliverOn( $this->helper->getDateTimeFromString( $result->deliver_on ) );
276 - $partialOrder->setLastApiErrorMessage( $result->api_error_message );
277 - $partialOrder->setLastApiErrorDateTime(
278 - ( null === $result->api_error_date )
279 - ? null
280 - : \DateTimeImmutable::createFromFormat(
281 - Helper::MYSQL_DATETIME_FORMAT,
282 - $result->api_error_date,
283 - new \DateTimeZone( 'UTC' )
284 - )->setTimezone( wp_timezone() )
285 - );
286 301
287 - if ( $result->delivery_address ) {
288 - $deliveryAddressDecoded = json_decode( $result->delivery_address, false );
289 - $deliveryAddress = new Address(
290 - $deliveryAddressDecoded->street,
291 - $deliveryAddressDecoded->city,
292 - $deliveryAddressDecoded->zip
293 - );
294 -
295 - $deliveryAddress->setHouseNumber( $deliveryAddressDecoded->houseNumber );
296 - $deliveryAddress->setLongitude( $deliveryAddressDecoded->longitude );
297 - $deliveryAddress->setLatitude( $deliveryAddressDecoded->latitude );
298 - $deliveryAddress->setCounty( $deliveryAddressDecoded->county );
299 -
300 - $partialOrder->setDeliveryAddress( $deliveryAddress );
302 + $packeteryOrderData = $this->getDataById( $wcOrder->get_id() );
303 + if ( ! is_object( $packeteryOrderData ) ) {
304 + return null;
301 305 }
302 306
303 - if ( null !== $result->point_id ) {
304 - $pickUpPoint = new PickupPoint(
305 - $result->point_id,
306 - $result->point_name,
307 - $result->point_city,
308 - $result->point_zip,
309 - $result->point_street,
310 - $result->point_url
311 - );
312 -
313 - $partialOrder->setPickupPoint( $pickUpPoint );
314 - }
315 -
316 - return $partialOrder;
307 + return $packeteryOrderData;
317 308 }
318 309
319 310 /**
320 - * Parses string value as float.
321 - *
322 - * @param string|float|null $value Value.
323 - *
324 - * @return float|null
311 + * @throws InvalidCarrierException
325 312 */
326 - private function parseFloat( $value ): ?float {
327 - if ( null === $value || '' === $value ) {
313 + public function getByWcOrder( WC_Order $wcOrder ): ?Order {
314 + $packeteryOrderData = $this->getDataByWcOrder( $wcOrder );
315 + if ( $packeteryOrderData === null ) {
328 316 return null;
329 317 }
330 318
331 - return (float) $value;
319 + return $this->builder->build( $wcOrder, $packeteryOrderData );
332 320 }
333 321
334 322 /**
335 - * Parses string value as float.
336 - *
337 - * @param string|int|null $value Value.
338 - *
339 - * @return bool|null
323 + * Ignores InvalidCarrierException.
340 324 */
341 - private function parseBool( $value ): ?bool {
342 - if ( null === $value || '' === $value ) {
325 + public function getByWcOrderWithValidCarrier( WC_Order $wcOrder ): ?Order {
326 + $packeteryOrderData = $this->getDataByWcOrder( $wcOrder );
327 + if ( $packeteryOrderData === null ) {
343 328 return null;
344 329 }
345 330
346 - return (bool) $value;
331 + try {
332 + return $this->builder->build( $wcOrder, $packeteryOrderData );
333 + } catch ( InvalidCarrierException $invalidCarrierException ) {
334 + return null;
335 + }
347 336 }
348 337
349 338 /**
350 339 * Transforms order to DB array.
@@ -350,52 +339,56 @@
350 339 * Transforms order to DB array.
351 340 *
352 341 * @param Order $order Order.
353 342 *
354 - * @return array
343 + * @return array<string, bool|float|int|string|null>
355 344 */
356 345 private function orderToDbArray( Order $order ): array {
357 346 $point = $order->getPickupPoint();
358 - if ( null === $point ) {
347 + if ( $point === null ) {
359 348 $point = new PickupPoint();
360 349 }
361 350
362 351 $deliveryAddress = null;
363 - if ( $order->isAddressValidated() && $order->getDeliveryAddress() ) {
352 + if ( $order->isAddressValidated() && $order->getDeliveryAddress() !== null ) {
364 353 $deliveryAddress = wp_json_encode( $order->getDeliveryAddress()->export() );
365 354 }
366 355
367 356 $apiErrorDateTime = $order->getLastApiErrorDateTime();
368 - if ( null !== $apiErrorDateTime ) {
369 - $apiErrorDateTime = $apiErrorDateTime->format( Helper::MYSQL_DATETIME_FORMAT );
357 + if ( $apiErrorDateTime !== null ) {
358 + $apiErrorDateTime = $apiErrorDateTime->format( CoreHelper::MYSQL_DATETIME_FORMAT );
370 359 }
371 360
372 361 $data = [
373 - 'id' => (int) $order->getNumber(),
374 - 'carrier_id' => $order->getCarrierId(),
375 - 'is_exported' => (int) $order->isExported(),
376 - 'packet_id' => $order->getPacketId(),
377 - 'packet_status' => $order->getPacketStatus(),
378 - 'is_label_printed' => (int) $order->isLabelPrinted(),
379 - 'carrier_number' => $order->getCarrierNumber(),
380 - 'weight' => $order->getWeight(),
381 - 'point_id' => $point->getId(),
382 - 'point_name' => $point->getName(),
383 - 'point_url' => $point->getUrl(),
384 - 'point_street' => $point->getStreet(),
385 - 'point_zip' => $point->getZip(),
386 - 'point_city' => $point->getCity(),
387 - 'address_validated' => (int) $order->isAddressValidated(),
388 - 'delivery_address' => $deliveryAddress,
389 - 'length' => $order->getLength(),
390 - 'width' => $order->getWidth(),
391 - 'height' => $order->getHeight(),
392 - 'adult_content' => $order->containsAdultContent(),
393 - 'cod' => $order->getCod(),
394 - 'value' => $order->getValue(),
395 - 'api_error_message' => $order->getLastApiErrorMessage(),
396 - 'api_error_date' => $apiErrorDateTime,
397 - 'deliver_on' => $this->helper->getStringFromDateTime( $order->getDeliverOn(), $this->helper::DATEPICKER_FORMAT ),
362 + 'id' => (int) $order->getNumber(),
363 + 'carrier_id' => $order->getCarrier()->getId(),
364 + 'is_exported' => (int) $order->isExported(),
365 + 'packet_id' => $order->getPacketId(),
366 + 'packet_claim_id' => $order->getPacketClaimId(),
367 + 'packet_claim_password' => $order->getPacketClaimPassword(),
368 + 'packet_status' => $order->getPacketStatus(),
369 + 'stored_until' => $this->coreHelper->getStringFromDateTime( $order->getStoredUntil(), CoreHelper::DATEPICKER_FORMAT ),
370 + 'is_label_printed' => (int) $order->isLabelPrinted(),
371 + 'carrier_number' => $order->getCarrierNumber(),
372 + 'weight' => $order->getWeight(),
373 + 'car_delivery_id' => $order->getCarDeliveryId(),
374 + 'point_id' => $point->getId(),
375 + 'point_name' => $point->getName(),
376 + 'point_url' => $point->getUrl(),
377 + 'point_street' => $point->getStreet(),
378 + 'point_zip' => $point->getZip(),
379 + 'point_city' => $point->getCity(),
380 + 'address_validated' => (int) $order->isAddressValidated(),
381 + 'delivery_address' => $deliveryAddress,
382 + 'length' => $order->getLength(),
383 + 'width' => $order->getWidth(),
384 + 'height' => $order->getHeight(),
385 + 'adult_content' => $order->containsAdultContent(),
386 + 'cod' => $order->getManualCod(),
387 + 'value' => $order->getManualValue(),
388 + 'api_error_message' => $order->getLastApiErrorMessage(),
389 + 'api_error_date' => $apiErrorDateTime,
390 + 'deliver_on' => $this->coreHelper->getStringFromDateTime( $order->getDeliverOn(), CoreHelper::DATEPICKER_FORMAT ),
398 391 ];
399 392
400 393 return $data;
401 394 }
@@ -407,20 +400,74 @@
407 400 *
408 401 * @return void
409 402 */
410 403 public function save( Order $order ): void {
411 - $this->wpdbAdapter->insertReplaceHelper( $this->wpdbAdapter->packetery_order, $this->orderToDbArray( $order ), null, 'REPLACE' );
404 + $this->saveData( $this->orderToDbArray( $order ) );
412 405 }
413 406
414 407 /**
408 + * Saves order data.
409 + *
410 + * @param array<string, int|string|null|DateTimeImmutable> $orderData Order data.
411 + *
412 + * @return void
413 + */
414 + public function saveData( array $orderData ): void {
415 + $this->onBeforeDataInsertion( $orderData );
416 + $this->wpdbAdapter->insertReplaceHelper( $this->wpdbAdapter->packeteryOrder, $orderData, null, 'REPLACE' );
417 + }
418 +
419 + /**
420 + * Calls logic before order data replace/insert.
421 + *
422 + * @param array<string, string|null|DateTimeImmutable> $orderData Order data.
423 + * @return void
424 + */
425 + private function onBeforeDataInsertion( array $orderData ): void {
426 + $pointId = $orderData['point_id'] ?? null;
427 + $carrierId = $orderData['carrier_id'] ?? null;
428 + /**
429 + * Tells if Packeta debug logs are enabled.
430 + *
431 + * @since 1.7.2
432 + */
433 + $isLoggingActive = (bool) apply_filters( 'packeta_enable_debug_logs', false );
434 +
435 + if ( ( $pointId !== null && $pointId !== '' ) || ! $isLoggingActive || ! $this->pickupPointsConfig->isInternalPickupPointCarrier( $carrierId ) ) {
436 + return;
437 + }
438 +
439 + $wcLogger = wc_get_logger();
440 + $dataToLog = [
441 + 'order' => $orderData,
442 + 'trace' => array_map(
443 + static function ( array $item ): array {
444 + return [
445 + 'file' => sprintf( '%s(%s)', $item['file'], $item['line'] ),
446 + 'method' => sprintf( '%s%s%s(...)', $item['class'] ?? '', $item['type'] ?? '', $item['function'] ),
447 + ];
448 + },
449 + ( new Exception() )->getTrace()
450 + ),
451 + ];
452 + $wcLogger->warning(
453 + sprintf(
454 + 'Required value for the pickup point order is not set: %s',
455 + wp_json_encode( $dataToLog, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE )
456 + ),
457 + [ 'source' => 'packeta' ]
458 + );
459 + }
460 +
461 + /**
415 462 * Loads order entities by list of ids.
416 463 *
417 - * @param array $orderIds Order ids.
464 + * @param string[] $orderIds Order ids.
418 465 *
419 466 * @return Order[]
420 467 */
421 468 public function getByIds( array $orderIds ): array {
422 - if ( empty( $orderIds ) ) {
469 + if ( count( $orderIds ) === 0 ) {
423 470 return [];
424 471 }
425 472
426 473 $wpdbAdapter = $this->wpdbAdapter;
@@ -426,10 +473,10 @@
426 473 $wpdbAdapter = $this->wpdbAdapter;
427 474 $ordersIdsPlaceholder = implode( ', ', array_fill( 0, count( $orderIds ), '%d' ) );
428 475 $packeteryOrdersResult = $wpdbAdapter->get_results(
429 476 $wpdbAdapter->prepare(
430 - 'SELECT * FROM `' . $wpdbAdapter->packetery_order . '`
431 - WHERE `id` IN (' . $ordersIdsPlaceholder . ')',
477 + 'SELECT * FROM `' . $wpdbAdapter->packeteryOrder . '`
478 + WHERE `id` IN (' . $ordersIdsPlaceholder . ')',
432 479 $orderIds
433 480 ),
434 481 OBJECT_K
435 482 );
@@ -440,12 +487,15 @@
440 487 continue;
441 488 }
442 489
443 490 $wcOrder = $this->getWcOrderById( (int) $orderId );
444 - assert( null !== $wcOrder, 'WC order has to be present' );
491 + assert( $wcOrder !== null, 'WC order has to be present' );
445 492
446 - $partialOrder = $this->createPartialOrder( $packeteryOrdersResult[ $orderId ] );
447 - $orderEntities[ $orderId ] = $this->builder->finalize( $wcOrder, $partialOrder );
493 + try {
494 + $orderEntities[ $orderId ] = $this->builder->build( $wcOrder, $packeteryOrdersResult[ $orderId ] );
495 + } catch ( InvalidCarrierException $exception ) {
496 + continue;
497 + }
448 498 }
449 499
450 500 return $orderEntities;
451 501 }
@@ -452,35 +502,42 @@
452 502
453 503 /**
454 504 * Finds orders.
455 505 *
456 - * @param array $allowedPacketStatuses Allowed packet statuses.
457 - * @param array $allowedOrderStatuses Allowed order statuses.
458 - * @param int $maxDays Max number of days of single packet sync.
459 - * @param int $limit Number of records.
506 + * @param string[] $allowedPacketStatuses Allowed packet statuses.
507 + * @param string[] $allowedOrderStatuses Allowed order statuses.
508 + * @param int $maxDays Max number of days of single packet sync.
509 + * @param int $limit Number of records.
460 510 *
461 - * @return iterable|Order[]
511 + * @return \Generator<int>
512 + * @throws Exception Exception.
462 513 */
463 - public function findStatusSyncingOrders( array $allowedPacketStatuses, array $allowedOrderStatuses, int $maxDays, int $limit ): iterable {
464 - $dateLimit = Helper::now()->modify( '- ' . $maxDays . ' days' )->format( 'Y-m-d H:i:s' );
514 + public function findStatusSyncingOrderIds( array $allowedPacketStatuses, array $allowedOrderStatuses, int $maxDays, int $limit ): \Generator {
515 + $dateLimit = CoreHelper::now()->modify( '- ' . $maxDays . ' days' )->format( 'Y-m-d H:i:s' );
465 516
466 - $andWhere = [];
517 + $andWhere = [ '`o`.`packet_id` IS NOT NULL' ];
518 + $hposEnabled = ModuleHelper::isHposEnabled();
467 519
468 - $andWhere[] = 'o.`packet_id` IS NOT NULL';
469 - $andWhere[] = $this->wpdbAdapter->prepare( 'wp_p.`post_date_gmt` >= %s', $dateLimit );
520 + if ( $hposEnabled ) {
521 + $andWhere[] = $this->wpdbAdapter->prepare( '`wc_o`.`date_created_gmt` >= %s', $dateLimit );
522 + } else {
523 + $andWhere[] = $this->wpdbAdapter->prepare( '`wp_p`.`post_date_gmt` >= %s', $dateLimit );
524 + }
470 525
471 526 $orPacketStatus = [];
472 - $orPacketStatus[] = 'o.`packet_status` IS NULL';
527 + $orPacketStatus[] = '`o`.`packet_status` IS NULL';
473 528
474 - if ( $allowedPacketStatuses ) {
475 - $orPacketStatus[] = '`o`.`packet_status` IN (' . $this->wpdbAdapter->prepareInClause( $allowedOrderStatuses ) . ')';
529 + if ( count( $allowedPacketStatuses ) > 0 ) {
530 + $orPacketStatus[] = '`o`.`packet_status` IN (' . $this->wpdbAdapter->prepareInClause( $allowedPacketStatuses ) . ')';
476 531 }
477 532
478 - if ( $orPacketStatus ) {
533 + if ( count( $orPacketStatus ) > 0 ) {
479 534 $andWhere[] = '(' . implode( ' OR ', $orPacketStatus ) . ')';
480 535 }
481 536
482 - if ( $allowedOrderStatuses ) {
537 + if ( count( $allowedOrderStatuses ) > 0 && $hposEnabled ) {
538 + $andWhere[] = '`wc_o`.`status` IN (' . $this->wpdbAdapter->prepareInClause( $allowedOrderStatuses ) . ')';
539 + } elseif ( count( $allowedOrderStatuses ) > 0 && $hposEnabled === false ) {
483 540 $andWhere[] = '`wp_p`.`post_status` IN (' . $this->wpdbAdapter->prepareInClause( $allowedOrderStatuses ) . ')';
484 541 } else {
485 542 $andWhere[] = '1 = 0';
486 543 }
@@ -485,18 +542,24 @@
485 542 $andWhere[] = '1 = 0';
486 543 }
487 544
488 545 $where = '';
489 - if ( $andWhere ) {
546 + if ( count( $andWhere ) > 0 ) {
490 547 $where = ' WHERE ' . implode( ' AND ', $andWhere );
491 548 }
492 549
550 + if ( $hposEnabled ) {
551 + $orderBy = ' ORDER BY `wc_o`.`date_created_gmt` ';
552 + } else {
553 + $orderBy = ' ORDER BY `wp_p`.`post_date_gmt` ';
554 + }
555 +
493 556 $sql = $this->wpdbAdapter->prepare(
494 557 '
495 - SELECT o.* FROM `' . $this->wpdbAdapter->packetery_order . '` o
496 - JOIN `' . $this->wpdbAdapter->posts . '` wp_p ON wp_p.`ID` = o.`id`
558 + SELECT `o`.`id` FROM `' . $this->wpdbAdapter->packeteryOrder . '` `o`
559 + ' . $this->getWcOrderJoinClause() . '
497 560 ' . $where . '
498 - ORDER BY wp_p.`post_date`
561 + ' . $orderBy . '
499 562 LIMIT %d',
500 563 $limit
501 564 );
502 565
@@ -503,14 +566,13 @@
503 566 $rows = $this->wpdbAdapter->get_results( $sql );
504 567
505 568 foreach ( $rows as $row ) {
506 569 $wcOrder = $this->getWcOrderById( (int) $row->id );
507 - if ( null === $wcOrder || ! $wcOrder->has_shipping_method( ShippingMethod::PACKETERY_METHOD_ID ) ) {
570 + if ( $wcOrder === null || ! ShippingProvider::wcOrderHasOurMethod( $wcOrder ) ) {
508 571 continue;
509 572 }
510 573
511 - $partial = $this->createPartialOrder( $row );
512 - yield $this->builder->finalize( $wcOrder, $partial );
574 + yield (int) $row->id;
513 575 }
514 576 }
515 577
516 578 /**
@@ -518,13 +580,9 @@
518 580 *
519 581 * @return int
520 582 */
521 583 public function countOrdersToSubmit(): int {
522 - return (int) $this->wpdbAdapter->get_var(
523 - 'SELECT COUNT(DISTINCT o.id) FROM `' . $this->wpdbAdapter->packetery_order . '` o
524 - JOIN `' . $this->wpdbAdapter->posts . '` wp_p ON wp_p.`ID` = o.`id`
525 - WHERE o.`carrier_id` IS NOT NULL AND o.`is_exported` = false'
526 - );
584 + return $this->countOrders( [ 'packetery_to_submit' => '1' ] );
527 585 }
528 586
529 587 /**
530 588 * Counts order to be printed.
@@ -531,37 +589,104 @@
531 589 *
532 590 * @return int
533 591 */
534 592 public function countOrdersToPrint(): int {
593 + return $this->countOrders( [ 'packetery_to_print' => '1' ] );
594 + }
595 +
596 + /**
597 + * Counts orders by given params.
598 + *
599 + * @param array<string, string> $params Params.
600 + *
601 + * @return int
602 + */
603 + private function countOrders( array $params ): int {
604 + $clauses = [ 'join' => '' ];
605 +
606 + if ( ModuleHelper::isHposEnabled() ) {
607 + $clauses['select'] = ' SELECT COUNT(DISTINCT `' . $this->wpdbAdapter->wcOrders . '`.`id`) ';
608 + $clauses['from'] = ' FROM `' . $this->wpdbAdapter->wcOrders . '` ';
609 + } else {
610 + $clauses['select'] = ' SELECT COUNT(DISTINCT `' . $this->wpdbAdapter->posts . '`.`ID`) ';
611 + $clauses['from'] = ' FROM `' . $this->wpdbAdapter->posts . '` ';
612 + }
613 +
614 + $clauses['where'] = ' WHERE `' . $this->wpdbAdapter->packeteryOrder . '`.`id` IS NOT NULL ';
615 + $clauses = $this->processClauses( $clauses, null, $params );
616 +
535 617 return (int) $this->wpdbAdapter->get_var(
536 - 'SELECT COUNT(DISTINCT o.id) FROM `' . $this->wpdbAdapter->packetery_order . '` o
537 - JOIN `' . $this->wpdbAdapter->posts . '` wp_p ON wp_p.`ID` = o.`id`
538 - WHERE o.`packet_id` IS NOT NULL AND o.`is_label_printed` = false'
618 + $clauses['select'] .
619 + $clauses['from'] .
620 + $clauses['join'] .
621 + $clauses['where']
539 622 );
540 623 }
541 624
542 625 /**
626 + * Gets WC Order join clause.
627 + *
628 + * @return string
629 + */
630 + public function getWcOrderJoinClause(): string {
631 + $packeteryTableAlias = 'o';
632 +
633 + if ( ModuleHelper::isHposEnabled() ) {
634 + $sourceTableAlias = 'wc_o';
635 +
636 + return sprintf(
637 + 'JOIN `%s` `%s` ON `%s`.`id` = `%s`.`id`',
638 + $this->wpdbAdapter->wcOrders,
639 + $sourceTableAlias,
640 + $sourceTableAlias,
641 + $packeteryTableAlias
642 + );
643 + }
644 +
645 + $sourceTableAlias = 'wp_p';
646 +
647 + return sprintf(
648 + 'JOIN `%s` `%s` ON `%s`.`ID` = `%s`.`id`',
649 + $this->wpdbAdapter->posts,
650 + $sourceTableAlias,
651 + $sourceTableAlias,
652 + $packeteryTableAlias
653 + );
654 + }
655 +
656 + /**
543 657 * Deletes all custom table records linked to permanently deleted orders.
544 658 *
545 659 * @return void
546 660 */
547 661 public function deleteOrphans(): void {
662 + if ( ModuleHelper::isHposEnabled() ) {
663 + $this->wpdbAdapter->query(
664 + 'DELETE `' . $this->wpdbAdapter->packeteryOrder . '` FROM `' . $this->wpdbAdapter->packeteryOrder . '`
665 + LEFT JOIN `' . $this->wpdbAdapter->wcOrders . '` ON `' . $this->wpdbAdapter->wcOrders . '`.`id` = `' . $this->wpdbAdapter->packeteryOrder . '`.`id`
666 + WHERE `' . $this->wpdbAdapter->wcOrders . '`.`id` IS NULL'
667 + );
668 +
669 + return;
670 + }
671 +
548 672 $this->wpdbAdapter->query(
549 - 'DELETE `' . $this->wpdbAdapter->packetery_order . '` FROM `' . $this->wpdbAdapter->packetery_order . '`
550 - LEFT JOIN `' . $this->wpdbAdapter->posts . '` ON `' . $this->wpdbAdapter->posts . '`.`ID` = `' . $this->wpdbAdapter->packetery_order . '`.`id`
673 + 'DELETE `' . $this->wpdbAdapter->packeteryOrder . '` FROM `' . $this->wpdbAdapter->packeteryOrder . '`
674 + LEFT JOIN `' . $this->wpdbAdapter->posts . '` ON `' . $this->wpdbAdapter->posts . '`.`ID` = `' . $this->wpdbAdapter->packeteryOrder . '`.`id`
551 675 WHERE `' . $this->wpdbAdapter->posts . '`.`ID` IS NULL'
552 676 );
553 677 }
554 678
555 679 /**
556 - * Deletes data from custom table.
680 + * Deletes order data including customs declaration and its items from custom tables.
557 681 *
558 682 * @param int $orderId Order id.
559 683 *
560 684 * @return void
561 685 */
562 - private function delete( int $orderId ): void {
563 - $this->wpdbAdapter->delete( $this->wpdbAdapter->packetery_order, [ 'id' => $orderId ], '%d' );
686 + public function delete( int $orderId ): void {
687 + $this->customsDeclarationRepository->delete( (string) $orderId );
688 + $this->wpdbAdapter->delete( $this->wpdbAdapter->packeteryOrder, [ 'id' => $orderId ], '%d' );
564 689 }
565 690
566 691 /**
567 692 * Fires after post deletion.
@@ -571,9 +696,10 @@
571 696 *
572 697 * @return void
573 698 */
574 699 public function deletedPostHook( int $postId, WP_Post $post ): void {
575 - if ( 'shop_order' === $post->post_type ) {
700 + // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
701 + if ( $post->post_type === 'shop_order' ) {
576 702 $this->delete( $postId );
577 703 }
578 704 }
579 705
@@ -591,6 +717,5 @@
591 717 }
592 718
593 719 return null;
594 720 }
595 -
596 721 }