PluginProbe
Packeta / 1.4
Packeta v1.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 / Order / LabelPrint.php

LabelPrint.php in Packeta 1.4, at src/Packetery/Module/Order/LabelPrint.php

508 lines 14.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class LabelPrint.
4 *
5 * @package Packetery\Order
6 */
7
8 declare( strict_types=1 );
9
10 namespace Packetery\Module\Order;
11
12 use Packetery\Core\Api\Soap\Client;
13 use Packetery\Core\Api\Soap\Request;
14 use Packetery\Core\Api\Soap\Response;
15 use Packetery\Core\Log;
16 use Packetery\Module\FormFactory;
17 use Packetery\Module\MessageManager;
18 use Packetery\Module\Options\Provider;
19 use Packetery\Module\Plugin;
20 use PacketeryLatte\Engine;
21 use PacketeryNette\Forms\Form;
22 use PacketeryNette\Http;
23 use Packetery\Module;
24
25 /**
26 * Class LabelPrint.
27 *
28 * @package Packetery\Order
29 */
30 class LabelPrint {
31 public const ACTION_PACKETA_LABELS = 'print_packeta_labels';
32 public const ACTION_CARRIER_LABELS = 'print_carrier_labels';
33 public const LABEL_TYPE_PARAM = 'label_type';
34 public const MENU_SLUG = 'label-print';
35
36 /**
37 * PacketeryLatte Engine.
38 *
39 * @var Engine PacketeryLatte engine.
40 */
41 private $latteEngine;
42
43 /**
44 * Options Provider
45 *
46 * @var Provider
47 */
48 private $optionsProvider;
49
50 /**
51 * Form factory.
52 *
53 * @var FormFactory Form factory.
54 */
55 private $formFactory;
56
57 /**
58 * Http Request.
59 *
60 * @var Http\Request
61 */
62 private $httpRequest;
63
64 /**
65 * SOAP API Client.
66 *
67 * @var Client SOAP API Client.
68 */
69 private $soapApiClient;
70
71 /**
72 * Message Manager.
73 *
74 * @var MessageManager
75 */
76 private $messageManager;
77
78 /**
79 * Logger.
80 *
81 * @var Log\ILogger
82 */
83 private $logger;
84
85 /**
86 * Order repository.
87 *
88 * @var Repository
89 */
90 private $orderRepository;
91
92 /**
93 * Log page.
94 *
95 * @var Module\Log\Page
96 */
97 private $logPage;
98
99 /**
100 * LabelPrint constructor.
101 *
102 * @param Engine $latteEngine Latte Engine.
103 * @param Provider $optionsProvider Options provider.
104 * @param FormFactory $formFactory Form factory.
105 * @param Http\Request $httpRequest Http Request.
106 * @param Client $soapApiClient SOAP API Client.
107 * @param MessageManager $messageManager Message Manager.
108 * @param Log\ILogger $logger Logger.
109 * @param Repository $orderRepository Order repository.
110 * @param Module\Log\Page $logPage Log page.
111 */
112 public function __construct(
113 Engine $latteEngine,
114 Provider $optionsProvider,
115 FormFactory $formFactory,
116 Http\Request $httpRequest,
117 Client $soapApiClient,
118 MessageManager $messageManager,
119 Log\ILogger $logger,
120 Repository $orderRepository,
121 Module\Log\Page $logPage
122 ) {
123 $this->latteEngine = $latteEngine;
124 $this->optionsProvider = $optionsProvider;
125 $this->formFactory = $formFactory;
126 $this->httpRequest = $httpRequest;
127 $this->soapApiClient = $soapApiClient;
128 $this->messageManager = $messageManager;
129 $this->logger = $logger;
130 $this->orderRepository = $orderRepository;
131 $this->logPage = $logPage;
132 }
133
134 /**
135 * Generates id of transient to store order ids.
136 *
137 * @return string
138 */
139 public static function getOrderIdsTransientName(): string {
140 return 'packetery_label_print_order_ids_' . wp_get_session_token();
141 }
142
143 /**
144 * Generates id of transient to store back link.
145 *
146 * @return string
147 */
148 public static function getBackLinkTransientName(): string {
149 return 'packetery_label_print_back_link_' . wp_get_session_token();
150 }
151
152 /**
153 * Prepares form and renders template.
154 */
155 public function render(): void {
156 $form = $this->createForm( $this->optionsProvider->getLabelMaxOffset( $this->getLabelFormat() ) );
157
158 $count = 0;
159 $isCarrierLabels = ( $this->httpRequest->getQuery( self::LABEL_TYPE_PARAM ) === self::ACTION_CARRIER_LABELS );
160
161 $orderIdsTransient = $this->getOrderIdsTransient();
162 if ( $orderIdsTransient ) {
163 $orderIds = $this->getPacketIdsFromTransient( $orderIdsTransient, $isCarrierLabels );
164 $count = count( $orderIds );
165 } else {
166 $this->messageManager->flash_message( __( 'No orders were selected', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, self::MENU_SLUG );
167 }
168
169 $this->latteEngine->render(
170 PACKETERY_PLUGIN_DIR . '/template/order/label-print.latte',
171 [
172 'form' => $form,
173 'count' => $count,
174 'backLink' => get_transient( self::getBackLinkTransientName() ),
175 'flashMessages' => $this->messageManager->renderToString( MessageManager::RENDERER_PACKETERY, self::MENU_SLUG ),
176 'translations' => [
177 'packeta' => __( 'Packeta', 'packeta' ),
178 'labelPrinting' => __( 'Print labels', 'packeta' ),
179 // translators: %s is count.
180 'numberOfLabelsToPrint' => __( 'Number of labels to print: %s', 'packeta' ),
181 'back' => __( 'Back', 'packeta' ),
182 'printLabels' => __( 'Print labels', 'packeta' ),
183 ],
184 ]
185 );
186 }
187
188 /**
189 * Gets label format for current job.
190 *
191 * @return string
192 */
193 private function getLabelFormat(): string {
194 $packetaLabelFormat = $this->optionsProvider->get_packeta_label_format();
195 $carrierLabelFormat = $this->optionsProvider->get_carrier_label_format();
196
197 return ( $this->httpRequest->getQuery( self::LABEL_TYPE_PARAM ) === self::ACTION_CARRIER_LABELS ? $carrierLabelFormat : $packetaLabelFormat );
198 }
199
200 /**
201 * Outputs pdf.
202 */
203 public function outputLabelsPdf(): void {
204 if ( $this->httpRequest->getQuery( 'page' ) !== self::MENU_SLUG ) {
205 return;
206 }
207
208 $fallbackToPacketaLabel = false;
209 $isCarrierLabels = ( $this->httpRequest->getQuery( self::LABEL_TYPE_PARAM ) === self::ACTION_CARRIER_LABELS );
210 $idParam = $this->httpRequest->getQuery( 'id' );
211 $packetIdParam = $this->httpRequest->getQuery( 'packet_id' );
212 if ( null !== $idParam && null !== $packetIdParam ) {
213 $fallbackToPacketaLabel = true;
214 $packetIds = [ $idParam => $packetIdParam ];
215 } else {
216 $orderIdsTransient = $this->getOrderIdsTransient();
217 if ( ! $orderIdsTransient ) {
218 return;
219 }
220
221 $packetIds = $this->getPacketIdsFromTransient( $orderIdsTransient, $isCarrierLabels );
222 }
223 if ( ! $packetIds ) {
224 $this->messageManager->flash_message( __( 'No suitable orders were selected', 'packeta' ), 'info' );
225 if ( wp_safe_redirect( add_query_arg( [ 'post_type' => 'shop_order' ], admin_url( 'edit.php' ) ) ) ) {
226 exit;
227 }
228 return;
229 }
230
231 $maxOffset = $this->optionsProvider->getLabelMaxOffset( $this->getLabelFormat() );
232 $form = $this->createForm( $maxOffset );
233 $offsetParam = $this->httpRequest->getQuery( 'offset' );
234 if ( 0 === $maxOffset ) {
235 $offset = 0;
236 } elseif ( null !== $offsetParam ) {
237 $offset = (int) $offsetParam;
238 } elseif ( $form->isSubmitted() ) {
239 $data = $form->getValues( 'array' );
240 $offset = $data['offset'];
241 } else {
242 return;
243 }
244
245 if ( $isCarrierLabels ) {
246 $response = $this->requestCarrierLabels( $offset, $packetIds );
247 if ( $fallbackToPacketaLabel && $response->hasFault() ) {
248 $response = $this->requestPacketaLabels( $offset, $packetIds );
249 }
250 } else {
251 $response = $this->requestPacketaLabels( $offset, $packetIds );
252 }
253 if ( ! $response || $response->hasFault() ) {
254 $message = ( null !== $response && $response->hasFault() ) ?
255 __( 'Label printing failed, you can find more information in the Packeta log.', 'packeta' ) :
256 __( 'You selected orders that were not submitted yet', 'packeta' );
257 $this->messageManager->flash_message( $message, MessageManager::TYPE_ERROR );
258 if ( wp_safe_redirect( 'edit.php?post_type=shop_order' ) ) {
259 exit;
260 }
261 }
262
263 header( 'Content-Type: application/pdf' );
264 header( 'Content-Transfer-Encoding: Binary' );
265 header( 'Content-Length: ' . strlen( $response->getPdfContents() ) );
266 header( 'Content-Disposition: attachment; filename="' . $this->getFilename() . '"' );
267 // @codingStandardsIgnoreStart
268 echo $response->getPdfContents();
269 // @codingStandardsIgnoreEnd
270 exit;
271 }
272
273 /**
274 * Creates offset setting form.
275 *
276 * @param int $maxOffset Maximal offset.
277 *
278 * @return Form
279 */
280 public function createForm( int $maxOffset ): Form {
281 $form = $this->formFactory->create();
282
283 $availableOffsets = [];
284 for ( $i = 0; $i <= $maxOffset; $i ++ ) {
285 // translators: %s is offset.
286 $availableOffsets[ $i ] = ( 0 === $i ? __( "don't skip any field on a print sheet", 'packeta' ) : sprintf( __( 'skip %s fields on first sheet', 'packeta' ), $i ) );
287 }
288 $form->addSelect(
289 'offset',
290 __( 'Skip fields', 'packeta' ),
291 $availableOffsets
292 )->checkDefaultValue( false );
293
294 return $form;
295 }
296
297 /**
298 * Registers submenu item.
299 */
300 public function register(): void {
301 add_submenu_page(
302 \Packetery\Module\Options\Page::SLUG,
303 __( 'Print labels', 'packeta' ),
304 __( 'Print labels', 'packeta' ),
305 'manage_options',
306 self::MENU_SLUG,
307 array(
308 $this,
309 'render',
310 ),
311 20
312 );
313 }
314
315 /**
316 * Hides submenu item.
317 */
318 public function hideFromMenus(): void {
319 Plugin::hideSubmenuItem( self::MENU_SLUG );
320 }
321
322 /**
323 * Prepares labels.
324 *
325 * @param int $offset Offset value.
326 * @param array $packetIds Packet ids.
327 *
328 * @return Response\PacketsLabelsPdf|null
329 */
330 private function requestPacketaLabels( int $offset, array $packetIds ): ?Response\PacketsLabelsPdf {
331 $request = new Request\PacketsLabelsPdf( array_values( $packetIds ), $this->getLabelFormat(), $offset );
332 $response = $this->soapApiClient->packetsLabelsPdf( $request );
333 // TODO: is possible to merge following part of requestPacketaLabels and requestCarrierLabels?
334
335 foreach ( $packetIds as $orderId => $packetId ) {
336 $record = new Log\Record();
337 $record->action = Log\Record::ACTION_LABEL_PRINT;
338 $record->orderId = $orderId;
339
340 if ( ! $response->hasFault() ) {
341 $order = $this->orderRepository->getById( $orderId );
342 if ( null !== $order ) {
343 $order->setIsLabelPrinted( true );
344 $this->orderRepository->save( $order );
345 }
346
347 $record->status = Log\Record::STATUS_SUCCESS;
348 $record->title = __( 'Label has been printed successfully.', 'packeta' );
349 } else {
350 $record->status = Log\Record::STATUS_ERROR;
351 $record->title = __( 'Label could not be printed.', 'packeta' );
352 $record->params = [
353 'packetId' => $packetId,
354 'isPacketIdInvalid' => $response->hasInvalidPacketId( (string) $packetId ),
355 'request' => [
356 'packetIds' => $request->getPacketIds(),
357 'format' => $request->getFormat(),
358 'offset' => $request->getOffset(),
359 ],
360 'errorMessage' => $response->getFaultString(),
361 ];
362 }
363
364 $this->logger->add( $record );
365 }
366
367 return $response;
368 }
369
370 /**
371 * Prepares carrier labels.
372 *
373 * @param int $offset Offset value.
374 * @param array $packetIds Packet ids.
375 *
376 * @return Response\PacketsCourierLabelsPdf
377 */
378 private function requestCarrierLabels( int $offset, array $packetIds ): Response\PacketsCourierLabelsPdf {
379 $packetIdsWithCourierNumbers = $this->getPacketIdsWithCourierNumbers( $packetIds );
380 $request = new Request\PacketsCourierLabelsPdf( array_values( $packetIdsWithCourierNumbers ), $this->getLabelFormat(), $offset );
381 $response = $this->soapApiClient->packetsCarrierLabelsPdf( $request );
382
383 foreach ( $packetIdsWithCourierNumbers as $orderId => $pairItem ) {
384 $record = new Log\Record();
385 $record->action = Log\Record::ACTION_CARRIER_LABEL_PRINT;
386 $record->orderId = $orderId;
387
388 if ( ! $response->hasFault() ) {
389 $order = $this->orderRepository->getById( $orderId );
390 if ( null !== $order ) {
391 $order->setIsLabelPrinted( true );
392 $order->setCarrierNumber( $pairItem['courierNumber'] );
393 $this->orderRepository->save( $order );
394 }
395
396 $record->status = Log\Record::STATUS_SUCCESS;
397 $record->title = __( 'Carrier label has been printed successfully.', 'packeta' );
398 } else {
399 $record->status = Log\Record::STATUS_ERROR;
400 $record->title = __( 'Carrier label could not be printed.', 'packeta' );
401 $record->params = [
402 'packetId' => $pairItem['packetId'],
403 'courierNumber' => $pairItem['courierNumber'],
404 'isPacketIdInvalid' => $response->hasInvalidPacketId( (string) $pairItem['packetId'] ),
405 'isCourierNumberInvalid' => $response->hasInvalidCourierNumber( (string) $pairItem['courierNumber'] ),
406 'request' => [
407 'packetIdsWithCourierNumbers' => $request->getPacketIdsWithCourierNumbers(),
408 'format' => $request->getFormat(),
409 'offset' => $request->getOffset(),
410 ],
411 'errorMessage' => $response->getFaultString(),
412 ];
413 }
414
415 $this->logger->add( $record );
416 }
417
418 return $response;
419 }
420
421 /**
422 * Gets filename for label pdf.
423 *
424 * @return string
425 */
426 private function getFilename(): string {
427 return 'packeta_labels_' . strtolower( str_replace( ' ', '_', $this->getLabelFormat() ) ) . '.pdf';
428 }
429
430 /**
431 * Gets saved packet ids.
432 *
433 * @param array $orderIds Order IDs from transient.
434 * @param bool $isCarrierLabels Are carrier labels requested?.
435 *
436 * @return string[]
437 */
438 private function getPacketIdsFromTransient( array $orderIds, bool $isCarrierLabels ): array {
439 $orders = $this->orderRepository->getByIds( $orderIds );
440 $packetIds = [];
441 foreach ( $orders as $order ) {
442 if ( null === $order->getPacketId() ) {
443 continue;
444 }
445 if ( ! $isCarrierLabels || $order->isExternalCarrier() ) {
446 $packetIds[ $order->getNumber() ] = $order->getPacketId();
447 }
448 }
449
450 return $packetIds;
451 }
452
453 /**
454 * Gets order IDs transient.
455 *
456 * @return array|null
457 */
458 private function getOrderIdsTransient(): ?array {
459 $orderIds = get_transient( self::getOrderIdsTransientName() );
460 if ( is_array( $orderIds ) ) {
461 return $orderIds;
462 }
463
464 return null;
465 }
466
467 /**
468 * Gets carrier packet numbers from API.
469 *
470 * @param string[] $packetIds List of packet ids.
471 *
472 * @return array[]
473 */
474 private function getPacketIdsWithCourierNumbers( array $packetIds ): array {
475 $pairs = [];
476 foreach ( $packetIds as $orderId => $packetId ) {
477 $request = new Request\PacketCourierNumber( $packetId );
478 $response = $this->soapApiClient->packetCourierNumber( $request );
479 if ( $response->hasFault() ) {
480 if ( $response->hasWrongPassword() ) {
481 $this->messageManager->flash_message( __( 'Please set a proper API password.', 'packeta' ), MessageManager::TYPE_ERROR );
482
483 return [];
484 }
485
486 $record = new Log\Record();
487 $record->action = Log\Record::ACTION_CARRIER_NUMBER_RETRIEVING;
488 $record->status = Log\Record::STATUS_ERROR;
489 $record->title = __( 'Carrier number could not be retrieved.', 'packeta' );
490 $record->params = [
491 'packetId' => $request->getPacketId(),
492 'errorMessage' => $response->getFaultString(),
493 ];
494 $record->orderId = $orderId;
495 $this->logger->add( $record );
496 continue;
497 }
498 $pairs[ $orderId ] = [
499 'packetId' => $packetId,
500 'courierNumber' => $response->getNumber(),
501 ];
502 }
503
504 return $pairs;
505 }
506
507 }
508