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 / Options / OptionsProvider.php

OptionsProvider.php in Packeta trunk, at src/Packetery/Module/Options/OptionsProvider.php

797 lines 19.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class OptionsProvider
4 *
5 * @package Packetery
6 */
7
8 declare( strict_types=1 );
9
10 namespace Packetery\Module\Options;
11
12 use Packetery\Core\Entity\PacketStatus;
13 use Packetery\Module\Framework\WpAdapter;
14 use Packetery\Module\ModuleHelper;
15
16 /**
17 * Class OptionsProvider
18 *
19 * @package Packetery
20 */
21 class OptionsProvider {
22
23 public const DEFAULT_VALUE_PACKETA_LABEL_FORMAT = 'A6 on A4';
24 public const DEFAULT_VALUE_CARRIER_LABEL_FORMAT = self::DEFAULT_VALUE_PACKETA_LABEL_FORMAT;
25 public const DEFAULT_VALUE_CARRIER_SETTINGS = true;
26 public const MAX_STATUS_SYNCING_PACKETS_DEFAULT = 100;
27 public const MAX_DAYS_OF_PACKET_STATUS_SYNCING_DEFAULT = 14;
28 public const FORCE_PACKET_CANCEL_DEFAULT = true;
29 public const PACKET_AUTO_SUBMISSION_ALLOWED_DEFAULT = false;
30 public const WIDGET_AUTO_OPEN_DEFAULT = false;
31 public const AUTO_ORDER_STATUS_DEFAULT = '';
32 public const EMAIL_HOOK_DEFAULT = 'woocommerce_email_footer';
33 public const AUTO_ORDER_STATUS = 'auto_order_status';
34 public const DISPLAY_FREE_SHIPPING_IN_CHECKOUT_DEFAULT = true;
35 public const PRICES_INCLUDE_TAX_DEFAULT = false;
36 public const HIDE_CHECKOUT_LOGO_DEFAULT = false;
37 public const AUTO_EMAIL_INFO_INSERTION_DEFAULT = true;
38 public const PICKUP_POINT_VALIDATION_ENABLED_DEFAULT = false;
39 public const SHOW_CONSIGN_PASSWORD_FOR_Z_BOX_DEFAULT = false;
40
41 public const AUTOMATIC_CHECKOUT_DETECTION = 'automatic_checkout_detection';
42 public const BLOCK_CHECKOUT_DETECTION = 'block_checkout_detection';
43 public const CLASSIC_CHECKOUT_DETECTION = 'classic_checkout_detection';
44
45 public const DEFAULT_DIMENSIONS_UNIT_MM = 'mm';
46 public const DIMENSIONS_UNIT_CM = 'cm';
47
48 /**
49 * Options data.
50 *
51 * @var array<string, mixed>
52 */
53 private $data;
54
55 /**
56 * Sync data.
57 *
58 * @var array<string, mixed>
59 * }
60 */
61 private $syncData;
62
63 /**
64 * Auto submission data.
65 *
66 * @var array<string, mixed>
67 */
68 private $autoSubmissionData;
69
70 /**
71 * @var array<string, mixed>
72 */
73 private $advancedData;
74
75 public function __construct( WpAdapter $wpAdapter ) {
76 $data = $wpAdapter->getOption( OptionNames::PACKETERY );
77 if ( $data === false || $data === null ) {
78 $data = array();
79 }
80
81 $syncData = $wpAdapter->getOption( OptionNames::PACKETERY_SYNC );
82 if ( $syncData === false || $syncData === null ) {
83 $syncData = [];
84 }
85
86 $autoSubmissionData = $wpAdapter->getOption( OptionNames::PACKETERY_AUTO_SUBMISSION );
87 if ( $autoSubmissionData === false || $autoSubmissionData === null ) {
88 $autoSubmissionData = [];
89 }
90
91 $advancedData = $wpAdapter->getOption( OptionNames::PACKETERY_ADVANCED );
92 if ( $advancedData === false || $advancedData === null ) {
93 $advancedData = [];
94 }
95
96 $this->data = $data;
97 $this->syncData = $syncData;
98 $this->autoSubmissionData = $autoSubmissionData;
99 $this->advancedData = $advancedData;
100 }
101
102 /**
103 * Gets data section.
104 *
105 * @param string $optionsName Option name of settings.
106 *
107 * @return array<string, mixed> Only section of options data by given $optionName.
108 * @throws \InvalidArgumentException When provided option name does not exist.
109 */
110 public function getOptionsByName( string $optionsName ): array {
111 $data = $this->getAllOptions();
112 if ( ! isset( $data[ $optionsName ] ) ) {
113 throw new \InvalidArgumentException( sprintf( 'Option name "%s" does not exist.', $optionsName ) );
114 }
115
116 return $data[ $optionsName ];
117 }
118
119 /**
120 * Gets data as array.
121 *
122 * @return array<string, array> All plugin options data by given $optionName.
123 */
124 public function getAllOptions(): array {
125 return [
126 OptionNames::PACKETERY => $this->data,
127 OptionNames::PACKETERY_SYNC => $this->syncData,
128 OptionNames::PACKETERY_AUTO_SUBMISSION => $this->autoSubmissionData,
129 OptionNames::PACKETERY_ADVANCED => $this->advancedData,
130 ];
131 }
132
133 /**
134 * Tells if provider has any data,
135 *
136 * @param string $optionName Option name of settings.
137 *
138 * @return bool Has any data.
139 */
140 public function has_any( string $optionName ): bool {
141 return count( $this->getOptionsByName( $optionName ) ) > 0;
142 }
143
144 /**
145 * Gets content from options array.
146 *
147 * @param string $key Options array key.
148 *
149 * @return mixed|null Content.
150 */
151 private function get( string $key ) {
152 return ( $this->data[ $key ] ?? null );
153 }
154
155 /**
156 * API key dynamically crafted from API password.
157 *
158 * @return string|null Content.
159 */
160 public function get_api_key(): ?string {
161 $apiKey = $this->get( 'api_key' );
162 if ( $apiKey !== null && $apiKey !== '' && $apiKey !== false ) {
163 return $apiKey;
164 }
165
166 return null;
167 }
168
169 /**
170 * API password from client section.
171 *
172 * @return string|null Content.
173 */
174 public function get_api_password(): ?string {
175 return $this->get( 'api_password' );
176 }
177
178 /**
179 * Sender.
180 *
181 * @return string|null Content.
182 */
183 public function get_sender(): ?string {
184 return $this->get( 'sender' );
185 }
186
187 /**
188 * Carrier label format.
189 *
190 * @return string Content.
191 */
192 public function get_carrier_label_format(): string {
193 return $this->get( 'carrier_label_format' ) ?? self::DEFAULT_VALUE_CARRIER_LABEL_FORMAT;
194 }
195
196 /**
197 * Packeta label format.
198 *
199 * @return string Content.
200 */
201 public function get_packeta_label_format(): string {
202 return $this->get( 'packeta_label_format' ) ?? self::DEFAULT_VALUE_PACKETA_LABEL_FORMAT;
203 }
204
205 /**
206 * Does user allow label emailing?
207 *
208 * @return bool|null Content.
209 */
210 public function get_allow_label_emailing(): ?bool {
211 return (bool) $this->get( 'allow_label_emailing' );
212 }
213
214 /**
215 * Returns COD payment methods.
216 *
217 * @return string[] Values.
218 */
219 public function getCodPaymentMethods(): array {
220 $value = $this->get( 'cod_payment_methods' );
221 if ( $value === null ) {
222 return [];
223 }
224
225 return $value;
226 }
227
228 /**
229 * Returns the location of the widget button in the cart
230 *
231 * @return string|null
232 */
233 public function getCheckoutWidgetButtonLocation(): ?string {
234 $value = $this->get( 'checkout_widget_button_location' );
235 if ( $value === null ) {
236 return null;
237 }
238
239 return $value;
240 }
241
242 /**
243 * Returns which checkout detection to return
244 *
245 * @return string
246 */
247 public function getCheckoutDetection(): string {
248 $value = $this->get( 'checkout_detection' );
249 if ( $value === null ) {
250 return self::AUTOMATIC_CHECKOUT_DETECTION;
251 }
252
253 return $value;
254 }
255
256 /**
257 * Order packaging weight.
258 *
259 * @return float
260 */
261 public function getPackagingWeight(): float {
262 return (float) $this->get( 'packaging_weight' );
263 }
264
265 public function getDimensionsUnit(): string {
266 $value = $this->get( 'dimensions_unit' );
267
268 return $value ?? self::DEFAULT_DIMENSIONS_UNIT_MM;
269 }
270
271 public function getDimensionsNumberOfDecimals(): int {
272 if ( $this->getDimensionsUnit() === self::DIMENSIONS_UNIT_CM ) {
273 return 1;
274 }
275
276 return 0;
277 }
278
279 /**
280 * Sanitises and formats a dimension value.
281 *
282 * @param string|float $value Dimension value.
283 *
284 * @return float|null
285 */
286 public function getSanitizedDimensionValueInMm( $value ): ?float {
287 if ( ! is_numeric( $value ) ) {
288 return null;
289 }
290
291 $sanitizedValue = (float) number_format( (float) $value, $this->getDimensionsNumberOfDecimals(), '.', '' );
292 if ( $this->getDimensionsUnit() === self::DIMENSIONS_UNIT_CM ) {
293 return ModuleHelper::convertToMillimeters( $sanitizedValue );
294 }
295
296 return $sanitizedValue;
297 }
298
299 /**
300 * Order default weight enabled.
301 *
302 * @return bool
303 */
304 public function isDefaultWeightEnabled(): bool {
305 return (bool) $this->get( 'default_weight_enabled' );
306 }
307
308 /**
309 * Order default weight.
310 *
311 * @return float
312 */
313 public function getDefaultWeight(): float {
314 if ( $this->get( 'default_weight' ) === null ) {
315 return 0.0;
316 }
317
318 return (float) $this->get( 'default_weight' );
319 }
320
321 /**
322 * Consignment's default dimensions enabled.
323 *
324 * @return bool
325 */
326 public function isDefaultDimensionsEnabled(): bool {
327 return (bool) $this->get( 'default_dimensions_enabled' );
328 }
329
330 /**
331 * Consignment's default length.
332 *
333 * @return float
334 */
335 public function getDefaultLength(): float {
336 if ( $this->get( 'default_length' ) === null ) {
337 return 0.0;
338 }
339
340 return (float) $this->get( 'default_length' );
341 }
342
343 /**
344 * Consignment's default height.
345 *
346 * @return float
347 */
348 public function getDefaultHeight(): float {
349 if ( $this->get( 'default_height' ) === null ) {
350 return 0.0;
351 }
352
353 return (float) $this->get( 'default_height' );
354 }
355
356 /**
357 * Consignment's default width.
358 *
359 * @return float
360 */
361 public function getDefaultWidth(): float {
362 if ( $this->get( 'default_width' ) === null ) {
363 return 0.0;
364 }
365
366 return (float) $this->get( 'default_width' );
367 }
368
369 /**
370 * Max syncing packets.
371 *
372 * @return int
373 */
374 public function getMaxStatusSyncingPackets(): int {
375 $value = ( $this->syncData['max_status_syncing_packets'] ?? null );
376 if ( is_numeric( $value ) ) {
377 return (int) $value;
378 }
379
380 return self::MAX_STATUS_SYNCING_PACKETS_DEFAULT;
381 }
382
383 /**
384 * Max days of packet status syncing.
385 *
386 * @return int
387 */
388 public function getMaxDaysOfPacketStatusSyncing(): int {
389 $value = ( $this->syncData['max_days_of_packet_status_syncing'] ?? null );
390 if ( is_numeric( $value ) ) {
391 return (int) $value;
392 }
393
394 return self::MAX_DAYS_OF_PACKET_STATUS_SYNCING_DEFAULT;
395 }
396
397 /**
398 * Status syncing order statuses.
399 *
400 * @return array
401 */
402 public function getStatusSyncingOrderStatuses(): array {
403 $value = ( $this->syncData['status_syncing_order_statuses'] ?? null );
404 if ( is_array( $value ) ) {
405 return $value;
406 }
407
408 return [];
409 }
410
411 /**
412 * Status syncing order statuses.
413 *
414 * @return array
415 */
416 public function getExistingStatusSyncingOrderStatuses(): array {
417 $statuses = $this->getStatusSyncingOrderStatuses();
418 $choices = array_column( Page::getOrderStatusesChoiceData(), 'key' );
419
420 return array_intersect( $statuses, $choices );
421 }
422
423 /**
424 * Status syncing packet statuses.
425 *
426 * @param PacketStatus[] $expectedPacketStatuses Expected packet statuses.
427 *
428 * @return string[]
429 */
430 public function getStatusSyncingPacketStatuses( array $expectedPacketStatuses ): array {
431 $packetStatusNames = $this->syncData['status_syncing_packet_statuses'] ?? null;
432 $expectedPacketStatusNames = array_map(
433 static function ( PacketStatus $status ): string {
434 return $status->getName();
435 },
436 $expectedPacketStatuses
437 );
438
439 if ( is_array( $packetStatusNames ) ) {
440 return array_intersect( $packetStatusNames, $expectedPacketStatusNames );
441 }
442
443 return $expectedPacketStatusNames;
444 }
445
446 /**
447 * Transform shipping address to contain pickup point address?
448 *
449 * @return bool
450 */
451 public function replaceShippingAddressWithPickupPointAddress(): bool {
452 return (bool) $this->get( 'replace_shipping_address_with_pickup_point_address' );
453 }
454
455 /**
456 * Turns on/off free shipping text in checkout.
457 *
458 * @return bool
459 */
460 public function isFreeShippingShown(): bool {
461 $freeShippingStatus = $this->get( 'free_shipping_shown' );
462 if ( $freeShippingStatus !== null ) {
463 return (bool) $freeShippingStatus;
464 }
465
466 return self::DISPLAY_FREE_SHIPPING_IN_CHECKOUT_DEFAULT;
467 }
468
469 /**
470 * Tells if prices include tax.
471 *
472 * @return bool
473 */
474 public function arePricesTaxInclusive(): bool {
475 $pricesIncludeTax = $this->get( 'prices_include_tax' );
476 if ( $pricesIncludeTax !== null ) {
477 return (bool) $pricesIncludeTax;
478 }
479
480 return self::PRICES_INCLUDE_TAX_DEFAULT;
481 }
482
483 public function isCheckoutLogoHidden(): bool {
484 $hideCheckoutLogo = $this->get( 'hide_checkout_logo' );
485 if ( $hideCheckoutLogo !== null ) {
486 return (bool) $hideCheckoutLogo;
487 }
488
489 return self::HIDE_CHECKOUT_LOGO_DEFAULT;
490 }
491
492 public function isAutoEmailInfoInsertionEnabled(): bool {
493 $autoEmailInfoInjection = $this->get( 'auto_email_info_insertion' );
494 if ( $autoEmailInfoInjection !== null ) {
495 return (bool) $autoEmailInfoInjection;
496 }
497
498 return self::AUTO_EMAIL_INFO_INSERTION_DEFAULT;
499 }
500
501 public function isCheckoutLogoShown(): bool {
502 return ! $this->isCheckoutLogoHidden();
503 }
504
505 /**
506 * Tells if packet cancellation should be forced.
507 *
508 * @return bool
509 */
510 public function isPacketCancellationForced(): bool {
511 $value = $this->get( 'force_packet_cancel' );
512 if ( $value !== null ) {
513 return (bool) $value;
514 }
515
516 return self::FORCE_PACKET_CANCEL_DEFAULT;
517 }
518
519 /**
520 * Gets packet auto submission payment method and event mapping.
521 *
522 * @return array
523 */
524 private function getPacketAutoSubmissionPaymentMethodEventsMapping(): array {
525 return $this->autoSubmissionData['payment_method_events'] ?? [];
526 }
527
528 /**
529 * Gets array of mapped events.
530 *
531 * @return string[]
532 */
533 public function getPacketAutoSubmissionMappedUniqueEvents(): array {
534 $mapping = $this->getPacketAutoSubmissionPaymentMethodEventsMapping();
535 $result = [];
536
537 foreach ( $mapping as $gatewayMapping ) {
538 if ( $gatewayMapping['event'] === null ) {
539 continue;
540 }
541 $result[ $gatewayMapping['event'] ] = $gatewayMapping['event'];
542 }
543
544 return $result;
545 }
546
547 /**
548 * Gets packet auto-submission event by payment gateway ID.
549 *
550 * @param string $paymentGatewayId Payment gateway ID.
551 *
552 * @return string|null
553 */
554 public function getPacketAutoSubmissionEventForPaymentGateway( string $paymentGatewayId ): ?string {
555 return $this->getPacketAutoSubmissionPaymentMethodEventsMapping()[ $paymentGatewayId ]['event'] ?? null;
556 }
557
558 /**
559 * Tells if packet auto submission is enabled.
560 *
561 * @return bool
562 */
563 public function isPacketAutoSubmissionEnabled(): bool {
564 $value = $this->autoSubmissionData['allow'] ?? null;
565 if ( $value !== null ) {
566 return (bool) $value;
567 }
568
569 return self::PACKET_AUTO_SUBMISSION_ALLOWED_DEFAULT;
570 }
571
572 /**
573 * Provides available labels.
574 *
575 * @return array[]
576 */
577 public function getLabelFormats(): array {
578 return [
579 'A6 on A4' => [
580 'name' => __( '1/4 A4, print on A4, 4pcs/page', 'packeta' ),
581 'directLabels' => true,
582 'maxOffset' => 3,
583 ],
584 'A6 on A6' => [
585 'name' => __( '1/4 A4, direct print, 1pc/page', 'packeta' ),
586 'directLabels' => true,
587 'maxOffset' => 0,
588 ],
589 'A7 on A7' => [
590 'name' => __( '1/8 A4, direct print, 1pc/page', 'packeta' ),
591 'directLabels' => false,
592 'maxOffset' => 0,
593 ],
594 'A7 on A4' => [
595 'name' => __( '1/8 A4, print on A4, 8pcs/page', 'packeta' ),
596 'directLabels' => false,
597 'maxOffset' => 7,
598 ],
599 '105x35mm on A4' => [
600 'name' => __( '105x35mm, print on A4, 16 pcs/page', 'packeta' ),
601 'directLabels' => false,
602 'maxOffset' => 15,
603 ],
604 'A8 on A8' => [
605 'name' => __( '1/16 A4, direct print, 1pc/page', 'packeta' ),
606 'directLabels' => false,
607 'maxOffset' => 0,
608 ],
609 ];
610 }
611
612 /**
613 * Gets maximum offset for selected Packeta labels format.
614 *
615 * @param string $format Selected format.
616 *
617 * @return int
618 */
619 public function getLabelMaxOffset( string $format ): int {
620 if ( $format === '' ) {
621 return 0;
622 }
623 $availableFormats = $this->getLabelFormats();
624
625 return $availableFormats[ $format ]['maxOffset'];
626 }
627
628 /**
629 * Gets list of Packeta labels for select creation.
630 *
631 * @return array
632 */
633 public function getPacketaLabelFormats(): array {
634 $availableFormats = $this->getLabelFormats();
635
636 return array_filter( array_combine( array_keys( $availableFormats ), array_column( $availableFormats, 'name' ) ) );
637 }
638
639 /**
640 * Gets list of carrier labels for select creation.
641 *
642 * @return array
643 */
644 public function getCarrierLabelFormat(): array {
645 $availableFormats = $this->getLabelFormats();
646 $carrierLabelFormats = [];
647 foreach ( $availableFormats as $format => $formatData ) {
648 if ( $formatData['directLabels'] === true ) {
649 $carrierLabelFormats[ $format ] = $formatData['name'];
650 }
651 }
652
653 return $carrierLabelFormats;
654 }
655
656 /**
657 * Tells if widget should open automatically.
658 *
659 * @return bool
660 */
661 public function shouldWidgetOpenAutomatically(): bool {
662 $value = $this->get( 'widget_auto_open' );
663 if ( $value !== null ) {
664 return (bool) $value;
665 }
666
667 return self::WIDGET_AUTO_OPEN_DEFAULT;
668 }
669
670 /**
671 * Auto order status change on packet submit enabled. Used in upgrade only.
672 *
673 * @return bool
674 */
675 public function isOrderStatusAutoChangeEnabled(): bool {
676 $orderStatusAutoChange = $this->get( 'order_status_auto_change' );
677 if ( $orderStatusAutoChange !== null ) {
678 return (bool) $orderStatusAutoChange;
679 }
680
681 return false;
682 }
683
684 /**
685 * Auto order status change.
686 *
687 * @return bool
688 */
689 public function isOrderStatusChangeAllowed(): bool {
690 $allowOrderStatusChange = ( $this->syncData['allow_order_status_change'] ?? null );
691 if ( $allowOrderStatusChange !== null ) {
692 return (bool) $allowOrderStatusChange;
693 }
694
695 return false;
696 }
697
698 public function isWcCarrierConfigEnabled(): bool {
699 $isEnabled = ( $this->advancedData['new_carrier_settings_enabled'] ?? null );
700 if ( $isEnabled !== null ) {
701 return (bool) $isEnabled;
702 }
703
704 return self::DEFAULT_VALUE_CARRIER_SETTINGS;
705 }
706
707 public function isWcCarrierConfigEnabledNullable(): ?bool {
708 $isEnabled = $this->advancedData['new_carrier_settings_enabled'] ?? null;
709 if ( $isEnabled !== null ) {
710 return (bool) $isEnabled;
711 }
712
713 return null;
714 }
715
716 /**
717 * Tells auto order status, if it is valid, otherwise empty string.
718 *
719 * @param string $packetStatus Packet status.
720 *
721 * @return string
722 */
723 public function getValidAutoOrderStatusFromMapping( string $packetStatus ): string {
724 $autoOrderStatus = $this->getAutoOrderStatusFromMapping( $packetStatus );
725 if ( wc_is_order_status( $autoOrderStatus ) ) {
726 return $autoOrderStatus;
727 }
728
729 return self::AUTO_ORDER_STATUS_DEFAULT;
730 }
731
732 /**
733 * Tells auto order status.
734 *
735 * @param string $packetStatus Packet status.
736 *
737 * @return string|null
738 */
739 public function getAutoOrderStatusFromMapping( string $packetStatus ): ?string {
740 return $this->syncData['order_status_change_packet_statuses'][ $packetStatus ] ?? null;
741 }
742
743 /**
744 * Tells auto order status. Used in upgrade only.
745 *
746 * @return string|null
747 */
748 public function getAutoOrderStatus(): ?string {
749 return $this->get( self::AUTO_ORDER_STATUS );
750 }
751
752 /**
753 * Gets email hook.
754 *
755 * @since 1.6.1
756 * @return string
757 */
758 public function getEmailHook(): string {
759 $emailHook = $this->get( 'email_hook' );
760 if ( $emailHook === null || $emailHook === '' ) {
761 return self::EMAIL_HOOK_DEFAULT;
762 }
763
764 return $emailHook;
765 }
766
767 /**
768 * Performs replacements needed by Nette form to pass validation, see https://github.com/dg/nette-component-model/blob/master/src/ComponentModel/Container.php#L50 .
769 * There may be an edge case where a replacement causes a conflict with another method. We do not address this issue yet.
770 *
771 * @param string $id Payment gateway id.
772 *
773 * @return string
774 */
775 public function sanitizePaymentGatewayId( string $id ): string {
776 return preg_replace( '/\W/', '_', $id );
777 }
778
779 public function isPickupPointValidationEnabled(): bool {
780 $isEnabled = $this->get( Page::FORM_PICKUP_POINT_VALIDATION_ENABLED );
781 if ( $isEnabled === null ) {
782 return self::PICKUP_POINT_VALIDATION_ENABLED_DEFAULT;
783 }
784
785 return (bool) $isEnabled;
786 }
787
788 public function isShowConsignPasswordForZBoxEnabled(): bool {
789 $value = $this->get( 'show_consign_password_for_z_box' );
790 if ( $value !== null ) {
791 return (bool) $value;
792 }
793
794 return self::SHOW_CONSIGN_PASSWORD_FOR_Z_BOX_DEFAULT;
795 }
796 }
797