PluginProbe
Packeta / trunk
Packeta vtrunk
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 trunk, at src/Packetery/Module/Order/LabelPrint.php

557 lines 17.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare( strict_types=1 );
4
5 namespace Packetery\Module\Order;
6
7 use Packetery\Core\Api\Soap\Client;
8 use Packetery\Core\Api\Soap\ILabelResponse;
9 use Packetery\Core\Api\Soap\Request;
10 use Packetery\Core\Api\Soap\Response;
11 use Packetery\Core\Log;
12 use Packetery\Latte\Engine;
13 use Packetery\Module\Dashboard\DashboardPage;
14 use Packetery\Module\Framework\WpAdapter;
15 use Packetery\Module\Labels\CarrierLabelService;
16 use Packetery\Module\Labels\LabelPrintParametersService;
17 use Packetery\Module\MessageManager;
18 use Packetery\Module\ModuleHelper;
19 use Packetery\Module\Options\OptionsProvider;
20 use Packetery\Module\Plugin;
21 use Packetery\Module\Transients;
22 use Packetery\Nette\Http;
23
24 class LabelPrint {
25
26 public const ACTION_PACKETA_LABELS = 'print_packeta_labels';
27 public const ACTION_CARRIER_LABELS = 'print_carrier_labels';
28 public const LABEL_TYPE_PARAM = 'label_type';
29 public const MENU_SLUG = 'label-print';
30
31 /**
32 * @var Engine
33 */
34 private $latteEngine;
35
36 /**
37 * @var OptionsProvider
38 */
39 private $optionsProvider;
40
41 /**
42 * @var Http\Request
43 */
44 private $httpRequest;
45
46 /**
47 * @var Client
48 */
49 private $soapApiClient;
50
51 /**
52 * @var MessageManager
53 */
54 private $messageManager;
55
56 /**
57 * @var Log\ILogger
58 */
59 private $logger;
60
61 /**
62 * @var Repository
63 */
64 private $orderRepository;
65
66 /**
67 * @var PacketActionsCommonLogic
68 */
69 private $packetActionsCommonLogic;
70
71 /**
72 * @var ModuleHelper
73 */
74 private $moduleHelper;
75
76 /**
77 * @var WpAdapter
78 */
79 private $wpAdapter;
80
81 /**
82 * @var CarrierLabelService
83 */
84 private $carrierLabelService;
85
86 /**
87 * @var LabelPrintParametersService
88 */
89 private $labelPrintParametersService;
90
91 public function __construct(
92 Engine $latteEngine,
93 OptionsProvider $optionsProvider,
94 Http\Request $httpRequest,
95 Client $soapApiClient,
96 MessageManager $messageManager,
97 Log\ILogger $logger,
98 Repository $orderRepository,
99 PacketActionsCommonLogic $packetActionsCommonLogic,
100 ModuleHelper $moduleHelper,
101 WpAdapter $wpAdapter,
102 CarrierLabelService $carrierLabelService,
103 LabelPrintParametersService $labelPrintParametersService
104 ) {
105 $this->latteEngine = $latteEngine;
106 $this->optionsProvider = $optionsProvider;
107 $this->httpRequest = $httpRequest;
108 $this->soapApiClient = $soapApiClient;
109 $this->messageManager = $messageManager;
110 $this->logger = $logger;
111 $this->orderRepository = $orderRepository;
112 $this->packetActionsCommonLogic = $packetActionsCommonLogic;
113 $this->moduleHelper = $moduleHelper;
114 $this->wpAdapter = $wpAdapter;
115 $this->carrierLabelService = $carrierLabelService;
116 $this->labelPrintParametersService = $labelPrintParametersService;
117 }
118
119 /**
120 * Generates id of transient to store order ids.
121 *
122 * @return string
123 */
124 public static function getOrderIdsTransientName(): string {
125 return Transients::LABEL_PRINT_ORDER_IDS_PREFIX . wp_get_session_token();
126 }
127
128 /**
129 * Generates id of transient to store back link.
130 *
131 * @return string
132 */
133 public static function getBackLinkTransientName(): string {
134 return Transients::LABEL_PRINT_BACK_LINK_PREFIX . wp_get_session_token();
135 }
136
137 /**
138 * Prepares form and renders template.
139 */
140 public function render(): void {
141 $form = $this->labelPrintParametersService->createForm( $this->optionsProvider->getLabelMaxOffset( $this->labelPrintParametersService->getLabelFormat() ) );
142
143 $count = 0;
144 $isCarrierLabels = ( $this->httpRequest->getQuery( self::LABEL_TYPE_PARAM ) === self::ACTION_CARRIER_LABELS );
145
146 $orderIdsTransient = $this->getOrderIdsTransient();
147 if ( $orderIdsTransient !== null ) {
148 $orderIds = $this->getPacketIdsFromTransient( $orderIdsTransient, $isCarrierLabels );
149 $count = count( $orderIds );
150 } else {
151 $this->messageManager->flash_message( __( 'No orders were selected', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, self::MENU_SLUG );
152 }
153
154 $this->latteEngine->render(
155 PACKETERY_PLUGIN_DIR . '/template/order/label-print.latte',
156 [
157 'form' => $form,
158 'count' => $count,
159 'backLink' => get_transient( self::getBackLinkTransientName() ),
160 'flashMessages' => $this->messageManager->renderToString( MessageManager::RENDERER_PACKETERY, self::MENU_SLUG ),
161 'translations' => [
162 'packeta' => __( 'Packeta', 'packeta' ),
163 'labelPrinting' => __( 'Print labels', 'packeta' ),
164 // translators: %s is count.
165 'numberOfLabelsToPrint' => __( 'Number of labels to print: %s', 'packeta' ),
166
167 'back' => __( 'Back', 'packeta' ),
168 'printLabels' => __( 'Print labels', 'packeta' ),
169 ],
170 ]
171 );
172 }
173
174 public function outputLabelsPdf(): void {
175 if ( $this->httpRequest->getQuery( 'page' ) !== self::MENU_SLUG ) {
176 return;
177 }
178
179 $fallbackToPacketaLabel = false;
180 $isCarrierLabels = ( $this->httpRequest->getQuery( self::LABEL_TYPE_PARAM ) === self::ACTION_CARRIER_LABELS );
181 $orderIdParam = $this->httpRequest->getQuery( 'id' ) !== null ? (int) $this->httpRequest->getQuery( 'id' ) : null;
182 $packetIdParam = $this->httpRequest->getQuery( 'packet_id' );
183 if ( $orderIdParam !== null && $packetIdParam !== null ) {
184 $fallbackToPacketaLabel = true;
185 $packetIds = [ $orderIdParam => $packetIdParam ];
186 } else {
187 $orderIdsTransient = $this->getOrderIdsTransient();
188 if ( $orderIdsTransient === null ) {
189 return;
190 }
191
192 $packetIds = $this->getPacketIdsFromTransient( $orderIdsTransient, $isCarrierLabels );
193 }
194 $packetIds = $this->labelPrintParametersService->removeExternalCarrierPacketIds( $packetIds, $isCarrierLabels, $fallbackToPacketaLabel );
195
196 if ( count( $packetIds ) === 0 ) {
197 if ( $isCarrierLabels === true ) {
198 $this->messageManager->flash_message(
199 $this->wpAdapter->__( 'No orders have been selected for Packeta carriers', 'packeta' ),
200 'info'
201 );
202 } else {
203 $this->messageManager->flash_message(
204 $this->wpAdapter->__( 'No orders have been selected for Packeta pick-up points', 'packeta' ),
205 'info'
206 );
207 }
208
209 $this->packetActionsCommonLogic->redirectTo( PacketActionsCommonLogic::REDIRECT_TO_ORDER_GRID );
210
211 return;
212 }
213
214 $offset = $this->labelPrintParametersService->getOffset();
215 if ( $offset === null ) {
216 return;
217 }
218
219 $response = $this->getResponse( $isCarrierLabels, $packetIds, $fallbackToPacketaLabel, $orderIdParam, $offset );
220 if ( $response === null ) {
221 return;
222 }
223
224 if ( $response->hasFault() ) {
225 if ( $fallbackToPacketaLabel === true && count( $packetIds ) === 1 ) {
226 $message = sprintf(
227 // translators: %s represents shipment tracking number
228 $this->wpAdapter->__( 'Label printing for shipment %s failed, you can find more information in the Packeta log.', 'packeta' ),
229 array_shift( $packetIds )
230 );
231 } elseif ( $isCarrierLabels === true ) {
232 $message = sprintf(
233 // translators: %s represents error message
234 $this->wpAdapter->__( 'Carrier label printing failed, you can find more information in the Packeta log. Error: %s', 'packeta' ),
235 $response->getFaultString()
236 );
237 } else {
238 $message = sprintf(
239 // translators: %s represents error message
240 $this->wpAdapter->__( 'Label printing failed, you can find more information in the Packeta log. Error: %s', 'packeta' ),
241 $response->getFaultString()
242 );
243 }
244
245 $this->flashMessageAndRedirect( $message, $orderIdParam );
246
247 return;
248 }
249
250 foreach ( $packetIds as $orderId => $packetId ) {
251 $this->addLabelCreationInfoToWcOrderNote( $orderId, $packetId, $response );
252 }
253
254 header( 'Content-Type: application/pdf' );
255 header( 'Content-Transfer-Encoding: Binary' );
256 header( 'Content-Length: ' . strlen( $response->getPdfContents() ) );
257 header( 'Content-Disposition: attachment; filename="' . $this->getFilename() . '"' );
258 // @codingStandardsIgnoreStart
259 echo $response->getPdfContents();
260 // @codingStandardsIgnoreEnd
261 exit;
262 }
263
264 /**
265 * Registers submenu item.
266 */
267 public function register(): void {
268 add_submenu_page(
269 DashboardPage::SLUG,
270 __( 'Print labels', 'packeta' ),
271 __( 'Print labels', 'packeta' ),
272 'manage_woocommerce',
273 self::MENU_SLUG,
274 array(
275 $this,
276 'render',
277 ),
278 20
279 );
280 }
281
282 /**
283 * Hides submenu item.
284 */
285 public function hideFromMenus(): void {
286 Plugin::hideSubmenuItem( self::MENU_SLUG );
287 }
288
289 /**
290 * @param int $offset
291 * @param string[] $packetIds
292 */
293 private function requestPacketaLabels( int $offset, array $packetIds ): Response\PacketsLabelsPdf {
294 $request = new Request\PacketsLabelsPdf( array_values( $packetIds ), $this->labelPrintParametersService->getLabelFormat(), $offset );
295 $response = $this->soapApiClient->packetsLabelsPdf( $request );
296
297 foreach ( $packetIds as $orderId => $packetId ) {
298 $isClaimAssistantLabel = false;
299 $order = $this->orderRepository->getByIdWithValidCarrier( $orderId );
300
301 if ( $order === null ) {
302 // TODO Only a temporary solution to prevent a situation where the order is null and we are unable to verify whether it is a printout from the claim assistant form.
303 // TODO Needs to be refactored - ticket PES-2896
304 $this->logLabelPrintWithoutWcOrder( $orderId, $packetId, $response, $request );
305
306 continue;
307 }
308
309 if ( $order->isPacketClaim( $packetId ) ) {
310 $isClaimAssistantLabel = true;
311 }
312
313 $record = new Log\Record();
314 $record->action = $isClaimAssistantLabel ? Log\Record::ACTION_CLAIM_LABEL_PRINT : Log\Record::ACTION_LABEL_PRINT;
315 $record->orderId = $orderId;
316
317 if ( ! $response->hasFault() ) {
318 if ( $isClaimAssistantLabel === false ) {
319 $order->setIsLabelPrinted( true );
320 }
321
322 $record->status = Log\Record::STATUS_SUCCESS;
323 if ( $isClaimAssistantLabel === true ) {
324 $record->title = $this->wpAdapter->__( 'Claim assistant label was printed successfully.', 'packeta' );
325 } else {
326 $record->title = $this->wpAdapter->__( 'Label was printed successfully.', 'packeta' );
327 }
328 } else {
329 $record->status = Log\Record::STATUS_ERROR;
330 if ( $isClaimAssistantLabel === true ) {
331 $record->title = $this->wpAdapter->__( 'Claim assistant label could not be printed.', 'packeta' );
332 } else {
333 $record->title = $this->wpAdapter->__( 'Label could not be printed.', 'packeta' );
334 }
335 $record->params = [
336 'packetId' => $packetId,
337 'isPacketIdInvalid' => $response->hasInvalidPacketId( (string) $packetId ),
338 'request' => [
339 'packetIds' => $request->getPacketIds(),
340 'format' => $request->getFormat(),
341 'offset' => $request->getOffset(),
342 ],
343 'errorMessage' => $response->getFaultString(),
344 ];
345 }
346
347 $this->logger->add( $record );
348
349 $order->updateApiErrorMessage( $response->getFaultString() );
350 $this->orderRepository->save( $order );
351 }
352
353 return $response;
354 }
355
356 /**
357 * @param int $offset
358 * @param array[] $packetIdsWithCourierNumbers
359 */
360 private function requestCarrierLabels( int $offset, array $packetIdsWithCourierNumbers ): Response\PacketsCourierLabelsPdf {
361 $request = new Request\PacketsCourierLabelsPdf( array_values( $packetIdsWithCourierNumbers ), $this->labelPrintParametersService->getLabelFormat(), $offset );
362 $response = $this->soapApiClient->packetsCarrierLabelsPdf( $request );
363
364 foreach ( $packetIdsWithCourierNumbers as $orderId => $pairItem ) {
365 $record = new Log\Record();
366 $record->action = Log\Record::ACTION_CARRIER_LABEL_PRINT;
367 $record->orderId = $orderId;
368 $order = $this->orderRepository->getByIdWithValidCarrier( $orderId );
369
370 if ( ! $response->hasFault() ) {
371 if ( $order !== null ) {
372 $order->setIsLabelPrinted( true );
373 }
374
375 $record->status = Log\Record::STATUS_SUCCESS;
376 $record->title = __( 'Carrier label has been printed successfully.', 'packeta' );
377 } else {
378 $record->status = Log\Record::STATUS_ERROR;
379 $record->title = __( 'Carrier label could not be printed.', 'packeta' );
380 $record->params = [
381 'packetId' => $pairItem['packetId'],
382 'courierNumber' => $pairItem['courierNumber'],
383 'isPacketIdInvalid' => $response->hasInvalidPacketId( (string) $pairItem['packetId'] ),
384 'isCourierNumberInvalid' => $response->hasInvalidCourierNumber( (string) $pairItem['courierNumber'] ),
385 'request' => [
386 'packetIdsWithCourierNumbers' => $request->getPacketIdsWithCourierNumbers(),
387 'format' => $request->getFormat(),
388 'offset' => $request->getOffset(),
389 ],
390 'errorMessage' => $response->getFaultString(),
391 ];
392 }
393 $this->logger->add( $record );
394
395 if ( $order !== null ) {
396 $order->updateApiErrorMessage( $response->getFaultString() );
397 $this->orderRepository->save( $order );
398 }
399 }
400
401 return $response;
402 }
403
404 /**
405 * Gets filename for label pdf.
406 *
407 * @return string
408 */
409 private function getFilename(): string {
410 return 'packeta_labels_' . strtolower( str_replace( ' ', '_', $this->labelPrintParametersService->getLabelFormat() ) ) . '.pdf';
411 }
412
413 /**
414 * @param string[] $orderIds Order IDs from transient.
415 * @return string[]
416 */
417 private function getPacketIdsFromTransient( array $orderIds, bool $isCarrierLabels ): array {
418 $orders = $this->orderRepository->getByIds( $orderIds );
419 $packetIds = [];
420 foreach ( $orders as $order ) {
421 if ( $order->getPacketId() === null ) {
422 continue;
423 }
424 if ( ! $isCarrierLabels || $order->isExternalCarrier() ) {
425 $packetIds[ $order->getNumber() ] = $order->getPacketId();
426 }
427 }
428
429 return $packetIds;
430 }
431
432 /**
433 * @return string[]|null
434 */
435 private function getOrderIdsTransient(): ?array {
436 $orderIds = get_transient( self::getOrderIdsTransientName() );
437 if ( is_array( $orderIds ) ) {
438 return $orderIds;
439 }
440
441 return null;
442 }
443
444 /**
445 * Saves information about the creation of the label in the order note.
446 */
447 private function addLabelCreationInfoToWcOrderNote( int $orderId, string $packetId, ?ILabelResponse $response ): void {
448 $order = $this->orderRepository->findById( $orderId );
449 $wcOrder = $this->orderRepository->getWcOrderById( $orderId );
450 if ( $wcOrder === null || $order === null ) {
451 return;
452 }
453
454 $linkText = $order->getPacketBarcode();
455 $trackingUrl = $order->getPacketTrackingUrl();
456 if ( $response instanceof Response\PacketsLabelsPdf ) {
457 if ( $order->isPacketClaim( $packetId ) ) {
458 // translators: %s represents a packet tracking link.
459 $message = __( 'Packeta: Label for packet claim %s has been created', 'packeta' );
460 $linkText = $order->getPacketClaimBarcode();
461 $trackingUrl = $order->getPacketClaimTrackingUrl();
462 } else {
463 // translators: %s represents a packet tracking link.
464 $message = __( 'Packeta: Label for packet %s has been created', 'packeta' );
465 }
466 } else {
467 // Response is of type Response\PacketsCourierLabelsPdf or null.
468 // translators: %s represents a packet tracking link.
469 $message = __( 'Packeta: Carrier label for packet %s has been created', 'packeta' );
470 }
471
472 $wcOrder->add_order_note(
473 sprintf(
474 $message,
475 $this->moduleHelper->createHtmlLink( $trackingUrl, $linkText )
476 )
477 );
478 $wcOrder->save();
479 }
480
481 /**
482 * Logs label print operation when there is no WooCommerce order.
483 */
484 private function logLabelPrintWithoutWcOrder( int $orderId, string $packetId, Response\PacketsLabelsPdf $response, Request\PacketsLabelsPdf $request ): void {
485 $record = new Log\Record();
486 $record->action = Log\Record::ACTION_LABEL_PRINT;
487 $record->orderId = $orderId;
488
489 if ( ! $response->hasFault() ) {
490 $record->status = Log\Record::STATUS_SUCCESS;
491 $record->title = $this->wpAdapter->__( 'Label was printed successfully.', 'packeta' );
492 } else {
493 $record->status = Log\Record::STATUS_ERROR;
494 $record->title = $this->wpAdapter->__( 'Label could not be printed.', 'packeta' );
495 }
496 $record->params = [
497 'packetId' => $packetId,
498 'isPacketIdInvalid' => $response->hasInvalidPacketId( $packetId ),
499 'request' => [
500 'packetIds' => $request->getPacketIds(),
501 'format' => $request->getFormat(),
502 'offset' => $request->getOffset(),
503 ],
504 'errorMessage' => $response->getFaultString(),
505 ];
506 $this->logger->add( $record );
507 }
508
509 public function flashMessageAndRedirect( string $message, ?int $orderId ): void {
510 $this->messageManager->flash_message( $message, MessageManager::TYPE_ERROR );
511
512 $redirectTo = $this->httpRequest->getQuery( PacketActionsCommonLogic::PARAM_REDIRECT_TO );
513 if ( $redirectTo === PacketActionsCommonLogic::REDIRECT_TO_ORDER_DETAIL && $orderId !== null ) {
514 $this->packetActionsCommonLogic->redirectTo( $redirectTo, $this->orderRepository->findById( $orderId ) );
515 }
516 $this->packetActionsCommonLogic->redirectTo( PacketActionsCommonLogic::REDIRECT_TO_ORDER_GRID );
517 }
518
519 /**
520 * @param bool $isCarrierLabels
521 * @param array<string, string> $packetIds
522 * @param bool $fallbackToPacketaLabel
523 * @param int|null $orderId
524 * @param int $offset
525 *
526 * @return Response\PacketsCourierLabelsPdf|Response\PacketsLabelsPdf|null
527 */
528 private function getResponse(
529 bool $isCarrierLabels,
530 array $packetIds,
531 bool $fallbackToPacketaLabel,
532 ?int $orderId,
533 int $offset
534 ) {
535 if ( $isCarrierLabels === false ) {
536 return $this->requestPacketaLabels( $offset, $packetIds );
537 }
538
539 $packetIdsWithCourierNumbers = $this->carrierLabelService->getPacketIdsWithCourierNumbers( $packetIds );
540 if ( $fallbackToPacketaLabel === false && $packetIdsWithCourierNumbers === [] ) {
541 $this->flashMessageAndRedirect(
542 (string) $this->wpAdapter->__( 'Carrier label printing failed, you can find more information in the Packeta log.', 'packeta' ),
543 $orderId
544 );
545
546 return null;
547 }
548
549 $response = $this->requestCarrierLabels( $offset, $packetIdsWithCourierNumbers );
550 if ( $fallbackToPacketaLabel === true && $response->hasFault() ) {
551 return $this->requestPacketaLabels( $offset, $packetIds );
552 }
553
554 return $response;
555 }
556 }
557