PluginProbe
Packeta / 2.0.9
Packeta v2.0.9
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 2.0.9, at src/Packetery/Module/Options/OptionsProvider.php

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