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 / Page.php

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

1,141 lines 44.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class Page
4 *
5 * @package Packetery\Options
6 */
7
8 declare( strict_types=1 );
9
10 namespace Packetery\Module\Options;
11
12 use DateTime;
13 use Packetery\Core\Api;
14 use Packetery\Core\Api\Soap\Request\SenderGetReturnRouting;
15 use Packetery\Core\CoreHelper;
16 use Packetery\Core\Entity\PacketStatus;
17 use Packetery\Core\Log;
18 use Packetery\Latte\Engine;
19 use Packetery\Module\Dashboard\DashboardPage;
20 use Packetery\Module\DiagnosticsLogger\DiagnosticsLogger;
21 use Packetery\Module\FormFactory;
22 use Packetery\Module\Forms\BugReportForm;
23 use Packetery\Module\Forms\DiagnosticsLoggingFormFactory;
24 use Packetery\Module\Framework\WpAdapter;
25 use Packetery\Module\MessageManager;
26 use Packetery\Module\ModuleHelper;
27 use Packetery\Module\Order\PacketAutoSubmitter;
28 use Packetery\Module\Order\PacketSynchronizer;
29 use Packetery\Module\PaymentGatewayHelper;
30 use Packetery\Module\Views\UrlBuilder;
31 use Packetery\Module\WcLogger;
32 use Packetery\Nette\Forms\Container;
33 use Packetery\Nette\Forms\Controls\BaseControl;
34 use Packetery\Nette\Forms\Controls\SubmitButton;
35 use Packetery\Nette\Forms\Form;
36 use Packetery\Nette\Http;
37
38 /**
39 * Class Page
40 *
41 * @package Packetery\Options
42 */
43 class Page {
44
45 private const FORM_FIELDS_CONTAINER = 'packetery';
46 private const FORM_FIELD_PACKETA_LABEL_FORMAT = 'packeta_label_format';
47 private const FORM_FIELD_CARRIER_LABEL_FORMAT = 'carrier_label_format';
48 private const FORM_FIELD_FREE_SHIPPING_SHOWN = 'free_shipping_shown';
49 public const FORM_PICKUP_POINT_VALIDATION_ENABLED = 'pickup_point_validation_enabled';
50
51 public const ACTION_VALIDATE_SENDER = 'validate-sender';
52
53 public const SLUG = 'packeta-options';
54
55 public const TAB_GENERAL = 'general';
56 public const TAB_ADVANCED = 'advanced';
57 public const TAB_SUPPORT = 'support';
58 public const TAB_PACKET_STATUS_SYNC = 'packet-status-sync';
59 public const TAB_AUTO_SUBMISSION = 'auto-submission';
60
61 public const PARAM_TAB = 'tab';
62
63 const PACKETA_SVG_LOGO = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI1LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IlZyc3R2YV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB2aWV3Qm94PSIwIDAgMzcgNDAiIHN0eWxlPSJmaWxsOiNhN2FhYWQiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiAjYTdhYWFkO30KPC9zdHlsZT4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTE5LjQsMTYuMWwtMC45LDAuNGwtMC45LTAuNGwtMTMtNi41bDYuMi0yLjRsMTMuNCw2LjVMMTkuNCwxNi4xeiBNMzIuNSw5LjZsLTQuNywyLjNsLTEzLjUtNmw0LjItMS42CglMMzIuNSw5LjZ6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xOSwwbDE3LjIsNi42bC0yLjQsMS45bC0xNS4yLTZMMy4yLDguNkwwLjgsNi42TDE4LDBMMTksMEwxOSwweiBNMzQuMSw5LjFsMi44LTEuMWwtMi4xLDE3LjZsLTAuNCwwLjgKCUwxOS40LDQwbC0wLjUtMy4xbDEzLjQtMTJMMzQuMSw5LjF6IE0yLjUsMjYuNWwtMC40LTAuOEwwLDguMWwyLjgsMS4xbDEuOSwxNS43bDEzLjQsMTJMMTcuNiw0MEwyLjUsMjYuNXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI4LjIsMTIuNGw0LjMtMi43bC0xLjcsMTQuMkwxOC42LDM1bDAuNi0xN2w1LjQtMy4zTDI0LjMsMjNsMy4zLTIuM0wyOC4yLDEyLjR6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xNy43LDE3LjlsMC42LDE3bC0xMi4yLTExTDQuNCw5LjhMMTcuNywxNy45eiIvPgo8L3N2Zz4K';
64
65 /**
66 * PacketeryLatte_engine.
67 *
68 * @var Engine PacketeryLatte engine.
69 */
70 private $latteEngine;
71
72 /**
73 * Options Provider
74 *
75 * @var OptionsProvider
76 */
77 private $optionsProvider;
78
79 /**
80 * Form factory.
81 *
82 * @var FormFactory Form factory.
83 */
84 private $formFactory;
85
86 /**
87 * Packeta client.
88 *
89 * @var Api\Soap\Client
90 */
91 private $packetaClient;
92
93 /**
94 * Logger
95 *
96 * @var Log\ILogger
97 */
98 private $logger;
99
100 /**
101 * Message manager.
102 *
103 * @var MessageManager
104 */
105 private $messageManager;
106
107 /**
108 * @var Http\Request
109 */
110 private $httpRequest;
111
112 /**
113 * @var ModuleHelper
114 */
115 private $moduleHelper;
116
117 /**
118 * @var UrlBuilder
119 */
120 private $urlBuilder;
121
122 /**
123 * @var PacketSynchronizer
124 */
125 private $packetSynchronizer;
126
127 /**
128 * @var WpAdapter
129 */
130 private $wpAdapter;
131
132 /**
133 * @var string
134 */
135 private $supportEmailAddress;
136
137 /**
138 * @var BugReportForm
139 */
140 private $bugReportForm;
141
142 /**
143 * @var DiagnosticsLoggingFormFactory
144 */
145 private $diagnosticsLoggingFormFactory;
146
147 /** @var DiagnosticsLogger */
148 private $diagnosticsLogger;
149
150 public function __construct(
151 Engine $latteEngine,
152 OptionsProvider $optionsProvider,
153 FormFactory $formFactory,
154 Api\Soap\Client $packetaClient,
155 Log\ILogger $logger,
156 MessageManager $messageManager,
157 Http\Request $httpRequest,
158 ModuleHelper $moduleHelper,
159 UrlBuilder $urlBuilder,
160 PacketSynchronizer $packetSynchronizer,
161 WpAdapter $wpAdapter,
162 string $supportEmailAddress,
163 BugReportForm $bugReportForm,
164 DiagnosticsLoggingFormFactory $diagnosticsLoggingFormFactory,
165 DiagnosticsLogger $diagnosticsLogger
166 ) {
167 $this->latteEngine = $latteEngine;
168 $this->optionsProvider = $optionsProvider;
169 $this->formFactory = $formFactory;
170 $this->packetaClient = $packetaClient;
171 $this->logger = $logger;
172 $this->messageManager = $messageManager;
173 $this->httpRequest = $httpRequest;
174 $this->moduleHelper = $moduleHelper;
175 $this->urlBuilder = $urlBuilder;
176 $this->packetSynchronizer = $packetSynchronizer;
177 $this->supportEmailAddress = $supportEmailAddress;
178 $this->wpAdapter = $wpAdapter;
179 $this->bugReportForm = $bugReportForm;
180 $this->diagnosticsLoggingFormFactory = $diagnosticsLoggingFormFactory;
181 $this->diagnosticsLogger = $diagnosticsLogger;
182 }
183
184 public function register(): void {
185 add_action( 'admin_init', [ $this, 'admin_init' ] );
186 add_action( 'admin_init', [ $this, 'processActions' ] );
187 add_filter( 'custom_menu_order', '__return_true' );
188 add_filter( 'menu_order', [ $this, 'customMenuOrder' ] );
189 }
190
191 public function registerMenuPage(): void {
192 $this->wpAdapter->addMenuPage(
193 $this->wpAdapter->__( 'Packeta', 'packeta' ),
194 $this->wpAdapter->__( 'Packeta', 'packeta' ),
195 'manage_options',
196 DashboardPage::SLUG,
197 function () {},
198 self::PACKETA_SVG_LOGO
199 );
200 }
201
202 public function registerSubmenuPage(): void {
203 $this->wpAdapter->addSubmenuPage(
204 DashboardPage::SLUG,
205 $this->wpAdapter->__( 'Settings', 'packeta' ),
206 $this->wpAdapter->__( 'Settings', 'packeta' ),
207 'manage_options',
208 self::SLUG,
209 array(
210 $this,
211 'render',
212 ),
213 1
214 );
215 }
216
217 /**
218 * Returns menu_order with Packeta item in last position.
219 *
220 * @param array|mixed $menuOrder WP $menu_order.
221 *
222 * @return array|mixed
223 */
224 public function customMenuOrder( $menuOrder ) {
225 if ( ! is_array( $menuOrder ) ) {
226 WcLogger::logArgumentTypeError( __METHOD__, 'menuOrder', 'array', $menuOrder );
227
228 return $menuOrder;
229 }
230
231 $currentPosition = array_search( self::SLUG, $menuOrder, true );
232
233 if ( $currentPosition !== false ) {
234 unset( $menuOrder[ $currentPosition ] );
235 $menuOrder[] = self::SLUG;
236 }
237
238 return $menuOrder;
239 }
240
241 /**
242 * Get chosen keys by hashed choice data.
243 *
244 * @param array $choiceData Choice data.
245 * @param array $chosenHashedFormOrderStatuses Picked items.
246 *
247 * @return array
248 */
249 private function getChosenKeys( array $choiceData, array $chosenHashedFormOrderStatuses ): array {
250 $statuses = [];
251 foreach ( $chosenHashedFormOrderStatuses as $hash => $chosen ) {
252 if ( $chosen ) {
253 $statuses[] = $choiceData[ $hash ]['key'];
254 }
255 }
256
257 return $statuses;
258 }
259
260 /**
261 * Translate hashes to packet status keys.
262 *
263 * @param array $choiceData Choice data.
264 * @param array $formData Picked items.
265 *
266 * @return array
267 */
268 private function translateStatuses( array $choiceData, array $formData ): array {
269 $statuses = [];
270 foreach ( $formData as $hash => $value ) {
271 if ( $value ) {
272 $statuses[ $choiceData[ $hash ]['key'] ] = $value;
273 }
274 }
275
276 return $statuses;
277 }
278
279 /**
280 * Gets status syncing packet statuses.
281 *
282 * @return array<string, array{key: int|string, default: bool, label:string}>
283 */
284 public function getStatusSyncingPacketStatusesChoiceData(): array {
285 $statuses = $this->packetSynchronizer->getDefaultPacketStatuses();
286
287 return $this->createPacketStatusChoiceData( $statuses );
288 }
289
290 /**
291 * Gets all packet statuses.
292 *
293 * @return array<string, array{key: int|string, default: bool, label:string}>
294 */
295 public function getAllPacketStatusesChoiceData(): array {
296 $statuses = $this->packetSynchronizer->getPacketStatuses();
297
298 return $this->createPacketStatusChoiceData( $statuses );
299 }
300
301 /**
302 * @param PacketStatus[] $statuses Packet statuses.
303 *
304 * @return array<string, array{key: int|string, default: bool, label:string}>
305 */
306 private function createPacketStatusChoiceData( array $statuses ): array {
307 $result = [];
308
309 foreach ( $statuses as $status => $statusEntity ) {
310 $result[ md5( $status ) ] = [
311 'key' => $status,
312 'default' => $statusEntity->hasDefaultSynchronization(),
313 'label' => $statusEntity->getTranslatedName(),
314 ];
315 }
316
317 return $result;
318 }
319
320 /**
321 * Gets order statuses for form.
322 *
323 * @return array<string, array<string, int|string>>
324 */
325 public static function getOrderStatusesChoiceData(): array {
326 $orderStatuses = wc_get_order_statuses();
327 $orderStatusesTransformed = [];
328
329 foreach ( $orderStatuses as $orderStatusKey => $orderStatusLabel ) {
330 $orderStatusesTransformed[ md5( $orderStatusKey ) ] = [
331 'key' => $orderStatusKey,
332 'label' => $orderStatusLabel,
333 ];
334 }
335
336 return $orderStatusesTransformed;
337 }
338
339 /**
340 * Creates auto submission form.
341 *
342 * @return Form
343 */
344 public function createAutoSubmissionForm(): Form {
345 $gateways = PaymentGatewayHelper::getAvailablePaymentGateways();
346 $form = $this->formFactory->create( 'packetery_auto_submission_form' );
347 $defaults = $this->optionsProvider->getOptionsByName( OptionNames::PACKETERY_AUTO_SUBMISSION );
348
349 $form->addCheckbox( 'allow', __( 'Allow packet auto-submission', 'packeta' ) )
350 ->setRequired( false )
351 ->setDefaultValue( OptionsProvider::PACKET_AUTO_SUBMISSION_ALLOWED_DEFAULT );
352
353 $eventChoices = [
354 PacketAutoSubmitter::EVENT_ON_ORDER_CREATION_FE => __( 'On order creation at e-shop checkout', 'packeta' ),
355 PacketAutoSubmitter::EVENT_ON_ORDER_PROCESSING => __( 'On order processing', 'packeta' ),
356 PacketAutoSubmitter::EVENT_ON_ORDER_COMPLETED => __( 'On order completed', 'packeta' ),
357 ];
358
359 $paymentMethodEvents = $form->addContainer( 'payment_method_events' );
360 foreach ( $gateways as $gateway ) {
361 $paymentMethodEventsMethod = $paymentMethodEvents->addContainer(
362 $this->optionsProvider->sanitizePaymentGatewayId( $gateway->id )
363 );
364 $paymentMethodEventsMethod->addSelect( 'event', $gateway->get_method_title(), $eventChoices )
365 ->setPrompt( __( 'Select event', 'packeta' ) )
366 ->checkDefaultValue( false );
367 }
368
369 $form->addSubmit( 'save', __( 'Save changes', 'packeta' ) );
370
371 $form->setDefaults( $defaults );
372
373 $form->onSuccess[] = [ $this, 'onAutoSubmissionFormSuccess' ];
374
375 return $form;
376 }
377
378 /**
379 * On auto submission form success.
380 *
381 * @param Form $form Form.
382 * @param array $values Form values.
383 *
384 * @return void
385 */
386 public function onAutoSubmissionFormSuccess( Form $form, array $values ): void {
387 update_option( OptionNames::PACKETERY_AUTO_SUBMISSION, $values );
388
389 $this->messageManager->flash_message( __( 'Settings saved.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
390
391 if ( wp_safe_redirect( $this->createLink( self::TAB_AUTO_SUBMISSION ) ) ) {
392 exit;
393 }
394 }
395
396 /**
397 * Creates settings form.
398 *
399 * @return Form
400 */
401 private function createPacketStatusSyncForm(): Form {
402 $form = $this->formFactory->create( 'packetery_packet_status_sync_form' );
403 $settings = $this->optionsProvider->getOptionsByName( OptionNames::PACKETERY_SYNC );
404
405 $form->addText( 'max_status_syncing_packets', __( 'Number of orders synced during one cron call', 'packeta' ) )
406 ->setRequired( false )
407 ->addRule( Form::INTEGER )
408 ->addRule( Form::MIN, null, 0 )
409 ->setDefaultValue( OptionsProvider::MAX_STATUS_SYNCING_PACKETS_DEFAULT );
410
411 $form->addText( 'max_days_of_packet_status_syncing', __( 'Number of days for which the order status is checked', 'packeta' ) )
412 ->setRequired( false )
413 ->addRule( Form::INTEGER )
414 ->addRule( Form::MIN, null, 0 )
415 ->setDefaultValue( OptionsProvider::MAX_DAYS_OF_PACKET_STATUS_SYNCING_DEFAULT );
416
417 $orderStatusesTransformed = self::getOrderStatusesChoiceData();
418 $orderStatusesContainer = $form->addContainer( 'status_syncing_order_statuses' );
419
420 foreach ( $orderStatusesTransformed as $orderStatusKeyHash => $orderStatusData ) {
421 $item = $orderStatusesContainer->addCheckbox( $orderStatusKeyHash, $orderStatusData['label'] );
422 if ( isset( $settings['status_syncing_order_statuses'] ) && in_array( $orderStatusData['key'], $settings['status_syncing_order_statuses'], true ) ) {
423 $item->setDefaultValue( true );
424 }
425 }
426 unset( $settings['status_syncing_order_statuses'] );
427
428 $packetStatuses = $this->getStatusSyncingPacketStatusesChoiceData();
429 $packetStatusesContainer = $form->addContainer( 'status_syncing_packet_statuses' );
430
431 foreach ( $packetStatuses as $packetStatusHash => $packetStatusData ) {
432 $item = $packetStatusesContainer->addCheckbox( $packetStatusHash, $packetStatusData['label'] );
433 if ( ! isset( $settings['status_syncing_packet_statuses'] ) ) {
434 $item->setDefaultValue( $packetStatusData['default'] );
435 } elseif ( in_array( $packetStatusData['key'], $settings['status_syncing_packet_statuses'], true ) ) {
436 $item->setDefaultValue( true );
437 }
438 }
439 unset( $settings['status_syncing_packet_statuses'] );
440
441 $form->addCheckbox( 'allow_order_status_change', __( 'Allow order status change', 'packeta' ) )
442 ->setRequired( false )
443 ->setDefaultValue( false )
444 ->addCondition( Form::EQUAL, true )
445 ->toggle( '.order_status_change_content' );
446
447 $orderStatusChangePacketStatuses = $form->addContainer( 'order_status_change_packet_statuses' );
448 $orderStatuses = wc_get_order_statuses();
449 $packetStatuses = $this->getAllPacketStatusesChoiceData();
450 foreach ( $packetStatuses as $packetStatusHash => $packetStatusData ) {
451 $item = $orderStatusChangePacketStatuses->addSelect( $packetStatusHash, $packetStatusData['label'], $orderStatuses )
452 ->setPrompt( __( 'Order status', 'packeta' ) );
453 $targetStatus = $settings['order_status_change_packet_statuses'][ $packetStatusData['key'] ] ?? null;
454 if ( $targetStatus !== null && array_key_exists( $targetStatus, $orderStatuses ) ) {
455 $item->setDefaultValue( $targetStatus );
456 }
457 }
458 unset( $settings['order_status_change_packet_statuses'] );
459
460 $form->setDefaults( $settings );
461
462 $form->addSubmit( 'save', __( 'Save changes', 'packeta' ) );
463
464 $form->onSuccess[] = [ $this, 'onPacketStatusSyncFormSuccess' ];
465
466 return $form;
467 }
468
469 /**
470 * On packet status sync form success.
471 *
472 * @param Form $form Form.
473 * @param array $values Values.
474 *
475 * @return void
476 */
477 public function onPacketStatusSyncFormSuccess( Form $form, array $values ): void {
478 $values['status_syncing_order_statuses'] = $this->getChosenKeys(
479 self::getOrderStatusesChoiceData(),
480 $values['status_syncing_order_statuses']
481 );
482 $values['status_syncing_packet_statuses'] = $this->getChosenKeys(
483 $this->getStatusSyncingPacketStatusesChoiceData(),
484 $values['status_syncing_packet_statuses']
485 );
486 $values['order_status_change_packet_statuses'] = $this->translateStatuses(
487 $this->getAllPacketStatusesChoiceData(),
488 $values['order_status_change_packet_statuses']
489 );
490
491 if ( $values['max_status_syncing_packets'] === '' ) {
492 unset( $values['max_status_syncing_packets'] );
493 }
494
495 if ( $values['max_days_of_packet_status_syncing'] === '' ) {
496 unset( $values['max_days_of_packet_status_syncing'] );
497 }
498
499 update_option( OptionNames::PACKETERY_SYNC, $values );
500
501 $this->messageManager->flash_message( __( 'Settings saved.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
502
503 if ( wp_safe_redirect( $this->createLink( self::TAB_PACKET_STATUS_SYNC ) ) ) {
504 exit;
505 }
506 }
507
508 public function createAdvancedForm(): Form {
509 $form = $this->formFactory->create( 'packetery_advanced_form' );
510 $defaults = $this->optionsProvider->getOptionsByName( OptionNames::PACKETERY_ADVANCED );
511
512 $form->addCheckbox( 'new_carrier_settings_enabled', __( 'Advanced carrier settings', 'packeta' ) )
513 ->setRequired( false )
514 ->setDefaultValue( OptionsProvider::DEFAULT_VALUE_CARRIER_SETTINGS );
515
516 $form->addSubmit( 'save', __( 'Save changes', 'packeta' ) );
517
518 $form->setDefaults( $defaults );
519
520 $form->onSuccess[] = [ $this, 'onAdvancedFormSuccess' ];
521
522 return $form;
523 }
524
525 public function onAdvancedFormSuccess( Form $form, array $values ): void {
526 update_option( OptionNames::PACKETERY_ADVANCED, $values );
527
528 $this->messageManager->flash_message( __( 'Settings saved.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
529
530 if ( wp_safe_redirect( $this->createLink( self::TAB_ADVANCED ) ) ) {
531 exit;
532 }
533 }
534
535 /**
536 * Creates settings form.
537 *
538 * @return Form
539 */
540 public function create_form(): Form {
541 $form = $this->formFactory->create();
542 $form->setAction( 'options.php' );
543
544 $container = $form->addContainer( self::FORM_FIELDS_CONTAINER );
545 $container->addText( 'api_password', __( 'API password', 'packeta' ) )
546 ->setRequired()
547 ->addRule( $form::PATTERN, __( 'API password must be 32 characters long and must contain valid characters!', 'packeta' ), '[a-z\d]{32}' );
548 $container->addText( 'sender', __( 'Sender', 'packeta' ) )
549 ->setRequired();
550
551 $packetaLabelFormats = $this->optionsProvider->getPacketaLabelFormats();
552 $container->addSelect(
553 self::FORM_FIELD_PACKETA_LABEL_FORMAT,
554 __( 'Packeta Label Format', 'packeta' ),
555 $packetaLabelFormats
556 )->checkDefaultValue( false )->setDefaultValue( OptionsProvider::DEFAULT_VALUE_PACKETA_LABEL_FORMAT );
557
558 $carrierLabelFormats = $this->optionsProvider->getCarrierLabelFormat();
559 $container->addSelect(
560 self::FORM_FIELD_CARRIER_LABEL_FORMAT,
561 __( 'Carrier Label Format', 'packeta' ),
562 $carrierLabelFormats
563 )->checkDefaultValue( false )->setDefaultValue( OptionsProvider::DEFAULT_VALUE_CARRIER_LABEL_FORMAT );
564
565 $gateways = PaymentGatewayHelper::getAvailablePaymentGateways();
566 $enabledGateways = [];
567 foreach ( $gateways as $gateway ) {
568 $enabledGateways[ $gateway->id ] = $gateway->get_method_title();
569 }
570 $container->addMultiSelect(
571 'cod_payment_methods',
572 __( 'Payment methods that represent cash on delivery', 'packeta' ),
573 $enabledGateways
574 )->checkDefaultValue( false );
575
576 $container->addText( 'packaging_weight', __( 'Weight of packaging material', 'packeta' ) . ' (kg)' )
577 ->setRequired()
578 ->addRule( Form::FLOAT )
579 ->addRule( Form::MIN, null, 0 )
580 ->setDefaultValue( 0 );
581
582 $container->addCheckbox( 'default_weight_enabled', __( 'Enable default weight', 'packeta' ) )
583 ->addCondition( Form::EQUAL, true )
584 ->toggle( '#packetery-default-weight-value' );
585
586 $container->addText( 'default_weight', __( 'Default weight', 'packeta' ) . ' (kg)' )
587 ->addConditionOn( $form[ self::FORM_FIELDS_CONTAINER ]['default_weight_enabled'], Form::EQUAL, true )
588 ->setRequired()
589 ->addRule( Form::FLOAT )
590 ->addRule( Form::MIN, null, 0.1 );
591
592 $container->addSelect(
593 'dimensions_unit',
594 __( 'Units used for dimensions', 'packeta' ),
595 [
596 OptionsProvider::DIMENSIONS_UNIT_CM => 'cm',
597 OptionsProvider::DEFAULT_DIMENSIONS_UNIT_MM => 'mm',
598 ]
599 )
600 ->setDefaultValue( $this->optionsProvider::DEFAULT_DIMENSIONS_UNIT_MM );
601
602 $container->addCheckbox( 'default_dimensions_enabled', __( 'Enable default dimensions', 'packeta' ) )
603 ->addCondition( Form::EQUAL, true )
604 ->toggle( '#packetery-default-dimensions-value' );
605
606 $container->addText( 'default_length', __( 'Length', 'packeta' ) )
607 ->addConditionOn( $form[ self::FORM_FIELDS_CONTAINER ]['default_dimensions_enabled'], Form::EQUAL, true )
608 ->setRequired()
609 ->addConditionOn( $form[ self::FORM_FIELDS_CONTAINER ]['dimensions_unit'], Form::EQUAL, $this->optionsProvider::DEFAULT_DIMENSIONS_UNIT_MM )
610 ->addRule( Form::INTEGER, __( 'Provide a full number!', 'packeta' ) )
611 ->addRule( Form::MIN, 'Value must be greater than 0', 1 )
612 ->elseCondition()
613 ->addRule( Form::FLOAT, __( 'Provide a decimal value!', 'packeta' ) )
614 ->addRule( Form::MIN, 'Value must be greater than 0', 0.1 )
615 ->endCondition();
616
617 $container->addText( 'default_height', __( 'Height', 'packeta' ) )
618 ->addConditionOn( $form[ self::FORM_FIELDS_CONTAINER ]['default_dimensions_enabled'], Form::EQUAL, true )
619 ->setRequired()
620 ->addConditionOn( $form[ self::FORM_FIELDS_CONTAINER ]['dimensions_unit'], Form::EQUAL, $this->optionsProvider::DEFAULT_DIMENSIONS_UNIT_MM )
621 ->addRule( Form::INTEGER, __( 'Provide a full number!', 'packeta' ) )
622 ->addRule( Form::MIN, 'Value must be greater than 0', 1 )
623 ->elseCondition()
624 ->addRule( Form::FLOAT, __( 'Provide a decimal value!', 'packeta' ) )
625 ->addRule( Form::MIN, 'Value must be greater than 0', 0.1 )
626 ->endCondition();
627
628 $container->addText( 'default_width', __( 'Width', 'packeta' ) )
629 ->addConditionOn( $form[ self::FORM_FIELDS_CONTAINER ]['default_dimensions_enabled'], Form::EQUAL, true )
630 ->setRequired()
631 ->addConditionOn( $form[ self::FORM_FIELDS_CONTAINER ]['dimensions_unit'], Form::EQUAL, $this->optionsProvider::DEFAULT_DIMENSIONS_UNIT_MM )
632 ->addRule( Form::INTEGER, __( 'Provide a full number!', 'packeta' ) )
633 ->addRule( Form::MIN, 'Value must be greater than 0', 1 )
634 ->elseCondition()
635 ->addRule( Form::FLOAT, __( 'Provide a decimal value!', 'packeta' ) )
636 ->addRule( Form::MIN, 'Value must be greater than 0', 0.1 )
637 ->endCondition();
638
639 $container->addCheckbox( 'replace_shipping_address_with_pickup_point_address', __( 'Replace shipping address with pickup point address', 'packeta' ) )
640 ->setRequired( false );
641
642 $container->addSelect(
643 'checkout_detection',
644 __( 'Force checkout type', 'packeta' ),
645 [
646 OptionsProvider::AUTOMATIC_CHECKOUT_DETECTION => __( 'Automatic detection', 'packeta' ),
647 OptionsProvider::CLASSIC_CHECKOUT_DETECTION => __( 'Classic checkout', 'packeta' ),
648 OptionsProvider::BLOCK_CHECKOUT_DETECTION => __( 'Block-based checkout', 'packeta' ),
649 ]
650 );
651
652 $container->addSelect(
653 'checkout_widget_button_location',
654 __( 'Widget button location in checkout', 'packeta' ),
655 [
656 'after_shipping_rate' => __( 'After shipping rate', 'packeta' ),
657 'after_transport_methods' => __( 'After transport methods', 'packeta' ),
658 ]
659 );
660
661 $container->addCheckbox( 'hide_checkout_logo', __( 'Hide Packeta checkout logo', 'packeta' ) )
662 ->setRequired( false )
663 ->setDefaultValue( OptionsProvider::HIDE_CHECKOUT_LOGO_DEFAULT );
664
665 $container->addCheckbox( 'auto_email_info_insertion', __( 'Automatically insert packet and pickup point information into emails', 'packeta' ) )
666 ->setRequired( false )
667 ->setDefaultValue( OptionsProvider::AUTO_EMAIL_INFO_INSERTION_DEFAULT )
668 ->addCondition( Form::EQUAL, true )
669 ->toggle( '#packetery-email-hook' );
670
671 $container->addSelect(
672 'email_hook',
673 __( 'Hook used to view information in email', 'packeta' ),
674 [
675 'woocommerce_email_footer' => 'woocommerce_email_footer',
676 'woocommerce_email_before_order_table' => 'woocommerce_email_before_order_table',
677 'woocommerce_email_after_order_table' => 'woocommerce_email_after_order_table',
678 'woocommerce_email_order_meta' => 'woocommerce_email_order_meta',
679 ]
680 );
681
682 $container->addCheckbox( 'force_packet_cancel', __( 'Force order cancellation', 'packeta' ) )
683 ->setRequired( false )
684 ->setDefaultValue( OptionsProvider::FORCE_PACKET_CANCEL_DEFAULT );
685
686 $container->addCheckbox( 'widget_auto_open', __( 'Automatically open widget when shipping was selected', 'packeta' ) )
687 ->setRequired( false )
688 ->setDefaultValue( OptionsProvider::WIDGET_AUTO_OPEN_DEFAULT );
689
690 $container->addCheckbox( self::FORM_FIELD_FREE_SHIPPING_SHOWN, __( 'Display the FREE shipping text in checkout', 'packeta' ) )
691 ->setRequired( false )
692 ->setDefaultValue( OptionsProvider::DISPLAY_FREE_SHIPPING_IN_CHECKOUT_DEFAULT );
693
694 $container->addCheckbox( 'prices_include_tax', __( 'Prices include tax', 'packeta' ) )
695 ->setRequired( false )
696 ->setDefaultValue( OptionsProvider::PRICES_INCLUDE_TAX_DEFAULT );
697
698 $container->addCheckbox( self::FORM_PICKUP_POINT_VALIDATION_ENABLED, __( 'Validate the pickup point using the API before accepting the order', 'packeta' ) )
699 ->setRequired( false )
700 ->setDefaultValue( OptionsProvider::PICKUP_POINT_VALIDATION_ENABLED_DEFAULT );
701
702 $container->addCheckbox( 'show_consign_password_for_z_box', __( 'Show consignment code', 'packeta' ) )
703 ->setRequired( false )
704 ->setDefaultValue( OptionsProvider::SHOW_CONSIGN_PASSWORD_FOR_Z_BOX_DEFAULT );
705
706 $form->addSubmit( 'save', __( 'Save changes', 'packeta' ) );
707
708 if ( $this->optionsProvider->has_any( OptionNames::PACKETERY ) ) {
709 $container->setDefaults( $this->optionsProvider->getOptionsByName( OptionNames::PACKETERY ) );
710 }
711
712 return $form;
713 }
714
715 /**
716 * Admin_init callback.
717 */
718 public function admin_init(): void {
719 add_filter( 'pre_update_option_packetery', [ $this, 'validatePacketeryOptions' ] );
720
721 // Registered callback is called when the form is submitted.
722 register_setting( self::FORM_FIELDS_CONTAINER, self::FORM_FIELDS_CONTAINER, [ $this, 'sanitizePacketeryOptions' ] );
723
724 add_settings_section( 'packetery_main', __( 'Main Settings', 'packeta' ), function () {}, self::SLUG );
725 }
726
727 /**
728 * Validates packetery options.
729 *
730 * @param array $options Options to be validated.
731 *
732 * @return array
733 */
734 public function validatePacketeryOptions( array $options ): array {
735 $form = $this->create_form();
736 /**
737 * Packetery container.
738 *
739 * @var Container $packeteryContainer
740 */
741 $packeteryContainer = $form[ self::FORM_FIELDS_CONTAINER ];
742 $packeteryContainer->setValues( $options );
743 if ( $form->isValid() === false ) {
744 foreach ( $packeteryContainer->getControls() as $control ) {
745 if ( $control->hasErrors() === false ) {
746 continue;
747 }
748
749 add_settings_error( OptionNames::PACKETERY, esc_attr( $control->getName() ), "{$control->getCaption()}: {$control->getError()}" );
750 }
751 }
752
753 $apiPassword = $packeteryContainer['api_password'];
754 if ( $apiPassword instanceof BaseControl && $apiPassword->hasErrors() === false ) {
755 $this->packetaClient->setApiPassword( $apiPassword->getValue() );
756 }
757
758 $this->validateSender( $options['sender'] );
759
760 return $options;
761 }
762
763 /**
764 * Sanitize options.
765 *
766 * @param array $options Options to be sanitized.
767 *
768 * @return array
769 */
770 public function sanitizePacketeryOptions( array $options ): array {
771 $form = $this->create_form();
772 /**
773 * Packetery container.
774 *
775 * @var Container $packeteryContainer
776 */
777 $packeteryContainer = $form[ self::FORM_FIELDS_CONTAINER ];
778 if ( ! isset( $options['auto_email_info_insertion'] ) ) {
779 $options['auto_email_info_insertion'] = false;
780 }
781 if ( ! isset( $options['show_consign_password_for_z_box'] ) ) {
782 $options['show_consign_password_for_z_box'] = false;
783 }
784 $packeteryContainer->setValues( $options );
785 if ( $form->isValid() === false ) {
786 foreach ( $packeteryContainer->getControls() as $control ) {
787 if ( $control->hasErrors() === false ) {
788 continue;
789 }
790
791 $options[ $control->getName() ] = '';
792 }
793 }
794
795 $apiPassword = $packeteryContainer['api_password'];
796
797 if ( $apiPassword instanceof BaseControl && $apiPassword->hasErrors() === false ) {
798 $apiPass = $apiPassword->getValue();
799 $options['api_key'] = substr( $apiPass, 0, 16 );
800 $this->packetaClient->setApiPassword( $apiPass );
801 } else {
802 $options['api_key'] = '';
803 }
804
805 if ( $packeteryContainer['default_weight'] instanceof BaseControl ) {
806 $defaultWeight = $packeteryContainer['default_weight']->getValue();
807 $options['default_weight'] = is_numeric( $defaultWeight ) ? CoreHelper::trimDecimalPlaces( (float) $defaultWeight, 3 ) : $defaultWeight;
808 }
809
810 foreach ( [ 'default_length', 'default_width', 'default_height' ] as $dimension ) {
811 if ( $packeteryContainer[ $dimension ] instanceof BaseControl ) {
812 $options[ $dimension ] = is_numeric( $packeteryContainer[ $dimension ]->getValue() )
813 ? CoreHelper::trimDecimalPlaces( (float) $packeteryContainer[ $dimension ]->getValue(), 1 )
814 : $packeteryContainer[ $dimension ]->getValue();
815 }
816 }
817
818 if ( $packeteryContainer['force_packet_cancel'] instanceof BaseControl ) {
819 $options['force_packet_cancel'] = (int) $packeteryContainer['force_packet_cancel']->getValue();
820 }
821
822 if ( $packeteryContainer['free_shipping_shown'] instanceof BaseControl ) {
823 $options['free_shipping_shown'] = (int) $packeteryContainer['free_shipping_shown']->getValue();
824 }
825
826 $previousOptions = $this->optionsProvider->getOptionsByName( OptionNames::PACKETERY );
827 if ( ! isset( $options['default_weight_enabled'] ) ) {
828 if ( isset( $previousOptions['default_weight'] ) ) {
829 $options['default_weight'] = $previousOptions['default_weight'];
830 } else {
831 unset( $options['default_weight'] );
832 }
833 }
834 if ( ! isset( $options['default_dimensions_enabled'] ) ) {
835 foreach ( [ 'default_length', 'default_width', 'default_height' ] as $dimension ) {
836 if ( isset( $previousOptions[ $dimension ] ) ) {
837 $options[ $dimension ] = $previousOptions[ $dimension ];
838 } else {
839 unset( $options[ $dimension ] );
840 }
841 }
842 }
843
844 if ( $options['api_key'] === '' ) {
845 $options[ self::FORM_PICKUP_POINT_VALIDATION_ENABLED ] = false;
846 }
847
848 return $options;
849 }
850
851 /**
852 * Validates sender.
853 *
854 * @param string $senderLabel Sender label.
855 *
856 * @return bool|null
857 */
858 private function validateSender( string $senderLabel ): ?bool {
859 $senderValidationRequest = new SenderGetReturnRouting( $senderLabel );
860 $senderValidationResponse = $this->packetaClient->senderGetReturnRouting( $senderValidationRequest );
861
862 $senderValidationLog = new Log\Record();
863 $senderValidationLog->action = Log\Record::ACTION_SENDER_VALIDATION;
864
865 $senderValidationLog->status = Log\Record::STATUS_SUCCESS;
866 $senderValidationLog->title = __( 'Sender validation was successful', 'packeta' );
867
868 if ( $senderValidationResponse->hasFault() ) {
869 $senderValidationLog->status = Log\Record::STATUS_ERROR;
870 $senderValidationLog->params = [
871 'errorMessage' => $senderValidationResponse->getFaultString(),
872 ];
873 $senderValidationLog->title = __( 'Sender could not be validated', 'packeta' );
874 }
875
876 $this->logger->add( $senderValidationLog );
877
878 $senderExists = $senderValidationResponse->senderExists();
879
880 if ( $senderExists === false ) {
881 $this->messageManager->flash_message( __( 'Specified sender does not exist', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
882 }
883
884 if ( $senderExists === null ) {
885 $this->messageManager->flash_message( __( 'Unable to check specified sender', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
886 }
887
888 return $senderExists;
889 }
890
891 /**
892 * Process actions.
893 *
894 * @return void
895 */
896 public function processActions(): void {
897 $action = $this->httpRequest->getQuery( 'action' );
898 if ( $action === self::ACTION_VALIDATE_SENDER ) {
899 $result = $this->validateSender( $this->optionsProvider->get_sender() );
900
901 if ( $result === true ) {
902 $this->messageManager->flash_message( __( 'Specified sender has been validated.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
903 }
904
905 $doRedirect = wp_safe_redirect(
906 add_query_arg(
907 [
908 'page' => self::SLUG,
909 ],
910 get_admin_url( null, 'admin.php' )
911 )
912 );
913
914 if ( $doRedirect ) {
915 exit;
916 }
917 }
918
919 $packetStatusSyncForm = $this->createPacketStatusSyncForm();
920 if (
921 $packetStatusSyncForm['save'] instanceof SubmitButton &&
922 $packetStatusSyncForm['save']->isSubmittedBy()
923 ) {
924 $packetStatusSyncForm->fireEvents();
925 }
926
927 $autoSubmissionForm = $this->createAutoSubmissionForm();
928 if (
929 $autoSubmissionForm['save'] instanceof SubmitButton &&
930 $autoSubmissionForm['save']->isSubmittedBy()
931 ) {
932 $autoSubmissionForm->fireEvents();
933 }
934
935 $advancedForm = $this->createAdvancedForm();
936 if (
937 $advancedForm['save'] instanceof SubmitButton &&
938 $advancedForm['save']->isSubmittedBy()
939 ) {
940 $advancedForm->fireEvents();
941 }
942
943 $bugReportForm = $this->bugReportForm->createForm();
944 if (
945 $bugReportForm['submit'] instanceof SubmitButton &&
946 $bugReportForm['submit']->isSubmittedBy() &&
947 $bugReportForm->isSuccess()
948 ) {
949 $bugReportForm->fireEvents();
950 }
951
952 $diagnosticsLoggingForm = $this->diagnosticsLoggingFormFactory->createForm();
953 if (
954 $diagnosticsLoggingForm['save'] instanceof SubmitButton &&
955 $diagnosticsLoggingForm['save']->isSubmittedBy() &&
956 $diagnosticsLoggingForm->isSuccess()
957 ) {
958 $diagnosticsLoggingForm->fireEvents();
959 }
960 }
961
962 /**
963 * Renders page.
964 */
965 public function render(): void {
966 $activeTab = ( $this->httpRequest->getQuery( self::PARAM_TAB ) ?? self::TAB_GENERAL );
967
968 $latteParams = [];
969 if ( $activeTab === self::TAB_PACKET_STATUS_SYNC ) {
970 $latteParams = [ 'form' => $this->createPacketStatusSyncForm() ];
971 } elseif ( $activeTab === self::TAB_AUTO_SUBMISSION ) {
972 $latteParams = [ 'form' => $this->createAutoSubmissionForm() ];
973 } elseif ( $activeTab === self::TAB_ADVANCED ) {
974 $latteParams = [ 'form' => $this->createAdvancedForm() ];
975 } elseif ( $activeTab === self::TAB_GENERAL ) {
976 $latteParams = [ 'form' => $this->create_form() ];
977 } elseif ( $activeTab === self::TAB_SUPPORT ) {
978 $latteParams = [
979 'bugReportFormEnabled' => false,
980 'bugReportForm' => $this->bugReportForm->createForm(),
981 'diagnosticsLoggingForm' => $this->diagnosticsLoggingFormFactory->createForm(),
982 'hasPacketaLog' => is_file( $this->diagnosticsLogger->getPacketaLogPath() ),
983 ];
984 }
985
986 if ( ! extension_loaded( 'soap' ) ) {
987 $latteParams['error'] = __( 'This plugin requires an active SOAP library for proper operation. Contact your web hosting administrator.', 'packeta' );
988 }
989
990 $latteParams['apiPasswordLink'] = trim( $this->latteEngine->renderToString( PACKETERY_PLUGIN_DIR . '/template/options/help-block-link.latte', [ 'href' => 'https://client.packeta.com/support' ] ) );
991
992 $latteParams['exportLink'] = add_query_arg(
993 [
994 'page' => self::SLUG,
995 'action' => Exporter::ACTION_EXPORT_SETTINGS,
996 ],
997 get_admin_url( null, 'admin.php' )
998 );
999
1000 $latteParams['deleteDiagnosticsLogsLink'] = add_query_arg(
1001 [
1002 'page' => self::SLUG,
1003 'action' => DiagnosticsLogger::ACTION_DELETE_PACKETA_LOG,
1004 'tab' => self::TAB_SUPPORT,
1005 ],
1006 get_admin_url( null, 'admin.php' )
1007 );
1008
1009 $latteParams['activeTab'] = ( $this->httpRequest->getQuery( self::PARAM_TAB ) ?? self::TAB_GENERAL );
1010 $latteParams['generalTabLink'] = $this->createLink();
1011 $latteParams['advancedTabLink'] = $this->createLink( self::TAB_ADVANCED );
1012 $latteParams['supportTabLink'] = $this->createLink( self::TAB_SUPPORT );
1013 $latteParams['packetStatusSyncTabLink'] = $this->createLink( self::TAB_PACKET_STATUS_SYNC );
1014 $latteParams['autoSubmissionTabLink'] = $this->createLink( self::TAB_AUTO_SUBMISSION );
1015
1016 $latteParams['canValidateSender'] = (bool) $this->optionsProvider->get_sender();
1017 $latteParams['senderValidationLink'] = add_query_arg(
1018 [
1019 'page' => self::SLUG,
1020 'action' => self::ACTION_VALIDATE_SENDER,
1021 ],
1022 get_admin_url( null, 'admin.php' )
1023 );
1024
1025 $lastExport = null;
1026 $lastExportOption = get_option( OptionNames::LAST_SETTINGS_EXPORT );
1027 if ( $lastExportOption !== false ) {
1028 $date = DateTime::createFromFormat( DATE_ATOM, $lastExportOption );
1029 if ( $date !== false ) {
1030 $date->setTimezone( wp_timezone() );
1031 $lastExport = $date->format( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
1032 }
1033 }
1034 if ( $lastExport !== null ) {
1035 $latteParams['lastExport'] = $lastExport;
1036 }
1037
1038 $latteParams['forcePacketCancelDescription'] = __( 'Cancel the packet for an order even if the cancellation in the Packeta system will not be successful.', 'packeta' );
1039 $latteParams['messages'] = $this->messageManager->renderToString( MessageManager::RENDERER_PACKETERY, 'plugin-options' );
1040 $latteParams['isCzechLocale'] = $this->moduleHelper->isCzechLocale();
1041 $latteParams['logoZasilkovna'] = $this->urlBuilder->buildAssetUrl( 'public/images/logo-zasilkovna.svg' );
1042 $latteParams['logoPacketa'] = $this->urlBuilder->buildAssetUrl( 'public/images/logo-packeta.svg' );
1043 $advancedCarrierSettingsDescription = sprintf(
1044 // translators: first %s is line break, second one is e-mail address
1045 __( 'When this feature is active, Packeta carriers will appear as separate shipping methods under WooCommerce → Settings → Shipping. After enabling or disabling this feature, you need to reconfigure your shipping methods in WooCommerce.%1$sIf you encounter any issues, please contact us at %2$s.', 'packeta' ),
1046 '<br>',
1047 '<a href="mailto:' . $this->supportEmailAddress . '">' . $this->supportEmailAddress . '</a>'
1048 );
1049 $latteParams['translations'] = [
1050 'packeta' => __( 'Packeta', 'packeta' ),
1051 'title' => __( 'Options', 'packeta' ),
1052 'general' => __( 'General', 'packeta' ),
1053 'packetAutoSubmission' => __( 'Packet auto-submission', 'packeta' ),
1054 'packetAutoSubmissionMappingDescription' => __( 'Choose events for payment methods that will trigger packet submission', 'packeta' ),
1055 // translators: %s represents URL.
1056 'apiPasswordCanBeFoundAt%sUrl' => __( 'API password can be found at %s', 'packeta' ),
1057
1058 'saveChanges' => __( 'Save changes', 'packeta' ),
1059 'validateSender' => __( 'Validate sender', 'packeta' ),
1060 'advanced' => __( 'Advanced', 'packeta' ),
1061 'support' => __( 'Support', 'packeta' ),
1062 'optionsExportInfo1' => __(
1063 'By clicking the button, you will export the settings of your plugin into a separate file. The export does not contain any sensitive information about your e-shop. Please send the resulting file to the technical support of Packeta (you can find the e-mail address here:',
1064 'packeta'
1065 ),
1066 'optionsExportInfo2' => __(
1067 ') along with the description of your problem. For a better understanding of your problem, we recommend adding screenshots, which show the problem (if possible).',
1068 'packeta'
1069 ),
1070 'exportPluginSettings' => __( 'Export the plugin settings', 'packeta' ),
1071 'settingsExportDatetime' => __( 'Date and time of the last export of settings', 'packeta' ),
1072 'settingsNotYetExported' => __( 'The settings have not been exported yet.', 'packeta' ),
1073 'bugReportTitle' => $this->wpAdapter->__( 'Report a bug', 'packeta' ),
1074 'bugReportDescription' => $this->wpAdapter->__( 'If you encounter any issues with the Packeta plugin, please use this form to report them. Your message will be sent to our technical support team along with system information.', 'packeta' ),
1075 'bugReportInfo' => $this->wpAdapter->__( 'We will also zip the following files and attach them to the email, if available: WooCommerce Log, Diagnostics Log, Tracy Log, Wordpress Debug Log, WooCommerce System Status Log, Packeta plugin settings export.', 'packeta' ),
1076 'exportSettingsTitle' => $this->wpAdapter->__( 'Export settings', 'packeta' ),
1077 'diagnosticsLoggingTitle' => $this->wpAdapter->__( 'Diagnostics logging', 'packeta' ),
1078 'senderDescription' => sprintf(
1079 /* translators: 1: emphasis start 2: emphasis end 3: client section link start 4: client section link end */
1080 esc_html__( 'Fill here %1$ssender label%2$s - you will find it in %3$sclient section%4$s - user information - field \'Indication\'.', 'packeta' ),
1081 '<strong>',
1082 '</strong>',
1083 '<a href="https://client.packeta.com/senders" target="_blank">',
1084 '</a>'
1085 ),
1086 'advancedCarrierSettingsDescription' => $advancedCarrierSettingsDescription,
1087 'packagingWeightDescription' => __( 'This parameter is used to determine the weight of the packaging material. This value is automatically added to the total weight of each order that contains products with non-zero weight. This value is also taken into account when evaluating the weight rules in the cart.', 'packeta' ),
1088 'defaultWeightDescription' => __( 'This value is automatically added to the total weight of each order that contains products with zero weight.', 'packeta' ),
1089 'defaultDimensionsDescription' => __( 'These dimensions will be applied to the packet by default, if required by the carrier.', 'packeta' ),
1090 'setCheckoutDetectionDescription' => __( 'If you have trouble displaying the widget button in the checkout, you can force what type of checkout you are using.', 'packeta' ),
1091 'packetStatusSyncTabLinkLabel' => __( 'Packet status tracking', 'packeta' ),
1092 'statusSyncingOrderStatusesLabel' => __( 'Order statuses, for which cron will check the packet status', 'packeta' ),
1093 'statusSyncingOrderStatusesDescription' => __( 'Cron will automatically track all orders with these statuses and check if the shipment status has changed.', 'packeta' ),
1094 'statusSyncingPacketStatusesLabel' => __( 'Packet statuses that are being checked', 'packeta' ),
1095 'statusSyncingPacketStatusesDescription' => __( 'If an order has a shipment with one of these selected statuses, the shipment status will be tracked.', 'packeta' ),
1096 'numberOfDaysToCheckDescription' => __( 'Number of days after the creation of an order, during which the order status will be checked.', 'packeta' ),
1097 'widgetAutoOpenDescription' => __( 'If this option is active, the widget for selecting pickup points will open automatically after selecting the shipping method at the checkout.', 'packeta' ),
1098 'autoOrderStatusChangeDescription' => __( 'Change order status after data submission to Packeta.', 'packeta' ),
1099 'freeShippingTextDescription' => __( 'If enabled, "FREE" will be displayed after the name of the shipping method, if free shipping is applied.', 'packeta' ),
1100 'orderStatusChangeSettings' => __( 'Order status change settings', 'packeta' ),
1101 'dimensionsLabel' => __( 'Dimensions', 'packeta' ),
1102 'autoEmailInfoInsertionDescription' => __( 'When enabled, the plugin automatically adds packet and pickup point details to emails. Disable this if you prefer to insert them manually using shortcodes.', 'packeta' ),
1103 'diagnosticsLoggingDescription' => $this->wpAdapter->__( 'If some plugin functionality is not working correctly, you can enable diagnostic logging. After enabling it, please repeat the action that is not working as expected. The log will then record important function calls, passed parameters, and their results. Once you have reproduced the issue, disable diagnostic logging again. This information can help developers troubleshoot the problem. You can find the log in the packeta.log file, which is stored by default in wp-content/plugins/packeta/log.', 'packeta' ),
1104 'diagnosticsLoggingLink' => $this->wpAdapter->__( 'Delete log', 'packeta' ),
1105 'bugReportScreenshotsTitle' => $this->wpAdapter->__( 'If possible, please provide screenshots showing the problem. You can do it this way:', 'packeta' ),
1106 'bugReportScreenshotsFirstStep' => sprintf(
1107 /* translators: 1: ImgBB link start 2: ImgBB link end */
1108 $this->wpAdapter->__( 'Go to %1$sImgBB%2$s and upload your screenshots.', 'packeta' ),
1109 '<a href="https://imgbb.com/" target="_blank">',
1110 '</a>'
1111 ),
1112 'bugReportScreenshotsSecondStep' => $this->wpAdapter->__( 'Copy the link(s) generated after uploading', 'packeta' ),
1113 'bugReportScreenshotsThirdStep' => $this->wpAdapter->__( 'Paste the link(s) into your message.', 'packeta' ),
1114 'message' => $this->wpAdapter->__( 'Message', 'packeta' ),
1115 ];
1116
1117 $this->latteEngine->render( PACKETERY_PLUGIN_DIR . '/template/options/page.latte', $latteParams );
1118 }
1119
1120 /**
1121 * Creates tab link.
1122 *
1123 * @param string|null $tab Tab ID.
1124 * @return string
1125 */
1126 public function createLink( ?string $tab = null ): string {
1127 $params = [
1128 'page' => self::SLUG,
1129 ];
1130
1131 if ( $tab !== null ) {
1132 $params[ self::PARAM_TAB ] = $tab;
1133 }
1134
1135 return add_query_arg(
1136 $params,
1137 get_admin_url( null, 'admin.php' )
1138 );
1139 }
1140 }
1141