PluginProbe
Packeta / 1.6.4
Packeta v1.6.4
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 1.6.4, at src/Packetery/Module/Options/Page.php

785 lines 28.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 Packetery\Core\Api\Soap\Request\SenderGetReturnRouting;
13 use Packetery\Core\Log;
14 use Packetery\Module\FormFactory;
15 use Packetery\Module\MessageManager;
16 use Packetery\Module\Order\PacketAutoSubmitter;
17 use Packetery\Module\Order\PacketSynchronizer;
18 use Packetery\Latte\Engine;
19 use Packetery\Module\PaymentGatewayHelper;
20 use Packetery\Nette\Forms\Container;
21 use Packetery\Nette\Forms\Form;
22
23 /**
24 * Class Page
25 *
26 * @package Packetery\Options
27 */
28 class Page {
29
30 private const FORM_FIELDS_CONTAINER = 'packetery';
31 private const FORM_FIELD_PACKETA_LABEL_FORMAT = 'packeta_label_format';
32 private const FORM_FIELD_CARRIER_LABEL_FORMAT = 'carrier_label_format';
33 private const FORM_FIELD_ORDER_STATUS_AUTO_CHANGE = 'order_status_auto_change';
34
35 public const ACTION_VALIDATE_SENDER = 'validate-sender';
36
37 public const SLUG = 'packeta-options';
38
39 public const TAB_GENERAL = 'general';
40 public const TAB_SUPPORT = 'support';
41 public const TAB_PACKET_STATUS_SYNC = 'packet-status-sync';
42 public const TAB_AUTO_SUBMISSION = 'auto-submission';
43
44 public const PARAM_TAB = 'tab';
45
46 /**
47 * PacketeryLatte_engine.
48 *
49 * @var Engine PacketeryLatte engine.
50 */
51 private $latte_engine;
52
53 /**
54 * Options Provider
55 *
56 * @var Provider
57 */
58 private $optionsProvider;
59
60 /**
61 * Form factory.
62 *
63 * @var FormFactory Form factory.
64 */
65 private $formFactory;
66
67 /**
68 * Packeta client.
69 *
70 * @var \Packetery\Core\Api\Soap\Client
71 */
72 private $packetaClient;
73
74 /**
75 * Logger
76 *
77 * @var Log\ILogger
78 */
79 private $logger;
80
81 /**
82 * Message manager.
83 *
84 * @var MessageManager
85 */
86 private $messageManager;
87
88 /**
89 * HTTP request.
90 *
91 * @var \Packetery\Nette\Http\Request
92 */
93 private $httpRequest;
94
95 /**
96 * Plugin constructor.
97 *
98 * @param Engine $latte_engine PacketeryLatte_engine.
99 * @param Provider $optionsProvider Options provider.
100 * @param FormFactory $formFactory Form factory.
101 * @param \Packetery\Core\Api\Soap\Client $packetaClient Packeta Client.
102 * @param Log\ILogger $logger Logger.
103 * @param MessageManager $messageManager Message manager.
104 * @param \Packetery\Nette\Http\Request $httpRequest HTTP request.
105 */
106 public function __construct(
107 Engine $latte_engine,
108 Provider $optionsProvider,
109 FormFactory $formFactory,
110 \Packetery\Core\Api\Soap\Client $packetaClient,
111 Log\ILogger $logger,
112 MessageManager $messageManager,
113 \Packetery\Nette\Http\Request $httpRequest
114 ) {
115 $this->latte_engine = $latte_engine;
116 $this->optionsProvider = $optionsProvider;
117 $this->formFactory = $formFactory;
118 $this->packetaClient = $packetaClient;
119 $this->logger = $logger;
120 $this->messageManager = $messageManager;
121 $this->httpRequest = $httpRequest;
122 }
123
124 /**
125 * Registers WP callbacks.
126 */
127 public function register(): void {
128 add_action( 'admin_init', array( $this, 'admin_init' ) );
129 $icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI1LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IlZyc3R2YV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB2aWV3Qm94PSIwIDAgMzcgNDAiIHN0eWxlPSJmaWxsOiNhN2FhYWQiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiAjYTdhYWFkO30KPC9zdHlsZT4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTE5LjQsMTYuMWwtMC45LDAuNGwtMC45LTAuNGwtMTMtNi41bDYuMi0yLjRsMTMuNCw2LjVMMTkuNCwxNi4xeiBNMzIuNSw5LjZsLTQuNywyLjNsLTEzLjUtNmw0LjItMS42CglMMzIuNSw5LjZ6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xOSwwbDE3LjIsNi42bC0yLjQsMS45bC0xNS4yLTZMMy4yLDguNkwwLjgsNi42TDE4LDBMMTksMEwxOSwweiBNMzQuMSw5LjFsMi44LTEuMWwtMi4xLDE3LjZsLTAuNCwwLjgKCUwxOS40LDQwbC0wLjUtMy4xbDEzLjQtMTJMMzQuMSw5LjF6IE0yLjUsMjYuNWwtMC40LTAuOEwwLDguMWwyLjgsMS4xbDEuOSwxNS43bDEzLjQsMTJMMTcuNiw0MEwyLjUsMjYuNXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI4LjIsMTIuNGw0LjMtMi43bC0xLjcsMTQuMkwxOC42LDM1bDAuNi0xN2w1LjQtMy4zTDI0LjMsMjNsMy4zLTIuM0wyOC4yLDEyLjR6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xNy43LDE3LjlsMC42LDE3bC0xMi4yLTExTDQuNCw5LjhMMTcuNywxNy45eiIvPgo8L3N2Zz4K';
130 add_menu_page(
131 __( 'Packeta', 'packeta' ),
132 __( 'Packeta', 'packeta' ),
133 'manage_options',
134 self::SLUG,
135 '',
136 $icon
137 );
138 add_submenu_page(
139 self::SLUG,
140 __( 'Settings', 'packeta' ),
141 __( 'Settings', 'packeta' ),
142 'manage_options',
143 self::SLUG,
144 array(
145 $this,
146 'render',
147 ),
148 1
149 );
150 add_action( 'admin_init', [ $this, 'processActions' ] );
151
152 add_filter( 'custom_menu_order', '__return_true' );
153 add_filter( 'menu_order', [ $this, 'customMenuOrder' ] );
154 }
155
156 /**
157 * Returns menu_order with Packeta item in last position.
158 *
159 * @param array $menuOrder WP $menu_order.
160 *
161 * @return array
162 */
163 public function customMenuOrder( array $menuOrder ): array {
164 $currentPosition = array_search( self::SLUG, $menuOrder, true );
165
166 if ( false !== $currentPosition ) {
167 unset( $menuOrder[ $currentPosition ] );
168 $menuOrder[] = self::SLUG;
169 }
170
171 return $menuOrder;
172 }
173
174 /**
175 * Get chosen keys by hashed choice data.
176 *
177 * @param array $choiceData Choice data.
178 * @param array $chosenHashedFormOrderStatuses Picked items.
179 *
180 * @return array
181 */
182 private function getChosenKeys( array $choiceData, array $chosenHashedFormOrderStatuses ): array {
183 $statuses = [];
184 foreach ( $chosenHashedFormOrderStatuses as $hash => $chosen ) {
185 if ( $chosen ) {
186 $statuses[] = $choiceData[ $hash ]['key'];
187 }
188 }
189
190 return $statuses;
191 }
192
193 /**
194 * Gets all packet statuses.
195 *
196 * @return array
197 */
198 public function getPacketStatusesChoiceData(): array {
199 $statuses = PacketSynchronizer::getPacketStatuses();
200
201 $result = [];
202
203 foreach ( $statuses as $status => $statusEntity ) {
204 $result[ md5( $status ) ] = [
205 'key' => $status,
206 'default' => $statusEntity->hasDefaultSynchronization(),
207 'label' => $statusEntity->getTranslatedName(),
208 ];
209 }
210
211 return $result;
212 }
213
214 /**
215 * Gets order statuses for form.
216 *
217 * @return array
218 */
219 public static function getOrderStatusesChoiceData(): array {
220 $orderStatuses = wc_get_order_statuses();
221 $orderStatusesTransformed = [];
222
223 foreach ( $orderStatuses as $orderStatusKey => $orderStatusLabel ) {
224 $orderStatusesTransformed[ md5( $orderStatusKey ) ] = [
225 'key' => $orderStatusKey,
226 'label' => $orderStatusLabel,
227 ];
228 }
229
230 return $orderStatusesTransformed;
231 }
232
233 /**
234 * Creates auto submission form.
235 *
236 * @return Form
237 */
238 public function createAutoSubmissionForm(): Form {
239 $gateways = PaymentGatewayHelper::getAvailablePaymentGateways();
240 $form = $this->formFactory->create( 'packetery_auto_submission_form' );
241 $defaults = $this->optionsProvider->getOptionsByName( Provider::OPTION_NAME_PACKETERY_AUTO_SUBMISSION );
242
243 $form->addCheckbox( 'allow', __( 'Allow packet auto-submission', 'packeta' ) )
244 ->setRequired( false )
245 ->setDefaultValue( Provider::PACKET_AUTO_SUBMISSION_ALLOWED_DEFAULT );
246
247 $eventChoices = [
248 PacketAutoSubmitter::EVENT_ON_ORDER_CREATION_FE => __( 'On order creation at e-shop checkout', 'packeta' ),
249 PacketAutoSubmitter::EVENT_ON_ORDER_PROCESSING => __( 'On order processing', 'packeta' ),
250 PacketAutoSubmitter::EVENT_ON_ORDER_COMPLETED => __( 'On order completed', 'packeta' ),
251 ];
252
253 $paymentMethodEvents = $form->addContainer( 'payment_method_events' );
254 foreach ( $gateways as $gateway ) {
255 $paymentMethodEventsMethod = $paymentMethodEvents->addContainer(
256 $this->optionsProvider->sanitizePaymentGatewayId( $gateway->id )
257 );
258 $paymentMethodEventsMethod->addSelect( 'event', $gateway->get_method_title(), $eventChoices )
259 ->setPrompt( __( 'Select event', 'packeta' ) )
260 ->checkDefaultValue( false );
261 }
262
263 $form->addSubmit( 'save', __( 'Save changes', 'packeta' ) );
264
265 $form->setDefaults( $defaults );
266
267 $form->onSuccess[] = [ $this, 'onAutoSubmissionFormSuccess' ];
268
269 return $form;
270 }
271
272 /**
273 * On auto submission form success.
274 *
275 * @param Form $form Form.
276 * @param array $values Form values.
277 *
278 * @return void
279 */
280 public function onAutoSubmissionFormSuccess( Form $form, array $values ): void {
281 update_option( Provider::OPTION_NAME_PACKETERY_AUTO_SUBMISSION, $values );
282
283 $this->messageManager->flash_message( __( 'Settings saved.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
284
285 if ( wp_safe_redirect( $this->createLink( self::TAB_AUTO_SUBMISSION ) ) ) {
286 exit;
287 }
288 }
289
290 /**
291 * Creates settings form.
292 *
293 * @return Form
294 */
295 private function createPacketStatusSyncForm(): Form {
296 $form = $this->formFactory->create( 'packetery_packet_status_sync_form' );
297 $settings = $this->optionsProvider->getOptionsByName( Provider::OPTION_NAME_PACKETERY_SYNC );
298
299 $form->addText( 'max_status_syncing_packets', __( 'Number of orders synced during one cron call', 'packeta' ) )
300 ->setRequired( false )
301 ->addRule( Form::INTEGER )
302 ->addRule( Form::MIN, null, 0 )
303 ->setDefaultValue( Provider::MAX_STATUS_SYNCING_PACKETS_DEFAULT );
304
305 $form->addText( 'max_days_of_packet_status_syncing', __( 'Number of days for which the order status is checked', 'packeta' ) )
306 ->setRequired( false )
307 ->addRule( Form::INTEGER )
308 ->addRule( Form::MIN, null, 0 )
309 ->setDefaultValue( Provider::MAX_DAYS_OF_PACKET_STATUS_SYNCING_DEFAULT );
310
311 $orderStatusesTransformed = self::getOrderStatusesChoiceData();
312 $orderStatusesContainer = $form->addContainer( 'status_syncing_order_statuses' );
313
314 foreach ( $orderStatusesTransformed as $orderStatusKeyHash => $orderStatusData ) {
315 $item = $orderStatusesContainer->addCheckbox( $orderStatusKeyHash, $orderStatusData['label'] );
316 if ( isset( $settings['status_syncing_order_statuses'] ) && in_array( $orderStatusData['key'], $settings['status_syncing_order_statuses'], true ) ) {
317 $item->setDefaultValue( true );
318 }
319 }
320 unset( $settings['status_syncing_order_statuses'] );
321
322 $packetStatuses = $this->getPacketStatusesChoiceData();
323 $packetStatusesContainer = $form->addContainer( 'status_syncing_packet_statuses' );
324
325 foreach ( $packetStatuses as $packetStatusHash => $packetStatusData ) {
326 $item = $packetStatusesContainer->addCheckbox( $packetStatusHash, $packetStatusData['label'] );
327 if ( ! isset( $settings['status_syncing_packet_statuses'] ) ) {
328 $item->setDefaultValue( $packetStatusData['default'] );
329 } elseif ( in_array( $packetStatusData['key'], $settings['status_syncing_packet_statuses'], true ) ) {
330 $item->setDefaultValue( true );
331 }
332 }
333 unset( $settings['status_syncing_packet_statuses'] );
334
335 $form->setDefaults( $settings );
336
337 $form->addSubmit( 'save', __( 'Save changes', 'packeta' ) );
338
339 $form->onSuccess[] = [ $this, 'onPacketStatusSyncFormSuccess' ];
340
341 return $form;
342 }
343
344 /**
345 * On packet status sync form success.
346 *
347 * @param Form $form Form.
348 * @param array $values Values.
349 *
350 * @return void
351 */
352 public function onPacketStatusSyncFormSuccess( Form $form, array $values ): void {
353
354 $values['status_syncing_order_statuses'] = $this->getChosenKeys(
355 self::getOrderStatusesChoiceData(),
356 $values['status_syncing_order_statuses']
357 );
358 $values['status_syncing_packet_statuses'] = $this->getChosenKeys(
359 $this->getPacketStatusesChoiceData(),
360 $values['status_syncing_packet_statuses']
361 );
362
363 if ( '' === $values['max_status_syncing_packets'] ) {
364 unset( $values['max_status_syncing_packets'] );
365 }
366
367 if ( '' === $values['max_days_of_packet_status_syncing'] ) {
368 unset( $values['max_days_of_packet_status_syncing'] );
369 }
370
371 update_option( Provider::OPTION_NAME_PACKETERY_SYNC, $values );
372
373 $this->messageManager->flash_message( __( 'Settings saved.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
374
375 if ( wp_safe_redirect( $this->createLink( self::TAB_PACKET_STATUS_SYNC ) ) ) {
376 exit;
377 }
378 }
379
380 /**
381 * Creates settings form.
382 *
383 * @return Form
384 */
385 public function create_form(): Form {
386 $form = $this->formFactory->create();
387 $form->setAction( 'options.php' );
388
389 $container = $form->addContainer( self::FORM_FIELDS_CONTAINER );
390 $container->addText( 'api_password', __( 'API password', 'packeta' ) )
391 ->setRequired()
392 ->addRule( $form::PATTERN, __( 'API password must be 32 characters long and must contain valid characters!', 'packeta' ), '[a-z\d]{32}' );
393 $container->addText( 'sender', __( 'Sender', 'packeta' ) )
394 ->setRequired();
395
396 $packetaLabelFormats = $this->optionsProvider->getPacketaLabelFormats();
397 $container->addSelect(
398 self::FORM_FIELD_PACKETA_LABEL_FORMAT,
399 __( 'Packeta Label Format', 'packeta' ),
400 $packetaLabelFormats
401 )->checkDefaultValue( false )->setDefaultValue( Provider::DEFAULT_VALUE_PACKETA_LABEL_FORMAT );
402
403 $carrierLabelFormats = $this->optionsProvider->getCarrierLabelFormat();
404 $container->addSelect(
405 self::FORM_FIELD_CARRIER_LABEL_FORMAT,
406 __( 'Carrier Label Format', 'packeta' ),
407 $carrierLabelFormats
408 )->checkDefaultValue( false )->setDefaultValue( Provider::DEFAULT_VALUE_CARRIER_LABEL_FORMAT );
409
410 $gateways = PaymentGatewayHelper::getAvailablePaymentGateways();
411 $enabledGateways = [];
412 foreach ( $gateways as $gateway ) {
413 $enabledGateways[ $gateway->id ] = $gateway->get_method_title();
414 }
415 $container->addSelect(
416 'cod_payment_method',
417 __( 'Payment method that represents cash on delivery', 'packeta' ),
418 $enabledGateways
419 )->setPrompt( '--' )->checkDefaultValue( false );
420
421 $container->addText( 'packaging_weight', __( 'Weight of packaging material', 'packeta' ) . ' (kg)' )
422 ->setRequired( true )
423 ->addRule( Form::FLOAT )
424 ->addRule( Form::MIN, null, 0 )
425 ->setDefaultValue( 0 );
426
427 $container->addCheckbox( 'default_weight_enabled', __( 'Enable default weight', 'packeta' ) )
428 ->addCondition( Form::EQUAL, true )
429 ->toggle( '#packetery-default-weight-value' );
430
431 $container->addText( 'default_weight', __( 'Default weight', 'packeta' ) . ' (kg)' )
432 ->addRule( Form::FLOAT )
433 ->addRule( Form::MIN, null, 0.1 )
434 ->addConditionOn( $form[ self::FORM_FIELDS_CONTAINER ]['default_weight_enabled'], Form::EQUAL, true )
435 ->setRequired();
436
437 // TODO: Packet status sync.
438
439 $container->addCheckbox( 'replace_shipping_address_with_pickup_point_address', __( 'Replace shipping address with pickup point address', 'packeta' ) )
440 ->setRequired( false );
441
442 $container->addSelect(
443 'checkout_widget_button_location',
444 __( 'Widget button location in checkout', 'packeta' ),
445 [
446 'after_shipping_rate' => __( 'After shipping rate', 'packeta' ),
447 'after_transport_methods' => __( 'After transport methods', 'packeta' ),
448 ]
449 );
450
451 $container->addSelect(
452 'email_hook',
453 __( 'Hook used to view information in email', 'packeta' ),
454 [
455 'woocommerce_email_footer' => 'woocommerce_email_footer',
456 'woocommerce_email_before_order_table' => 'woocommerce_email_before_order_table',
457 'woocommerce_email_after_order_table' => 'woocommerce_email_after_order_table',
458 'woocommerce_email_order_meta' => 'woocommerce_email_order_meta',
459 ]
460 );
461
462 $container->addCheckbox( 'force_packet_cancel', __( 'Force order cancellation', 'packeta' ) )
463 ->setRequired( false )
464 ->setDefaultValue( Provider::FORCE_PACKET_CANCEL_DEFAULT );
465
466 $container->addCheckbox( 'widget_auto_open', __( 'Automatically open widget when shipping was selected', 'packeta' ) )
467 ->setRequired( false )
468 ->setDefaultValue( Provider::WIDGET_AUTO_OPEN_DEFAULT );
469
470 $container->addCheckbox( self::FORM_FIELD_ORDER_STATUS_AUTO_CHANGE, __( 'Order status change after parcel creation', 'packeta' ) )
471 ->setRequired( false )
472 ->setDefaultValue( Provider::ORDER_STATUS_AUTO_CHANGE_DEFAULT )
473 ->addCondition( Form::EQUAL, true )
474 ->toggle( '.packetery-order-status-auto-change-row' );
475
476 $orderStatuses = wc_get_order_statuses();
477 $container->addSelect(
478 Provider::AUTO_ORDER_STATUS,
479 __( 'New order status', 'packeta' ),
480 $orderStatuses
481 )
482 ->checkDefaultValue( false )
483 ->setDefaultValue( Provider::AUTO_ORDER_STATUS_DEFAULT )
484 ->setPrompt( __( 'Select new order status', 'packeta' ) )
485 ->addRule( Form::IS_IN, __( 'Select valid order status', 'packeta' ), array_keys( $orderStatuses ) )
486 ->addConditionOn( $form[ self::FORM_FIELDS_CONTAINER ][ self::FORM_FIELD_ORDER_STATUS_AUTO_CHANGE ], Form::EQUAL, true )
487 ->setRequired();
488
489 $container->addCheckbox(
490 'order_status_auto_change_for_auto_submit_at_frontend',
491 __( 'Change order status after automatic packet submit at checkout', 'packeta' )
492 );
493
494 $form->addSubmit( 'save', __( 'Save changes', 'packeta' ) );
495
496 if ( $this->optionsProvider->has_any( Provider::OPTION_NAME_PACKETERY ) ) {
497 $container->setDefaults( $this->optionsProvider->getOptionsByName( Provider::OPTION_NAME_PACKETERY ) );
498 }
499
500 return $form;
501 }
502
503 /**
504 * Admin_init callback.
505 */
506 public function admin_init(): void {
507 add_filter( 'pre_update_option_packetery', [ $this, 'validatePacketeryOptions' ] );
508 register_setting( self::FORM_FIELDS_CONTAINER, self::FORM_FIELDS_CONTAINER, [ $this, 'sanitizePacketeryOptions' ] );
509 add_settings_section( 'packetery_main', __( 'Main Settings', 'packeta' ), '', self::SLUG );
510 }
511
512 /**
513 * Validates packetery options.
514 *
515 * @param array $options Options to be validated.
516 *
517 * @return array
518 */
519 public function validatePacketeryOptions( array $options ): array {
520 $form = $this->create_form();
521 /** Packetery container. @var Container $packeteryContainer */
522 $packeteryContainer = $form[ self::FORM_FIELDS_CONTAINER ];
523 $packeteryContainer->setValues( $options );
524 if ( $form->isValid() === false ) {
525 foreach ( $packeteryContainer->getControls() as $control ) {
526 if ( $control->hasErrors() === false ) {
527 continue;
528 }
529
530 add_settings_error( $control->getCaption(), esc_attr( $control->getName() ), $control->getError() );
531 }
532 }
533
534 $apiPassword = $packeteryContainer['api_password'];
535 if ( $apiPassword->hasErrors() === false ) {
536 $this->packetaClient->setApiPassword( $apiPassword->getValue() );
537 }
538
539 $this->validateSender( $options['sender'] );
540
541 return $options;
542 }
543
544 /**
545 * Sanitize options.
546 *
547 * @param array $options Options to be sanitized.
548 *
549 * @return array
550 */
551 public function sanitizePacketeryOptions( array $options ): array {
552 $form = $this->create_form();
553 /** Packetery container. @var Container $packeteryContainer */
554 $packeteryContainer = $form[ self::FORM_FIELDS_CONTAINER ];
555 $packeteryContainer->setValues( $options );
556 if ( $form->isValid() === false ) {
557 foreach ( $packeteryContainer->getControls() as $control ) {
558 if ( $control->hasErrors() === false ) {
559 continue;
560 }
561
562 $options[ $control->getName() ] = '';
563 }
564 }
565
566 $api_password = $packeteryContainer['api_password'];
567 if ( $api_password->hasErrors() === false ) {
568 $api_pass = $api_password->getValue();
569 $options['api_key'] = substr( $api_pass, 0, 16 );
570 $this->packetaClient->setApiPassword( $api_pass );
571 } else {
572 $options['api_key'] = '';
573 }
574
575 $options['force_packet_cancel'] = (int) $packeteryContainer['force_packet_cancel']->getValue();
576
577 return $options;
578 }
579
580 /**
581 * Validates sender.
582 *
583 * @param string $senderLabel Sender label.
584 *
585 * @return bool|null
586 */
587 private function validateSender( string $senderLabel ): ?bool {
588 $senderValidationRequest = new SenderGetReturnRouting( $senderLabel );
589 $senderValidationResponse = $this->packetaClient->senderGetReturnRouting( $senderValidationRequest );
590
591 $senderValidationLog = new Log\Record();
592 $senderValidationLog->action = Log\Record::ACTION_SENDER_VALIDATION;
593
594 $senderValidationLog->status = Log\Record::STATUS_SUCCESS;
595 $senderValidationLog->title = __( 'Sender validation was successful', 'packeta' );
596
597 if ( $senderValidationResponse->hasFault() ) {
598 $senderValidationLog->status = Log\Record::STATUS_ERROR;
599 $senderValidationLog->params = [
600 'errorMessage' => $senderValidationResponse->getFaultString(),
601 ];
602 $senderValidationLog->title = __( 'Sender could not be validated', 'packeta' );
603 }
604
605 $this->logger->add( $senderValidationLog );
606
607 $senderExists = $senderValidationResponse->senderExists();
608
609 if ( false === $senderExists ) {
610 $this->messageManager->flash_message( __( 'Specified sender does not exist', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
611 }
612
613 if ( null === $senderExists ) {
614 $this->messageManager->flash_message( __( 'Unable to check specified sender', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
615 }
616
617 return $senderExists;
618 }
619
620 /**
621 * Process actions.
622 *
623 * @return void
624 */
625 public function processActions(): void {
626 $action = $this->httpRequest->getQuery( 'action' );
627 if ( self::ACTION_VALIDATE_SENDER === $action ) {
628 $result = $this->validateSender( $this->optionsProvider->get_sender() );
629
630 if ( true === $result ) {
631 $this->messageManager->flash_message( __( 'Specified sender has been validated.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
632 }
633
634 $doRedirect = wp_safe_redirect(
635 add_query_arg(
636 [
637 'page' => self::SLUG,
638 ],
639 get_admin_url( null, 'admin.php' )
640 )
641 );
642
643 if ( $doRedirect ) {
644 exit;
645 }
646 }
647
648 $packetStatusSyncForm = $this->createPacketStatusSyncForm();
649 if ( $packetStatusSyncForm['save']->isSubmittedBy() ) {
650 $packetStatusSyncForm->fireEvents();
651 }
652
653 $autoSubmissionForm = $this->createAutoSubmissionForm();
654 if ( $autoSubmissionForm['save']->isSubmittedBy() ) {
655 $autoSubmissionForm->fireEvents();
656 }
657 }
658
659 /**
660 * Renders page.
661 */
662 public function render(): void {
663 $activeTab = ( $this->httpRequest->getQuery( self::PARAM_TAB ) ?? self::TAB_GENERAL );
664
665 $latteParams = [];
666 if ( self::TAB_PACKET_STATUS_SYNC === $activeTab ) {
667 $latteParams = [ 'form' => $this->createPacketStatusSyncForm() ];
668 } elseif ( self::TAB_AUTO_SUBMISSION === $activeTab ) {
669 $latteParams = [ 'form' => $this->createAutoSubmissionForm() ];
670 } elseif ( self::TAB_GENERAL === $activeTab ) {
671 $latteParams = [ 'form' => $this->create_form() ];
672 }
673
674 if ( ! extension_loaded( 'soap' ) ) {
675 $latteParams['error'] = __( 'This plugin requires an active SOAP library for proper operation. Contact your web hosting administrator.', 'packeta' );
676 }
677
678 $latteParams['apiPasswordLink'] = trim( $this->latte_engine->renderToString( PACKETERY_PLUGIN_DIR . '/template/options/help-block-link.latte', [ 'href' => 'https://client.packeta.com/support' ] ) );
679
680 $latteParams['exportLink'] = add_query_arg(
681 [
682 'page' => self::SLUG,
683 'action' => Exporter::ACTION_EXPORT_SETTINGS,
684 ],
685 get_admin_url( null, 'admin.php' )
686 );
687
688 $latteParams['activeTab'] = ( $this->httpRequest->getQuery( self::PARAM_TAB ) ?? self::TAB_GENERAL );
689 $latteParams['generalTabLink'] = $this->createLink();
690 $latteParams['supportTabLink'] = $this->createLink( self::TAB_SUPPORT );
691 $latteParams['packetStatusSyncTabLink'] = $this->createLink( self::TAB_PACKET_STATUS_SYNC );
692 $latteParams['autoSubmissionTabLink'] = $this->createLink( self::TAB_AUTO_SUBMISSION );
693
694 $latteParams['canValidateSender'] = (bool) $this->optionsProvider->get_sender();
695 $latteParams['senderValidationLink'] = add_query_arg(
696 [
697 'page' => self::SLUG,
698 'action' => self::ACTION_VALIDATE_SENDER,
699 ],
700 get_admin_url( null, 'admin.php' )
701 );
702
703 $lastExport = null;
704 $lastExportOption = get_option( Exporter::OPTION_LAST_SETTINGS_EXPORT );
705 if ( false !== $lastExportOption ) {
706 $date = \DateTime::createFromFormat( DATE_ATOM, $lastExportOption );
707 if ( false !== $date ) {
708 $date->setTimezone( wp_timezone() );
709 $lastExport = $date->format( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
710 }
711 }
712 if ( $lastExport ) {
713 $latteParams['lastExport'] = $lastExport;
714 }
715
716 $latteParams['forcePacketCancelDescription'] = __( 'Cancel the packet for an order even if the cancellation in the Packeta system will not be successful.', 'packeta' );
717 $latteParams['messages'] = $this->messageManager->renderToString( MessageManager::RENDERER_PACKETERY, 'plugin-options' );
718 $latteParams['translations'] = [
719 'packeta' => __( 'Packeta', 'packeta' ),
720 'title' => __( 'Options', 'packeta' ),
721 'general' => __( 'General', 'packeta' ),
722 'packetAutoSubmission' => __( 'Packet auto-submission', 'packeta' ),
723 'packetAutoSubmissionMappingDescription' => __( 'Choose events for payment methods that will trigger packet submission', 'packeta' ),
724 // translators: %s represents URL.
725 'apiPasswordCanBeFoundAt%sUrl' => __( 'API password can be found at %s', 'packeta' ),
726
727 'saveChanges' => __( 'Save changes', 'packeta' ),
728 'validateSender' => __( 'Validate sender', 'packeta' ),
729 'support' => __( 'Support', 'packeta' ),
730 'optionsExportInfo1' => __(
731 '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:',
732 'packeta'
733 ),
734 'optionsExportInfo2' => __(
735 ') along with the description of your problem. For a better understanding of your problem, we recommend adding screenshots, which show the problem (if possible).',
736 'packeta'
737 ),
738 'exportPluginSettings' => __( 'Export the plugin settings', 'packeta' ),
739 'settingsExportDatetime' => __( 'Date and time of the last export of settings', 'packeta' ),
740 'settingsNotYetExported' => __( 'The settings have not been exported yet.', 'packeta' ),
741 'senderDescription' => sprintf(
742 /* translators: 1: emphasis start 2: emphasis end 3: client section link start 4: client section link end */
743 esc_html__( 'Fill here %1$ssender label%2$s - you will find it in %3$sclient section%4$s - user information - field \'Indication\'.', 'packeta' ),
744 '<strong>',
745 '</strong>',
746 '<a href="https://client.packeta.com/senders" target="_blank">',
747 '</a>'
748 ),
749 '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' ),
750 'defaultWeightDescription' => __( 'This value is automatically added to the total weight of each order that contains products with zero weight.', 'packeta' ),
751 'packetStatusSyncTabLinkLabel' => __( 'Packet status tracking', 'packeta' ),
752 'statusSyncingOrderStatusesLabel' => __( 'Order statuses, for which cron will check the packet status', 'packeta' ),
753 'statusSyncingOrderStatusesDescription' => __( 'Cron will automatically track all orders with these statuses and check if the shipment status has changed.', 'packeta' ),
754 'statusSyncingPacketStatusesLabel' => __( 'Packet statuses that are being checked', 'packeta' ),
755 'statusSyncingPacketStatusesDescription' => __( 'If an order has a shipment with one of these selected statuses, the shipment status will be tracked.', 'packeta' ),
756 'numberOfDaysToCheckDescription' => __( 'Number of days after the creation of an order, during which the order status will be checked.', 'packeta' ),
757 'widgetAutoOpenDescription' => __( 'If this option is active, the widget for selecting pickup points will open automatically after selecting the shipping method at the checkout.', 'packeta' ),
758 'autoOrderStatusChangeDescription' => __( 'Change order status after data submission to Packeta.', 'packeta' ),
759 ];
760
761 $this->latte_engine->render( PACKETERY_PLUGIN_DIR . '/template/options/page.latte', $latteParams );
762 }
763
764 /**
765 * Creates tab link.
766 *
767 * @param string|null $tab Tab ID.
768 * @return string
769 */
770 public function createLink( ?string $tab = null ): string {
771 $params = [
772 'page' => self::SLUG,
773 ];
774
775 if ( null !== $tab ) {
776 $params[ self::PARAM_TAB ] = $tab;
777 }
778
779 return add_query_arg(
780 $params,
781 get_admin_url( null, 'admin.php' )
782 );
783 }
784 }
785