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
packeta / src / Packetery / Module / Order / LabelPrint.php

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

509 lines 15.9 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 'packetery_label_print_back_link_' . 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 $record = new Log\Record();
299 $record->action = Log\Record::ACTION_LABEL_PRINT;
300 $record->orderId = $orderId;
301 $order = $this->orderRepository->getByIdWithValidCarrier( $orderId );
302
303 if ( ! $response->hasFault() ) {
304 if ( $order !== null ) {
305 $order->setIsLabelPrinted( true );
306 }
307
308 $record->status = Log\Record::STATUS_SUCCESS;
309 $record->title = __( 'Label has been printed successfully.', 'packeta' );
310 } else {
311 $record->status = Log\Record::STATUS_ERROR;
312 $record->title = __( 'Label could not be printed.', 'packeta' );
313 $record->params = [
314 'packetId' => $packetId,
315 'isPacketIdInvalid' => $response->hasInvalidPacketId( (string) $packetId ),
316 'request' => [
317 'packetIds' => $request->getPacketIds(),
318 'format' => $request->getFormat(),
319 'offset' => $request->getOffset(),
320 ],
321 'errorMessage' => $response->getFaultString(),
322 ];
323 }
324
325 $this->logger->add( $record );
326
327 if ( $order !== null ) {
328 $order->updateApiErrorMessage( $response->getFaultString() );
329 $this->orderRepository->save( $order );
330 }
331 }
332
333 return $response;
334 }
335
336 /**
337 * @param int $offset
338 * @param array[] $packetIdsWithCourierNumbers
339 */
340 private function requestCarrierLabels( int $offset, array $packetIdsWithCourierNumbers ): Response\PacketsCourierLabelsPdf {
341 $request = new Request\PacketsCourierLabelsPdf( array_values( $packetIdsWithCourierNumbers ), $this->labelPrintParametersService->getLabelFormat(), $offset );
342 $response = $this->soapApiClient->packetsCarrierLabelsPdf( $request );
343
344 foreach ( $packetIdsWithCourierNumbers as $orderId => $pairItem ) {
345 $record = new Log\Record();
346 $record->action = Log\Record::ACTION_CARRIER_LABEL_PRINT;
347 $record->orderId = $orderId;
348 $order = $this->orderRepository->getByIdWithValidCarrier( $orderId );
349
350 if ( ! $response->hasFault() ) {
351 if ( $order !== null ) {
352 $order->setIsLabelPrinted( true );
353 }
354
355 $record->status = Log\Record::STATUS_SUCCESS;
356 $record->title = __( 'Carrier label has been printed successfully.', 'packeta' );
357 } else {
358 $record->status = Log\Record::STATUS_ERROR;
359 $record->title = __( 'Carrier label could not be printed.', 'packeta' );
360 $record->params = [
361 'packetId' => $pairItem['packetId'],
362 'courierNumber' => $pairItem['courierNumber'],
363 'isPacketIdInvalid' => $response->hasInvalidPacketId( (string) $pairItem['packetId'] ),
364 'isCourierNumberInvalid' => $response->hasInvalidCourierNumber( (string) $pairItem['courierNumber'] ),
365 'request' => [
366 'packetIdsWithCourierNumbers' => $request->getPacketIdsWithCourierNumbers(),
367 'format' => $request->getFormat(),
368 'offset' => $request->getOffset(),
369 ],
370 'errorMessage' => $response->getFaultString(),
371 ];
372 }
373 $this->logger->add( $record );
374
375 if ( $order !== null ) {
376 $order->updateApiErrorMessage( $response->getFaultString() );
377 $this->orderRepository->save( $order );
378 }
379 }
380
381 return $response;
382 }
383
384 /**
385 * Gets filename for label pdf.
386 *
387 * @return string
388 */
389 private function getFilename(): string {
390 return 'packeta_labels_' . strtolower( str_replace( ' ', '_', $this->labelPrintParametersService->getLabelFormat() ) ) . '.pdf';
391 }
392
393 /**
394 * @param string[] $orderIds Order IDs from transient.
395 * @return string[]
396 */
397 private function getPacketIdsFromTransient( array $orderIds, bool $isCarrierLabels ): array {
398 $orders = $this->orderRepository->getByIds( $orderIds );
399 $packetIds = [];
400 foreach ( $orders as $order ) {
401 if ( $order->getPacketId() === null ) {
402 continue;
403 }
404 if ( ! $isCarrierLabels || $order->isExternalCarrier() ) {
405 $packetIds[ $order->getNumber() ] = $order->getPacketId();
406 }
407 }
408
409 return $packetIds;
410 }
411
412 /**
413 * @return string[]|null
414 */
415 private function getOrderIdsTransient(): ?array {
416 $orderIds = get_transient( self::getOrderIdsTransientName() );
417 if ( is_array( $orderIds ) ) {
418 return $orderIds;
419 }
420
421 return null;
422 }
423
424 /**
425 * Saves information about the creation of the label in the order note.
426 */
427 private function addLabelCreationInfoToWcOrderNote( int $orderId, string $packetId, ?ILabelResponse $response ): void {
428 $order = $this->orderRepository->findById( $orderId );
429 $wcOrder = $this->orderRepository->getWcOrderById( $orderId );
430 if ( $wcOrder === null || $order === null ) {
431 return;
432 }
433
434 $linkText = $order->getPacketBarcode();
435 $trackingUrl = $order->getPacketTrackingUrl();
436 if ( $response instanceof Response\PacketsLabelsPdf ) {
437 if ( $order->isPacketClaim( $packetId ) ) {
438 // translators: %s represents a packet tracking link.
439 $message = __( 'Packeta: Label for packet claim %s has been created', 'packeta' );
440 $linkText = $order->getPacketClaimBarcode();
441 $trackingUrl = $order->getPacketClaimTrackingUrl();
442 } else {
443 // translators: %s represents a packet tracking link.
444 $message = __( 'Packeta: Label for packet %s has been created', 'packeta' );
445 }
446 } else {
447 // Response is of type Response\PacketsCourierLabelsPdf or null.
448 // translators: %s represents a packet tracking link.
449 $message = __( 'Packeta: Carrier label for packet %s has been created', 'packeta' );
450 }
451
452 $wcOrder->add_order_note(
453 sprintf(
454 $message,
455 $this->moduleHelper->createHtmlLink( $trackingUrl, $linkText )
456 )
457 );
458 $wcOrder->save();
459 }
460
461 public function flashMessageAndRedirect( string $message, ?int $orderId ): void {
462 $this->messageManager->flash_message( $message, MessageManager::TYPE_ERROR );
463
464 $redirectTo = $this->httpRequest->getQuery( PacketActionsCommonLogic::PARAM_REDIRECT_TO );
465 if ( $redirectTo === PacketActionsCommonLogic::REDIRECT_TO_ORDER_DETAIL && $orderId !== null ) {
466 $this->packetActionsCommonLogic->redirectTo( $redirectTo, $this->orderRepository->findById( $orderId ) );
467 }
468 $this->packetActionsCommonLogic->redirectTo( PacketActionsCommonLogic::REDIRECT_TO_ORDER_GRID );
469 }
470
471 /**
472 * @param bool $isCarrierLabels
473 * @param array<string, string> $packetIds
474 * @param bool $fallbackToPacketaLabel
475 * @param int|null $orderId
476 * @param int $offset
477 *
478 * @return Response\PacketsCourierLabelsPdf|Response\PacketsLabelsPdf|null
479 */
480 private function getResponse(
481 bool $isCarrierLabels,
482 array $packetIds,
483 bool $fallbackToPacketaLabel,
484 ?int $orderId,
485 int $offset
486 ) {
487 if ( $isCarrierLabels === false ) {
488 return $this->requestPacketaLabels( $offset, $packetIds );
489 }
490
491 $packetIdsWithCourierNumbers = $this->carrierLabelService->getPacketIdsWithCourierNumbers( $packetIds );
492 if ( $fallbackToPacketaLabel === false && $packetIdsWithCourierNumbers === [] ) {
493 $this->flashMessageAndRedirect(
494 (string) $this->wpAdapter->__( 'Carrier label printing failed, you can find more information in the Packeta log.', 'packeta' ),
495 $orderId
496 );
497
498 return null;
499 }
500
501 $response = $this->requestCarrierLabels( $offset, $packetIdsWithCourierNumbers );
502 if ( $fallbackToPacketaLabel === true && $response->hasFault() ) {
503 return $this->requestPacketaLabels( $offset, $packetIds );
504 }
505
506 return $response;
507 }
508 }
509