PluginProbe
Packeta / 1.5.1
Packeta v1.5.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 / Plugin.php

Plugin.php in Packeta 1.5.1, at src/Packetery/Module/Plugin.php

982 lines 29.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Main Packeta plugin class.
4 *
5 * @package Packetery
6 */
7
8 declare( strict_types=1 );
9
10 namespace Packetery\Module;
11
12 use Packetery\Core\Log\ILogger;
13 use Packetery\Module\Carrier\OptionsPage;
14 use Packetery\Module\Log;
15 use Packetery\Module\Options;
16 use Packetery\Module\Order;
17 use Packetery\Module\Product;
18 use PacketeryLatte\Engine;
19 use PacketeryNette\Http\Request;
20 use PacketeryNette\Utils\Html;
21 use WC_Email;
22 use WC_Order;
23
24 /**
25 * Class Plugin
26 *
27 * @package Packetery
28 */
29 class Plugin {
30
31 public const VERSION = '1.5.1';
32 public const DOMAIN = 'packeta';
33 public const MIN_LISTENER_PRIORITY = - 9998;
34 public const PARAM_PACKETERY_ACTION = 'packetery_action';
35 public const PARAM_NONCE = '_wpnonce';
36
37 /**
38 * Options page.
39 *
40 * @var Options\Page Options page,
41 */
42 private $options_page;
43
44 /**
45 * PacketeryLatte engine.
46 *
47 * @var Engine
48 */
49 private $latte_engine;
50
51 /**
52 * Dashboard widget.
53 *
54 * @var DashboardWidget
55 */
56 private $dashboardWidget;
57
58 /**
59 * Country options page.
60 *
61 * @var OptionsPage
62 */
63 private $carrierOptionsPage;
64
65 /**
66 * Path to main plugin file.
67 *
68 * @var string Path to main plugin file.
69 */
70 private $main_file_path;
71
72 /**
73 * Admin edit order page Packeta metabox.
74 *
75 * @var Order\Metabox
76 */
77 private $order_metabox;
78
79 /**
80 * Message manager.
81 *
82 * @var MessageManager
83 */
84 private $message_manager;
85
86 /**
87 * Checkout object.
88 *
89 * @var Checkout
90 */
91 private $checkout;
92
93 /**
94 * Order BulkActions.
95 *
96 * @var Order\BulkActions
97 */
98 private $orderBulkActions;
99
100 /**
101 * Label printing.
102 *
103 * @var Order\LabelPrint
104 */
105 private $labelPrint;
106
107 /**
108 * Order collection printing.
109 *
110 * @var Order\CollectionPrint
111 */
112 private $orderCollectionPrint;
113
114 /**
115 * Order grid extender.
116 *
117 * @var Order\GridExtender
118 */
119 private $gridExtender;
120
121 /**
122 * Product tab.
123 *
124 * @var Product\DataTab
125 */
126 private $productTab;
127
128 /**
129 * Log page.
130 *
131 * @var Log\Page
132 */
133 private $logPage;
134
135 /**
136 * Log manager.
137 *
138 * @var ILogger
139 */
140 private $logger;
141
142 /**
143 * Cron service.
144 *
145 * @var CronService
146 */
147 private $cronService;
148
149 /**
150 * Order controller.
151 *
152 * @var Order\Controller
153 */
154 private $orderController;
155
156 /**
157 * Order modal.
158 *
159 * @var Order\Modal
160 */
161 private $orderModal;
162
163 /**
164 * Options exporter.
165 *
166 * @var Options\Exporter
167 */
168 private $exporter;
169
170 /**
171 * Request.
172 *
173 * @var Request
174 */
175 private $request;
176
177 /**
178 * Order repository.
179 *
180 * @var Order\Repository
181 */
182 private $orderRepository;
183
184 /**
185 * Plugin upgrade.
186 *
187 * @var Upgrade
188 */
189 private $upgrade;
190
191 /**
192 * QueryProcessor.
193 *
194 * @var QueryProcessor
195 */
196 private $queryProcessor;
197
198 /**
199 * Options provider.
200 *
201 * @var Options\Provider
202 */
203 private $optionsProvider;
204
205 /**
206 * Packet canceller.
207 *
208 * @var Order\PacketCanceller
209 */
210 private $packetCanceller;
211
212 /**
213 * Context resolver.
214 *
215 * @var ContextResolver
216 */
217 private $contextResolver;
218
219 /**
220 * Packet submitter
221 *
222 * @var Order\PacketSubmitter
223 */
224 private $packetSubmitter;
225
226 /**
227 * Category form fields.
228 *
229 * @var ProductCategory\FormFields
230 */
231 private $productCategoryFormFields;
232
233 /**
234 * Packet auto submitter.
235 *
236 * @var Order\PacketAutoSubmitter
237 */
238 private $packetAutoSubmitter;
239
240 /**
241 * Feature Flag Manager.
242 *
243 * @var Options\FeatureFlagManager
244 */
245 private $featureFlagManager;
246
247 /**
248 * Plugin constructor.
249 *
250 * @param Order\Metabox $order_metabox Order metabox.
251 * @param MessageManager $message_manager Message manager.
252 * @param Options\Page $options_page Options page.
253 * @param Checkout $checkout Checkout class.
254 * @param Engine $latte_engine PacketeryLatte engine.
255 * @param OptionsPage $carrierOptionsPage Carrier options page.
256 * @param Order\BulkActions $orderBulkActions Order BulkActions.
257 * @param Order\LabelPrint $labelPrint Label printing.
258 * @param Order\GridExtender $gridExtender Order grid extender.
259 * @param Product\DataTab $productTab Product tab.
260 * @param Log\Page $logPage Log page.
261 * @param ILogger $logger Log manager.
262 * @param Order\Controller $orderController Order controller.
263 * @param Order\Modal $orderModal Order modal.
264 * @param Options\Exporter $exporter Options exporter.
265 * @param Order\CollectionPrint $orderCollectionPrint Order collection print.
266 * @param Request $request HTTP request.
267 * @param Order\Repository $orderRepository Order repository.
268 * @param Upgrade $upgrade Plugin upgrade.
269 * @param QueryProcessor $queryProcessor QueryProcessor.
270 * @param Options\Provider $optionsProvider Options provider.
271 * @param CronService $cronService Cron service.
272 * @param Order\PacketCanceller $packetCanceller Packet canceller.
273 * @param ContextResolver $contextResolver Context resolver.
274 * @param DashboardWidget $dashboardWidget Dashboard widget.
275 * @param Order\PacketSubmitter $packetSubmitter Packet submitter.
276 * @param ProductCategory\FormFields $productCategoryFormFields Product category form fields.
277 * @param Order\PacketAutoSubmitter $packetAutoSubmitter Packet auto submitter.
278 * @param Options\FeatureFlagManager $featureFlagManager Feature Flag Manager.
279 */
280 public function __construct(
281 Order\Metabox $order_metabox,
282 MessageManager $message_manager,
283 Options\Page $options_page,
284 Checkout $checkout,
285 Engine $latte_engine,
286 OptionsPage $carrierOptionsPage,
287 Order\BulkActions $orderBulkActions,
288 Order\LabelPrint $labelPrint,
289 Order\GridExtender $gridExtender,
290 Product\DataTab $productTab,
291 Log\Page $logPage,
292 ILogger $logger,
293 Order\Controller $orderController,
294 Order\Modal $orderModal,
295 Options\Exporter $exporter,
296 Order\CollectionPrint $orderCollectionPrint,
297 Request $request,
298 Order\Repository $orderRepository,
299 Upgrade $upgrade,
300 QueryProcessor $queryProcessor,
301 Options\Provider $optionsProvider,
302 CronService $cronService,
303 Order\PacketCanceller $packetCanceller,
304 ContextResolver $contextResolver,
305 DashboardWidget $dashboardWidget,
306 Order\PacketSubmitter $packetSubmitter,
307 ProductCategory\FormFields $productCategoryFormFields,
308 Order\PacketAutoSubmitter $packetAutoSubmitter,
309 Options\FeatureFlagManager $featureFlagManager
310 ) {
311 $this->options_page = $options_page;
312 $this->latte_engine = $latte_engine;
313 $this->main_file_path = PACKETERY_PLUGIN_DIR . '/packeta.php';
314 $this->order_metabox = $order_metabox;
315 $this->message_manager = $message_manager;
316 $this->checkout = $checkout;
317 $this->carrierOptionsPage = $carrierOptionsPage;
318 $this->orderBulkActions = $orderBulkActions;
319 $this->labelPrint = $labelPrint;
320 $this->gridExtender = $gridExtender;
321 $this->productTab = $productTab;
322 $this->logPage = $logPage;
323 $this->logger = $logger;
324 $this->orderController = $orderController;
325 $this->orderModal = $orderModal;
326 $this->exporter = $exporter;
327 $this->orderCollectionPrint = $orderCollectionPrint;
328 $this->request = $request;
329 $this->orderRepository = $orderRepository;
330 $this->upgrade = $upgrade;
331 $this->queryProcessor = $queryProcessor;
332 $this->optionsProvider = $optionsProvider;
333 $this->cronService = $cronService;
334 $this->packetCanceller = $packetCanceller;
335 $this->contextResolver = $contextResolver;
336 $this->dashboardWidget = $dashboardWidget;
337 $this->packetSubmitter = $packetSubmitter;
338 $this->productCategoryFormFields = $productCategoryFormFields;
339 $this->packetAutoSubmitter = $packetAutoSubmitter;
340 $this->featureFlagManager = $featureFlagManager;
341 }
342
343 /**
344 * Method to register hooks
345 */
346 public function run(): void {
347 add_action( 'init', [ $this, 'loadTranslation' ] );
348
349 if ( ! self::isWooCommercePluginActive() ) {
350 add_action( 'admin_notices', [ $this, 'echoInactiveWooCommerceNotice' ] );
351
352 return;
353 }
354
355 add_action( 'init', [ $this->upgrade, 'check' ] );
356 add_action( 'init', [ $this->logger, 'register' ] );
357 add_action( 'init', [ $this->message_manager, 'init' ] );
358 add_action( 'rest_api_init', [ $this->orderController, 'registerRoutes' ] );
359
360 add_action( 'admin_enqueue_scripts', array( $this, 'enqueueAdminAssets' ) );
361 add_action( 'wp_enqueue_scripts', [ $this, 'enqueueFrontAssets' ] );
362
363 add_action(
364 'admin_notices',
365 function () {
366 $this->message_manager->render( MessageManager::RENDERER_WORDPRESS );
367 },
368 self::MIN_LISTENER_PRIORITY
369 );
370 add_action( 'init', array( $this, 'init' ) );
371
372 // TODO: deactivation_hook.
373 register_deactivation_hook(
374 $this->main_file_path,
375 static function () {
376 CronService::deactivate();
377 }
378 );
379
380 register_uninstall_hook( $this->main_file_path, array( __CLASS__, 'uninstall' ) );
381
382 add_action( 'woocommerce_email_footer', [ $this, 'renderEmailFooter' ] );
383 add_filter( 'woocommerce_shipping_methods', array( $this, 'add_shipping_method' ) );
384
385 add_filter( 'views_edit-shop_order', [ $this->gridExtender, 'addFilterLinks' ] );
386 add_action( 'restrict_manage_posts', [ $this->gridExtender, 'renderOrderTypeSelect' ] );
387 $this->queryProcessor->register();
388
389 add_filter( 'manage_edit-shop_order_columns', [ $this->gridExtender, 'addOrderListColumns' ] );
390 add_action( 'manage_shop_order_posts_custom_column', [ $this->gridExtender, 'fillCustomOrderListColumns' ] );
391
392 add_filter( 'woocommerce_order_data_store_cpt_get_orders_query', [ $this->upgrade, 'handleCustomQueryVar' ], 10, 2 );
393
394 add_action( 'admin_menu', array( $this, 'add_menu_pages' ) );
395 add_action( 'admin_head', array( $this->labelPrint, 'hideFromMenus' ) );
396 add_action( 'admin_head', array( $this->orderCollectionPrint, 'hideFromMenus' ) );
397 add_action( 'admin_head', [ $this, 'renderConfirmModalTemplate' ] );
398 $this->orderModal->register();
399 $this->order_metabox->register();
400
401 $this->checkout->register_hooks();
402 $this->productTab->register();
403 $this->cronService->register();
404 $this->productCategoryFormFields->register();
405 $this->packetAutoSubmitter->register();
406
407 add_action( 'woocommerce_admin_order_data_after_shipping_address', [ $this, 'renderDeliveryDetail' ] );
408 add_action( 'woocommerce_order_details_after_order_table', [ $this, 'renderOrderDetail' ] );
409
410 // Adding custom actions to dropdown in admin order list.
411 add_filter( 'bulk_actions-edit-shop_order', [ $this->orderBulkActions, 'addActions' ], 20, 1 );
412 // Execute the action for selected orders.
413 add_filter(
414 'handle_bulk_actions-edit-shop_order',
415 [
416 $this->orderBulkActions,
417 'handleActions',
418 ],
419 10,
420 3
421 );
422 // Print packets export result.
423 add_action( 'admin_notices', [ $this->orderBulkActions, 'renderPacketsExportResult' ], self::MIN_LISTENER_PRIORITY );
424
425 add_action( 'admin_init', [ $this->labelPrint, 'outputLabelsPdf' ] );
426 add_action( 'admin_init', [ $this->orderCollectionPrint, 'print' ] );
427
428 add_action( 'admin_init', [ $this->exporter, 'outputExportTxt' ] );
429 add_action( 'admin_init', [ $this, 'handleActions' ] );
430 add_filter( 'woocommerce_order_data_store_cpt_get_orders_query', [ $this, 'transformGetOrdersQuery' ] );
431
432 add_action( 'deleted_post', [ $this->orderRepository, 'deletedPostHook' ], 10, 2 );
433 $this->dashboardWidget->register();
434 }
435
436 /**
437 * Print inactive WooCommerce notice.
438 *
439 * @return void
440 */
441 public function echoInactiveWooCommerceNotice(): void {
442 if ( self::isWooCommercePluginActive() ) {
443 // When Packeta plugin is active and WooCommerce plugin is inactive.
444 // If user decides to activate WooCommerce plugin then invalid notice will not be rendered.
445 // Packeta plugin probably bootstraps twice in such case.
446 return;
447 }
448
449 $this->latte_engine->render(
450 PACKETERY_PLUGIN_DIR . '/template/admin-notice.latte',
451 [
452 'message' => [
453 'type' => 'error',
454 'message' => __( 'Packeta plugin requires WooCommerce. Please install and activate it first.', 'packeta' ),
455 ],
456 ]
457 );
458 }
459
460 /**
461 * Is WC plugin active.
462 *
463 * @return bool
464 */
465 private static function isWooCommercePluginActive(): bool {
466 return Helper::isPluginActive( 'woocommerce/woocommerce.php' );
467 }
468
469 /**
470 * Creates HTML link parts in array.
471 *
472 * @param string $href Href.
473 * @param string|null $target Target.
474 * @param string|null $class Class.
475 *
476 * @return string[]
477 */
478 public static function createLinkParts( string $href, ?string $target = null, ?string $class = null ): array {
479 $link = Html::el( 'a' )->href( $href );
480
481 if ( null !== $target ) {
482 $link->target( $target );
483 }
484
485 if ( null !== $class ) {
486 $link->class( $class );
487 }
488
489 return [ $link->startTag(), $link->endTag() ];
490 }
491
492 /**
493 * Filter queries.
494 *
495 * @param array $query Query.
496 *
497 * @return array
498 */
499 public function transformGetOrdersQuery( array $query ): array {
500 if ( ! empty( $query['packetery_meta_query'] ) ) {
501 // @codingStandardsIgnoreStart
502 $query['meta_query'] = $query['packetery_meta_query'];
503 // @codingStandardsIgnoreEnd
504 }
505
506 return $query;
507 }
508
509 /**
510 * Renders delivery detail for packetery orders.
511 *
512 * @param WC_Order $order WordPress order.
513 */
514 public function renderDeliveryDetail( WC_Order $order ): void {
515 $orderEntity = $this->orderRepository->getByWcOrder( $order );
516 if ( null === $orderEntity ) {
517 return;
518 }
519
520 $carrierId = $orderEntity->getCarrierId();
521 $carrierOptions = Carrier\Options::createByCarrierId( $carrierId );
522
523 $this->latte_engine->render(
524 PACKETERY_PLUGIN_DIR . '/template/order/delivery-detail.latte',
525 [
526 'pickupPoint' => $orderEntity->getPickupPoint(),
527 'validatedDeliveryAddress' => $orderEntity->getValidatedDeliveryAddress(),
528 'carrierAddressValidation' => $carrierOptions->getAddressValidation(),
529 'isExternalCarrier' => $orderEntity->isExternalCarrier(),
530 'translations' => [
531 'packeta' => __( 'Packeta', 'packeta' ),
532 'pickupPointDetail' => __( 'Pickup Point Detail', 'packeta' ),
533 'name' => __( 'Name', 'packeta' ),
534 'address' => __( 'Address', 'packeta' ),
535 'pickupPointDetailCaps' => __( 'Pickup Point Detail', 'packeta' ),
536 'addressWasNotValidated' => __( 'Address was not validated', 'packeta' ),
537 'validatedAddress' => __( 'Validated address', 'packeta' ),
538 'street' => __( 'Street', 'packeta' ),
539 'houseNumber' => __( 'House number', 'packeta' ),
540 'city' => __( 'City', 'packeta' ),
541 'zip' => __( 'Zip', 'packeta' ),
542 'county' => __( 'County', 'packeta' ),
543 'gps' => __( 'GPS', 'packeta' ),
544 ],
545 ]
546 );
547 }
548
549 /**
550 * Renders delivery detail for packetery orders, on "thank you" page and in frontend detail.
551 *
552 * @param WC_Order $wcOrder WordPress order.
553 */
554 public function renderOrderDetail( WC_Order $wcOrder ): void {
555 $order = $this->orderRepository->getById( $wcOrder->get_id() );
556 if ( null === $order ) {
557 return;
558 }
559
560 $pickupPoint = $order->getPickupPoint();
561 $validatedDeliveryAddress = $order->getValidatedDeliveryAddress();
562 if ( null === $pickupPoint && null === $validatedDeliveryAddress ) {
563 return;
564 }
565
566 $this->latte_engine->render(
567 PACKETERY_PLUGIN_DIR . '/template/order/detail.latte',
568 [
569 'displayPickupPointInfo' => $this->shouldDisplayPickupPointInfo(),
570 'pickupPoint' => $pickupPoint,
571 'validatedDeliveryAddress' => $validatedDeliveryAddress,
572 'isExternalCarrier' => $order->isExternalCarrier(),
573 'translations' => [
574 'packeta' => __( 'Packeta', 'packeta' ),
575 'selectedPickupPoint' => __( 'Selected pickup point', 'packeta' ),
576 'pickupPointName' => __( 'Pickup Point Name', 'packeta' ),
577 'pickupPointDetail' => __( 'Pickup Point Detail', 'packeta' ),
578 'validatedAddress' => __( 'Validated address', 'packeta' ),
579 'address' => __( 'Address', 'packeta' ),
580 ],
581 ]
582 );
583 }
584
585 /**
586 * Renders email footer.
587 *
588 * @param mixed $email Email data.
589 */
590 public function renderEmailFooter( $email ): void {
591 if ( ! $email instanceof WC_Email || ! $email->object instanceof WC_Order ) {
592 return;
593 }
594
595 $packeteryOrder = $this->orderRepository->getByWcOrder( $email->object );
596 if ( null === $packeteryOrder ) {
597 return;
598 }
599
600 $pickupPoint = $packeteryOrder->getPickupPoint();
601 $validatedDeliveryAddress = $packeteryOrder->getValidatedDeliveryAddress();
602
603 $this->latte_engine->render(
604 PACKETERY_PLUGIN_DIR . '/template/email/footer.latte',
605 [
606 'displayPickupPointInfo' => $this->shouldDisplayPickupPointInfo(),
607 'pickupPoint' => $pickupPoint,
608 'validatedDeliveryAddress' => $validatedDeliveryAddress,
609 'isExternalCarrier' => $packeteryOrder->isExternalCarrier(),
610 'translations' => [
611 'packeta' => __( 'Packeta', 'packeta' ),
612 'pickupPointDetail' => __( 'Pickup Point Detail', 'packeta' ),
613 'pickupPointName' => __( 'Pickup Point Name', 'packeta' ),
614 'link' => __( 'Link', 'packeta' ),
615 'pickupPointAddress' => __( 'Pickup Point Address', 'packeta' ),
616 'validatedDeliveryAddress' => __( 'validated delivery address', 'packeta' ),
617 'street' => __( 'Street', 'packeta' ),
618 'houseNumber' => __( 'House number', 'packeta' ),
619 'city' => __( 'City', 'packeta' ),
620 'zip' => __( 'Zip', 'packeta' ),
621 'county' => __( 'County', 'packeta' ),
622 ],
623 ]
624 );
625 }
626
627 /**
628 * Tells if pickup point info should be displayed.
629 *
630 * @return bool
631 */
632 public function shouldDisplayPickupPointInfo(): bool {
633 return ! $this->optionsProvider->replaceShippingAddressWithPickupPointAddress() || wc_ship_to_billing_address_only();
634 }
635
636 /**
637 * Renders confirm modal template.
638 */
639 public function renderConfirmModalTemplate(): void {
640 if ( $this->contextResolver->isPacketeryConfirmPage() ) {
641 $this->latte_engine->render(
642 PACKETERY_PLUGIN_DIR . '/template/confirm-modal-template.latte',
643 [
644 'translations' => [
645 'closeModalPanel' => __( 'Close modal panel', 'packeta' ),
646 'no' => __( 'No', 'packeta' ),
647 'yes' => __( 'Yes', 'packeta' ),
648 ],
649 ]
650 );
651 }
652 }
653
654 /**
655 * Enqueues admin JS file.
656 *
657 * @param string $name Name of script.
658 * @param string $file Relative file path.
659 * @param bool $inFooter Tells where to include script.
660 * @param array $deps Script dependencies.
661 */
662 private function enqueueScript( string $name, string $file, bool $inFooter, array $deps = [] ): void {
663 wp_enqueue_script(
664 $name,
665 plugin_dir_url( $this->main_file_path ) . $file,
666 $deps,
667 md5( (string) filemtime( PACKETERY_PLUGIN_DIR . '/' . $file ) ),
668 $inFooter
669 );
670 }
671
672 /**
673 * Enqueues CSS file.
674 *
675 * @param string $name Name of script.
676 * @param string $file Relative file path.
677 */
678 private function enqueueStyle( string $name, string $file ): void {
679 wp_enqueue_style(
680 $name,
681 plugin_dir_url( $this->main_file_path ) . $file,
682 [],
683 md5( (string) filemtime( PACKETERY_PLUGIN_DIR . '/' . $file ) )
684 );
685 }
686
687 /**
688 * Builds asset URL.
689 *
690 * @param string $asset Relative asset path without leading slash.
691 *
692 * @return string|null
693 */
694 public static function buildAssetUrl( string $asset ): ?string {
695 $url = plugin_dir_url( PACKETERY_PLUGIN_DIR . '/packeta.php' ) . $asset;
696 $filename = PACKETERY_PLUGIN_DIR . '/' . $asset;
697
698 if ( ! file_exists( $filename ) ) {
699 return null;
700 }
701
702 return add_query_arg( [ 'v' => md5( (string) filemtime( $filename ) ) ], $url );
703 }
704
705 /**
706 * Enqueues javascript files and stylesheets for checkout.
707 */
708 public function enqueueFrontAssets(): void {
709 if ( is_checkout() ) {
710 $this->enqueueStyle( 'packetery-front-styles', 'public/front.css' );
711 $this->enqueueStyle( 'packetery-custom-front-styles', 'public/custom-front.css' );
712 $this->enqueueScript( 'packetery-checkout', 'public/checkout.js', true, [ 'jquery' ] );
713 wp_localize_script( 'packetery-checkout', 'packeteryCheckoutSettings', $this->checkout->createSettings() );
714 }
715 }
716
717 /**
718 * Enqueues javascript files and stylesheets for administration.
719 */
720 public function enqueueAdminAssets(): void {
721 $page = $this->request->getQuery( 'page' );
722 $isOrderGridPage = $this->contextResolver->isOrderGridPage();
723 $isOrderDetailPage = $this->contextResolver->isOrderDetailPage();
724 $isProductCategoryPage = $this->contextResolver->isProductCategoryDetailPage() || $this->contextResolver->isProductCategoryGridPage();
725 $datePickerSettings = [
726 'deliverOnMinDate' => wp_date( \Packetery\Core\Helper::DATEPICKER_FORMAT, strtotime( 'tomorrow' ) ),
727 ];
728
729 if ( $isOrderGridPage || $isOrderDetailPage || in_array( $page, [ Carrier\OptionsPage::SLUG, Options\Page::SLUG ], true ) ) {
730 $this->enqueueScript( 'live-form-validation-options', 'public/live-form-validation-options.js', false );
731 $this->enqueueScript( 'live-form-validation', 'public/libs/live-form-validation/live-form-validation.js', false, [ 'live-form-validation-options' ] );
732 $this->enqueueScript( 'live-form-validation-extension', 'public/live-form-validation-extension.js', false, [ 'live-form-validation' ] );
733 }
734
735 if ( Carrier\OptionsPage::SLUG === $page ) {
736 $this->enqueueScript( 'packetery-admin-country-carrier', 'public/admin-country-carrier.js', true, [ 'jquery' ] );
737 }
738
739 $isProductPage = $this->contextResolver->isProductPage();
740 $screen = get_current_screen();
741 $isDashboard = ( $screen && 'dashboard' === $screen->id );
742
743 if (
744 $isOrderGridPage || $isOrderDetailPage || $isProductPage || $isProductCategoryPage || $isDashboard ||
745 in_array(
746 $page,
747 [
748 Options\Page::SLUG,
749 Carrier\OptionsPage::SLUG,
750 Log\Page::SLUG,
751 Order\labelPrint::MENU_SLUG,
752 ],
753 true
754 )
755 ) {
756 $this->enqueueStyle( 'packetery-admin-styles', 'public/admin.css' );
757 // We want to trigger the message on all pages and show it on first request.
758 $this->featureFlagManager->isSplitActive();
759 // It is placed here so that typenow in contextResolver works and there is no need to repeat the conditions.
760 if ( $this->featureFlagManager->hasSplitActivationNotice() ) {
761 add_action( 'admin_notices', [ $this->featureFlagManager, 'renderSplitActivationNotice' ] );
762 }
763 }
764
765 if ( $isOrderGridPage ) {
766 $this->enqueueScript( 'packetery-admin-grid-order-edit-js', 'public/admin-grid-order-edit.js', true, [ 'jquery', 'wp-util', 'backbone' ] );
767 wp_localize_script( 'packetery-admin-grid-order-edit-js', 'datePickerSettings', $datePickerSettings );
768 }
769
770 $pickupPointPickerSettings = null;
771 $addressPickerSettings = null;
772
773 if ( $isOrderDetailPage ) {
774 $this->enqueueScript( 'admin-order-detail', 'public/admin-order-detail.js', true, [ 'jquery' ] );
775 wp_localize_script( 'admin-order-detail', 'datePickerSettings', $datePickerSettings );
776 $pickupPointPickerSettings = $this->order_metabox->getPickupPointWidgetSettings();
777 $addressPickerSettings = $this->order_metabox->getAddressWidgetSettings();
778 }
779
780 if ( null !== $pickupPointPickerSettings || null !== $addressPickerSettings ) {
781 wp_enqueue_script( 'packetery-widget-library', 'https://widget.packeta.com/v6/www/js/library.js', [], self::VERSION, true );
782 }
783
784 if ( null !== $pickupPointPickerSettings ) {
785 $this->enqueueScript( 'packetery-admin-pickup-point-picker', 'public/admin-pickup-point-picker.js', true, [ 'jquery', 'packetery-widget-library' ] );
786 wp_localize_script( 'packetery-admin-pickup-point-picker', 'packeteryPickupPointPickerSettings', $pickupPointPickerSettings );
787 }
788
789 if ( null !== $addressPickerSettings ) {
790 $this->enqueueScript( 'packetery-admin-address-picker', 'public/admin-address-picker.js', true, [ 'jquery', 'packetery-widget-library' ] );
791 wp_localize_script( 'packetery-admin-address-picker', 'packeteryAddressPickerSettings', $addressPickerSettings );
792 }
793
794 if ( $this->contextResolver->isPacketeryConfirmPage() ) {
795 $this->enqueueScript( 'packetery-confirm', 'public/confirm.js', true, [ 'jquery', 'backbone' ] );
796 }
797 }
798
799 /**
800 * Add links to left admin menu.
801 */
802 public function add_menu_pages(): void {
803 $this->options_page->register();
804 $this->carrierOptionsPage->register();
805 $this->labelPrint->register();
806 $this->orderCollectionPrint->register();
807 $this->logPage->register();
808 }
809
810 /**
811 * Gets current locale.
812 */
813 public static function getLocale(): string {
814 /**
815 * Applies plugin_locale filters.
816 *
817 * @since 1.0.0
818 */
819 return (string) apply_filters(
820 'plugin_locale',
821 ( is_admin() ? get_user_locale() : get_locale() ),
822 self::DOMAIN
823 );
824 }
825
826 /**
827 * Loads plugin translation file by user locale.
828 */
829 public function loadTranslation(): void {
830 $domain = self::DOMAIN;
831 $locale = self::getLocale();
832
833 $moFile = PACKETERY_PLUGIN_DIR . "/languages/$domain-$locale.mo";
834 $result = load_textdomain( $domain, $moFile );
835
836 if ( false === $result ) {
837 $moFile = PACKETERY_PLUGIN_DIR . "/languages/$domain-en_US.mo";
838 load_textdomain( $domain, $moFile );
839 }
840 }
841
842 /**
843 * Inits plugin.
844 */
845 public function init(): void {
846 add_filter(
847 'plugin_action_links_' . plugin_basename( $this->main_file_path ),
848 [
849 $this,
850 'addPluginActionLinks',
851 ]
852 );
853 add_filter( 'plugin_row_meta', [ $this, 'addPluginRowMeta' ], 10, 2 );
854 }
855
856 /**
857 * Uninstalls plugin and drops custom database table.
858 * Only a static class method or function can be used in an uninstall hook.
859 */
860 public static function uninstall(): void {
861 if ( defined( 'PACKETERY_DEBUG' ) && PACKETERY_DEBUG === true ) {
862 return;
863 }
864
865 $container = require PACKETERY_PLUGIN_DIR . '/bootstrap.php';
866
867 $optionsRepository = $container->getByType( Options\Repository::class );
868 $pluginOptions = $optionsRepository->getPluginOptions();
869 foreach ( $pluginOptions as $option ) {
870 delete_option( $option->option_name );
871 }
872
873 $logRepository = $container->getByType( Log\Repository::class );
874 $logRepository->drop();
875
876 $carrierRepository = $container->getByType( Carrier\Repository::class );
877 $carrierRepository->drop();
878
879 $orderRepository = $container->getByType( Order\Repository::class );
880 $orderRepository->drop();
881 }
882
883 /**
884 * Adds action links visible at the plugin screen.
885 *
886 * @link https://developer.wordpress.org/reference/hooks/plugin_action_links_plugin_file/
887 *
888 * @param array $links Plugin Action links.
889 *
890 * @return array
891 */
892 public function addPluginActionLinks( array $links ): array {
893 $settingsLink = '<a href="' . esc_url( admin_url( 'admin.php?page=' . Options\Page::SLUG ) ) . '" aria-label="' .
894 esc_attr__( 'View the plugin documentation', 'packeta' ) . '">' .
895 esc_html__( 'Settings', 'packeta' ) . '</a>';
896
897 array_unshift( $links, $settingsLink );
898
899 return $links;
900 }
901
902 /**
903 * Show row meta on the plugin screen.
904 *
905 * @link https://developer.wordpress.org/reference/hooks/plugin_row_meta/
906 *
907 * @param array $links Plugin Row Meta.
908 * @param string $pluginFileName Plugin Base file.
909 *
910 * @return array
911 */
912 public function addPluginRowMeta( array $links, string $pluginFileName ): array {
913 if ( ! strpos( $pluginFileName, basename( $this->main_file_path ) ) ) {
914 return $links;
915 }
916 $links[] = '<a href="' . esc_url( 'https://github.com/Zasilkovna/WooCommerce/wiki' ) . '" aria-label="' .
917 esc_attr__( 'View Packeta documentation', 'packeta' ) . '">' .
918 esc_html__( 'Documentation', 'packeta' ) . '</a>';
919
920 return $links;
921 }
922
923 /**
924 * Adds Packeta method to available shipping methods.
925 *
926 * @param array $methods Previous state.
927 *
928 * @return array
929 */
930 public function add_shipping_method( array $methods ): array {
931 $methods[ ShippingMethod::PACKETERY_METHOD_ID ] = ShippingMethod::class;
932
933 return $methods;
934 }
935
936 /**
937 * Hides submenu item. Must not be called too early.
938 *
939 * @param string $itemSlug Item slug.
940 */
941 public static function hideSubmenuItem( string $itemSlug ): void {
942 global $submenu;
943 if ( isset( $submenu[ Options\Page::SLUG ] ) ) {
944 foreach ( $submenu[ Options\Page::SLUG ] as $key => $menu ) {
945 if ( $itemSlug === $menu[2] ) {
946 unset( $submenu[ Options\Page::SLUG ][ $key ] );
947 }
948 }
949 }
950 }
951
952 /**
953 * Gets software identity for Packeta APIs.
954 *
955 * @return string
956 */
957 public static function getAppIdentity(): string {
958 return 'WordPress-' . get_bloginfo( 'version' ) . '-Woocommerce-' . WC_VERSION . '-Packeta-' . self::VERSION;
959 }
960
961 /**
962 * Check for action parameter and process wanted action.
963 *
964 * @return void
965 */
966 public function handleActions(): void {
967 $action = $this->request->getQuery( self::PARAM_PACKETERY_ACTION );
968
969 if ( Order\PacketActionsCommonLogic::ACTION_SUBMIT_PACKET === $action ) {
970 $this->packetSubmitter->processAction();
971 }
972
973 if ( Order\PacketActionsCommonLogic::ACTION_CANCEL_PACKET === $action ) {
974 $this->packetCanceller->processAction();
975 }
976
977 if ( Options\FeatureFlagManager::ACTION_HIDE_SPLIT_MESSAGE === $action ) {
978 $this->featureFlagManager->dismissSplitActivationNotice();
979 }
980 }
981 }
982