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

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