PluginProbe
Packeta / 2.3.2
Packeta v2.3.2
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
← All changes | src/Packetery/Module/Options/Page.php +637 -149 1.4.22.3.2 View file →
@@ -8,15 +8,33 @@
8 8 declare( strict_types=1 );
9 9
10 10 namespace Packetery\Module\Options;
11 11
12 +use DateTime;
13 +use Packetery\Core\Api;
12 14 use Packetery\Core\Api\Soap\Request\SenderGetReturnRouting;
15 +use Packetery\Core\CoreHelper;
16 +use Packetery\Core\Entity\PacketStatus;
13 17 use Packetery\Core\Log;
18 +use Packetery\Latte\Engine;
19 +use Packetery\Module\Dashboard\DashboardPage;
20 +use Packetery\Module\DiagnosticsLogger\DiagnosticsLogger;
14 21 use Packetery\Module\FormFactory;
22 +use Packetery\Module\Forms\BugReportForm;
23 +use Packetery\Module\Forms\DiagnosticsLoggingFormFactory;
24 +use Packetery\Module\Framework\WpAdapter;
15 25 use Packetery\Module\MessageManager;
26 +use Packetery\Module\ModuleHelper;
27 +use Packetery\Module\Order\PacketAutoSubmitter;
16 28 use Packetery\Module\Order\PacketSynchronizer;
17 -use PacketeryLatte\Engine;
18 -use PacketeryNette\Forms\Form;
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;
19 37
20 38 /**
21 39 * Class Page
22 40 *
@@ -23,11 +41,13 @@
23 41 * @package Packetery\Options
24 42 */
25 43 class Page {
26 44
27 - private const FORM_FIELDS_CONTAINER = 'packetery';
28 - private const FORM_FIELD_PACKETA_LABEL_FORMAT = 'packeta_label_format';
29 - private const FORM_FIELD_CARRIER_LABEL_FORMAT = 'carrier_label_format';
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';
30 50
31 51 public const ACTION_VALIDATE_SENDER = 'validate-sender';
32 52
33 53 public const SLUG = 'packeta-options';
@@ -32,24 +52,28 @@
32 52
33 53 public const SLUG = 'packeta-options';
34 54
35 55 public const TAB_GENERAL = 'general';
56 + public const TAB_ADVANCED = 'advanced';
36 57 public const TAB_SUPPORT = 'support';
37 58 public const TAB_PACKET_STATUS_SYNC = 'packet-status-sync';
59 + public const TAB_AUTO_SUBMISSION = 'auto-submission';
38 60
39 61 public const PARAM_TAB = 'tab';
40 62
63 + const PACKETA_SVG_LOGO = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI1LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IlZyc3R2YV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB2aWV3Qm94PSIwIDAgMzcgNDAiIHN0eWxlPSJmaWxsOiNhN2FhYWQiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiAjYTdhYWFkO30KPC9zdHlsZT4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTE5LjQsMTYuMWwtMC45LDAuNGwtMC45LTAuNGwtMTMtNi41bDYuMi0yLjRsMTMuNCw2LjVMMTkuNCwxNi4xeiBNMzIuNSw5LjZsLTQuNywyLjNsLTEzLjUtNmw0LjItMS42CglMMzIuNSw5LjZ6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xOSwwbDE3LjIsNi42bC0yLjQsMS45bC0xNS4yLTZMMy4yLDguNkwwLjgsNi42TDE4LDBMMTksMEwxOSwweiBNMzQuMSw5LjFsMi44LTEuMWwtMi4xLDE3LjZsLTAuNCwwLjgKCUwxOS40LDQwbC0wLjUtMy4xbDEzLjQtMTJMMzQuMSw5LjF6IE0yLjUsMjYuNWwtMC40LTAuOEwwLDguMWwyLjgsMS4xbDEuOSwxNS43bDEzLjQsMTJMMTcuNiw0MEwyLjUsMjYuNXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI4LjIsMTIuNGw0LjMtMi43bC0xLjcsMTQuMkwxOC42LDM1bDAuNi0xN2w1LjQtMy4zTDI0LjMsMjNsMy4zLTIuM0wyOC4yLDEyLjR6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xNy43LDE3LjlsMC42LDE3bC0xMi4yLTExTDQuNCw5LjhMMTcuNywxNy45eiIvPgo8L3N2Zz4K';
64 +
41 65 /**
42 66 * PacketeryLatte_engine.
43 67 *
44 68 * @var Engine PacketeryLatte engine.
45 69 */
46 - private $latte_engine;
70 + private $latteEngine;
47 71
48 72 /**
49 73 * Options Provider
50 74 *
51 - * @var Provider
75 + * @var OptionsProvider
52 76 */
53 77 private $optionsProvider;
54 78
55 79 /**
@@ -61,9 +85,9 @@
61 85
62 86 /**
63 87 * Packeta client.
64 88 *
65 - * @var \Packetery\Core\Api\Soap\Client
89 + * @var Api\Soap\Client
66 90 */
67 91 private $packetaClient;
68 92
69 93 /**
@@ -80,62 +104,107 @@
80 104 */
81 105 private $messageManager;
82 106
83 107 /**
84 - * HTTP request.
85 - *
86 - * @var \PacketeryNette\Http\Request
108 + * @var Http\Request
87 109 */
88 110 private $httpRequest;
89 111
90 112 /**
91 - * Packet synchronizer.
92 - *
113 + * @var ModuleHelper
114 + */
115 + private $moduleHelper;
116 +
117 + /**
118 + * @var UrlBuilder
119 + */
120 + private $urlBuilder;
121 +
122 + /**
93 123 * @var PacketSynchronizer
94 124 */
95 125 private $packetSynchronizer;
96 126
97 127 /**
98 - * Plugin constructor.
99 - *
100 - * @param Engine $latte_engine PacketeryLatte_engine.
101 - * @param Provider $optionsProvider Options provider.
102 - * @param FormFactory $formFactory Form factory.
103 - * @param \Packetery\Core\Api\Soap\Client $packetaClient Packeta Client.
104 - * @param Log\ILogger $logger Logger.
105 - * @param MessageManager $messageManager Message manager.
106 - * @param \PacketeryNette\Http\Request $httpRequest HTTP request.
107 - * @param PacketSynchronizer $packetSynchronizer Packet synchronizer.
128 + * @var WpAdapter
108 129 */
109 - public function __construct( Engine $latte_engine, Provider $optionsProvider, FormFactory $formFactory, \Packetery\Core\Api\Soap\Client $packetaClient, Log\ILogger $logger, MessageManager $messageManager, \PacketeryNette\Http\Request $httpRequest, PacketSynchronizer $packetSynchronizer ) {
110 - $this->latte_engine = $latte_engine;
111 - $this->optionsProvider = $optionsProvider;
112 - $this->formFactory = $formFactory;
113 - $this->packetaClient = $packetaClient;
114 - $this->logger = $logger;
115 - $this->messageManager = $messageManager;
116 - $this->httpRequest = $httpRequest;
117 - $this->packetSynchronizer = $packetSynchronizer;
118 - }
130 + private $wpAdapter;
119 131
120 132 /**
121 - * Registers WP callbacks.
133 + * @var string
122 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 +
123 184 public function register(): void {
124 - add_action( 'admin_init', array( $this, 'admin_init' ) );
125 - $icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI1LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IlZyc3R2YV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB2aWV3Qm94PSIwIDAgMzcgNDAiIHN0eWxlPSJmaWxsOiNhN2FhYWQiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiAjYTdhYWFkO30KPC9zdHlsZT4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTE5LjQsMTYuMWwtMC45LDAuNGwtMC45LTAuNGwtMTMtNi41bDYuMi0yLjRsMTMuNCw2LjVMMTkuNCwxNi4xeiBNMzIuNSw5LjZsLTQuNywyLjNsLTEzLjUtNmw0LjItMS42CglMMzIuNSw5LjZ6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xOSwwbDE3LjIsNi42bC0yLjQsMS45bC0xNS4yLTZMMy4yLDguNkwwLjgsNi42TDE4LDBMMTksMEwxOSwweiBNMzQuMSw5LjFsMi44LTEuMWwtMi4xLDE3LjZsLTAuNCwwLjgKCUwxOS40LDQwbC0wLjUtMy4xbDEzLjQtMTJMMzQuMSw5LjF6IE0yLjUsMjYuNWwtMC40LTAuOEwwLDguMWwyLjgsMS4xbDEuOSwxNS43bDEzLjQsMTJMMTcuNiw0MEwyLjUsMjYuNXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI4LjIsMTIuNGw0LjMtMi43bC0xLjcsMTQuMkwxOC42LDM1bDAuNi0xN2w1LjQtMy4zTDI0LjMsMjNsMy4zLTIuM0wyOC4yLDEyLjR6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xNy43LDE3LjlsMC42LDE3bC0xMi4yLTExTDQuNCw5LjhMMTcuNywxNy45eiIvPgo8L3N2Zz4K';
126 - add_menu_page(
127 - __( 'Packeta', 'packeta' ),
128 - __( 'Packeta', 'packeta' ),
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' ),
129 195 'manage_options',
130 - self::SLUG,
131 - '',
132 - $icon
196 + DashboardPage::SLUG,
197 + function () {},
198 + self::PACKETA_SVG_LOGO
133 199 );
134 - add_submenu_page(
135 - self::SLUG,
136 - __( 'Settings', 'packeta' ),
137 - __( 'Settings', 'packeta' ),
200 + }
201 +
202 + public function registerSubmenuPage(): void {
203 + $this->wpAdapter->addSubmenuPage(
204 + DashboardPage::SLUG,
205 + $this->wpAdapter->__( 'Settings', 'packeta' ),
206 + $this->wpAdapter->__( 'Settings', 'packeta' ),
138 207 'manage_options',
139 208 self::SLUG,
140 209 array(
141 210 $this,
@@ -142,25 +211,27 @@
142 211 'render',
143 212 ),
144 213 1
145 214 );
146 - add_action( 'admin_init', [ $this, 'processActions' ] );
147 -
148 - add_filter( 'custom_menu_order', '__return_true' );
149 - add_filter( 'menu_order', [ $this, 'customMenuOrder' ] );
150 215 }
151 216
152 217 /**
153 218 * Returns menu_order with Packeta item in last position.
154 219 *
155 - * @param array $menuOrder WP $menu_order.
220 + * @param array|mixed $menuOrder WP $menu_order.
156 221 *
157 - * @return array
222 + * @return array|mixed
158 223 */
159 - public function customMenuOrder( array $menuOrder ): array {
224 + public function customMenuOrder( $menuOrder ) {
225 + if ( ! is_array( $menuOrder ) ) {
226 + WcLogger::logArgumentTypeError( __METHOD__, 'menuOrder', 'array', $menuOrder );
227 +
228 + return $menuOrder;
229 + }
230 +
160 231 $currentPosition = array_search( self::SLUG, $menuOrder, true );
161 232
162 - if ( false !== $currentPosition ) {
233 + if ( $currentPosition !== false ) {
163 234 unset( $menuOrder[ $currentPosition ] );
164 235 $menuOrder[] = self::SLUG;
165 236 }
166 237
@@ -186,22 +257,61 @@
186 257 return $statuses;
187 258 }
188 259
189 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 + /**
190 291 * Gets all packet statuses.
191 292 *
192 - * @return array
293 + * @return array<string, array{key: int|string, default: bool, label:string}>
193 294 */
194 - public function getPacketStatusesChoiceData(): array {
195 - $statuses = PacketSynchronizer::getPacketStatuses();
295 + public function getAllPacketStatusesChoiceData(): array {
296 + $statuses = $this->packetSynchronizer->getPacketStatuses();
196 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 {
197 307 $result = [];
198 308
199 - foreach ( $statuses as $status => $defaultValue ) {
309 + foreach ( $statuses as $status => $statusEntity ) {
200 310 $result[ md5( $status ) ] = [
201 311 'key' => $status,
202 - 'default' => $defaultValue,
203 - 'label' => $this->packetSynchronizer->getPacketStatusTranslated( $status ),
312 + 'default' => $statusEntity->hasDefaultSynchronization(),
313 + 'label' => $statusEntity->getTranslatedName(),
204 314 ];
205 315 }
206 316
207 317 return $result;
@@ -209,9 +319,9 @@
209 319
210 320 /**
211 321 * Gets order statuses for form.
212 322 *
213 - * @return array
323 + * @return array<string, array<string, int|string>>
214 324 */
215 325 public static function getOrderStatusesChoiceData(): array {
216 326 $orderStatuses = wc_get_order_statuses();
217 327 $orderStatusesTransformed = [];
@@ -226,8 +336,65 @@
226 336 return $orderStatusesTransformed;
227 337 }
228 338
229 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 + /**
230 397 * Creates settings form.
231 398 *
232 399 * @return Form
233 400 */
@@ -232,21 +399,21 @@
232 399 * @return Form
233 400 */
234 401 private function createPacketStatusSyncForm(): Form {
235 402 $form = $this->formFactory->create( 'packetery_packet_status_sync_form' );
236 - $settings = $this->optionsProvider->data_to_array( Provider::OPTION_NAME_PACKETERY_SYNC );
403 + $settings = $this->optionsProvider->getOptionsByName( OptionNames::PACKETERY_SYNC );
237 404
238 405 $form->addText( 'max_status_syncing_packets', __( 'Number of orders synced during one cron call', 'packeta' ) )
239 406 ->setRequired( false )
240 407 ->addRule( Form::INTEGER )
241 408 ->addRule( Form::MIN, null, 0 )
242 - ->setDefaultValue( Provider::MAX_STATUS_SYNCING_PACKETS_DEFAULT );
409 + ->setDefaultValue( OptionsProvider::MAX_STATUS_SYNCING_PACKETS_DEFAULT );
243 410
244 411 $form->addText( 'max_days_of_packet_status_syncing', __( 'Number of days for which the order status is checked', 'packeta' ) )
245 412 ->setRequired( false )
246 413 ->addRule( Form::INTEGER )
247 414 ->addRule( Form::MIN, null, 0 )
248 - ->setDefaultValue( Provider::MAX_DAYS_OF_PACKET_STATUS_SYNCING_DEFAULT );
415 + ->setDefaultValue( OptionsProvider::MAX_DAYS_OF_PACKET_STATUS_SYNCING_DEFAULT );
249 416
250 417 $orderStatusesTransformed = self::getOrderStatusesChoiceData();
251 418 $orderStatusesContainer = $form->addContainer( 'status_syncing_order_statuses' );
252 419
@@ -257,9 +424,9 @@
257 424 }
258 425 }
259 426 unset( $settings['status_syncing_order_statuses'] );
260 427
261 - $packetStatuses = $this->getPacketStatusesChoiceData();
428 + $packetStatuses = $this->getStatusSyncingPacketStatusesChoiceData();
262 429 $packetStatusesContainer = $form->addContainer( 'status_syncing_packet_statuses' );
263 430
264 431 foreach ( $packetStatuses as $packetStatusHash => $packetStatusData ) {
265 432 $item = $packetStatusesContainer->addCheckbox( $packetStatusHash, $packetStatusData['label'] );
@@ -270,8 +437,27 @@
270 437 }
271 438 }
272 439 unset( $settings['status_syncing_packet_statuses'] );
273 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 +
274 460 $form->setDefaults( $settings );
275 461
276 462 $form->addSubmit( 'save', __( 'Save changes', 'packeta' ) );
277 463
@@ -288,27 +474,30 @@
288 474 *
289 475 * @return void
290 476 */
291 477 public function onPacketStatusSyncFormSuccess( Form $form, array $values ): void {
292 -
293 - $values['status_syncing_order_statuses'] = $this->getChosenKeys(
478 + $values['status_syncing_order_statuses'] = $this->getChosenKeys(
294 479 self::getOrderStatusesChoiceData(),
295 480 $values['status_syncing_order_statuses']
296 481 );
297 - $values['status_syncing_packet_statuses'] = $this->getChosenKeys(
298 - $this->getPacketStatusesChoiceData(),
482 + $values['status_syncing_packet_statuses'] = $this->getChosenKeys(
483 + $this->getStatusSyncingPacketStatusesChoiceData(),
299 484 $values['status_syncing_packet_statuses']
300 485 );
486 + $values['order_status_change_packet_statuses'] = $this->translateStatuses(
487 + $this->getAllPacketStatusesChoiceData(),
488 + $values['order_status_change_packet_statuses']
489 + );
301 490
302 - if ( '' === $values['max_status_syncing_packets'] ) {
491 + if ( $values['max_status_syncing_packets'] === '' ) {
303 492 unset( $values['max_status_syncing_packets'] );
304 493 }
305 494
306 - if ( '' === $values['max_days_of_packet_status_syncing'] ) {
495 + if ( $values['max_days_of_packet_status_syncing'] === '' ) {
307 496 unset( $values['max_days_of_packet_status_syncing'] );
308 497 }
309 498
310 - update_option( Provider::OPTION_NAME_PACKETERY_SYNC, $values );
499 + update_option( OptionNames::PACKETERY_SYNC, $values );
311 500
312 501 $this->messageManager->flash_message( __( 'Settings saved.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
313 502
314 503 if ( wp_safe_redirect( $this->createLink( self::TAB_PACKET_STATUS_SYNC ) ) ) {
@@ -315,8 +504,35 @@
315 504 exit;
316 505 }
317 506 }
318 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 +
319 535 /**
320 536 * Creates settings form.
321 537 *
322 538 * @return Form
@@ -326,12 +542,12 @@
326 542 $form->setAction( 'options.php' );
327 543
328 544 $container = $form->addContainer( self::FORM_FIELDS_CONTAINER );
329 545 $container->addText( 'api_password', __( 'API password', 'packeta' ) )
330 - ->setRequired()
331 - ->addRule( $form::PATTERN, __( 'API password must be 32 characters long and must contain valid characters!', 'packeta' ), '[a-z\d]{32}' );
546 + ->setRequired()
547 + ->addRule( $form::PATTERN, __( 'API password must be 32 characters long and must contain valid characters!', 'packeta' ), '[a-z\d]{32}' );
332 548 $container->addText( 'sender', __( 'Sender', 'packeta' ) )
333 - ->setRequired();
549 + ->setRequired();
334 550
335 551 $packetaLabelFormats = $this->optionsProvider->getPacketaLabelFormats();
336 552 $container->addSelect(
337 553 self::FORM_FIELD_PACKETA_LABEL_FORMAT,
@@ -336,9 +552,9 @@
336 552 $container->addSelect(
337 553 self::FORM_FIELD_PACKETA_LABEL_FORMAT,
338 554 __( 'Packeta Label Format', 'packeta' ),
339 555 $packetaLabelFormats
340 - )->checkDefaultValue( false )->setDefaultValue( Provider::DEFAULT_VALUE_PACKETA_LABEL_FORMAT );
556 + )->checkDefaultValue( false )->setDefaultValue( OptionsProvider::DEFAULT_VALUE_PACKETA_LABEL_FORMAT );
341 557
342 558 $carrierLabelFormats = $this->optionsProvider->getCarrierLabelFormat();
343 559 $container->addSelect(
344 560 self::FORM_FIELD_CARRIER_LABEL_FORMAT,
@@ -343,33 +559,98 @@
343 559 $container->addSelect(
344 560 self::FORM_FIELD_CARRIER_LABEL_FORMAT,
345 561 __( 'Carrier Label Format', 'packeta' ),
346 562 $carrierLabelFormats
347 - )->checkDefaultValue( false )->setDefaultValue( Provider::DEFAULT_VALUE_CARRIER_LABEL_FORMAT );
563 + )->checkDefaultValue( false )->setDefaultValue( OptionsProvider::DEFAULT_VALUE_CARRIER_LABEL_FORMAT );
348 564
349 - $gateways = $this->getAvailablePaymentGateways();
565 + $gateways = PaymentGatewayHelper::getAvailablePaymentGateways();
350 566 $enabledGateways = [];
351 567 foreach ( $gateways as $gateway ) {
352 568 $enabledGateways[ $gateway->id ] = $gateway->get_method_title();
353 569 }
354 - $container->addSelect(
355 - 'cod_payment_method',
356 - __( 'Payment method that represents cash on delivery', 'packeta' ),
570 + $container->addMultiSelect(
571 + 'cod_payment_methods',
572 + __( 'Payment methods that represent cash on delivery', 'packeta' ),
357 573 $enabledGateways
358 - )->setPrompt( '--' )->checkDefaultValue( false );
574 + )->checkDefaultValue( false );
359 575
360 576 $container->addText( 'packaging_weight', __( 'Weight of packaging material', 'packeta' ) . ' (kg)' )
361 - ->setRequired( true )
362 - ->addRule( Form::FLOAT )
363 - ->addRule( Form::MIN, null, 0 )
364 - ->setDefaultValue( 0 );
577 + ->setRequired()
578 + ->addRule( Form::FLOAT )
579 + ->addRule( Form::MIN, null, 0 )
580 + ->setDefaultValue( 0 );
365 581
366 - // TODO: Packet status sync.
582 + $container->addCheckbox( 'default_weight_enabled', __( 'Enable default weight', 'packeta' ) )
583 + ->addCondition( Form::EQUAL, true )
584 + ->toggle( '#packetery-default-weight-value' );
367 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 +
368 639 $container->addCheckbox( 'replace_shipping_address_with_pickup_point_address', __( 'Replace shipping address with pickup point address', 'packeta' ) )
369 - ->setRequired( false );
640 + ->setRequired( false );
370 641
371 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(
372 653 'checkout_widget_button_location',
373 654 __( 'Widget button location in checkout', 'packeta' ),
374 655 [
375 656 'after_shipping_rate' => __( 'After shipping rate', 'packeta' ),
@@ -376,14 +657,57 @@
376 657 'after_transport_methods' => __( 'After transport methods', 'packeta' ),
377 658 ]
378 659 );
379 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 +
380 682 $container->addCheckbox( 'force_packet_cancel', __( 'Force order cancellation', 'packeta' ) )
381 - ->setRequired( false )
382 - ->setDefaultValue( Provider::FORCE_PACKET_CANCEL_DEFAULT );
683 + ->setRequired( false )
684 + ->setDefaultValue( OptionsProvider::FORCE_PACKET_CANCEL_DEFAULT );
383 685
384 - if ( $this->optionsProvider->has_any( Provider::OPTION_NAME_PACKETERY ) ) {
385 - $container->setDefaults( $this->optionsProvider->data_to_array( Provider::OPTION_NAME_PACKETERY ) );
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 ) );
386 710 }
387 711
388 712 return $form;
389 713 }
@@ -388,75 +712,140 @@
388 712 return $form;
389 713 }
390 714
391 715 /**
392 - * Get available gateways.
393 - *
394 - * @return \WC_Payment_Gateway[]
716 + * Admin_init callback.
395 717 */
396 - public function getAvailablePaymentGateways(): array {
397 - $availableGateways = [];
718 + public function admin_init(): void {
719 + add_filter( 'pre_update_option_packetery', [ $this, 'validatePacketeryOptions' ] );
398 720
399 - foreach ( WC()->payment_gateways()->payment_gateways() as $gateway ) {
400 - if ( 'yes' === $gateway->enabled ) {
401 - $availableGateways[ $gateway->id ] = $gateway;
402 - }
403 - }
721 + // Registered callback is called when the form is submitted.
722 + register_setting( self::FORM_FIELDS_CONTAINER, self::FORM_FIELDS_CONTAINER, [ $this, 'sanitizePacketeryOptions' ] );
404 723
405 - return array_filter( $availableGateways, [ $this, 'filterValidGatewayClass' ] );
724 + add_settings_section( 'packetery_main', __( 'Main Settings', 'packeta' ), function () {}, self::SLUG );
406 725 }
407 726
408 727 /**
409 - * Callback for array filter. Returns true if gateway is of correct type.
728 + * Validates packetery options.
410 729 *
411 - * @param object $gateway Gateway to check.
412 - * @return bool
730 + * @param array $options Options to be validated.
731 + *
732 + * @return array
413 733 */
414 - protected function filterValidGatewayClass( object $gateway ): bool {
415 - return ( $gateway instanceof \WC_Payment_Gateway );
416 - }
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 + }
417 748
418 - /**
419 - * Admin_init callback.
420 - */
421 - public function admin_init(): void {
422 - register_setting( self::FORM_FIELDS_CONTAINER, self::FORM_FIELDS_CONTAINER, array( $this, 'options_validate' ) );
423 - add_settings_section( 'packetery_main', __( 'Main Settings', 'packeta' ), '', self::SLUG );
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;
424 761 }
425 762
426 763 /**
427 - * Validates options.
764 + * Sanitize options.
428 765 *
429 - * @param array $options Packetery_options.
766 + * @param array $options Options to be sanitized.
430 767 *
431 768 * @return array
432 769 */
433 - public function options_validate( array $options ): array {
770 + public function sanitizePacketeryOptions( array $options ): array {
434 771 $form = $this->create_form();
435 - $form[ self::FORM_FIELDS_CONTAINER ]->setValues( $options );
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 );
436 785 if ( $form->isValid() === false ) {
437 - foreach ( $form[ self::FORM_FIELDS_CONTAINER ]->getControls() as $control ) {
786 + foreach ( $packeteryContainer->getControls() as $control ) {
438 787 if ( $control->hasErrors() === false ) {
439 788 continue;
440 789 }
441 790
442 - add_settings_error( $control->getCaption(), esc_attr( $control->getName() ), $control->getError() );
443 791 $options[ $control->getName() ] = '';
444 792 }
445 793 }
446 794
447 - $api_password = $form[ self::FORM_FIELDS_CONTAINER ]['api_password'];
448 - if ( $api_password->hasErrors() === false ) {
449 - $api_pass = $api_password->getValue();
450 - $options['api_key'] = substr( $api_pass, 0, 16 );
451 - $this->packetaClient->setApiPassword( $api_pass );
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 );
452 801 } else {
453 802 $options['api_key'] = '';
454 803 }
455 804
456 - $this->validateSender( $options['sender'] );
457 - $options['force_packet_cancel'] = (int) $form[ self::FORM_FIELDS_CONTAINER ]['force_packet_cancel']->getValue();
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 + }
458 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 +
459 848 return $options;
460 849 }
461 850
462 851 /**
@@ -461,9 +850,9 @@
461 850
462 851 /**
463 852 * Validates sender.
464 853 *
465 - * @param string $senderLabel Sender lbel.
854 + * @param string $senderLabel Sender label.
466 855 *
467 856 * @return bool|null
468 857 */
469 858 private function validateSender( string $senderLabel ): ?bool {
@@ -487,13 +876,13 @@
487 876 $this->logger->add( $senderValidationLog );
488 877
489 878 $senderExists = $senderValidationResponse->senderExists();
490 879
491 - if ( false === $senderExists ) {
880 + if ( $senderExists === false ) {
492 881 $this->messageManager->flash_message( __( 'Specified sender does not exist', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
493 882 }
494 883
495 - if ( null === $senderExists ) {
884 + if ( $senderExists === null ) {
496 885 $this->messageManager->flash_message( __( 'Unable to check specified sender', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
497 886 }
498 887
499 888 return $senderExists;
@@ -505,12 +894,12 @@
505 894 * @return void
506 895 */
507 896 public function processActions(): void {
508 897 $action = $this->httpRequest->getQuery( 'action' );
509 - if ( self::ACTION_VALIDATE_SENDER === $action ) {
898 + if ( $action === self::ACTION_VALIDATE_SENDER ) {
510 899 $result = $this->validateSender( $this->optionsProvider->get_sender() );
511 900
512 - if ( true === $result ) {
901 + if ( $result === true ) {
513 902 $this->messageManager->flash_message( __( 'Specified sender has been validated.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
514 903 }
515 904
516 905 $doRedirect = wp_safe_redirect(
@@ -527,11 +916,48 @@
527 916 }
528 917 }
529 918
530 919 $packetStatusSyncForm = $this->createPacketStatusSyncForm();
531 - if ( $packetStatusSyncForm['save']->isSubmittedBy() ) {
920 + if (
921 + $packetStatusSyncForm['save'] instanceof SubmitButton &&
922 + $packetStatusSyncForm['save']->isSubmittedBy()
923 + ) {
532 924 $packetStatusSyncForm->fireEvents();
533 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 + }
534 960 }
535 961
536 962 /**
537 963 * Renders page.
@@ -539,12 +965,23 @@
539 965 public function render(): void {
540 966 $activeTab = ( $this->httpRequest->getQuery( self::PARAM_TAB ) ?? self::TAB_GENERAL );
541 967
542 968 $latteParams = [];
543 - if ( self::TAB_PACKET_STATUS_SYNC === $activeTab ) {
969 + if ( $activeTab === self::TAB_PACKET_STATUS_SYNC ) {
544 970 $latteParams = [ 'form' => $this->createPacketStatusSyncForm() ];
545 - } elseif ( self::TAB_GENERAL === $activeTab ) {
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 ) {
546 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 + ];
547 984 }
548 985
549 986 if ( ! extension_loaded( 'soap' ) ) {
550 987 $latteParams['error'] = __( 'This plugin requires an active SOAP library for proper operation. Contact your web hosting administrator.', 'packeta' );
@@ -549,9 +986,9 @@
549 986 if ( ! extension_loaded( 'soap' ) ) {
550 987 $latteParams['error'] = __( 'This plugin requires an active SOAP library for proper operation. Contact your web hosting administrator.', 'packeta' );
551 988 }
552 989
553 - $latteParams['apiPasswordLink'] = trim( $this->latte_engine->renderToString( PACKETERY_PLUGIN_DIR . '/template/options/help-block-link.latte', [ 'href' => 'https://client.packeta.com/support' ] ) );
990 + $latteParams['apiPasswordLink'] = trim( $this->latteEngine->renderToString( PACKETERY_PLUGIN_DIR . '/template/options/help-block-link.latte', [ 'href' => 'https://client.packeta.com/support' ] ) );
554 991
555 992 $latteParams['exportLink'] = add_query_arg(
556 993 [
557 994 'page' => self::SLUG,
@@ -559,12 +996,23 @@
559 996 ],
560 997 get_admin_url( null, 'admin.php' )
561 998 );
562 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 +
563 1009 $latteParams['activeTab'] = ( $this->httpRequest->getQuery( self::PARAM_TAB ) ?? self::TAB_GENERAL );
564 1010 $latteParams['generalTabLink'] = $this->createLink();
1011 + $latteParams['advancedTabLink'] = $this->createLink( self::TAB_ADVANCED );
565 1012 $latteParams['supportTabLink'] = $this->createLink( self::TAB_SUPPORT );
566 1013 $latteParams['packetStatusSyncTabLink'] = $this->createLink( self::TAB_PACKET_STATUS_SYNC );
1014 + $latteParams['autoSubmissionTabLink'] = $this->createLink( self::TAB_AUTO_SUBMISSION );
567 1015
568 1016 $latteParams['canValidateSender'] = (bool) $this->optionsProvider->get_sender();
569 1017 $latteParams['senderValidationLink'] = add_query_arg(
570 1018 [
@@ -574,30 +1022,43 @@
574 1022 get_admin_url( null, 'admin.php' )
575 1023 );
576 1024
577 1025 $lastExport = null;
578 - $lastExportOption = get_option( Exporter::OPTION_LAST_SETTINGS_EXPORT );
579 - if ( false !== $lastExportOption ) {
580 - $date = \DateTime::createFromFormat( DATE_ATOM, $lastExportOption );
581 - if ( false !== $date ) {
1026 + $lastExportOption = get_option( OptionNames::LAST_SETTINGS_EXPORT );
1027 + if ( $lastExportOption !== false ) {
1028 + $date = DateTime::createFromFormat( DATE_ATOM, $lastExportOption );
1029 + if ( $date !== false ) {
582 1030 $date->setTimezone( wp_timezone() );
583 1031 $lastExport = $date->format( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
584 1032 }
585 1033 }
586 - if ( $lastExport ) {
1034 + if ( $lastExport !== null ) {
587 1035 $latteParams['lastExport'] = $lastExport;
588 1036 }
589 1037
590 - $latteParams['forcePacketCancelDescription'] = __( 'Cancel the order even if the cancellation in the Packeta system will be unsuccessful', 'packeta' );
1038 + $latteParams['forcePacketCancelDescription'] = __( 'Cancel the packet for an order even if the cancellation in the Packeta system will not be successful.', 'packeta' );
591 1039 $latteParams['messages'] = $this->messageManager->renderToString( MessageManager::RENDERER_PACKETERY, 'plugin-options' );
592 - $latteParams['translations'] = [
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'] = [
593 1050 'packeta' => __( 'Packeta', 'packeta' ),
594 - 'options' => __( 'Options', 'packeta' ),
1051 + 'title' => __( 'Options', 'packeta' ),
595 1052 'general' => __( 'General', 'packeta' ),
596 - // translators: %s represents URL, keep intact.
1053 + 'packetAutoSubmission' => __( 'Packet auto-submission', 'packeta' ),
1054 + 'packetAutoSubmissionMappingDescription' => __( 'Choose events for payment methods that will trigger packet submission', 'packeta' ),
1055 + // translators: %s represents URL.
597 1056 'apiPasswordCanBeFoundAt%sUrl' => __( 'API password can be found at %s', 'packeta' ),
1057 +
598 1058 'saveChanges' => __( 'Save changes', 'packeta' ),
599 1059 'validateSender' => __( 'Validate sender', 'packeta' ),
1060 + 'advanced' => __( 'Advanced', 'packeta' ),
600 1061 'support' => __( 'Support', 'packeta' ),
601 1062 'optionsExportInfo1' => __(
602 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:',
603 1064 'packeta'
@@ -608,10 +1069,15 @@
608 1069 ),
609 1070 'exportPluginSettings' => __( 'Export the plugin settings', 'packeta' ),
610 1071 'settingsExportDatetime' => __( 'Date and time of the last export of settings', 'packeta' ),
611 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' ),
612 1078 'senderDescription' => sprintf(
613 - /* translators: 1: emphasis start 2: emphasis end 3: client section link start 4: client section link end */
1079 + /* translators: 1: emphasis start 2: emphasis end 3: client section link start 4: client section link end */
614 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' ),
615 1081 '<strong>',
616 1082 '</strong>',
617 1083 '<a href="https://client.packeta.com/senders" target="_blank">',
@@ -616,9 +1082,13 @@
616 1082 '</strong>',
617 1083 '<a href="https://client.packeta.com/senders" target="_blank">',
618 1084 '</a>'
619 1085 ),
1086 + 'advancedCarrierSettingsDescription' => $advancedCarrierSettingsDescription,
620 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' ),
621 1091 'packetStatusSyncTabLinkLabel' => __( 'Packet status tracking', 'packeta' ),
622 1092 'statusSyncingOrderStatusesLabel' => __( 'Order statuses, for which cron will check the packet status', 'packeta' ),
623 1093 'statusSyncingOrderStatusesDescription' => __( 'Cron will automatically track all orders with these statuses and check if the shipment status has changed.', 'packeta' ),
624 1094 'statusSyncingPacketStatusesLabel' => __( 'Packet statuses that are being checked', 'packeta' ),
@@ -623,11 +1093,29 @@
623 1093 'statusSyncingOrderStatusesDescription' => __( 'Cron will automatically track all orders with these statuses and check if the shipment status has changed.', 'packeta' ),
624 1094 'statusSyncingPacketStatusesLabel' => __( 'Packet statuses that are being checked', 'packeta' ),
625 1095 'statusSyncingPacketStatusesDescription' => __( 'If an order has a shipment with one of these selected statuses, the shipment status will be tracked.', 'packeta' ),
626 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' ),
627 1115 ];
628 1116
629 - $this->latte_engine->render( PACKETERY_PLUGIN_DIR . '/template/options/page.latte', $latteParams );
1117 + $this->latteEngine->render( PACKETERY_PLUGIN_DIR . '/template/options/page.latte', $latteParams );
630 1118 }
631 1119
632 1120 /**
633 1121 * Creates tab link.
@@ -639,9 +1127,9 @@
639 1127 $params = [
640 1128 'page' => self::SLUG,
641 1129 ];
642 1130
643 - if ( null !== $tab ) {
1131 + if ( $tab !== null ) {
644 1132 $params[ self::PARAM_TAB ] = $tab;
645 1133 }
646 1134
647 1135 return add_query_arg(