PluginProbe
Packeta / 1.2.3
Packeta v1.2.3
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 / Order / Repository.php

Repository.php in Packeta 1.2.3, at src/Packetery/Module/Order/Repository.php

436 lines 11.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class Repository.
4 *
5 * @package Packetery\Module\Order
6 */
7
8 declare( strict_types=1 );
9
10 namespace Packetery\Module\Order;
11
12 use Packetery\Core\Entity\Order;
13 use Packetery\Core\Entity\PickupPoint;
14 use Packetery\Core\Entity\Size;
15 use Packetery\Core\Entity\Address;
16 use Packetery\Module\Calculator;
17 use Packetery\Module\Carrier;
18 use Packetery\Module\Product;
19 use Packetery\Module\ShippingMethod;
20
21 /**
22 * Class Repository.
23 *
24 * @package Packetery\Module\Order
25 */
26 class Repository {
27
28 /**
29 * Wpdb.
30 *
31 * @var \wpdb
32 */
33 private $wpdb;
34
35 /**
36 * Order factory.
37 *
38 * @var Builder
39 */
40 private $builder;
41
42 /**
43 * Calculator.
44 *
45 * @var Calculator
46 */
47 private $calculator;
48
49 /**
50 * Repository constructor.
51 *
52 * @param \wpdb $wpdb Wpdb.
53 * @param Builder $orderFactory Order factory.
54 * @param Calculator $calculator Calculator.
55 */
56 public function __construct( \wpdb $wpdb, Builder $orderFactory, Calculator $calculator ) {
57 $this->wpdb = $wpdb;
58 $this->builder = $orderFactory;
59 $this->calculator = $calculator;
60 }
61
62 /**
63 * Extends WP_Query to include custom table.
64 *
65 * @link https://wordpress.stackexchange.com/questions/50305/how-to-extend-wp-query-to-include-custom-table-in-query
66 *
67 * @param array $clauses Clauses.
68 * @param \WP_Query $queryObject WP_Query.
69 * @param array $paramValues Param values.
70 *
71 * @return array
72 */
73 public function processPostClauses( array $clauses, \WP_Query $queryObject, array $paramValues ): array {
74 if ( isset( $queryObject->query['post_type'] ) &&
75 (
76 'shop_order' === $queryObject->query['post_type'] ||
77 ( is_array( $queryObject->query['post_type'] ) && in_array( 'shop_order', $queryObject->query['post_type'], true ) )
78 )
79 ) {
80 // TODO: Introduce variable.
81 $clauses['join'] .= ' LEFT JOIN `' . $this->wpdb->packetery_order . '` ON `' . $this->wpdb->packetery_order . '`.`id` = `' . $this->wpdb->posts . '`.`id`';
82
83 if ( $paramValues['packetery_carrier_id'] ) {
84 $clauses['where'] .= ' AND `' . $this->wpdb->packetery_order . '`.`carrier_id` = "' . $this->wpdb->_real_escape( $paramValues['packetery_carrier_id'] ) . '"';
85 }
86 if ( $paramValues['packetery_to_submit'] ) {
87 $clauses['where'] .= ' AND `' . $this->wpdb->packetery_order . '`.`carrier_id` IS NOT NULL ';
88 $clauses['where'] .= ' AND `' . $this->wpdb->packetery_order . '`.`is_exported` = false ';
89 }
90 if ( $paramValues['packetery_to_print'] ) {
91 $clauses['where'] .= ' AND `' . $this->wpdb->packetery_order . '`.`packet_id` IS NOT NULL ';
92 $clauses['where'] .= ' AND `' . $this->wpdb->packetery_order . '`.`is_label_printed` = false ';
93 }
94 if ( $paramValues['packetery_order_type'] ) {
95 if ( Carrier\Repository::INTERNAL_PICKUP_POINTS_ID === $paramValues['packetery_order_type'] ) {
96 $clauses['where'] .= ' AND `' . $this->wpdb->packetery_order . '`.`carrier_id` = "' . $this->wpdb->_real_escape( Carrier\Repository::INTERNAL_PICKUP_POINTS_ID ) . '"';
97 } else {
98 $clauses['where'] .= ' AND `' . $this->wpdb->packetery_order . '`.`carrier_id` != "' . $this->wpdb->_real_escape( Carrier\Repository::INTERNAL_PICKUP_POINTS_ID ) . '"';
99 }
100 }
101 }
102
103 return $clauses;
104 }
105
106 /**
107 * Create table to store orders.
108 *
109 * @return bool
110 */
111 public function createTable(): bool {
112 $wpdb = $this->wpdb;
113
114 return $wpdb->query(
115 'CREATE TABLE IF NOT EXISTS `' . $wpdb->packetery_order . '` (
116 `id` bigint(20) unsigned NOT NULL,
117 `carrier_id` varchar(255) NOT NULL,
118 `is_exported` boolean NOT NULL,
119 `packet_id` varchar(255) NULL,
120 `is_label_printed` boolean NOT NULL,
121 `point_id` varchar(255) NULL,
122 `point_name` varchar(255) NULL,
123 `point_url` varchar(255) NULL,
124 `point_street` varchar(255) NULL,
125 `point_zip` varchar(255) NULL,
126 `point_city` varchar(255) NULL,
127 `address_validated` boolean NOT NULL,
128 `delivery_address` TEXT NULL,
129 `weight` float NULL,
130 `length` float NULL,
131 `width` float NULL,
132 `height` float NULL,
133 `carrier_number` varchar(255) NULL,
134 `packet_status` varchar(255) NULL,
135 PRIMARY KEY (`id`)
136 ) ' . $wpdb->get_charset_collate()
137 );
138 }
139
140 /**
141 * Drop table used to store orders.
142 */
143 public function drop(): void {
144 $wpdb = $this->wpdb;
145 $wpdb->query( 'DROP TABLE IF EXISTS `' . $wpdb->packetery_order . '`' );
146 }
147
148 /**
149 * Gets order data.
150 *
151 * @param int $id Order id.
152 *
153 * @return Order|null
154 */
155 public function getById( int $id ): ?Order {
156 $wcOrder = wc_get_order( $id );
157 if ( ! $wcOrder instanceof \WC_Order ) {
158 return null;
159 }
160
161 return $this->getByWcOrder( $wcOrder );
162 }
163
164 /**
165 * Gets order by wc order.
166 *
167 * @param \WC_Order $wcOrder WC Order.
168 *
169 * @return Order|null
170 */
171 public function getByWcOrder( \WC_Order $wcOrder ): ?Order {
172 if ( ! $wcOrder->has_shipping_method( ShippingMethod::PACKETERY_METHOD_ID ) ) {
173 return null;
174 }
175
176 $wpdb = $this->wpdb;
177
178 $result = $wpdb->get_row(
179 $wpdb->prepare(
180 '
181 SELECT o.* FROM `' . $wpdb->packetery_order . '` o
182 JOIN `' . $wpdb->posts . '` as wp_p ON wp_p.ID = o.id
183 WHERE o.`id` = %d',
184 $wcOrder->get_id()
185 )
186 );
187
188 if ( ! $result ) {
189 return null;
190 }
191
192 $partialOrder = $this->createPartialOrder( $wcOrder, $result );
193 return $this->builder->finalize( $wcOrder, $partialOrder );
194 }
195
196 /**
197 * Creates partial order.
198 *
199 * @param \WC_Order $wcOrder WC Order.
200 * @param \stdClass $result DB result.
201 *
202 * @return Order
203 */
204 private function createPartialOrder( \WC_Order $wcOrder, \stdClass $result ): Order {
205 $orderWeight = $this->parseFloat( $result->weight );
206 if ( null === $orderWeight ) {
207 $orderWeight = $this->calculator->calculateOrderWeight( $wcOrder );
208 }
209
210 $partialOrder = new Order(
211 $result->id,
212 $result->carrier_id
213 );
214
215 $partialOrder->setWeight( $orderWeight );
216 $partialOrder->setPacketId( $result->packet_id );
217 $partialOrder->setSize( new Size( $this->parseFloat( $result->length ), $this->parseFloat( $result->width ), $this->parseFloat( $result->height ) ) );
218 $partialOrder->setIsExported( (bool) $result->is_exported );
219 $partialOrder->setIsLabelPrinted( (bool) $result->is_label_printed );
220 $partialOrder->setCarrierNumber( $result->carrier_number );
221 $partialOrder->setPacketStatus( $result->packet_status );
222 $partialOrder->setAdultContent( $this->containsAdultContent( $wcOrder ) );
223 $partialOrder->setAddressValidated( (bool) $result->address_validated );
224
225 if ( $result->delivery_address ) {
226 $deliveryAddressDecoded = json_decode( $result->delivery_address );
227 $deliveryAddress = new Address(
228 $deliveryAddressDecoded->street,
229 $deliveryAddressDecoded->city,
230 $deliveryAddressDecoded->zip
231 );
232
233 $deliveryAddress->setHouseNumber( $deliveryAddressDecoded->houseNumber );
234 $deliveryAddress->setLongitude( $deliveryAddressDecoded->longitude );
235 $deliveryAddress->setLatitude( $deliveryAddressDecoded->latitude );
236 $deliveryAddress->setCounty( $deliveryAddressDecoded->county );
237
238 $partialOrder->setDeliveryAddress( $deliveryAddress );
239 }
240
241 if ( null !== $result->point_id ) {
242 $pickUpPoint = new PickupPoint(
243 $result->point_id,
244 $result->point_name,
245 $result->point_city,
246 $result->point_zip,
247 $result->point_street,
248 $result->point_url
249 );
250
251 $partialOrder->setPickupPoint( $pickUpPoint );
252 }
253
254 return $partialOrder;
255 }
256
257 /**
258 * Parses string value as float.
259 *
260 * @param string|float|null $value Value.
261 *
262 * @return float|null
263 */
264 private function parseFloat( $value ): ?float {
265 if ( null === $value || '' === $value ) {
266 return null;
267 }
268
269 return (float) $value;
270 }
271
272 /**
273 * Transforms order to DB array.
274 *
275 * @param Order $order Order.
276 *
277 * @return array
278 */
279 private function orderToDbArray( Order $order ): array {
280 $point = $order->getPickupPoint();
281 if ( null === $point ) {
282 $point = new PickupPoint();
283 }
284
285 $deliveryAddress = null;
286 if ( $order->isAddressValidated() && $order->getDeliveryAddress() ) {
287 $deliveryAddress = wp_json_encode( $order->getDeliveryAddress()->export() );
288 }
289
290 $data = [
291 'id' => (int) $order->getNumber(),
292 'carrier_id' => $order->getCarrierId(),
293 'is_exported' => (int) $order->isExported(),
294 'packet_id' => $order->getPacketId(),
295 'packet_status' => $order->getPacketStatus(),
296 'is_label_printed' => (int) $order->isLabelPrinted(),
297 'carrier_number' => $order->getCarrierNumber(),
298 'weight' => $order->getWeight(),
299 'point_id' => $point->getId(),
300 'point_name' => $point->getName(),
301 'point_url' => $point->getUrl(),
302 'point_street' => $point->getStreet(),
303 'point_zip' => $point->getZip(),
304 'point_city' => $point->getCity(),
305 'address_validated' => (int) $order->isAddressValidated(),
306 'delivery_address' => $deliveryAddress,
307 'length' => $order->getLength(),
308 'width' => $order->getWidth(),
309 'height' => $order->getHeight(),
310 ];
311
312 return $data;
313 }
314
315 /**
316 * Saves order.
317 *
318 * @param Order $order Order.
319 *
320 * @return void
321 */
322 public function save( Order $order ): void {
323 $this->wpdb->_insert_replace_helper( $this->wpdb->packetery_order, $this->orderToDbArray( $order ), null, 'REPLACE' );
324 }
325
326 /**
327 * Loads order entities by list of ids.
328 *
329 * @param array $orderIds Order ids.
330 *
331 * @return Order[]
332 */
333 public function getByIds( array $orderIds ): array {
334 $orderEntities = [];
335 $posts = get_posts(
336 [
337 'post_type' => 'shop_order',
338 'post__in' => $orderIds,
339 'post_status' => [ 'any', 'trash' ],
340 'nopaging' => true,
341 ]
342 );
343 foreach ( $posts as $post ) {
344 $wcOrder = wc_get_order( $post );
345 $order = $this->getByWcOrder( $wcOrder );
346 if ( $wcOrder && $order ) {
347 $orderEntities[ $order->getNumber() ] = $order;
348 }
349 }
350
351 return $orderEntities;
352 }
353
354 /**
355 * Finds orders.
356 *
357 * @param int $limit Number of records.
358 *
359 * @return iterable|Order[]
360 */
361 public function findStatusSyncingOrders( int $limit ): iterable {
362 $wpdb = $this->wpdb;
363
364 $rows = $wpdb->get_results(
365 $wpdb->prepare(
366 '
367 SELECT o.* FROM `' . $wpdb->packetery_order . '` o
368 JOIN `' . $wpdb->posts . '` wp_p ON wp_p.`ID` = o.`id`
369 WHERE ( o.`packet_status` IS NULL OR o.`packet_status` NOT IN ("delivered", "returned", "cancelled") ) AND o.`packet_id` IS NOT NULL
370 ORDER BY wp_p.`post_date`
371 LIMIT %d',
372 $limit
373 )
374 );
375
376 foreach ( $rows as $row ) {
377 $wcOrder = wc_get_order( $row->id );
378 if ( ! $wcOrder->has_shipping_method( ShippingMethod::PACKETERY_METHOD_ID ) ) {
379 continue;
380 }
381
382 $partial = $this->createPartialOrder( $wcOrder, $row );
383 yield $this->builder->finalize( $wcOrder, $partial );
384 }
385 }
386
387 /**
388 * Finds out if adult content is present.
389 *
390 * @param \WC_Order $wcOrder WC Order.
391 *
392 * @return bool
393 */
394 private function containsAdultContent( \WC_Order $wcOrder ): bool {
395 foreach ( $wcOrder->get_items() as $item ) {
396 $itemData = $item->get_data();
397 $productEntity = Product\Entity::fromPostId( $itemData['product_id'] );
398 if ( $productEntity->isAgeVerification18PlusRequired() ) {
399 return true;
400 }
401 }
402
403 return false;
404 }
405
406 /**
407 * Counts order to be submitted.
408 *
409 * @return int
410 */
411 public function countOrdersToSubmit(): int {
412 $wpdb = $this->wpdb;
413
414 return (int) $wpdb->get_var(
415 'SELECT COUNT(DISTINCT o.id) FROM `' . $wpdb->packetery_order . '` o
416 JOIN `' . $wpdb->posts . '` wp_p ON wp_p.`ID` = o.`id`
417 WHERE o.`carrier_id` IS NOT NULL AND o.`is_exported` = false'
418 );
419 }
420
421 /**
422 * Counts order to be printed.
423 *
424 * @return int
425 */
426 public function countOrdersToPrint(): int {
427 $wpdb = $this->wpdb;
428
429 return (int) $wpdb->get_var(
430 'SELECT COUNT(DISTINCT o.id) FROM `' . $wpdb->packetery_order . '` o
431 JOIN `' . $wpdb->posts . '` wp_p ON wp_p.`ID` = o.`id`
432 WHERE o.`packet_id` IS NOT NULL AND o.`is_label_printed` = false'
433 );
434 }
435 }
436