PluginProbe
seQura / 3.0.7
seQura v3.0.7
4.3.4 4.3.3 4.3.2 4.3.1 trunk 2.0.0 2.0.10 2.0.11 2.0.12 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 3.0.0 3.0.2 3.0.5 3.0.6 3.0.7 3.1.0 3.1.1 3.2.0 3.2.1 3.2.2 4.0.0 All 30 releases
sequra / src / Controllers / Rest / class-onboarding-rest-controller.php

class-onboarding-rest-controller.php in seQura 3.0.7, at src/Controllers/Rest/class-onboarding-rest-controller.php

670 lines 25.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * REST Onboarding Controller
4 *
5 * @package SeQura/WC
6 * @subpackage SeQura/WC/Controllers/Rest
7 */
8
9 namespace SeQura\WC\Controllers\Rest;
10
11 use SeQura\Core\BusinessLogic\AdminAPI\AdminAPI;
12 use SeQura\Core\BusinessLogic\AdminAPI\Connection\Requests\ConnectionRequest;
13 use SeQura\Core\BusinessLogic\AdminAPI\Connection\Requests\OnboardingRequest;
14 use SeQura\Core\BusinessLogic\AdminAPI\CountryConfiguration\Requests\CountryConfigurationRequest;
15 use SeQura\WC\Core\Extension\BusinessLogic\AdminAPI\PromotionalWidgets\Requests\Widget_Settings_Request;
16 use SeQura\WC\Core\Extension\BusinessLogic\Domain\PromotionalWidgets\Models\Mini_Widget;
17 use SeQura\WC\Services\Interface_Logger_Service;
18 use WP_Error;
19 use WP_REST_Request;
20 use WP_REST_Response;
21
22 /**
23 * REST Onboarding Controller
24 */
25 class Onboarding_REST_Controller extends REST_Controller {
26
27 private const PARAM_ENVIRONMENT = 'environment';
28 private const PARAM_USERNAME = 'username';
29 private const PARAM_PASSWORD = 'password';
30 private const PARAM_SEND_STATISTICAL_DATA = 'sendStatisticalData';
31 private const PARAM_USE_WIDGETS = 'useWidgets';
32 private const PARAM_ASSETS_KEY = 'assetsKey';
33 private const PARAM_DISPLAY_WIDGET_ON_PRODUCT_PAGE = 'displayWidgetOnProductPage';
34 private const PARAM_SHOW_INSTALLMENT_AMOUNT_IN_PRODUCT_LISTING = 'showInstallmentAmountInProductListing';
35 private const PARAM_SHOW_INSTALLMENT_AMOUNT_IN_CART_PAGE = 'showInstallmentAmountInCartPage';
36 private const PARAM_MINI_WIDGET_SELECTOR = 'miniWidgetSelector';
37 private const PARAM_WIDGET_STYLES = 'widgetStyles';
38 private const PARAM_WIDGET_LABELS = 'widgetLabels';
39 private const PARAM_SEL_FOR_PRICE = 'selForPrice';
40 private const PARAM_SEL_FOR_ALT_PRICE = 'selForAltPrice';
41 private const PARAM_SEL_FOR_ALT_PRICE_TRIGGER = 'selForAltPriceTrigger';
42 private const PARAM_SEL_FOR_DEFAULT_LOCATION = 'selForDefaultLocation';
43 private const PARAM_CUSTOM_LOCATIONS = 'customLocations';
44 private const PARAM_CUSTOM_LOCATION_SEL_FOR_TARGET = 'selForTarget';
45 private const PARAM_CUSTOM_LOCATION_WIDGET_STYLES = 'widgetStyles';
46 private const PARAM_CUSTOM_LOCATION_DISPLAY_WIDGET = 'displayWidget';
47 private const PARAM_CUSTOM_LOCATION_COUNTRY = 'country';
48 private const PARAM_CUSTOM_LOCATION_PRODUCT = 'product';
49 private const PARAM_CUSTOM_LOCATION_CAMPAIGN = 'campaign';
50
51 // Cart widget config.
52 private const PARAM_CART_SEL_FOR_PRICE = 'selForCartPrice';
53 private const PARAM_CART_SEL_FOR_DEFAULT_LOCATION = 'selForCartLocation';
54 // Product listing widget config.
55 private const PARAM_LISTING_SEL_FOR_PRICE = 'selForListingPrice';
56 private const PARAM_LISTING_SEL_FOR_LOCATION = 'selForListingLocation';
57
58 /**
59 * Constructor.
60 *
61 * @param string $rest_namespace The namespace.
62 * @param Interface_Logger_Service $logger The logger service.
63 */
64 public function __construct( $rest_namespace, Interface_Logger_Service $logger ) {
65 parent::__construct( $logger );
66 $this->namespace = $rest_namespace;
67 $this->rest_base = '/onboarding';
68 }
69
70 /**
71 * Register the API endpoints.
72 *
73 * @return void
74 */
75 public function register_routes() {
76 $this->logger->log_debug( 'Hook executed', __FUNCTION__, __CLASS__ );
77 $store_id_args = array( self::PARAM_STORE_ID => $this->get_arg_string() );
78
79 $data_args = array_merge(
80 $store_id_args,
81 array(
82 self::PARAM_ENVIRONMENT => array_merge(
83 $this->get_arg_string(),
84 array( 'enum' => array( 'sandbox', 'production' ) )
85 ),
86 self::PARAM_USERNAME => $this->get_arg_string(),
87 self::PARAM_PASSWORD => $this->get_arg_string(),
88 self::PARAM_SEND_STATISTICAL_DATA => $this->get_arg_bool(),
89 )
90 );
91
92 $validate_data_args = array_merge(
93 $data_args,
94 array(
95 self::PARAM_MERCHANT_ID => $this->get_arg_string(),
96 )
97 );
98
99 $widget_args = array_merge(
100 $store_id_args,
101 array(
102 self::PARAM_USE_WIDGETS => $this->get_arg_bool(),
103 self::PARAM_ASSETS_KEY => $this->get_arg_string( true, '', array( $this, 'validate_assets_key' ) ),
104 self::PARAM_DISPLAY_WIDGET_ON_PRODUCT_PAGE => $this->get_arg_bool(),
105 self::PARAM_SHOW_INSTALLMENT_AMOUNT_IN_PRODUCT_LISTING => $this->get_arg_bool(),
106 self::PARAM_SHOW_INSTALLMENT_AMOUNT_IN_CART_PAGE => $this->get_arg_bool(),
107 self::PARAM_MINI_WIDGET_SELECTOR => $this->get_arg_string( true, '', '__return_true' ), // TODO: Add this field to form in the UI.
108 self::PARAM_WIDGET_STYLES => $this->get_arg_string(),
109 self::PARAM_WIDGET_LABELS => array(
110 'default' => array(
111 'message' => '',
112 'messageBelowLimit' => '',
113 ),
114 'required' => false,
115 'validate_callback' => array( $this, 'validate_widget_labels' ),
116 'sanitize_callback' => array( $this, 'sanitize_widget_labels' ),
117 ),
118 self::PARAM_SEL_FOR_PRICE => $this->get_arg_string( true, null, array( $this, 'validate_required_widget_selector' ) ),
119 self::PARAM_SEL_FOR_ALT_PRICE => $this->get_arg_string( true, null, array( $this, 'validate_optional_widget_selector' ) ),
120 self::PARAM_SEL_FOR_ALT_PRICE_TRIGGER => $this->get_arg_string( true, null, array( $this, 'validate_optional_widget_selector' ) ),
121 self::PARAM_SEL_FOR_DEFAULT_LOCATION => $this->get_arg_string( true, null, array( $this, 'validate_required_widget_selector' ) ),
122 self::PARAM_CUSTOM_LOCATIONS => $this->get_arg_widget_location_list(),
123
124 self::PARAM_CART_SEL_FOR_PRICE => $this->get_arg_string( true, null, array( $this, 'validate_required_cart_widget_selector' ) ),
125 self::PARAM_CART_SEL_FOR_DEFAULT_LOCATION => $this->get_arg_string( true, null, array( $this, 'validate_required_cart_widget_selector' ) ),
126
127 self::PARAM_LISTING_SEL_FOR_PRICE => $this->get_arg_string( true, null, array( $this, 'validate_required_listing_widget_selector' ) ),
128 self::PARAM_LISTING_SEL_FOR_LOCATION => $this->get_arg_string( true, null, array( $this, 'validate_required_listing_widget_selector' ) ),
129 )
130 );
131
132 $store_id = $this->url_param_pattern( self::PARAM_STORE_ID );
133
134 $this->register_get( "data/{$store_id}", 'get_connection_data', $store_id_args );
135 $this->register_post( "data/{$store_id}", 'save_connection_data', $data_args );
136 $this->register_post( "data/validate/{$store_id}", 'validate_connection_data', $validate_data_args );
137 $this->register_post( "data/disconnect/{$store_id}", 'disconnect', $store_id_args );
138
139 $this->register_get( "widgets/{$store_id}", 'get_widgets', $store_id_args );
140 $this->register_post( "widgets/{$store_id}", 'save_widgets', $widget_args );
141
142 $this->register_get( "countries/selling/{$store_id}", 'get_selling_countries', $store_id_args );
143 $this->register_get( "countries/{$store_id}", 'get_countries', $store_id_args );
144 $this->register_post( "countries/{$store_id}", 'save_countries', $store_id_args );
145 }
146
147 /**
148 * Get connection data.
149 *
150 * @param WP_REST_Request $request The request.
151 *
152 * @return WP_REST_Response|WP_Error
153 */
154 public function get_connection_data( WP_REST_Request $request ) {
155 $response = null;
156 try {
157 $response = AdminAPI::get()
158 ->connection( strval( $request->get_param( self::PARAM_STORE_ID ) ) )
159 ->getOnboardingData()
160 ->toArray();
161 } catch ( \Throwable $e ) {
162 $this->logger->log_throwable( $e, __FUNCTION__, __CLASS__ );
163 $response = new WP_Error( 'error', $e->getMessage() );
164 }
165 return \rest_ensure_response( $response );
166 }
167
168 /**
169 * Validate connection data before saving.
170 *
171 * @param WP_REST_Request $request The request.
172 *
173 * @return WP_REST_Response|WP_Error
174 */
175 public function validate_connection_data( WP_REST_Request $request ) {
176 $response = null;
177 try {
178 $response = AdminAPI::get()
179 ->connection( strval( $request->get_param( self::PARAM_STORE_ID ) ) )
180 ->isConnectionDataValid(
181 new ConnectionRequest(
182 strval( $request->get_param( self::PARAM_ENVIRONMENT ) ),
183 strval( $request->get_param( self::PARAM_MERCHANT_ID ) ),
184 strval( $request->get_param( self::PARAM_USERNAME ) ),
185 strval( $request->get_param( self::PARAM_PASSWORD ) )
186 )
187 );
188 $response = $response->toArray();
189 } catch ( \Throwable $e ) {
190 $this->logger->log_throwable( $e, __FUNCTION__, __CLASS__ );
191 $response = new WP_Error( 'error', $e->getMessage() );
192 }
193 return \rest_ensure_response( $response );
194 }
195
196 /**
197 * Check if the assets key is valid.
198 *
199 * @param mixed $param The parameter.
200 * @param WP_REST_Request $request The request.
201 * @param string $key The key.
202 */
203 public function validate_assets_key( $param, $request, $key ): bool {
204 return is_string( $param )
205 && ( ! boolval( $request->get_param( self::PARAM_USE_WIDGETS ) ) || '' !== trim( $param ) );
206 }
207
208 /**
209 * Save connection data.
210 *
211 * @throws \Exception
212 * @param WP_REST_Request $request The request.
213 *
214 * @return WP_REST_Response|WP_Error
215 */
216 public function save_connection_data( WP_REST_Request $request ) {
217 $response = null;
218 try {
219 $response = AdminAPI::get()
220 ->connection( strval( $request->get_param( self::PARAM_STORE_ID ) ) )
221 ->saveOnboardingData(
222 new OnboardingRequest(
223 strval( $request->get_param( self::PARAM_ENVIRONMENT ) ),
224 strval( $request->get_param( self::PARAM_USERNAME ) ),
225 strval( $request->get_param( self::PARAM_PASSWORD ) ),
226 (bool) $request->get_param( self::PARAM_SEND_STATISTICAL_DATA ),
227 null === $request->get_param( self::PARAM_MERCHANT_ID ) ? null : strval( $request->get_param( self::PARAM_MERCHANT_ID ) )
228 )
229 );
230
231 $is_ok = $response->isSuccessful();
232 $response = $response->toArray();
233
234 if ( ! $is_ok ) {
235 throw new \Exception( $response['errorMessage'] );
236 }
237 } catch ( \Throwable $e ) {
238 $this->logger->log_throwable( $e, __FUNCTION__, __CLASS__ );
239 $response = new WP_Error( 'error', $e->getMessage() );
240 }
241 return \rest_ensure_response( $response );
242 }
243
244 /**
245 * Disconnects integration from the shop.
246 *
247 * @param WP_REST_Request $request The request.
248 *
249 * @return WP_REST_Response|WP_Error
250 */
251 public function disconnect( WP_REST_Request $request ) {
252 $response = null;
253 try {
254 $response = AdminAPI::get()
255 ->disconnect( strval( $request->get_param( self::PARAM_STORE_ID ) ) )
256 ->disconnect()
257 ->toArray();
258 } catch ( \Throwable $e ) {
259 $this->logger->log_throwable( $e, __FUNCTION__, __CLASS__ );
260 $response = new WP_Error( 'error', $e->getMessage() );
261 }
262 return \rest_ensure_response( $response );
263 }
264
265 /**
266 * GET selling countries.
267 *
268 * @param WP_REST_Request $request The request.
269 *
270 * @return WP_REST_Response|WP_Error
271 */
272 public function get_selling_countries( WP_REST_Request $request ) {
273 $response = null;
274 try {
275 $response = AdminAPI::get()
276 ->countryConfiguration( strval( $request->get_param( self::PARAM_STORE_ID ) ) )
277 ->getSellingCountries()
278 ->toArray();
279 } catch ( \Throwable $e ) {
280 $this->logger->log_throwable( $e, __FUNCTION__, __CLASS__ );
281 $response = new WP_Error( 'error', $e->getMessage() );
282 }
283 return \rest_ensure_response( $response );
284 }
285
286 /**
287 * GET countries.
288 *
289 * @param WP_REST_Request $request The request.
290 *
291 * @return WP_REST_Response|WP_Error
292 */
293 public function get_countries( WP_REST_Request $request ) {
294 $response = null;
295 try {
296 $response = AdminAPI::get()
297 ->countryConfiguration( strval( $request->get_param( self::PARAM_STORE_ID ) ) )
298 ->getCountryConfigurations()
299 ->toArray();
300 } catch ( \Throwable $e ) {
301 $this->logger->log_throwable( $e, __FUNCTION__, __CLASS__ );
302 $response = new WP_Error( 'error', $e->getMessage() );
303 }
304 return \rest_ensure_response( $response );
305 }
306
307 /**
308 * Save countries.
309 *
310 * @throws \Exception
311 * @param WP_REST_Request $request The request.
312 *
313 * @return WP_REST_Response|WP_Error
314 */
315 public function save_countries( WP_REST_Request $request ) {
316 if ( ! $this->validate_countries( $request ) ) {
317 return new WP_REST_Response( 'Invalid data', 400 );
318 }
319
320 $response = null;
321 try {
322 /**
323 * Data
324 *
325 * @var array<int, array<string, string>> $data The data.
326 */
327 $data = (array) json_decode( $request->get_body(), true );
328
329 $response = AdminAPI::get()
330 ->countryConfiguration( strval( $request->get_param( self::PARAM_STORE_ID ) ) )
331 ->saveCountryConfigurations( new CountryConfigurationRequest( $data ) )
332 ->toArray();
333 } catch ( \Throwable $e ) {
334 $this->logger->log_throwable( $e, __FUNCTION__, __CLASS__ );
335 $response = new WP_Error( 'error', $e->getMessage() );
336 }
337 return \rest_ensure_response( $response );
338 }
339
340 /**
341 * GET widgets.
342 *
343 * @param WP_REST_Request $request The request.
344 *
345 * @return WP_REST_Response|WP_Error
346 */
347 public function get_widgets( WP_REST_Request $request ) {
348 $response = null;
349 try {
350 $response = AdminAPI::get()
351 ->widgetConfiguration( strval( $request->get_param( self::PARAM_STORE_ID ) ) )
352 ->getWidgetSettings()
353 ->toArray();
354
355 if ( ! empty( $response ) ) {
356 $response[ self::PARAM_WIDGET_LABELS ]['message'] = ! empty( $response[ self::PARAM_WIDGET_LABELS ]['messages'] ) ?
357 reset( $response[ self::PARAM_WIDGET_LABELS ]['messages'] ) : '';
358 $response[ self::PARAM_WIDGET_LABELS ]['messageBelowLimit'] = ! empty( $response[ self::PARAM_WIDGET_LABELS ]['messagesBelowLimit'] ) ?
359 reset( $response[ self::PARAM_WIDGET_LABELS ]['messagesBelowLimit'] ) : '';
360 $response[ self::PARAM_WIDGET_STYLES ] = $response['widgetConfiguration'];
361 unset( $response[ self::PARAM_WIDGET_LABELS ]['messages'], $response[ self::PARAM_WIDGET_LABELS ]['messagesBelowLimit'] );
362 unset( $response['widgetConfiguration'] );
363 }
364 } catch ( \Throwable $e ) {
365 $this->logger->log_throwable( $e, __FUNCTION__, __CLASS__ );
366 $response = new WP_Error( 'error', $e->getMessage() );
367 }
368 return \rest_ensure_response( $response );
369 }
370
371 /**
372 * Save countries.
373 *
374 * @throws \Exception
375 * @param WP_REST_Request $request The request.
376 *
377 * @return WP_REST_Response|WP_Error
378 */
379 public function save_widgets( WP_REST_Request $request ) {
380 $response = null;
381 try {
382 //phpcs:disable Squiz.Commenting.InlineComment.InvalidEndChar
383 // $labels = $request->get_param( 'widgetLabels' );
384 // $messages = $labels['message'] ? array( $storeConfig->getLocale() => $labels['message'] ) : array();
385 // $messages_below_limit = $labels['messageBelowLimit'] ? array( $storeConfig->getLocale() => $labels['messageBelowLimit'] ) : array();
386 //phpcs:enable
387 $messages = array();
388 $messages_below_limit = array();
389
390 $store_id = strval( $request->get_param( self::PARAM_STORE_ID ) );
391
392 /**
393 * Filter the cart mini widgets.
394 *
395 * @since 3.0.0
396 * @var Mini_Widget[] $cart_mini_widgets The cart mini widgets.
397 */
398 $cart_mini_widgets = \apply_filters( 'sequra_widget_settings_cart_mini_widgets', array(), $store_id );
399 if ( ! is_array( $cart_mini_widgets ) ) {
400 $this->logger->log_debug( 'Invalid cart mini widgets. ' . Mini_Widget::class . '[] is expected', __FUNCTION__, __CLASS__ );
401 $cart_mini_widgets = array();
402 }
403 foreach ( $cart_mini_widgets as $mini_widget ) {
404 if ( ! $mini_widget instanceof Mini_Widget ) {
405 $this->logger->log_debug( 'Invalid cart mini widgets. ' . Mini_Widget::class . '[] is expected', __FUNCTION__, __CLASS__ );
406 $cart_mini_widgets = array();
407 break;
408 }
409 }
410
411 /**
412 * Filter the product listing mini widgets.
413 *
414 * @since 3.0.0
415 * @var Mini_Widget[] $listing_mini_widgets The product listing mini widgets.
416 */
417 $listing_mini_widgets = \apply_filters( 'sequra_widget_settings_product_listing_mini_widgets', array(), $store_id );
418 if ( ! is_array( $listing_mini_widgets ) ) {
419 $this->logger->log_debug( 'Invalid product listing mini widgets. ' . Mini_Widget::class . '[] is expected', __FUNCTION__, __CLASS__ );
420 $listing_mini_widgets = array();
421 }
422 foreach ( $listing_mini_widgets as $mini_widget ) {
423 if ( ! $mini_widget instanceof Mini_Widget ) {
424 $this->logger->log_debug( 'Invalid product listing mini widgets. ' . Mini_Widget::class . '[] is expected', __FUNCTION__, __CLASS__ );
425 $listing_mini_widgets = array();
426 break;
427 }
428 }
429
430 $response = AdminAPI::get()
431 ->widgetConfiguration( $store_id )
432 ->setWidgetSettings(
433 new Widget_Settings_Request(
434 (bool) $request->get_param( self::PARAM_USE_WIDGETS ),
435 null === $request->get_param( self::PARAM_ASSETS_KEY ) ? null : strval( $request->get_param( self::PARAM_ASSETS_KEY ) ),
436 (bool) $request->get_param( self::PARAM_DISPLAY_WIDGET_ON_PRODUCT_PAGE ),
437 (bool) $request->get_param( self::PARAM_SHOW_INSTALLMENT_AMOUNT_IN_PRODUCT_LISTING ),
438 (bool) $request->get_param( self::PARAM_SHOW_INSTALLMENT_AMOUNT_IN_CART_PAGE ),
439 strval( $request->get_param( self::PARAM_MINI_WIDGET_SELECTOR ) ),
440 strval( $request->get_param( self::PARAM_WIDGET_STYLES ) ),
441 (array) $messages,
442 (array) $messages_below_limit,
443 strval( $request->get_param( self::PARAM_SEL_FOR_PRICE ) ),
444 strval( $request->get_param( self::PARAM_SEL_FOR_ALT_PRICE ) ),
445 strval( $request->get_param( self::PARAM_SEL_FOR_ALT_PRICE_TRIGGER ) ),
446 strval( $request->get_param( self::PARAM_SEL_FOR_DEFAULT_LOCATION ) ),
447 (array) $request->get_param( self::PARAM_CUSTOM_LOCATIONS ),
448 strval( $request->get_param( self::PARAM_CART_SEL_FOR_PRICE ) ),
449 strval( $request->get_param( self::PARAM_CART_SEL_FOR_DEFAULT_LOCATION ) ),
450 $cart_mini_widgets,
451 strval( $request->get_param( self::PARAM_LISTING_SEL_FOR_PRICE ) ),
452 strval( $request->get_param( self::PARAM_LISTING_SEL_FOR_LOCATION ) ),
453 $listing_mini_widgets
454 )
455 )
456 ->toArray();
457 } catch ( \Throwable $e ) {
458 $this->logger->log_throwable( $e, __FUNCTION__, __CLASS__ );
459 $response = new WP_Error( 'error', $e->getMessage() );
460 }
461 return \rest_ensure_response( $response );
462 }
463
464 /**
465 * Validate if countries payload is valid.
466 *
467 * @param WP_REST_Request $request The request.
468 */
469 public function validate_countries( WP_REST_Request $request ): bool {
470 try {
471 $data = json_decode( $request->get_body(), true );
472 if ( ! is_array( $data ) ) {
473 return false;
474 }
475 $allowed_countries = AdminAPI::get()
476 ->countryConfiguration( strval( $request->get_param( self::PARAM_STORE_ID ) ) )
477 ->getSellingCountries()
478 ->toArray();
479
480 $allowed_countries = array_column( $allowed_countries, 'code' );
481
482 foreach ( $data as $country ) {
483 if ( ! isset( $country['countryCode'] )
484 || ! isset( $country['merchantId'] )
485 || ! is_string( $country['countryCode'] )
486 || ! is_string( $country['merchantId'] )
487 || ! in_array( $country['countryCode'], $allowed_countries, true )
488 ) {
489 return false;
490 }
491 }
492 } catch ( \Throwable $e ) {
493 return false;
494 }
495 return true;
496 }
497
498 /**
499 * Validate if widget label is valid.
500 *
501 * @param mixed $param The parameter.
502 * @param WP_REST_Request $request The request.
503 * @param string $key The key.
504 */
505 public function validate_widget_labels( $param, $request, $key ): bool {
506 return is_array( $param )
507 && isset( $param['message'] )
508 && is_string( $param['message'] )
509 && isset( $param['messageBelowLimit'] )
510 && is_string( $param['messageBelowLimit'] );
511 }
512
513 /**
514 * Validate if required selector is valid.
515 *
516 * @param mixed $param The parameter.
517 */
518 private function validate_required_selector( string $dependant_param_key, $param, WP_REST_Request $request, string $key ): bool {
519
520 $use_widgets = (bool) $request->get_param( $dependant_param_key );
521 if ( ! $use_widgets ) {
522 return null === $param || is_string( $param );
523 }
524
525 return null !== $param
526 && is_string( $param )
527 && '' !== trim( $param );
528 }
529
530 /**
531 * Validate if required widget selector is valid.
532 *
533 * @param mixed $param The param.
534 */
535 public function validate_required_widget_selector( $param, WP_REST_Request $request, string $key ): bool {
536 return $this->validate_required_selector( self::PARAM_USE_WIDGETS, $param, $request, $key );
537 }
538
539 /**
540 * Validate if required cart widget selector is valid.
541 *
542 * @param mixed $param The param.
543 */
544 public function validate_required_cart_widget_selector( $param, WP_REST_Request $request, string $key ): bool {
545 return $this->validate_required_selector( self::PARAM_SHOW_INSTALLMENT_AMOUNT_IN_CART_PAGE, $param, $request, $key );
546 }
547
548 /**
549 * Validate if required listing widget selector is valid.
550 *
551 * @param mixed $param The param.
552 */
553 public function validate_required_listing_widget_selector( $param, WP_REST_Request $request, string $key ): bool {
554 return $this->validate_required_selector( self::PARAM_SHOW_INSTALLMENT_AMOUNT_IN_PRODUCT_LISTING, $param, $request, $key );
555 }
556
557 /**
558 * Validate if optional widget selector is valid.
559 *
560 * @param mixed $param The parameter.
561 * @param WP_REST_Request $request The request.
562 * @param string $key The key.
563 */
564 public function validate_optional_widget_selector( $param, $request, $key ): bool {
565 return null === $param || is_string( $param );
566 }
567
568 /**
569 * Sanitize widget label.
570 *
571 * @param mixed[] $param The parameter.
572 * @return mixed[]
573 */
574 public function sanitize_widget_labels( $param ): array {
575 return array(
576 'message' => \sanitize_text_field( strval( $param['message'] ) ),
577 'messageBelowLimit' => \sanitize_text_field( strval( $param['messageBelowLimit'] ) ),
578 );
579 }
580
581 /**
582 * Get argument structure for the widget location list.
583 *
584 * @param bool $required If the argument is required.
585 * @param mixed $default_value The default value. Null will be ignored.
586 * @param callable $validate The validate callback. Leave null to use the default.
587 * @param callable $sanitize The sanitize callback. Leave null to use the default.
588 * @return mixed[]
589 */
590 protected function get_arg_widget_location_list( $required = true, $default_value = array(), $validate = null, $sanitize = null ): array {
591 return array_merge(
592 $this->get_arg( $required, $default_value ),
593 array(
594 'validate_callback' => null === $validate ? array( $this, 'validate_widget_location_list' ) : $validate,
595 'sanitize_callback' => null === $sanitize ? array( $this, 'sanitize_widget_location_list' ) : $sanitize,
596 )
597 );
598 }
599
600 /**
601 * Validate if widget location list is valid.
602 *
603 * @param mixed $param The parameter.
604 * @param WP_REST_Request $request The request.
605 * @param string $key The key.
606 */
607 public function validate_widget_location_list( $param, $request, $key ): bool {
608 if ( ! is_array( $param ) ) {
609 return false;
610 }
611 foreach ( $param as $location ) {
612 if ( ! isset(
613 $location[ self::PARAM_CUSTOM_LOCATION_SEL_FOR_TARGET ],
614 $location[ self::PARAM_CUSTOM_LOCATION_PRODUCT ],
615 $location[ self::PARAM_CUSTOM_LOCATION_COUNTRY ],
616 $location[ self::PARAM_CUSTOM_LOCATION_WIDGET_STYLES ],
617 $location[ self::PARAM_CUSTOM_LOCATION_DISPLAY_WIDGET ]
618 )
619 || ! is_string( $location[ self::PARAM_CUSTOM_LOCATION_SEL_FOR_TARGET ] )
620 || ! is_string( $location[ self::PARAM_CUSTOM_LOCATION_PRODUCT ] )
621 || ! is_string( $location[ self::PARAM_CUSTOM_LOCATION_COUNTRY ] )
622 || ! is_string( $location[ self::PARAM_CUSTOM_LOCATION_WIDGET_STYLES ] )
623 || ! is_bool( $location[ self::PARAM_CUSTOM_LOCATION_DISPLAY_WIDGET ] )
624 || empty( $location[ self::PARAM_CUSTOM_LOCATION_PRODUCT ] )
625 || empty( $location[ self::PARAM_CUSTOM_LOCATION_COUNTRY ] )
626 ) {
627 return false;
628 }
629
630 // check if exists another location with the same country title and product.
631 $country = $location[ self::PARAM_CUSTOM_LOCATION_COUNTRY ];
632 $product = $location[ self::PARAM_CUSTOM_LOCATION_PRODUCT ];
633 $campaign = $location[ self::PARAM_CUSTOM_LOCATION_CAMPAIGN ] ?? null;
634 $found = \array_filter(
635 $param,
636 function ( $loc ) use ( $country, $product, $campaign ) {
637 return isset( $loc[ self::PARAM_CUSTOM_LOCATION_PRODUCT ], $loc[ self::PARAM_CUSTOM_LOCATION_COUNTRY ] )
638 && $loc[ self::PARAM_CUSTOM_LOCATION_COUNTRY ] === $country
639 && $loc[ self::PARAM_CUSTOM_LOCATION_PRODUCT ] === $product
640 && ( $loc[ self::PARAM_CUSTOM_LOCATION_CAMPAIGN ] ?? null ) === $campaign;
641 }
642 );
643 if ( count( $found ) > 1 ) {
644 return false;
645 }
646 }
647 return true;
648 }
649
650 /**
651 * Sanitize widget location list.
652 *
653 * @param array<int, array<string, string>> $param The parameter.
654 * @return array<int, array<string, string>>
655 */
656 public function sanitize_widget_location_list( $param ): array {
657 foreach ( $param as &$location ) {
658 $location = array(
659 self::PARAM_CUSTOM_LOCATION_SEL_FOR_TARGET => \sanitize_text_field( strval( $location[ self::PARAM_CUSTOM_LOCATION_SEL_FOR_TARGET ] ) ),
660 self::PARAM_CUSTOM_LOCATION_PRODUCT => \sanitize_text_field( strval( $location[ self::PARAM_CUSTOM_LOCATION_PRODUCT ] ) ),
661 self::PARAM_CUSTOM_LOCATION_COUNTRY => \sanitize_text_field( strval( $location[ self::PARAM_CUSTOM_LOCATION_COUNTRY ] ) ),
662 self::PARAM_CUSTOM_LOCATION_CAMPAIGN => isset( $location[ self::PARAM_CUSTOM_LOCATION_CAMPAIGN ] ) ? \sanitize_text_field( strval( $location[ self::PARAM_CUSTOM_LOCATION_CAMPAIGN ] ) ) : null,
663 self::PARAM_CUSTOM_LOCATION_WIDGET_STYLES => \sanitize_text_field( strval( $location[ self::PARAM_CUSTOM_LOCATION_WIDGET_STYLES ] ) ),
664 self::PARAM_CUSTOM_LOCATION_DISPLAY_WIDGET => (bool) $location[ self::PARAM_CUSTOM_LOCATION_DISPLAY_WIDGET ],
665 );
666 }
667 return $param;
668 }
669 }
670