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

459 lines 13.1 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 ]
162 );
163 }
164
165 /**
166 * Gets label format for current job.
167 *
168 * @return string
169 */
170 private function getLabelFormat(): string {
171 $packetaLabelFormat = ( $this->optionsProvider->get_packeta_label_format() ?? '' );
172 $carrierLabelFormat = ( $this->optionsProvider->get_carrier_label_format() ?? '' );
173
174 return ( $this->httpRequest->getQuery( self::LABEL_TYPE_PARAM ) === self::ACTION_CARRIER_LABELS ? $carrierLabelFormat : $packetaLabelFormat );
175 }
176
177 /**
178 * Outputs pdf.
179 */
180 public function outputLabelsPdf(): void {
181 if ( $this->httpRequest->getQuery( 'page' ) !== self::MENU_SLUG ) {
182 return;
183 }
184
185 $fallbackToPacketaLabel = false;
186 $isCarrierLabels = ( $this->httpRequest->getQuery( self::LABEL_TYPE_PARAM ) === self::ACTION_CARRIER_LABELS );
187 $idParam = $this->httpRequest->getQuery( 'id' );
188 $packetIdParam = $this->httpRequest->getQuery( 'packet_id' );
189 if ( null !== $idParam && null !== $packetIdParam ) {
190 $fallbackToPacketaLabel = true;
191 $packetIds = [ $idParam => $packetIdParam ];
192 } else {
193 if ( ! get_transient( self::getOrderIdsTransientName() ) ) {
194 $this->messageManager->flash_message( __( 'noOrdersSelected', 'packetery' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, self::MENU_SLUG );
195
196 return;
197 }
198
199 $packetIds = $this->getPacketIdsFromTransient( $isCarrierLabels );
200 }
201 if ( ! $packetIds ) {
202 $this->messageManager->flash_message( __( 'noSuitableOrdersSelected', 'packetery' ), 'info' );
203 if ( wp_safe_redirect( add_query_arg( [ 'post_type' => 'shop_order' ], admin_url( 'edit.php' ) ) ) ) {
204 exit;
205 }
206 return;
207 }
208
209 $maxOffset = $this->optionsProvider->getLabelMaxOffset( $this->getLabelFormat() );
210 $form = $this->createForm( $maxOffset );
211 $offsetParam = $this->httpRequest->getQuery( 'offset' );
212 if ( 0 === $maxOffset ) {
213 $offset = 0;
214 } elseif ( null !== $offsetParam ) {
215 $offset = (int) $offsetParam;
216 } elseif ( $form->isSubmitted() ) {
217 $data = $form->getValues( 'array' );
218 $offset = $data['offset'];
219 } else {
220 return;
221 }
222
223 if ( $isCarrierLabels ) {
224 $response = $this->requestCarrierLabels( $offset, $packetIds );
225 if ( $fallbackToPacketaLabel && $response->hasFault() ) {
226 $response = $this->requestPacketaLabels( $offset, $packetIds );
227 }
228 } else {
229 $response = $this->requestPacketaLabels( $offset, $packetIds );
230 }
231 if ( ! $response || $response->hasFault() ) {
232 $message = ( null !== $response && $response->hasFault() ) ?
233 __( 'labelPrintFailedMoreInfoInLog', 'packetery' ) :
234 __( 'youSelectedOrdersThatWereNotSubmitted', 'packetery' );
235 $this->messageManager->flash_message( $message, MessageManager::TYPE_ERROR );
236 if ( wp_safe_redirect( 'edit.php?post_type=shop_order' ) ) {
237 exit;
238 }
239 }
240
241 header( 'Content-Type: application/pdf' );
242 header( 'Content-Transfer-Encoding: Binary' );
243 header( 'Content-Length: ' . strlen( $response->getPdfContents() ) );
244 header( 'Content-Disposition: attachment; filename="' . $this->getFilename() . '"' );
245 // @codingStandardsIgnoreStart
246 echo $response->getPdfContents();
247 // @codingStandardsIgnoreEnd
248 exit;
249 }
250
251 /**
252 * Creates offset setting form.
253 *
254 * @param int $maxOffset Maximal offset.
255 *
256 * @return Form
257 */
258 public function createForm( int $maxOffset ): Form {
259 $form = $this->formFactory->create();
260
261 $availableOffsets = [];
262 for ( $i = 0; $i <= $maxOffset; $i ++ ) {
263 // translators: %s is offset.
264 $availableOffsets[ $i ] = ( 0 === $i ? __( 'dontSkipAnyField', 'packetery' ) : sprintf( __( 'skip%sFields', 'packetery' ), $i ) );
265 }
266 $form->addSelect(
267 'offset',
268 __( 'labelsOffset', 'packetery' ),
269 $availableOffsets
270 )->checkDefaultValue( false );
271
272 return $form;
273 }
274
275 /**
276 * Registers submenu item.
277 */
278 public function register(): void {
279 add_submenu_page(
280 \Packetery\Module\Options\Page::SLUG,
281 __( 'printLabels', 'packetery' ),
282 __( 'printLabels', 'packetery' ),
283 'manage_options',
284 self::MENU_SLUG,
285 array(
286 $this,
287 'render',
288 ),
289 20
290 );
291 }
292
293 /**
294 * Hides submenu item.
295 */
296 public function hideFromMenus(): void {
297 Plugin::hideSubmenuItem( self::MENU_SLUG );
298 }
299
300 /**
301 * Prepares labels.
302 *
303 * @param int $offset Offset value.
304 * @param array $packetIds Packet ids.
305 *
306 * @return Response\PacketsLabelsPdf|null
307 */
308 private function requestPacketaLabels( int $offset, array $packetIds ): ?Response\PacketsLabelsPdf {
309 $request = new Request\PacketsLabelsPdf( array_values( $packetIds ), $this->getLabelFormat(), $offset );
310 $response = $this->soapApiClient->packetsLabelsPdf( $request );
311 // TODO: is possible to merge following part of requestPacketaLabels and requestCarrierLabels?
312 $record = new Log\Record();
313 $record->action = Log\Record::ACTION_LABEL_PRINT;
314 if ( ! $response->hasFault() ) {
315 foreach ( array_keys( $packetIds ) as $orderId ) {
316 $order = $this->orderRepository->getById( $orderId );
317 if ( null === $order ) { // Collection was already limited, so we do not need to log this.
318 continue;
319 }
320 $order->setIsLabelPrinted( true );
321 $this->orderRepository->save( $order );
322 }
323
324 $record->status = Log\Record::STATUS_SUCCESS;
325 $record->title = __( 'labelPrintSuccessLogTitle', 'packetery' );
326 } else {
327 $record->status = Log\Record::STATUS_ERROR;
328 $record->title = __( 'labelPrintErrorLogTitle', 'packetery' );
329 $record->params = [
330 'request' => [
331 'packetIds' => implode( ',', $request->getPacketIds() ),
332 'format' => $request->getFormat(),
333 'offset' => $request->getOffset(),
334 ],
335 'errorMessage' => $response->getFaultString(),
336 ];
337 }
338 $this->logger->add( $record );
339
340 return $response;
341 }
342
343 /**
344 * Prepares carrier labels.
345 *
346 * @param int $offset Offset value.
347 * @param array $packetIds Packet ids.
348 *
349 * @return Response\PacketsCourierLabelsPdf
350 */
351 private function requestCarrierLabels( int $offset, array $packetIds ): Response\PacketsCourierLabelsPdf {
352 $packetIdsWithCourierNumbers = $this->getPacketIdsWithCourierNumbers( $packetIds );
353 $request = new Request\PacketsCourierLabelsPdf( array_values( $packetIdsWithCourierNumbers ), $this->getLabelFormat(), $offset );
354 $response = $this->soapApiClient->packetsCarrierLabelsPdf( $request );
355 $record = new Log\Record();
356 $record->action = Log\Record::ACTION_CARRIER_LABEL_PRINT;
357 if ( ! $response->hasFault() ) {
358 foreach ( array_keys( $packetIdsWithCourierNumbers ) as $orderId ) {
359 $order = $this->orderRepository->getById( $orderId );
360 if ( null === $order ) { // Collection was already limited, so we do not need to log this.
361 continue;
362 }
363 $order->setIsLabelPrinted( true );
364 $order->setCarrierNumber( $packetIdsWithCourierNumbers[ $orderId ]['courierNumber'] );
365 $this->orderRepository->save( $order );
366 }
367
368 $record->status = Log\Record::STATUS_SUCCESS;
369 $record->title = __( 'carrierLabelPrintSuccessLogTitle', 'packetery' );
370 } else {
371 $record->status = Log\Record::STATUS_ERROR;
372 $record->title = __( 'carrierLabelPrintErrorLogTitle', 'packetery' );
373 $record->params = [
374 'request' => [
375 'packetIdsWithCourierNumbers' => $request->getPacketIdsWithCourierNumbers(),
376 'format' => $request->getFormat(),
377 'offset' => $request->getOffset(),
378 ],
379 'errorMessage' => $response->getFaultString(),
380 ];
381 }
382 $this->logger->add( $record );
383
384 return $response;
385 }
386
387 /**
388 * Gets filename for label pdf.
389 *
390 * @return string
391 */
392 private function getFilename(): string {
393 return 'packeta_labels_' . strtolower( str_replace( ' ', '_', $this->getLabelFormat() ) ) . '.pdf';
394 }
395
396 /**
397 * Gets saved packet ids.
398 *
399 * @param bool $isCarrierLabels Are carrier labels requested?.
400 *
401 * @return string[]
402 */
403 private function getPacketIdsFromTransient( bool $isCarrierLabels ): array {
404 $orderIds = get_transient( self::getOrderIdsTransientName() );
405 $orders = $this->orderRepository->getByIds( $orderIds );
406 $packetIds = [];
407 foreach ( $orders as $order ) {
408 if ( null === $order->getPacketId() ) {
409 continue;
410 }
411 if ( ! $isCarrierLabels || $order->isExternalCarrier() ) {
412 $packetIds[ $order->getNumber() ] = $order->getPacketId();
413 }
414 }
415
416 return $packetIds;
417 }
418
419 /**
420 * Gets carrier packet numbers from API.
421 *
422 * @param string[] $packetIds List of packet ids.
423 *
424 * @return array[]
425 */
426 private function getPacketIdsWithCourierNumbers( array $packetIds ): array {
427 $pairs = [];
428 foreach ( $packetIds as $orderId => $packetId ) {
429 $request = new Request\PacketCourierNumber( $packetId );
430 $response = $this->soapApiClient->packetCourierNumber( $request );
431 if ( $response->hasFault() ) {
432 if ( $response->hasWrongPassword() ) {
433 $this->messageManager->flash_message( __( 'pleaseSetProperPassword', 'packetery' ), MessageManager::TYPE_ERROR );
434
435 return [];
436 }
437
438 $record = new Log\Record();
439 $record->action = Log\Record::ACTION_CARRIER_NUMBER_RETRIEVING;
440 $record->status = Log\Record::STATUS_ERROR;
441 $record->title = __( 'carrierNumberRetrievingErrorLogTitle', 'packetery' );
442 $record->params = [
443 'packetId' => $request->getPacketId(),
444 'errorMessage' => $response->getFaultString(),
445 ];
446 $this->logger->add( $record );
447 continue;
448 }
449 $pairs[ $orderId ] = [
450 'packetId' => $packetId,
451 'courierNumber' => $response->getNumber(),
452 ];
453 }
454
455 return $pairs;
456 }
457
458 }
459