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 +552 -187 1.5.32.3.2 View file →
@@ -8,16 +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;
16 27 use Packetery\Module\Order\PacketAutoSubmitter;
17 28 use Packetery\Module\Order\PacketSynchronizer;
18 -use PacketeryLatte\Engine;
19 -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;
20 37
21 38 /**
22 39 * Class Page
23 40 *
@@ -27,9 +44,10 @@
27 44
28 45 private const FORM_FIELDS_CONTAINER = 'packetery';
29 46 private const FORM_FIELD_PACKETA_LABEL_FORMAT = 'packeta_label_format';
30 47 private const FORM_FIELD_CARRIER_LABEL_FORMAT = 'carrier_label_format';
31 - private const FORM_FIELD_ORDER_STATUS_AUTO_CHANGE = 'order_status_auto_change';
48 + private const FORM_FIELD_FREE_SHIPPING_SHOWN = 'free_shipping_shown';
49 + public const FORM_PICKUP_POINT_VALIDATION_ENABLED = 'pickup_point_validation_enabled';
32 50
33 51 public const ACTION_VALIDATE_SENDER = 'validate-sender';
34 52
35 53 public const SLUG = 'packeta-options';
@@ -34,8 +52,9 @@
34 52
35 53 public const SLUG = 'packeta-options';
36 54
37 55 public const TAB_GENERAL = 'general';
56 + public const TAB_ADVANCED = 'advanced';
38 57 public const TAB_SUPPORT = 'support';
39 58 public const TAB_PACKET_STATUS_SYNC = 'packet-status-sync';
40 59 public const TAB_AUTO_SUBMISSION = 'auto-submission';
41 60
@@ -40,19 +59,21 @@
40 59 public const TAB_AUTO_SUBMISSION = 'auto-submission';
41 60
42 61 public const PARAM_TAB = 'tab';
43 62
63 + const PACKETA_SVG_LOGO = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI1LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IlZyc3R2YV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB2aWV3Qm94PSIwIDAgMzcgNDAiIHN0eWxlPSJmaWxsOiNhN2FhYWQiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiAjYTdhYWFkO30KPC9zdHlsZT4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTE5LjQsMTYuMWwtMC45LDAuNGwtMC45LTAuNGwtMTMtNi41bDYuMi0yLjRsMTMuNCw2LjVMMTkuNCwxNi4xeiBNMzIuNSw5LjZsLTQuNywyLjNsLTEzLjUtNmw0LjItMS42CglMMzIuNSw5LjZ6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xOSwwbDE3LjIsNi42bC0yLjQsMS45bC0xNS4yLTZMMy4yLDguNkwwLjgsNi42TDE4LDBMMTksMEwxOSwweiBNMzQuMSw5LjFsMi44LTEuMWwtMi4xLDE3LjZsLTAuNCwwLjgKCUwxOS40LDQwbC0wLjUtMy4xbDEzLjQtMTJMMzQuMSw5LjF6IE0yLjUsMjYuNWwtMC40LTAuOEwwLDguMWwyLjgsMS4xbDEuOSwxNS43bDEzLjQsMTJMMTcuNiw0MEwyLjUsMjYuNXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI4LjIsMTIuNGw0LjMtMi43bC0xLjcsMTQuMkwxOC42LDM1bDAuNi0xN2w1LjQtMy4zTDI0LjMsMjNsMy4zLTIuM0wyOC4yLDEyLjR6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xNy43LDE3LjlsMC42LDE3bC0xMi4yLTExTDQuNCw5LjhMMTcuNywxNy45eiIvPgo8L3N2Zz4K';
64 +
44 65 /**
45 66 * PacketeryLatte_engine.
46 67 *
47 68 * @var Engine PacketeryLatte engine.
48 69 */
49 - private $latte_engine;
70 + private $latteEngine;
50 71
51 72 /**
52 73 * Options Provider
53 74 *
54 - * @var Provider
75 + * @var OptionsProvider
55 76 */
56 77 private $optionsProvider;
57 78
58 79 /**
@@ -64,9 +85,9 @@
64 85
65 86 /**
66 87 * Packeta client.
67 88 *
68 - * @var \Packetery\Core\Api\Soap\Client
89 + * @var Api\Soap\Client
69 90 */
70 91 private $packetaClient;
71 92
72 93 /**
@@ -83,61 +104,107 @@
83 104 */
84 105 private $messageManager;
85 106
86 107 /**
87 - * HTTP request.
88 - *
89 - * @var \PacketeryNette\Http\Request
108 + * @var Http\Request
90 109 */
91 110 private $httpRequest;
92 111
93 112 /**
94 - * Plugin constructor.
95 - *
96 - * @param Engine $latte_engine PacketeryLatte_engine.
97 - * @param Provider $optionsProvider Options provider.
98 - * @param FormFactory $formFactory Form factory.
99 - * @param \Packetery\Core\Api\Soap\Client $packetaClient Packeta Client.
100 - * @param Log\ILogger $logger Logger.
101 - * @param MessageManager $messageManager Message manager.
102 - * @param \PacketeryNette\Http\Request $httpRequest HTTP request.
113 + * @var ModuleHelper
103 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 +
104 150 public function __construct(
105 - Engine $latte_engine,
106 - Provider $optionsProvider,
151 + Engine $latteEngine,
152 + OptionsProvider $optionsProvider,
107 153 FormFactory $formFactory,
108 - \Packetery\Core\Api\Soap\Client $packetaClient,
154 + Api\Soap\Client $packetaClient,
109 155 Log\ILogger $logger,
110 156 MessageManager $messageManager,
111 - \PacketeryNette\Http\Request $httpRequest
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
112 166 ) {
113 - $this->latte_engine = $latte_engine;
114 - $this->optionsProvider = $optionsProvider;
115 - $this->formFactory = $formFactory;
116 - $this->packetaClient = $packetaClient;
117 - $this->logger = $logger;
118 - $this->messageManager = $messageManager;
119 - $this->httpRequest = $httpRequest;
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;
120 182 }
121 183
122 - /**
123 - * Registers WP callbacks.
124 - */
125 184 public function register(): void {
126 - add_action( 'admin_init', array( $this, 'admin_init' ) );
127 - $icon = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDI1LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IlZyc3R2YV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCIKCSB2aWV3Qm94PSIwIDAgMzcgNDAiIHN0eWxlPSJmaWxsOiNhN2FhYWQiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsLXJ1bGU6ZXZlbm9kZDtjbGlwLXJ1bGU6ZXZlbm9kZDtmaWxsOiAjYTdhYWFkO30KPC9zdHlsZT4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTE5LjQsMTYuMWwtMC45LDAuNGwtMC45LTAuNGwtMTMtNi41bDYuMi0yLjRsMTMuNCw2LjVMMTkuNCwxNi4xeiBNMzIuNSw5LjZsLTQuNywyLjNsLTEzLjUtNmw0LjItMS42CglMMzIuNSw5LjZ6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xOSwwbDE3LjIsNi42bC0yLjQsMS45bC0xNS4yLTZMMy4yLDguNkwwLjgsNi42TDE4LDBMMTksMEwxOSwweiBNMzQuMSw5LjFsMi44LTEuMWwtMi4xLDE3LjZsLTAuNCwwLjgKCUwxOS40LDQwbC0wLjUtMy4xbDEzLjQtMTJMMzQuMSw5LjF6IE0yLjUsMjYuNWwtMC40LTAuOEwwLDguMWwyLjgsMS4xbDEuOSwxNS43bDEzLjQsMTJMMTcuNiw0MEwyLjUsMjYuNXoiLz4KPHBhdGggY2xhc3M9InN0MCIgZD0iTTI4LjIsMTIuNGw0LjMtMi43bC0xLjcsMTQuMkwxOC42LDM1bDAuNi0xN2w1LjQtMy4zTDI0LjMsMjNsMy4zLTIuM0wyOC4yLDEyLjR6Ii8+CjxwYXRoIGNsYXNzPSJzdDAiIGQ9Ik0xNy43LDE3LjlsMC42LDE3bC0xMi4yLTExTDQuNCw5LjhMMTcuNywxNy45eiIvPgo8L3N2Zz4K';
128 - add_menu_page(
129 - __( 'Packeta', 'packeta' ),
130 - __( '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' ),
131 195 'manage_options',
132 - self::SLUG,
133 - '',
134 - $icon
196 + DashboardPage::SLUG,
197 + function () {},
198 + self::PACKETA_SVG_LOGO
135 199 );
136 - add_submenu_page(
137 - self::SLUG,
138 - __( 'Settings', 'packeta' ),
139 - __( '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' ),
140 207 'manage_options',
141 208 self::SLUG,
142 209 array(
143 210 $this,
@@ -144,25 +211,27 @@
144 211 'render',
145 212 ),
146 213 1
147 214 );
148 - add_action( 'admin_init', [ $this, 'processActions' ] );
149 -
150 - add_filter( 'custom_menu_order', '__return_true' );
151 - add_filter( 'menu_order', [ $this, 'customMenuOrder' ] );
152 215 }
153 216
154 217 /**
155 218 * Returns menu_order with Packeta item in last position.
156 219 *
157 - * @param array $menuOrder WP $menu_order.
220 + * @param array|mixed $menuOrder WP $menu_order.
158 221 *
159 - * @return array
222 + * @return array|mixed
160 223 */
161 - 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 +
162 231 $currentPosition = array_search( self::SLUG, $menuOrder, true );
163 232
164 - if ( false !== $currentPosition ) {
233 + if ( $currentPosition !== false ) {
165 234 unset( $menuOrder[ $currentPosition ] );
166 235 $menuOrder[] = self::SLUG;
167 236 }
168 237
@@ -188,15 +257,54 @@
188 257 return $statuses;
189 258 }
190 259
191 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 + /**
192 291 * Gets all packet statuses.
193 292 *
194 - * @return array
293 + * @return array<string, array{key: int|string, default: bool, label:string}>
195 294 */
196 - public function getPacketStatusesChoiceData(): array {
197 - $statuses = PacketSynchronizer::getPacketStatuses();
295 + public function getAllPacketStatusesChoiceData(): array {
296 + $statuses = $this->packetSynchronizer->getPacketStatuses();
198 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 {
199 307 $result = [];
200 308
201 309 foreach ( $statuses as $status => $statusEntity ) {
202 310 $result[ md5( $status ) ] = [
@@ -211,9 +319,9 @@
211 319
212 320 /**
213 321 * Gets order statuses for form.
214 322 *
215 - * @return array
323 + * @return array<string, array<string, int|string>>
216 324 */
217 325 public static function getOrderStatusesChoiceData(): array {
218 326 $orderStatuses = wc_get_order_statuses();
219 327 $orderStatusesTransformed = [];
@@ -233,15 +341,15 @@
233 341 *
234 342 * @return Form
235 343 */
236 344 public function createAutoSubmissionForm(): Form {
237 - $gateways = $this->getAvailablePaymentGateways();
345 + $gateways = PaymentGatewayHelper::getAvailablePaymentGateways();
238 346 $form = $this->formFactory->create( 'packetery_auto_submission_form' );
239 - $defaults = $this->optionsProvider->data_to_array( Provider::OPTION_NAME_PACKETERY_AUTO_SUBMISSION );
347 + $defaults = $this->optionsProvider->getOptionsByName( OptionNames::PACKETERY_AUTO_SUBMISSION );
240 348
241 349 $form->addCheckbox( 'allow', __( 'Allow packet auto-submission', 'packeta' ) )
242 350 ->setRequired( false )
243 - ->setDefaultValue( Provider::PACKET_AUTO_SUBMISSION_ALLOWED_DEFAULT );
351 + ->setDefaultValue( OptionsProvider::PACKET_AUTO_SUBMISSION_ALLOWED_DEFAULT );
244 352
245 353 $eventChoices = [
246 354 PacketAutoSubmitter::EVENT_ON_ORDER_CREATION_FE => __( 'On order creation at e-shop checkout', 'packeta' ),
247 355 PacketAutoSubmitter::EVENT_ON_ORDER_PROCESSING => __( 'On order processing', 'packeta' ),
@@ -253,10 +361,10 @@
253 361 $paymentMethodEventsMethod = $paymentMethodEvents->addContainer(
254 362 $this->optionsProvider->sanitizePaymentGatewayId( $gateway->id )
255 363 );
256 364 $paymentMethodEventsMethod->addSelect( 'event', $gateway->get_method_title(), $eventChoices )
257 - ->setPrompt( __( 'Select event', 'packeta' ) )
258 - ->checkDefaultValue( false );
365 + ->setPrompt( __( 'Select event', 'packeta' ) )
366 + ->checkDefaultValue( false );
259 367 }
260 368
261 369 $form->addSubmit( 'save', __( 'Save changes', 'packeta' ) );
262 370
@@ -275,9 +383,9 @@
275 383 *
276 384 * @return void
277 385 */
278 386 public function onAutoSubmissionFormSuccess( Form $form, array $values ): void {
279 - update_option( Provider::OPTION_NAME_PACKETERY_AUTO_SUBMISSION, $values );
387 + update_option( OptionNames::PACKETERY_AUTO_SUBMISSION, $values );
280 388
281 389 $this->messageManager->flash_message( __( 'Settings saved.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
282 390
283 391 if ( wp_safe_redirect( $this->createLink( self::TAB_AUTO_SUBMISSION ) ) ) {
@@ -291,21 +399,21 @@
291 399 * @return Form
292 400 */
293 401 private function createPacketStatusSyncForm(): Form {
294 402 $form = $this->formFactory->create( 'packetery_packet_status_sync_form' );
295 - $settings = $this->optionsProvider->data_to_array( Provider::OPTION_NAME_PACKETERY_SYNC );
403 + $settings = $this->optionsProvider->getOptionsByName( OptionNames::PACKETERY_SYNC );
296 404
297 405 $form->addText( 'max_status_syncing_packets', __( 'Number of orders synced during one cron call', 'packeta' ) )
298 406 ->setRequired( false )
299 407 ->addRule( Form::INTEGER )
300 408 ->addRule( Form::MIN, null, 0 )
301 - ->setDefaultValue( Provider::MAX_STATUS_SYNCING_PACKETS_DEFAULT );
409 + ->setDefaultValue( OptionsProvider::MAX_STATUS_SYNCING_PACKETS_DEFAULT );
302 410
303 411 $form->addText( 'max_days_of_packet_status_syncing', __( 'Number of days for which the order status is checked', 'packeta' ) )
304 412 ->setRequired( false )
305 413 ->addRule( Form::INTEGER )
306 414 ->addRule( Form::MIN, null, 0 )
307 - ->setDefaultValue( Provider::MAX_DAYS_OF_PACKET_STATUS_SYNCING_DEFAULT );
415 + ->setDefaultValue( OptionsProvider::MAX_DAYS_OF_PACKET_STATUS_SYNCING_DEFAULT );
308 416
309 417 $orderStatusesTransformed = self::getOrderStatusesChoiceData();
310 418 $orderStatusesContainer = $form->addContainer( 'status_syncing_order_statuses' );
311 419
@@ -316,9 +424,9 @@
316 424 }
317 425 }
318 426 unset( $settings['status_syncing_order_statuses'] );
319 427
320 - $packetStatuses = $this->getPacketStatusesChoiceData();
428 + $packetStatuses = $this->getStatusSyncingPacketStatusesChoiceData();
321 429 $packetStatusesContainer = $form->addContainer( 'status_syncing_packet_statuses' );
322 430
323 431 foreach ( $packetStatuses as $packetStatusHash => $packetStatusData ) {
324 432 $item = $packetStatusesContainer->addCheckbox( $packetStatusHash, $packetStatusData['label'] );
@@ -329,8 +437,27 @@
329 437 }
330 438 }
331 439 unset( $settings['status_syncing_packet_statuses'] );
332 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 +
333 460 $form->setDefaults( $settings );
334 461
335 462 $form->addSubmit( 'save', __( 'Save changes', 'packeta' ) );
336 463
@@ -347,27 +474,30 @@
347 474 *
348 475 * @return void
349 476 */
350 477 public function onPacketStatusSyncFormSuccess( Form $form, array $values ): void {
351 -
352 - $values['status_syncing_order_statuses'] = $this->getChosenKeys(
478 + $values['status_syncing_order_statuses'] = $this->getChosenKeys(
353 479 self::getOrderStatusesChoiceData(),
354 480 $values['status_syncing_order_statuses']
355 481 );
356 - $values['status_syncing_packet_statuses'] = $this->getChosenKeys(
357 - $this->getPacketStatusesChoiceData(),
482 + $values['status_syncing_packet_statuses'] = $this->getChosenKeys(
483 + $this->getStatusSyncingPacketStatusesChoiceData(),
358 484 $values['status_syncing_packet_statuses']
359 485 );
486 + $values['order_status_change_packet_statuses'] = $this->translateStatuses(
487 + $this->getAllPacketStatusesChoiceData(),
488 + $values['order_status_change_packet_statuses']
489 + );
360 490
361 - if ( '' === $values['max_status_syncing_packets'] ) {
491 + if ( $values['max_status_syncing_packets'] === '' ) {
362 492 unset( $values['max_status_syncing_packets'] );
363 493 }
364 494
365 - if ( '' === $values['max_days_of_packet_status_syncing'] ) {
495 + if ( $values['max_days_of_packet_status_syncing'] === '' ) {
366 496 unset( $values['max_days_of_packet_status_syncing'] );
367 497 }
368 498
369 - update_option( Provider::OPTION_NAME_PACKETERY_SYNC, $values );
499 + update_option( OptionNames::PACKETERY_SYNC, $values );
370 500
371 501 $this->messageManager->flash_message( __( 'Settings saved.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
372 502
373 503 if ( wp_safe_redirect( $this->createLink( self::TAB_PACKET_STATUS_SYNC ) ) ) {
@@ -374,8 +504,35 @@
374 504 exit;
375 505 }
376 506 }
377 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 +
378 535 /**
379 536 * Creates settings form.
380 537 *
381 538 * @return Form
@@ -385,12 +542,12 @@
385 542 $form->setAction( 'options.php' );
386 543
387 544 $container = $form->addContainer( self::FORM_FIELDS_CONTAINER );
388 545 $container->addText( 'api_password', __( 'API password', 'packeta' ) )
389 - ->setRequired()
390 - ->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}' );
391 548 $container->addText( 'sender', __( 'Sender', 'packeta' ) )
392 - ->setRequired();
549 + ->setRequired();
393 550
394 551 $packetaLabelFormats = $this->optionsProvider->getPacketaLabelFormats();
395 552 $container->addSelect(
396 553 self::FORM_FIELD_PACKETA_LABEL_FORMAT,
@@ -395,9 +552,9 @@
395 552 $container->addSelect(
396 553 self::FORM_FIELD_PACKETA_LABEL_FORMAT,
397 554 __( 'Packeta Label Format', 'packeta' ),
398 555 $packetaLabelFormats
399 - )->checkDefaultValue( false )->setDefaultValue( Provider::DEFAULT_VALUE_PACKETA_LABEL_FORMAT );
556 + )->checkDefaultValue( false )->setDefaultValue( OptionsProvider::DEFAULT_VALUE_PACKETA_LABEL_FORMAT );
400 557
401 558 $carrierLabelFormats = $this->optionsProvider->getCarrierLabelFormat();
402 559 $container->addSelect(
403 560 self::FORM_FIELD_CARRIER_LABEL_FORMAT,
@@ -402,43 +559,98 @@
402 559 $container->addSelect(
403 560 self::FORM_FIELD_CARRIER_LABEL_FORMAT,
404 561 __( 'Carrier Label Format', 'packeta' ),
405 562 $carrierLabelFormats
406 - )->checkDefaultValue( false )->setDefaultValue( Provider::DEFAULT_VALUE_CARRIER_LABEL_FORMAT );
563 + )->checkDefaultValue( false )->setDefaultValue( OptionsProvider::DEFAULT_VALUE_CARRIER_LABEL_FORMAT );
407 564
408 - $gateways = $this->getAvailablePaymentGateways();
565 + $gateways = PaymentGatewayHelper::getAvailablePaymentGateways();
409 566 $enabledGateways = [];
410 567 foreach ( $gateways as $gateway ) {
411 568 $enabledGateways[ $gateway->id ] = $gateway->get_method_title();
412 569 }
413 - $container->addSelect(
414 - 'cod_payment_method',
415 - __( 'Payment method that represents cash on delivery', 'packeta' ),
570 + $container->addMultiSelect(
571 + 'cod_payment_methods',
572 + __( 'Payment methods that represent cash on delivery', 'packeta' ),
416 573 $enabledGateways
417 - )->setPrompt( '--' )->checkDefaultValue( false );
574 + )->checkDefaultValue( false );
418 575
419 576 $container->addText( 'packaging_weight', __( 'Weight of packaging material', 'packeta' ) . ' (kg)' )
420 - ->setRequired( true )
421 - ->addRule( Form::FLOAT )
422 - ->addRule( Form::MIN, null, 0 )
423 - ->setDefaultValue( 0 );
577 + ->setRequired()
578 + ->addRule( Form::FLOAT )
579 + ->addRule( Form::MIN, null, 0 )
580 + ->setDefaultValue( 0 );
424 581
425 582 $container->addCheckbox( 'default_weight_enabled', __( 'Enable default weight', 'packeta' ) )
426 - ->addCondition( Form::EQUAL, true )
427 - ->toggle( '#packetery-default-weight-value' );
583 + ->addCondition( Form::EQUAL, true )
584 + ->toggle( '#packetery-default-weight-value' );
428 585
429 586 $container->addText( 'default_weight', __( 'Default weight', 'packeta' ) . ' (kg)' )
430 - ->addRule( Form::FLOAT )
431 - ->addRule( Form::MIN, null, 0.1 )
432 - ->addConditionOn( $form[ self::FORM_FIELDS_CONTAINER ]['default_weight_enabled'], Form::EQUAL, true )
433 - ->setRequired();
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 );
434 591
435 - // TODO: Packet status sync.
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 );
436 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 +
437 639 $container->addCheckbox( 'replace_shipping_address_with_pickup_point_address', __( 'Replace shipping address with pickup point address', 'packeta' ) )
438 - ->setRequired( false );
640 + ->setRequired( false );
439 641
440 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(
441 653 'checkout_widget_button_location',
442 654 __( 'Widget button location in checkout', 'packeta' ),
443 655 [
444 656 'after_shipping_rate' => __( 'After shipping rate', 'packeta' ),
@@ -445,44 +657,57 @@
445 657 'after_transport_methods' => __( 'After transport methods', 'packeta' ),
446 658 ]
447 659 );
448 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 +
449 682 $container->addCheckbox( 'force_packet_cancel', __( 'Force order cancellation', 'packeta' ) )
450 - ->setRequired( false )
451 - ->setDefaultValue( Provider::FORCE_PACKET_CANCEL_DEFAULT );
683 + ->setRequired( false )
684 + ->setDefaultValue( OptionsProvider::FORCE_PACKET_CANCEL_DEFAULT );
452 685
453 686 $container->addCheckbox( 'widget_auto_open', __( 'Automatically open widget when shipping was selected', 'packeta' ) )
454 - ->setRequired( false )
455 - ->setDefaultValue( Provider::WIDGET_AUTO_OPEN_DEFAULT );
687 + ->setRequired( false )
688 + ->setDefaultValue( OptionsProvider::WIDGET_AUTO_OPEN_DEFAULT );
456 689
457 - $container->addCheckbox( self::FORM_FIELD_ORDER_STATUS_AUTO_CHANGE, __( 'Order status change after parcel creation', 'packeta' ) )
458 - ->setRequired( false )
459 - ->setDefaultValue( Provider::ORDER_STATUS_AUTO_CHANGE_DEFAULT )
460 - ->addCondition( Form::EQUAL, true )
461 - ->toggle( '.packetery-order-status-auto-change-row' );
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 );
462 693
463 - $orderStatuses = wc_get_order_statuses();
464 - $container->addSelect(
465 - Provider::AUTO_ORDER_STATUS,
466 - __( 'New order status', 'packeta' ),
467 - $orderStatuses
468 - )
469 - ->checkDefaultValue( false )
470 - ->setDefaultValue( Provider::AUTO_ORDER_STATUS_DEFAULT )
471 - ->setPrompt( __( 'Select new order status', 'packeta' ) )
472 - ->addRule( Form::IS_IN, __( 'Select valid order status', 'packeta' ), array_keys( $orderStatuses ) )
473 - ->addConditionOn( $form[ self::FORM_FIELDS_CONTAINER ][ self::FORM_FIELD_ORDER_STATUS_AUTO_CHANGE ], Form::EQUAL, true )
474 - ->setRequired();
694 + $container->addCheckbox( 'prices_include_tax', __( 'Prices include tax', 'packeta' ) )
695 + ->setRequired( false )
696 + ->setDefaultValue( OptionsProvider::PRICES_INCLUDE_TAX_DEFAULT );
475 697
476 - $container->addCheckbox(
477 - 'order_status_auto_change_for_auto_submit_at_frontend',
478 - __( 'Change order status after automatic packet submit at checkout', 'packeta' )
479 - );
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 );
480 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 +
481 706 $form->addSubmit( 'save', __( 'Save changes', 'packeta' ) );
482 707
483 - if ( $this->optionsProvider->has_any( Provider::OPTION_NAME_PACKETERY ) ) {
484 - $container->setDefaults( $this->optionsProvider->data_to_array( Provider::OPTION_NAME_PACKETERY ) );
708 + if ( $this->optionsProvider->has_any( OptionNames::PACKETERY ) ) {
709 + $container->setDefaults( $this->optionsProvider->getOptionsByName( OptionNames::PACKETERY ) );
485 710 }
486 711
487 712 return $form;
488 713 }
@@ -487,86 +712,140 @@
487 712 return $form;
488 713 }
489 714
490 715 /**
491 - * Get available gateways.
492 - *
493 - * @return \WC_Payment_Gateway[]
716 + * Admin_init callback.
494 717 */
495 - public function getAvailablePaymentGateways(): array {
496 - $availableGateways = [];
718 + public function admin_init(): void {
719 + add_filter( 'pre_update_option_packetery', [ $this, 'validatePacketeryOptions' ] );
497 720
498 - foreach ( WC()->payment_gateways()->payment_gateways() as $gateway ) {
499 - if ( 'yes' === $gateway->enabled ) {
500 - $availableGateways[ $gateway->id ] = $gateway;
501 - }
502 - }
721 + // Registered callback is called when the form is submitted.
722 + register_setting( self::FORM_FIELDS_CONTAINER, self::FORM_FIELDS_CONTAINER, [ $this, 'sanitizePacketeryOptions' ] );
503 723
504 - return array_filter( $availableGateways, [ $this, 'filterValidGatewayClass' ] );
724 + add_settings_section( 'packetery_main', __( 'Main Settings', 'packeta' ), function () {}, self::SLUG );
505 725 }
506 726
507 727 /**
508 - * Tells if options page uses given payment gateway.
728 + * Validates packetery options.
509 729 *
510 - * @param \WC_Payment_Gateway $paymentGateway Payment gateway.
730 + * @param array $options Options to be validated.
511 731 *
512 - * @return bool
732 + * @return array
513 733 */
514 - public function hasPaymentGateway( \WC_Payment_Gateway $paymentGateway ): bool {
515 - return array_key_exists( $paymentGateway->id, $this->getAvailablePaymentGateways() );
516 - }
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 + }
517 748
518 - /**
519 - * Callback for array filter. Returns true if gateway is of correct type.
520 - *
521 - * @param object $gateway Gateway to check.
522 - * @return bool
523 - */
524 - protected function filterValidGatewayClass( object $gateway ): bool {
525 - return ( $gateway instanceof \WC_Payment_Gateway );
526 - }
749 + add_settings_error( OptionNames::PACKETERY, esc_attr( $control->getName() ), "{$control->getCaption()}: {$control->getError()}" );
750 + }
751 + }
527 752
528 - /**
529 - * Admin_init callback.
530 - */
531 - public function admin_init(): void {
532 - register_setting( self::FORM_FIELDS_CONTAINER, self::FORM_FIELDS_CONTAINER, array( $this, 'options_validate' ) );
533 - add_settings_section( 'packetery_main', __( 'Main Settings', 'packeta' ), '', self::SLUG );
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;
534 761 }
535 762
536 763 /**
537 - * Validates options.
764 + * Sanitize options.
538 765 *
539 - * @param array $options Packetery_options.
766 + * @param array $options Options to be sanitized.
540 767 *
541 768 * @return array
542 769 */
543 - public function options_validate( array $options ): array {
770 + public function sanitizePacketeryOptions( array $options ): array {
544 771 $form = $this->create_form();
545 - $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 );
546 785 if ( $form->isValid() === false ) {
547 - foreach ( $form[ self::FORM_FIELDS_CONTAINER ]->getControls() as $control ) {
786 + foreach ( $packeteryContainer->getControls() as $control ) {
548 787 if ( $control->hasErrors() === false ) {
549 788 continue;
550 789 }
551 790
552 - add_settings_error( $control->getCaption(), esc_attr( $control->getName() ), $control->getError() );
553 791 $options[ $control->getName() ] = '';
554 792 }
555 793 }
556 794
557 - $api_password = $form[ self::FORM_FIELDS_CONTAINER ]['api_password'];
558 - if ( $api_password->hasErrors() === false ) {
559 - $api_pass = $api_password->getValue();
560 - $options['api_key'] = substr( $api_pass, 0, 16 );
561 - $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 );
562 801 } else {
563 802 $options['api_key'] = '';
564 803 }
565 804
566 - $this->validateSender( $options['sender'] );
567 - $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 + }
568 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 +
569 848 return $options;
570 849 }
571 850
572 851 /**
@@ -597,13 +876,13 @@
597 876 $this->logger->add( $senderValidationLog );
598 877
599 878 $senderExists = $senderValidationResponse->senderExists();
600 879
601 - if ( false === $senderExists ) {
880 + if ( $senderExists === false ) {
602 881 $this->messageManager->flash_message( __( 'Specified sender does not exist', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
603 882 }
604 883
605 - if ( null === $senderExists ) {
884 + if ( $senderExists === null ) {
606 885 $this->messageManager->flash_message( __( 'Unable to check specified sender', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
607 886 }
608 887
609 888 return $senderExists;
@@ -615,12 +894,12 @@
615 894 * @return void
616 895 */
617 896 public function processActions(): void {
618 897 $action = $this->httpRequest->getQuery( 'action' );
619 - if ( self::ACTION_VALIDATE_SENDER === $action ) {
898 + if ( $action === self::ACTION_VALIDATE_SENDER ) {
620 899 $result = $this->validateSender( $this->optionsProvider->get_sender() );
621 900
622 - if ( true === $result ) {
901 + if ( $result === true ) {
623 902 $this->messageManager->flash_message( __( 'Specified sender has been validated.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
624 903 }
625 904
626 905 $doRedirect = wp_safe_redirect(
@@ -637,16 +916,48 @@
637 916 }
638 917 }
639 918
640 919 $packetStatusSyncForm = $this->createPacketStatusSyncForm();
641 - if ( $packetStatusSyncForm['save']->isSubmittedBy() ) {
920 + if (
921 + $packetStatusSyncForm['save'] instanceof SubmitButton &&
922 + $packetStatusSyncForm['save']->isSubmittedBy()
923 + ) {
642 924 $packetStatusSyncForm->fireEvents();
643 925 }
644 926
645 927 $autoSubmissionForm = $this->createAutoSubmissionForm();
646 - if ( $autoSubmissionForm['save']->isSubmittedBy() ) {
928 + if (
929 + $autoSubmissionForm['save'] instanceof SubmitButton &&
930 + $autoSubmissionForm['save']->isSubmittedBy()
931 + ) {
647 932 $autoSubmissionForm->fireEvents();
648 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 + }
649 960 }
650 961
651 962 /**
652 963 * Renders page.
@@ -654,14 +965,23 @@
654 965 public function render(): void {
655 966 $activeTab = ( $this->httpRequest->getQuery( self::PARAM_TAB ) ?? self::TAB_GENERAL );
656 967
657 968 $latteParams = [];
658 - if ( self::TAB_PACKET_STATUS_SYNC === $activeTab ) {
969 + if ( $activeTab === self::TAB_PACKET_STATUS_SYNC ) {
659 970 $latteParams = [ 'form' => $this->createPacketStatusSyncForm() ];
660 - } elseif ( self::TAB_AUTO_SUBMISSION === $activeTab ) {
971 + } elseif ( $activeTab === self::TAB_AUTO_SUBMISSION ) {
661 972 $latteParams = [ 'form' => $this->createAutoSubmissionForm() ];
662 - } elseif ( self::TAB_GENERAL === $activeTab ) {
973 + } elseif ( $activeTab === self::TAB_ADVANCED ) {
974 + $latteParams = [ 'form' => $this->createAdvancedForm() ];
975 + } elseif ( $activeTab === self::TAB_GENERAL ) {
663 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 + ];
664 984 }
665 985
666 986 if ( ! extension_loaded( 'soap' ) ) {
667 987 $latteParams['error'] = __( 'This plugin requires an active SOAP library for proper operation. Contact your web hosting administrator.', 'packeta' );
@@ -666,9 +986,9 @@
666 986 if ( ! extension_loaded( 'soap' ) ) {
667 987 $latteParams['error'] = __( 'This plugin requires an active SOAP library for proper operation. Contact your web hosting administrator.', 'packeta' );
668 988 }
669 989
670 - $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' ] ) );
671 991
672 992 $latteParams['exportLink'] = add_query_arg(
673 993 [
674 994 'page' => self::SLUG,
@@ -676,10 +996,20 @@
676 996 ],
677 997 get_admin_url( null, 'admin.php' )
678 998 );
679 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 +
680 1009 $latteParams['activeTab'] = ( $this->httpRequest->getQuery( self::PARAM_TAB ) ?? self::TAB_GENERAL );
681 1010 $latteParams['generalTabLink'] = $this->createLink();
1011 + $latteParams['advancedTabLink'] = $this->createLink( self::TAB_ADVANCED );
682 1012 $latteParams['supportTabLink'] = $this->createLink( self::TAB_SUPPORT );
683 1013 $latteParams['packetStatusSyncTabLink'] = $this->createLink( self::TAB_PACKET_STATUS_SYNC );
684 1014 $latteParams['autoSubmissionTabLink'] = $this->createLink( self::TAB_AUTO_SUBMISSION );
685 1015
@@ -692,32 +1022,43 @@
692 1022 get_admin_url( null, 'admin.php' )
693 1023 );
694 1024
695 1025 $lastExport = null;
696 - $lastExportOption = get_option( Exporter::OPTION_LAST_SETTINGS_EXPORT );
697 - if ( false !== $lastExportOption ) {
698 - $date = \DateTime::createFromFormat( DATE_ATOM, $lastExportOption );
699 - 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 ) {
700 1030 $date->setTimezone( wp_timezone() );
701 1031 $lastExport = $date->format( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
702 1032 }
703 1033 }
704 - if ( $lastExport ) {
1034 + if ( $lastExport !== null ) {
705 1035 $latteParams['lastExport'] = $lastExport;
706 1036 }
707 1037
708 - $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' );
709 1039 $latteParams['messages'] = $this->messageManager->renderToString( MessageManager::RENDERER_PACKETERY, 'plugin-options' );
710 - $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'] = [
711 1050 'packeta' => __( 'Packeta', 'packeta' ),
712 1051 'title' => __( 'Options', 'packeta' ),
713 1052 'general' => __( 'General', 'packeta' ),
714 1053 'packetAutoSubmission' => __( 'Packet auto-submission', 'packeta' ),
715 1054 'packetAutoSubmissionMappingDescription' => __( 'Choose events for payment methods that will trigger packet submission', 'packeta' ),
716 - // translators: %s represents URL, keep intact.
1055 + // translators: %s represents URL.
717 1056 'apiPasswordCanBeFoundAt%sUrl' => __( 'API password can be found at %s', 'packeta' ),
1057 +
718 1058 'saveChanges' => __( 'Save changes', 'packeta' ),
719 1059 'validateSender' => __( 'Validate sender', 'packeta' ),
1060 + 'advanced' => __( 'Advanced', 'packeta' ),
720 1061 'support' => __( 'Support', 'packeta' ),
721 1062 'optionsExportInfo1' => __(
722 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:',
723 1064 'packeta'
@@ -728,8 +1069,13 @@
728 1069 ),
729 1070 'exportPluginSettings' => __( 'Export the plugin settings', 'packeta' ),
730 1071 'settingsExportDatetime' => __( 'Date and time of the last export of settings', 'packeta' ),
731 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' ),
732 1078 'senderDescription' => sprintf(
733 1079 /* translators: 1: emphasis start 2: emphasis end 3: client section link start 4: client section link end */
734 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' ),
735 1081 '<strong>',
@@ -736,10 +1082,13 @@
736 1082 '</strong>',
737 1083 '<a href="https://client.packeta.com/senders" target="_blank">',
738 1084 '</a>'
739 1085 ),
1086 + 'advancedCarrierSettingsDescription' => $advancedCarrierSettingsDescription,
740 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' ),
741 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' ),
742 1091 'packetStatusSyncTabLinkLabel' => __( 'Packet status tracking', 'packeta' ),
743 1092 'statusSyncingOrderStatusesLabel' => __( 'Order statuses, for which cron will check the packet status', 'packeta' ),
744 1093 'statusSyncingOrderStatusesDescription' => __( 'Cron will automatically track all orders with these statuses and check if the shipment status has changed.', 'packeta' ),
745 1094 'statusSyncingPacketStatusesLabel' => __( 'Packet statuses that are being checked', 'packeta' ),
@@ -746,11 +1095,27 @@
746 1095 'statusSyncingPacketStatusesDescription' => __( 'If an order has a shipment with one of these selected statuses, the shipment status will be tracked.', 'packeta' ),
747 1096 'numberOfDaysToCheckDescription' => __( 'Number of days after the creation of an order, during which the order status will be checked.', 'packeta' ),
748 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' ),
749 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' ),
750 1115 ];
751 1116
752 - $this->latte_engine->render( PACKETERY_PLUGIN_DIR . '/template/options/page.latte', $latteParams );
1117 + $this->latteEngine->render( PACKETERY_PLUGIN_DIR . '/template/options/page.latte', $latteParams );
753 1118 }
754 1119
755 1120 /**
756 1121 * Creates tab link.
@@ -762,9 +1127,9 @@
762 1127 $params = [
763 1128 'page' => self::SLUG,
764 1129 ];
765 1130
766 - if ( null !== $tab ) {
1131 + if ( $tab !== null ) {
767 1132 $params[ self::PARAM_TAB ] = $tab;
768 1133 }
769 1134
770 1135 return add_query_arg(