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