PluginProbe
Packeta / 1.3.2
Packeta v1.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
packeta / src / Packetery / Module / Options / Page.php

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

435 lines 14.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class Page
4 *
5 * @package Packetery\Options
6 */
7
8 declare( strict_types=1 );
9
10 namespace Packetery\Module\Options;
11
12 use Packetery\Core\Api\Soap\Request\SenderGetReturnRouting;
13 use Packetery\Core\Log;
14 use Packetery\Module\FormFactory;
15 use Packetery\Module\MessageManager;
16 use PacketeryLatte\Engine;
17 use PacketeryNette\Forms\Form;
18
19 /**
20 * Class Page
21 *
22 * @package Packetery\Options
23 */
24 class Page {
25
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';
29
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 public const ACTION_VALIDATE_SENDER = 'validate-sender';
34
35 public const SLUG = 'packeta-options';
36
37 /**
38 * PacketeryLatte_engine.
39 *
40 * @var Engine PacketeryLatte engine.
41 */
42 private $latte_engine;
43
44 /**
45 * Options Provider
46 *
47 * @var Provider
48 */
49 private $optionsProvider;
50
51 /**
52 * Form factory.
53 *
54 * @var FormFactory Form factory.
55 */
56 private $formFactory;
57
58 /**
59 * Packeta client.
60 *
61 * @var \Packetery\Core\Api\Soap\Client
62 */
63 private $packetaClient;
64
65 /**
66 * Logger
67 *
68 * @var Log\ILogger
69 */
70 private $logger;
71
72 /**
73 * Message manager.
74 *
75 * @var MessageManager
76 */
77 private $messageManager;
78
79 /**
80 * HTTP request.
81 *
82 * @var \PacketeryNette\Http\Request
83 */
84 private $httpRequest;
85
86 /**
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.
96 */
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 }
106
107 /**
108 * Registers WP callbacks.
109 */
110 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', 'packeta' ),
115 __( 'Packeta', 'packeta' ),
116 'manage_options',
117 self::SLUG,
118 '',
119 $icon,
120 55 // todo Move item to last position in menu.
121 );
122 add_submenu_page(
123 self::SLUG,
124 __( 'Settings', 'packeta' ),
125 __( 'Settings', 'packeta' ),
126 'manage_options',
127 self::SLUG,
128 array(
129 $this,
130 'render',
131 ),
132 1
133 );
134 add_action( 'admin_init', [ $this, 'processActions' ] );
135 }
136
137 /**
138 * Sets default values.
139 */
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 );
145 }
146
147 /**
148 * Creates settings form.
149 *
150 * @return Form
151 */
152 private function create_form(): Form {
153 $form = $this->formFactory->create();
154 $form->setAction( 'options.php' );
155
156 $container = $form->addContainer( self::FORM_FIELDS_CONTAINER );
157 $container->addText( 'api_password', __( 'API password', 'packeta' ) )
158 ->setRequired()
159 ->addRule( $form::PATTERN, __( 'API password must be 32 characters long and must contain valid characters!', 'packeta' ), '[a-z\d]{32}' );
160 $container->addText( 'sender', __( 'Sender', 'packeta' ) )
161 ->setRequired();
162
163 $packetaLabelFormats = $this->optionsProvider->getPacketaLabelFormats();
164 $container->addSelect(
165 self::FORM_FIELD_PACKETA_LABEL_FORMAT,
166 __( 'Packeta Label Format', 'packeta' ),
167 $packetaLabelFormats
168 )->checkDefaultValue( false )->setDefaultValue( self::DEFAULT_VALUE_PACKETA_LABEL_FORMAT );
169
170 $carrierLabelFormats = $this->optionsProvider->getCarrierLabelFormat();
171 $container->addSelect(
172 self::FORM_FIELD_CARRIER_LABEL_FORMAT,
173 __( 'Carrier Label Format', 'packeta' ),
174 $carrierLabelFormats
175 )->checkDefaultValue( false )->setDefaultValue( self::DEFAULT_VALUE_CARRIER_LABEL_FORMAT );
176
177 $gateways = $this->getAvailablePaymentGateways();
178 $enabledGateways = [];
179 foreach ( $gateways as $gateway ) {
180 $enabledGateways[ $gateway->id ] = $gateway->get_method_title();
181 }
182 $container->addSelect(
183 'cod_payment_method',
184 __( 'Payment method that represents cash on delivery', 'packeta' ),
185 $enabledGateways
186 )->setPrompt( '--' )->checkDefaultValue( false );
187
188 $container->addText( 'packaging_weight', __( 'Packaging weight', 'packeta' ) . ' (kg)' )
189 ->setRequired( true )
190 ->addRule( Form::FLOAT )
191 ->addRule( Form::MIN, null, 0 )
192 ->setDefaultValue( 0 );
193
194 // TODO: Packet status sync.
195
196 $container->addCheckbox( 'replace_shipping_address_with_pickup_point_address', __( 'Replace shipping address with pickup point address', 'packeta' ) )
197 ->setRequired( false );
198
199 $container->addSelect(
200 'checkout_widget_button_location',
201 __( 'Widget button location in checkout', 'packeta' ),
202 [
203 'after_shipping_rate' => __( 'After shipping rate', 'packeta' ),
204 'after_transport_methods' => __( 'After transport methods', 'packeta' ),
205 ]
206 );
207
208 if ( $this->optionsProvider->has_any() ) {
209 $container->setDefaults( $this->optionsProvider->data_to_array() );
210 }
211
212 return $form;
213 }
214
215 /**
216 * Get available gateways.
217 *
218 * @return \WC_Payment_Gateway[]
219 */
220 public function getAvailablePaymentGateways(): array {
221 $availableGateways = [];
222
223 foreach ( WC()->payment_gateways()->payment_gateways() as $gateway ) {
224 if ( 'yes' === $gateway->enabled ) {
225 $availableGateways[ $gateway->id ] = $gateway;
226 }
227 }
228
229 /**
230 * Applies woocommerce_available_payment_gateways filters.
231 *
232 * @since 1.0.5
233 */
234 return array_filter( (array) apply_filters( 'woocommerce_available_payment_gateways', $availableGateways ), [ $this, 'filterValidGatewayClass' ] );
235 }
236
237 /**
238 * Callback for array filter. Returns true if gateway is of correct type.
239 *
240 * @param object $gateway Gateway to check.
241 * @return bool
242 */
243 protected function filterValidGatewayClass( object $gateway ): bool {
244 return ( $gateway instanceof \WC_Payment_Gateway );
245 }
246
247 /**
248 * Admin_init callback.
249 */
250 public function admin_init(): void {
251 register_setting( self::FORM_FIELDS_CONTAINER, self::FORM_FIELDS_CONTAINER, array( $this, 'options_validate' ) );
252 add_settings_section( 'packetery_main', __( 'Main Settings', 'packeta' ), '', self::SLUG );
253 }
254
255 /**
256 * Validates options.
257 *
258 * @param array $options Packetery_options.
259 *
260 * @return array
261 */
262 public function options_validate( array $options ): array {
263 $form = $this->create_form();
264 $form[ self::FORM_FIELDS_CONTAINER ]->setValues( $options );
265 if ( $form->isValid() === false ) {
266 foreach ( $form[ self::FORM_FIELDS_CONTAINER ]->getControls() as $control ) {
267 if ( $control->hasErrors() === false ) {
268 continue;
269 }
270
271 add_settings_error( $control->getCaption(), esc_attr( $control->getName() ), $control->getError() );
272 $options[ $control->getName() ] = '';
273 }
274 }
275
276 $api_password = $form[ self::FORM_FIELDS_CONTAINER ]['api_password'];
277 if ( $api_password->hasErrors() === false ) {
278 $api_pass = $api_password->getValue();
279 $options['api_key'] = substr( $api_pass, 0, 16 );
280 $this->packetaClient->setApiPassword( $api_pass );
281 } else {
282 $options['api_key'] = '';
283 }
284
285 $this->validateSender( $options['sender'] );
286
287 return $options;
288 }
289
290 /**
291 * Validates sender.
292 *
293 * @param string $senderLabel Sender lbel.
294 *
295 * @return bool|null
296 */
297 private function validateSender( string $senderLabel ): ?bool {
298 $senderValidationRequest = new SenderGetReturnRouting( $senderLabel );
299 $senderValidationResponse = $this->packetaClient->senderGetReturnRouting( $senderValidationRequest );
300
301 $senderValidationLog = new Log\Record();
302 $senderValidationLog->action = Log\Record::ACTION_SENDER_VALIDATION;
303
304 $senderValidationLog->status = Log\Record::STATUS_SUCCESS;
305 $senderValidationLog->title = __( 'Sender validation was successful', 'packeta' );
306
307 if ( $senderValidationResponse->hasFault() ) {
308 $senderValidationLog->status = Log\Record::STATUS_ERROR;
309 $senderValidationLog->params = [
310 'errorMessage' => $senderValidationResponse->getFaultString(),
311 ];
312 $senderValidationLog->title = __( 'Sender could not be validated', 'packeta' );
313 }
314
315 $this->logger->add( $senderValidationLog );
316
317 $senderExists = $senderValidationResponse->senderExists();
318
319 if ( false === $senderExists ) {
320 $this->messageManager->flash_message( __( 'Specified sender does not exist', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
321 }
322
323 if ( null === $senderExists ) {
324 $this->messageManager->flash_message( __( 'Unable to check specified sender', 'packeta' ), MessageManager::TYPE_INFO, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
325 }
326
327 return $senderExists;
328 }
329
330 /**
331 * Process actions.
332 *
333 * @return void
334 */
335 public function processActions(): void {
336 $action = $this->httpRequest->getQuery( 'action' );
337 if ( self::ACTION_VALIDATE_SENDER === $action ) {
338 $result = $this->validateSender( $this->optionsProvider->get_sender() );
339
340 if ( true === $result ) {
341 $this->messageManager->flash_message( __( 'Specified sender has been validated.', 'packeta' ), MessageManager::TYPE_SUCCESS, MessageManager::RENDERER_PACKETERY, 'plugin-options' );
342 }
343
344 $doRedirect = wp_safe_redirect(
345 add_query_arg(
346 [
347 'page' => self::SLUG,
348 ],
349 get_admin_url( null, 'admin.php' )
350 )
351 );
352
353 if ( $doRedirect ) {
354 exit;
355 }
356 }
357 }
358
359 /**
360 * Renders page.
361 */
362 public function render(): void {
363 $latteParams = [ 'form' => $this->create_form() ];
364 if ( ! extension_loaded( 'soap' ) ) {
365 $latteParams['error'] = __( 'This plugin requires an active SOAP library for proper operation. Contact your web hosting administrator.', 'packeta' );
366 }
367
368 $latteParams['apiPasswordLink'] = trim( $this->latte_engine->renderToString( PACKETERY_PLUGIN_DIR . '/template/options/help-block-link.latte', [ 'href' => 'https://client.packeta.com/support' ] ) );
369
370 $latteParams['senderDescription'] = sprintf(
371 /* translators: 1: emphasis start 2: emphasis end 3: client section link start 4: client section link end */
372 esc_html__( 'Fill here %1$ssender label%2$s - you will find it in %3$sclient section%4$s - user information - field \'Indication\'.', 'packeta' ),
373 '<strong>',
374 '</strong>',
375 '<a href="https://client.packeta.com/senders" target="_blank">',
376 '</a>'
377 );
378
379 $latteParams['exportLink'] = add_query_arg(
380 [
381 'page' => self::SLUG,
382 'action' => Exporter::ACTION_EXPORT_SETTINGS,
383 ],
384 get_admin_url( null, 'admin.php' )
385 );
386
387 $latteParams['canValidateSender'] = (bool) $this->optionsProvider->get_sender();
388 $latteParams['senderValidationLink'] = add_query_arg(
389 [
390 'page' => self::SLUG,
391 'action' => self::ACTION_VALIDATE_SENDER,
392 ],
393 get_admin_url( null, 'admin.php' )
394 );
395
396 $lastExport = null;
397 $lastExportOption = get_option( Exporter::OPTION_LAST_SETTINGS_EXPORT );
398 if ( false !== $lastExportOption ) {
399 $date = \DateTime::createFromFormat( DATE_ATOM, $lastExportOption );
400 if ( false !== $date ) {
401 $date->setTimezone( wp_timezone() );
402 $lastExport = $date->format( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );
403 }
404 }
405 if ( $lastExport ) {
406 $latteParams['lastExport'] = $lastExport;
407 }
408
409 $latteParams['messages'] = $this->messageManager->renderToString( MessageManager::RENDERER_PACKETERY, 'plugin-options' );
410 $latteParams['translations'] = [
411 'packeta' => __( 'Packeta', 'packeta' ),
412 'options' => __( 'Options', 'packeta' ),
413 'general' => __( 'General', 'packeta' ),
414 // translators: %s represents URL, keep intact.
415 'apiPasswordCanBeFoundAt%sUrl' => __( 'API password can be found at %s', 'packeta' ),
416 'saveChanges' => __( 'Save changes', 'packeta' ),
417 'validateSender' => __( 'Validate sender', 'packeta' ),
418 'support' => __( 'Support', 'packeta' ),
419 'optionsExportInfo1' => __(
420 '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:',
421 'packeta'
422 ),
423 'optionsExportInfo2' => __(
424 ') along with the description of your problem. For a better understanding of your problem, we recommend adding screenshots, which show the problem (if possible).',
425 'packeta'
426 ),
427 'exportPluginSettings' => __( 'Export the plugin settings', 'packeta' ),
428 'settingsExportDatetime' => __( 'Date and time of the last export of settings', 'packeta' ),
429 'settingsNotYetExported' => __( 'The settings have not been exported yet.', 'packeta' ),
430 ];
431
432 $this->latte_engine->render( PACKETERY_PLUGIN_DIR . '/template/options/page.latte', $latteParams );
433 }
434 }
435