PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 2.3.2
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v2.3.2
2.3.2 2.3.1 2.3.0 2.2.8 2.2.7 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.11.0 1.11.1 1.11.2 1.6 1.7 1.8 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 1.9.10 1.9.11 All 60 releases
← All changes | admin/classes/class-merchant-admin-options.php +453 -1609 1.8.22.3.2 View file →
@@ -1,1609 +1,453 @@
1 -<?php
2 -/**
3 - * Merchant_Admin_Options Class.
4 - */
5 -
6 -if ( ! defined( 'ABSPATH' ) ) {
7 - exit; // Exit if accessed directly
8 -}
9 -
10 -if ( ! class_exists( 'Merchant_Admin_Options' ) ) {
11 - class Merchant_Admin_Options {
12 -
13 - /**
14 - * The single class instance.
15 - */
16 - private static $instance = null;
17 -
18 - /**
19 - * Instance.
20 - */
21 - public static function instance() {
22 - if ( is_null( self::$instance ) ) {
23 - self::$instance = new self();
24 - }
25 -
26 - return self::$instance;
27 - }
28 -
29 - /**
30 - * Constructor.
31 - */
32 - public function __construct() {
33 - // Enqueue hooks.
34 - add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
35 -
36 - // Ajax callbacks.
37 - add_action( 'wp_ajax_merchant_create_page_control', array( $this, 'create_page_control_ajax_callback' ) );
38 - add_action( 'wp_ajax_merchant_admin_options_select_ajax', array( $this, 'select_content_ajax' ) );
39 - }
40 -
41 - /**
42 - * Enqueue scripts.
43 - */
44 - public function enqueue_scripts() {
45 - if (
46 - isset( $_GET['page'] ) && 'merchant' === $_GET['page'] // phpcs:ignore WordPress.Security.NonceVerification.Recommended
47 - && isset( $_GET['module'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
48 - ) {
49 - wp_enqueue_script( 'merchant-select2', MERCHANT_URI . 'assets/vendor/select2/select2.full.min.js', array( 'jquery' ), '4.0.13', true );
50 - wp_enqueue_style( 'merchant-select2', MERCHANT_URI . 'assets/vendor/select2/select2.min.css', array(), '4.0.13', 'all' );
51 -
52 - wp_localize_script( 'merchant-select2', 'merchant_admin_options', array(
53 - 'ajaxurl' => admin_url( 'admin-ajax.php' ),
54 - 'ajaxnonce' => wp_create_nonce( 'merchant_admin_options' ),
55 - ) );
56 - }
57 - }
58 -
59 - /**
60 - * Ajax callbacks.
61 - */
62 - public function create_page_control_ajax_callback() {
63 - check_ajax_referer( 'customize-create-page-control-nonce', 'nonce' );
64 -
65 - // Check current user capabilities
66 - if ( ! current_user_can( 'manage_options' ) ) {
67 - wp_send_json_error( 'You are not allowed to do this.' );
68 - }
69 -
70 - $page_title = isset( $_POST['page_title'] ) ? sanitize_text_field( $_POST['page_title'] ) : '';
71 - $page_meta_key = isset( $_POST['page_meta_key'] ) ? sanitize_text_field( $_POST['page_meta_key'] ) : '';
72 - $page_meta_value = isset( $_POST['page_meta_value'] ) ? sanitize_text_field( $_POST['page_meta_value'] ) : '';
73 - $option_name = isset( $_POST['option_name'] ) ? sanitize_text_field( $_POST['option_name'] ) : '';
74 -
75 - $meta_input = array();
76 - if ( $page_meta_key && $page_meta_value ) {
77 - $meta_input = array(
78 - $page_meta_key => $page_meta_value,
79 - );
80 - }
81 -
82 - $postarr = array(
83 - 'post_type' => 'page',
84 - 'post_status' => 'publish',
85 - 'post_title' => $page_title,
86 - 'post_content' => '',
87 - 'meta_input' => $meta_input,
88 - );
89 -
90 - $page_id = wp_insert_post( $postarr );
91 -
92 - if ( ! is_wp_error( $page_id ) ) {
93 - if ( $option_name ) {
94 - update_option( $option_name, $page_id );
95 - }
96 -
97 - wp_send_json( array(
98 - 'status' => 'success',
99 - 'page_id' => $page_id,
100 - ) );
101 - } else {
102 - wp_send_json( array(
103 - 'status' => 'error',
104 - ) );
105 - }
106 - }
107 -
108 - /**
109 - * Select content ajax callback.
110 - *
111 - */
112 - public function select_content_ajax() {
113 - $term = ( isset( $_GET['term'] ) ) ? sanitize_text_field( wp_unslash( $_GET['term'] ) ) : '';
114 - $nonce = ( isset( $_GET['nonce'] ) ) ? sanitize_text_field( wp_unslash( $_GET['nonce'] ) ) : '';
115 - $source = ( isset( $_GET['source'] ) ) ? sanitize_text_field( wp_unslash( $_GET['source'] ) ) : '';
116 -
117 - // Check current user capabilities
118 - if ( ! current_user_can( 'manage_options' ) ) {
119 - wp_send_json_error( 'You are not allowed to do this.' );
120 - }
121 -
122 - if ( ! empty( $term ) && ! empty( $source ) && ! empty( $nonce ) && wp_verify_nonce( $nonce, 'merchant_admin_options' ) ) {
123 - $options = array();
124 -
125 - switch ( $source ) {
126 - case 'post':
127 - case 'product':
128 - $query = new WP_Query( array(
129 - 's' => $term,
130 - 'post_type' => $source,
131 - 'post_status' => 'publish',
132 - 'posts_per_page' => 25,
133 - 'order' => 'DESC',
134 - ) );
135 -
136 - if ( ! empty( $query->posts ) ) {
137 - foreach ( $query->posts as $post ) {
138 - $options[] = array(
139 - 'id' => $post->ID,
140 - 'text' => $post->post_title,
141 - );
142 - }
143 - }
144 -
145 - break;
146 - }
147 -
148 - wp_send_json_success( $options );
149 - } else {
150 - wp_send_json_error();
151 - }
152 - }
153 -
154 - /**
155 - * Get option.
156 - */
157 - public static function get( $module, $setting, $default_val ) {
158 - $options = get_option( 'merchant', array() );
159 -
160 - $value = $default_val;
161 -
162 - if ( isset( $options[ $module ] ) && isset( $options[ $module ][ $setting ] ) ) {
163 - $value = $options[ $module ][ $setting ];
164 - }
165 -
166 - return $value;
167 - }
168 -
169 - /**
170 - * Get all options.
171 - */
172 - public static function get_all( $module ) {
173 - $options = get_option( 'merchant', array() );
174 - $value = array();
175 -
176 - if ( isset( $options[ $module ] ) ) {
177 - $value = $options[ $module ];
178 - }
179 -
180 - return $value;
181 - }
182 -
183 - /**
184 - * Create options.
185 - */
186 - public static function create( $settings ) {
187 - /**
188 - * Hook: merchant_module_settings
189 - *
190 - * @since 1.0
191 - */
192 - $settings = apply_filters( 'merchant_module_settings', $settings );
193 -
194 - self::save_options( $settings );
195 -
196 - $options = get_option( 'merchant', array() );
197 -
198 - ?>
199 - <div class="merchant-module-page-settings">
200 - <div class="merchant-module-page-setting-box">
201 - <?php
202 - if ( ! empty( $settings['title'] ) ) : ?>
203 - <div class="merchant-module-page-setting-title">
204 - <?php
205 - echo esc_html( $settings['title'] ); ?>
206 - <?php
207 - if ( ! empty( $settings['subtitle'] ) ) : ?>
208 - <div class="merchant-module-page-setting-subtitle"><?php
209 - echo esc_html( $settings['subtitle'] ); ?></div>
210 - <?php
211 - endif; ?>
212 - </div>
213 - <?php
214 - endif; ?>
215 - <div class="merchant-module-page-setting-fields">
216 - <?php
217 -
218 - if ( ! empty( $settings['fields'] ) ) {
219 - foreach ( $settings['fields'] as $field ) {
220 - $value = null;
221 -
222 - if ( isset( $field['default'] ) ) {
223 - $value = $field['default'];
224 - }
225 -
226 - if ( isset( $field['id'] ) && isset( $options[ $settings['module'] ] ) && isset( $options[ $settings['module'] ][ $field['id'] ] ) ) {
227 - $value = $options[ $settings['module'] ][ $field['id'] ];
228 - }
229 -
230 - $module_info = Merchant_Admin_Modules::get_module_info( $settings['module'] );
231 - if ( ( $module_info && $module_info['pro'] ) && ! defined( 'MERCHANT_PRO_DIR' ) ) {
232 - self::disabled_field( $field, $value );
233 - } else {
234 - self::field( $field, $value );
235 - }
236 - }
237 - }
238 -
239 - ?>
240 - </div>
241 - </div>
242 - </div>
243 - <?php
244 - }
245 -
246 - /**
247 - * Save options.
248 - */
249 - public static function save_options( $settings ) {
250 - $save = ( isset( $_POST['merchant_save'] ) ) ? sanitize_text_field( wp_unslash( $_POST['merchant_save'] ) ) : '';
251 - $reset = ( isset( $_POST['merchant_reset'] ) ) ? sanitize_text_field( wp_unslash( $_POST['merchant_reset'] ) ) : '';
252 - $nonce = ( isset( $_POST['merchant_nonce'] ) ) ? sanitize_text_field( wp_unslash( $_POST['merchant_nonce'] ) ) : '';
253 -
254 - if ( ! wp_verify_nonce( $nonce, 'merchant_nonce' ) ) {
255 - return;
256 - }
257 -
258 - if ( ! current_user_can( 'manage_options' ) ) {
259 - return;
260 - }
261 -
262 - $options = get_option( 'merchant', array() );
263 -
264 - if ( ! empty( $save ) ) {
265 - if ( ! empty( $settings['fields'] ) ) {
266 - foreach ( $settings['fields'] as $field ) {
267 - if ( ! isset( $field['id'] ) ) {
268 - continue;
269 - }
270 -
271 - $value = null;
272 -
273 - if ( isset( $_POST['merchant'] ) && isset( $_POST['merchant'][ $field['id'] ] ) ) {
274 - if ( 'textarea_code' === $field['type'] ) {
275 - $value = wp_kses( $_POST['merchant'][ $field['id'] ], merchant_kses_allowed_tags_for_code_snippets() );
276 - } elseif ( 'textarea_multiline' === $field['type'] ) {
277 - $value = sanitize_textarea_field( $_POST['merchant'][ $field['id'] ] );
278 - } elseif ( is_array( $_POST['merchant'][ $field['id'] ] ) ) {
279 - $value = array_filter( map_deep( wp_unslash( $_POST['merchant'][ $field['id'] ] ), 'sanitize_text_field' ) );
280 - } else {
281 - $value = sanitize_text_field( wp_unslash( $_POST['merchant'][ $field['id'] ] ) );
282 - }
283 - }
284 -
285 -
286 - $options[ $settings['module'] ][ $field['id'] ] = self::sanitize( $field, $value );
287 - }
288 - }
289 - } elseif ( ! empty( $reset ) ) {
290 - $options[ $settings['module'] ] = array();
291 - }
292 -
293 - update_option( 'merchant', $options );
294 - }
295 -
296 - /**
297 - * Sanitize options.
298 - */
299 - public static function sanitize( $field, $value ) {
300 - // Callback for custom sanitize methods.
301 - if ( ! empty( $field['sanitize'] ) && is_callable( $field['sanitize'] ) ) {
302 - return call_user_func( $field['sanitize'], $value );
303 - }
304 -
305 - switch ( $field['type'] ) {
306 - case 'text':
307 - case 'color':
308 - case 'number':
309 - case 'select_size_chart':
310 - $value = sanitize_text_field( $value );
311 - break;
312 -
313 - case 'textarea':
314 - $value = sanitize_textarea_field( $value );
315 - break;
316 -
317 - case 'textarea_code':
318 - $value = $value;
319 - break;
320 -
321 - case 'checkbox':
322 - case 'switcher':
323 - $value = ( '1' === $value ) ? 1 : 0;
324 - break;
325 -
326 - case 'range':
327 - case 'number':
328 - $value = absint( $value );
329 - break;
330 - case 'select_ajax':
331 - if ( is_array( $value ) && ! empty( $value ) ) {
332 - $value = array_filter( array_map( 'sanitize_text_field', $value ) );
333 - } elseif ( is_string( $value ) ) {
334 - $value = sanitize_text_field( $value );
335 - } else {
336 - $value = isset( $field['multiple'] ) && $field['multiple'] === false ? '' : array();
337 - }
338 - break;
339 - case 'radio':
340 - case 'radio_alt':
341 - case 'select':
342 - case 'choices':
343 - case 'buttons':
344 - case 'buttons_alt':
345 - $value = ( in_array( $value, array_keys( $field['options'] ), true ) ) ? sanitize_key( $value ) : '';
346 - break;
347 -
348 - case 'hook_select':
349 - $value = is_array( $value ) ? $value : array();
350 -
351 - foreach ( $value as $key => $val ) {
352 - if ( $key === 'hook_name' ) {
353 - $value[ $key ] = in_array( $val, array_keys( $field['options'] ), true ) ? sanitize_key( $val ) : '';
354 - } else {
355 - $value[ $key ] = (int) $val;
356 - }
357 - }
358 -
359 - break;
360 -
361 - case 'code-editor':
362 - $value = wp_kses_post( $value );
363 - break;
364 -
365 - case 'sortable':
366 - $values = json_decode( $value );
367 - $value = array();
368 -
369 - foreach ( $values as $val ) {
370 - if ( in_array( $val, array_keys( $field['options'] ), true ) ) {
371 - $value[] = sanitize_key( $val );
372 - }
373 - }
374 - break;
375 - case 'dimensions':
376 - $values = is_array( $value ) ? $value : array();
377 -
378 - foreach ( $values as $key => $val ) {
379 - if ( $key === 'unit' ) {
380 - $value[ $key ] = sanitize_key( $value[ $key ] );
381 - } else {
382 - $value[ $key ] = absint( $value[ $key ] );
383 - }
384 - }
385 - break;
386 - case 'responsive_dimensions':
387 - $values = is_array( $value ) ? $value : array();
388 -
389 - foreach ( $values as $device => $device_fields ) {
390 - foreach ( $device_fields as $device_field => $device_field_val ) {
391 - if ( $device_field === 'unit' ) {
392 - $value[ $device ][ $device_field ] = sanitize_key( $device_field_val );
393 - } else {
394 - $value[ $device ][ $device_field ] = absint( $device_field_val );
395 - }
396 - }
397 - }
398 - break;
399 -
400 - case 'sortable_repeater':
401 - $values = json_decode( $value );
402 - $value = array_map( 'sanitize_text_field', $values );
403 - break;
404 - case 'flexible_content':
405 - $value = ! is_array( $value ) || empty( $value ) ? array() : $value;
406 -
407 - $value = array_map( function ( $sub_fields ) use ( $field ) {
408 - foreach ( $sub_fields as $sub_field => $value ) {
409 - if ( $sub_field === 'layout' ) {
410 - $sub_fields[ $sub_field ] = sanitize_text_field( $value );
411 - } else {
412 - $layout_field = array_filter( $field['layouts'][ $sub_fields['layout'] ]['fields'], function ( $layout_field ) use ( $sub_field ) {
413 - return $layout_field['id'] === $sub_field;
414 - } );
415 -
416 -
417 - $sub_fields[ $sub_field ] = self::sanitize( reset( $layout_field ), $value );
418 - }
419 - }
420 -
421 - return $sub_fields;
422 - }, $value );
423 -
424 - break;
425 - }
426 -
427 - return $value;
428 - }
429 -
430 - /**
431 - * Field
432 - */
433 - public static function field( $settings, $value ) {
434 - if ( ! empty( $settings['type'] ) ) {
435 - $type = $settings['type'];
436 -
437 - $id = ( ! empty( $settings['id'] ) ) ? $settings['id'] : '';
438 - $class = ( ! empty( $settings['class'] ) ) ? ' ' . $settings['class'] : '';
439 - $condition = ( ! empty( $settings['condition'] ) ) ? $settings['condition'] : array();
440 - $default = ( ! empty( $settings['default'] ) ) ? $settings['default'] : null;
441 -
442 - if ( ! $value && 0 !== $value ) {
443 - $value = $default;
444 - }
445 -
446 - echo '<div class="merchant-module-page-setting-field merchant-module-page-setting-field-' . esc_attr( $type ) . '' . esc_attr( $class ) . '" data-id="'
447 - . esc_attr( $id ) . '" data-type="' . esc_attr( $type ) . '" data-condition="' . esc_attr( wp_json_encode( $condition ) ) . '">';
448 - if ( ! empty( $settings['title'] ) ) {
449 - printf( '<div class="merchant-module-page-setting-field-title">%s</div>', esc_html( $settings['title'] ) );
450 - }
451 -
452 - echo '<div class="merchant-module-page-setting-field-inner">';
453 - if ( method_exists( 'Merchant_Admin_Options', $type ) ) {
454 - call_user_func( array( 'Merchant_Admin_Options', $type ), $settings, $value );
455 - } else {
456 - esc_html_e( 'Field not found!', 'merchant' );
457 - }
458 - echo '</div>';
459 -
460 - if ( ! empty( $settings['desc'] ) ) {
461 - printf( '<div class="merchant-module-page-setting-field-desc">%s</div>', wp_kses_post( $settings['desc'] ) );
462 - }
463 -
464 - echo '</div>';
465 - }
466 - }
467 -
468 - /**
469 - * Disabled field
470 - *
471 - * @param array $settings
472 - * @param mixed $value
473 - *
474 - * @return void
475 - */
476 - public static function disabled_field( $settings, $value ) {
477 - static::replace_field(
478 - $settings,
479 - $value,
480 - array(
481 - '<input ',
482 - '<select ',
483 - 'merchant-module-page-setting-field-inner',
484 - ),
485 - array(
486 - '<input disabled ',
487 - '<select disabled ',
488 - 'merchant-module-page-setting-field-inner disabled',
489 - )
490 - );
491 - }
492 -
493 - /**
494 - * Modified field.
495 - *
496 - * @param $settings
497 - * @param $value
498 - * @param $search
499 - * @param $replace
500 - *
501 - * @return void
502 - */
503 - public static function replace_field( $settings, $value, $search, $replace ) {
504 - ob_start();
505 - self::field( $settings, $value );
506 - $field = ob_get_clean();
507 -
508 - echo wp_kses( str_replace( $search, $replace, $field ), merchant_kses_allowed_tags( array( 'all' ) ) );
509 - }
510 -
511 - /**
512 - * Field: Text
513 - */
514 - public static function text( $settings, $value ) {
515 - ?>
516 - <input type="text" name="merchant[<?php
517 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
518 - echo esc_attr( $value ); ?>"/>
519 - <?php
520 - }
521 -
522 - /**
523 - * Field: Text (readonly)
524 - */
525 - public static function text_readonly( $settings, $value ) {
526 - ?>
527 - <input type="text" value="<?php
528 - echo esc_attr( $value ); ?>" readonly/>
529 - <?php
530 - }
531 -
532 - /**
533 - * Field: Number
534 - */
535 - public static function number( $settings, $value ) {
536 - ?>
537 - <input type="number" name="merchant[<?php
538 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
539 - echo esc_attr( $value ); ?>"/>
540 - <?php
541 - }
542 -
543 - /**
544 - * Field: Textarea
545 - */
546 - public static function textarea( $settings, $value ) {
547 - $value = ( $value ) ? $value : '';
548 - ?>
549 - <textarea name="merchant[<?php
550 - echo esc_attr( $settings['id'] ); ?>]"><?php
551 - echo wp_kses_post( $value ); ?></textarea>
552 - <?php
553 - }
554 -
555 - /**
556 - * Field: Textarea
557 - */
558 - public static function textarea_multiline( $settings, $value ) {
559 - $value = ( $value ) ? $value : '';
560 - ?>
561 - <textarea name="merchant[<?php
562 - echo esc_attr( $settings['id'] ); ?>]"><?php
563 - echo wp_kses_post( $value ); ?></textarea>
564 - <?php
565 - }
566 -
567 - /**
568 - * Field: Textarea Code Snippet.
569 - */
570 - public static function textarea_code( $settings, $value ) {
571 - $value = ( $value ) ? $value : '';
572 - ?>
573 - <textarea name="merchant[<?php
574 - echo esc_attr( $settings['id'] ); ?>]"><?php
575 - echo wp_kses( $value, merchant_kses_allowed_tags_for_code_snippets() ); ?></textarea>
576 - <?php
577 - }
578 -
579 - /**
580 - * Field: Checkbox
581 - */
582 - public static function checkbox( $settings, $value ) {
583 - ?>
584 - <div>
585 - <label>
586 - <input type="checkbox" name="merchant[<?php
587 - echo esc_attr( $settings['id'] ); ?>]" value="1" <?php
588 - checked( $value, 1, true ); ?> />
589 - <?php
590 - if ( ! empty( $settings['label'] ) ) : ?>
591 - <span><?php
592 - echo esc_html( $settings['label'] ); ?></span>
593 - <?php
594 - endif; ?>
595 - </label>
596 - </div>
597 - <?php
598 - }
599 -
600 - /**
601 - * Field: Switcher
602 - */
603 - public static function switcher( $settings, $value ) {
604 - ?>
605 - <div class="merchant-toggle-switch">
606 - <input type="checkbox" id="<?php
607 - echo esc_attr( $settings['id'] ); ?>" name="merchant[<?php
608 - echo esc_attr( $settings['id'] ); ?>]" value="1" <?php
609 - checked( $value, 1, true ); ?>
610 - class="toggle-switch-checkbox"/>
611 - <label class="toggle-switch-label" for="<?php
612 - echo esc_attr( $settings['id'] ); ?>">
613 - <span class="toggle-switch-inner"></span>
614 - <span class="toggle-switch-switch"></span>
615 - </label>
616 - <?php
617 - if ( ! empty( $settings['label'] ) ) : ?>
618 - <span><?php
619 - echo esc_html( $settings['label'] ); ?></span>
620 - <?php
621 - endif; ?>
622 - </div>
623 - <?php
624 - }
625 -
626 - /**
627 - * Field: Radio
628 - */
629 - public static function radio( $settings, $value ) {
630 - ?>
631 - <?php
632 - if ( ! empty( $settings['options'] ) ) : ?>
633 - <?php
634 - foreach ( $settings['options'] as $key => $option ) : ?>
635 - <label>
636 - <input type="radio" name="merchant[<?php
637 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
638 - echo esc_attr( $key ); ?>" <?php
639 - checked( $value, $key, true ); ?>/>
640 - <span><?php
641 - echo esc_html( $option ); ?></span>
642 - </label>
643 - <?php
644 - endforeach; ?>
645 - <?php
646 - endif; ?>
647 - <?php
648 - }
649 -
650 - /**
651 - * Field: Radio Alt
652 - */
653 - public static function radio_alt( $settings, $value ) {
654 - ?>
655 - <?php
656 - if ( ! empty( $settings['options'] ) ) : ?>
657 - <?php
658 - foreach ( $settings['options'] as $key => $option ) : ?>
659 - <div>
660 - <label>
661 - <input type="radio" name="merchant[<?php
662 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
663 - echo esc_attr( $key ); ?>" <?php
664 - checked( $value, $key, true ); ?>/>
665 - <span><?php
666 - echo esc_html( $option['title'] ); ?></span>
667 - </label>
668 - <p><?php
669 - echo esc_html( $option['desc'] ); ?></p>
670 - </div>
671 - <?php
672 - endforeach; ?>
673 - <?php
674 - endif; ?>
675 - <?php
676 - }
677 -
678 - /**
679 - * Field: Choices
680 - */
681 - public static function choices( $settings, $value ) {
682 - ?>
683 - <div class="merchant-choices merchant-choices-<?php
684 - echo esc_attr( $settings['id'] ) ?>">
685 - <?php
686 - if ( ! empty( $settings['options'] ) ) : ?>
687 - <?php
688 - foreach ( $settings['options'] as $key => $option ) : ?>
689 - <label>
690 - <input type="radio" name="merchant[<?php
691 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
692 - echo esc_attr( $key ); ?>" <?php
693 - checked( $value, $key, true ); ?>/>
694 - <?php
695 - if ( ! empty( $option['svg'] ) ) : ?>
696 - <span class="merchant-svg">
697 - <?php
698 - echo wp_kses( Merchant_SVG_Icons::get_svg_icon( $option['svg'] ), merchant_kses_allowed_tags( array(), false ) ); ?>
699 -
700 - <?php
701 - if ( ! empty( $option['label'] ) ) : ?>
702 - <span class="merchant-tooltip"><?php
703 - echo esc_html( $option['label'] ); ?></span>
704 - <?php
705 - endif; ?>
706 - </span>
707 - <?php
708 - else : ?>
709 - <figure>
710 - <?php
711 - if ( ! empty( $option['image'] ) ) : ?>
712 - <img src="<?php
713 - echo esc_url( sprintf( $option['image'], MERCHANT_URI . 'assets/images' ) ); ?>"/>
714 - <?php
715 - else : ?>
716 - <img src="<?php
717 - echo esc_url( sprintf( $option, MERCHANT_URI . 'assets/images' ) ); ?>"/>
718 - <?php
719 - endif; ?>
720 - <?php
721 - if ( ! empty( $option['label'] ) ) : ?>
722 - <span class="merchant-tooltip"><?php
723 - echo esc_html( $option['label'] ); ?></span>
724 - <?php
725 - endif; ?>
726 - </figure>
727 - <?php
728 - endif; ?>
729 - </label>
730 - <?php
731 - endforeach; ?>
732 - <?php
733 - endif; ?>
734 - </div>
735 - <?php
736 - }
737 -
738 - /**
739 - * Field: Select
740 - */
741 - public static function select( $settings, $value ) {
742 - ?>
743 - <?php
744 - if ( ! empty( $settings['options'] ) ) : ?>
745 - <select name="merchant[<?php
746 - echo esc_attr( $settings['id'] ); ?>]">
747 - <?php
748 - foreach ( $settings['options'] as $key => $option ) : ?>
749 - <option value="<?php
750 - echo esc_attr( $key ); ?>" <?php
751 - selected( $value, $key, true ); ?>><?php
752 - echo esc_html( $option ); ?></option>
753 - <?php
754 - endforeach; ?>
755 - </select>
756 - <?php
757 - endif; ?>
758 - <?php
759 - }
760 -
761 - /**
762 - * Field: Hook Select
763 - */
764 - public static function hook_select( $settings, $value ) {
765 - $hook_name = isset( $value['hook_name'] ) ? $value['hook_name'] : '';
766 - $hook_priority = isset( $value['hook_priority'] ) ? $value['hook_priority'] : '';
767 -
768 - ?>
769 - <div class="merchant-module-page-setting-field-hook_select-wrapper">
770 - <div class="merchant-module-page-setting-field-select">
771 - <select name="merchant[<?php
772 - echo esc_attr( $settings['id'] ); ?>][hook_name]">
773 - <?php
774 - if ( ! empty( $settings['options'] ) ) : ?>
775 - <?php
776 - foreach ( $settings['options'] as $key => $option ) : ?>
777 - <option value="<?php
778 - echo esc_attr( $key ); ?>" <?php
779 - selected( $hook_name, $key, true ); ?>><?php
780 - echo esc_html( $option ); ?></option>
781 - <?php
782 - endforeach; ?>
783 - <?php
784 - endif; ?>
785 - </select>
786 - </div>
787 - <?php
788 -
789 - if ( isset( $settings['order'] ) && true === $settings['order'] ) {
790 - ?>
791 - <div class="merchant-module-page-setting-field-number">
792 - <input type="number" name="merchant[<?php
793 - echo esc_attr( $settings['id'] ); ?>][hook_priority]" value="<?php
794 - echo esc_attr( $hook_priority ); ?>"/>
795 - </div>
796 - <?php
797 - } ?>
798 - </div>
799 -
800 - <?php
801 - }
802 -
803 - /**
804 - * Field: Select ajax
805 - *
806 - * @param $settings
807 - * @param $value
808 - *
809 - * @return void
810 - */
811 - public static function select_ajax( $settings, $value ) {
812 - $settings = wp_parse_args( $settings, array(
813 - 'source' => 'post',
814 - ) );
815 -
816 - $ids = ( is_array( $value ) && ! empty( $value ) ) ? $value : (array) $value;
817 -
818 - if ( isset( $settings['multiple'] ) ) {
819 - $multiple = $settings['multiple'] === true ? 'multiple' : '';
820 - } else {
821 - $multiple = 'multiple';
822 - }
823 - ?>
824 - <select name="merchant[<?php
825 - echo esc_attr( $settings['id'] ); ?>]" <?php
826 - echo esc_attr( $multiple ) ?> data-source="<?php
827 - echo esc_attr( $settings['source'] ) ?>">
828 - <?php
829 - if ( ! empty( $ids ) ) {
830 - foreach ( $ids as $id ) {
831 - switch ( $settings['source'] ) {
832 - case 'post':
833 - case 'product':
834 - $post = get_post( $id );
835 -
836 - if ( ! empty( $post ) ) {
837 - echo '<option value="' . esc_attr( $post->ID ) . '" selected>' . esc_html( $post->post_title ) . '</option>';
838 - }
839 - break;
840 - case 'options':
841 - }
842 - }
843 - }
844 - if ( $settings['source'] === 'options' ) {
845 - $value = ! empty( $value ) ? $value : '';
846 -
847 - foreach ( $settings['options'] as $option ) {
848 - if ( isset( $option['options'] ) ) {
849 - echo '<optgroup label="' . esc_attr( $option['text'] ) . '">';
850 -
851 - foreach ( $option['options'] as $child_option ) {
852 - echo '<option value="' . esc_attr( $child_option['id'] ) . '" ' . selected( $child_option['id'], $value ) . '>' . esc_html( $child_option['text'] )
853 - . '</option>';
854 - }
855 -
856 - echo '</optgroup>';
857 - } else {
858 - echo '<option value="' . esc_attr( $option['id'] ) . '" ' . selected( $option['id'], $value ) . '>' . esc_html( $option['text'] ) . '</option>';
859 - }
860 - }
861 - } ?>
862 - </select>
863 - <?php
864 - }
865 -
866 - /**
867 - * Field: Select Size Chart
868 - */
869 - public static function select_size_chart( $settings, $value ) {
870 - $options = array(
871 - '' => esc_html__( 'Default', 'merchant' ),
872 - );
873 -
874 - $posts = get_posts( array(
875 - 'post_type' => 'merchant_size_chart',
876 - 'posts_per_page' => - 1,
877 - 'post_status' => 'publish',
878 - ) );
879 -
880 - if ( ! is_wp_error( $posts ) && ! empty( $posts ) ) {
881 - foreach ( $posts as $_post ) {
882 - $options[ $_post->ID ] = $_post->post_title;
883 - }
884 - }
885 -
886 - ?>
887 - <?php
888 - if ( ! empty( $options ) ) : ?>
889 - <select name="merchant[<?php
890 - echo esc_attr( $settings['id'] ); ?>]">
891 - <?php
892 - foreach ( $options as $key => $option ) : ?>
893 - <option value="<?php
894 - echo esc_attr( $key ); ?>" <?php
895 - selected( $value, $key, true ); ?>><?php
896 - echo esc_html( $option ); ?></option>
897 - <?php
898 - endforeach; ?>
899 - </select>
900 - <?php
901 - endif; ?>
902 - <?php
903 - }
904 -
905 - /**
906 - * Field: Buttons
907 - */
908 - public static function buttons( $settings, $value ) {
909 - ?>
910 - <div class="merchant-buttons">
911 - <?php
912 - if ( ! empty( $settings['options'] ) ) : ?>
913 - <?php
914 - foreach ( $settings['options'] as $key => $option ) : ?>
915 - <label class="merchant-button-<?php
916 - echo esc_attr( $key ); ?>"">
917 - <input type="radio" name="merchant[<?php
918 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
919 - echo esc_attr( $key ); ?>" <?php
920 - checked( $value, $key, true ); ?>/>
921 - <span><?php
922 - echo esc_html( $option ); ?></span>
923 - </label>
924 - <?php
925 - endforeach; ?>
926 - <?php
927 - endif; ?>
928 - </div>
929 - <?php
930 - }
931 -
932 - /**
933 - * Field: Buttons Alt
934 - */
935 - public static function buttons_alt( $settings, $value ) {
936 - ?>
937 - <div class="merchant-buttons">
938 - <?php
939 - if ( ! empty( $settings['options'] ) ) : ?>
940 - <?php
941 - foreach ( $settings['options'] as $key => $option ) : ?>
942 - <label class="merchant-button-<?php
943 - echo esc_attr( $key ); ?>">
944 - <input type="radio" name="merchant[<?php
945 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
946 - echo esc_attr( $key ); ?>" <?php
947 - checked( $value, $key, true ); ?>/>
948 - <span><?php
949 - echo esc_html( $option ); ?></span>
950 - </label>
951 - <?php
952 - endforeach; ?>
953 - <?php
954 - endif; ?>
955 - </div>
956 - <?php
957 - }
958 -
959 - /**
960 - * Field: Range
961 - */
962 - public static function range( $settings, $value ) {
963 - $settings = wp_parse_args( $settings, array(
964 - 'min' => '',
965 - 'max' => '',
966 - 'step' => '',
967 - 'unit' => '',
968 - ) );
969 -
970 - ?>
971 - <div class="merchant-range">
972 - <input type="range" class="merchant-range-input" name="" min="<?php
973 - echo esc_attr( $settings['min'] ); ?>" max="<?php
974 - echo esc_attr( $settings['max'] ); ?>"
975 - step="<?php
976 - echo esc_attr( $settings['step'] ); ?>" value="<?php
977 - echo esc_attr( $value ); ?>"/>
978 - <input type="number" class="merchant-range-number-input" name="merchant[<?php
979 - echo esc_attr( $settings['id'] ); ?>]" min="<?php
980 - echo esc_attr( $settings['min'] ); ?>"
981 - max="<?php
982 - echo esc_attr( $settings['max'] ); ?>" step="<?php
983 - echo esc_attr( $settings['step'] ); ?>" value="<?php
984 - echo esc_attr( $value ); ?>"/>
985 - <?php
986 - if ( ! empty( $settings['unit'] ) ) : ?>
987 - <span class="merchant-range-unit"><?php
988 - echo esc_html( $settings['unit'] ); ?></span>
989 - <?php
990 - endif; ?>
991 - </div>
992 - <?php
993 - }
994 -
995 - /**
996 - * Field: Color
997 - */
998 - public static function color( $settings, $value ) {
999 - $settings = wp_parse_args( $settings, array(
1000 - 'default' => '#212121',
1001 - ) );
1002 -
1003 - ?>
1004 - <div class="merchant-color">
1005 - <div class="merchant-color-picker" data-default-color="<?php
1006 - echo esc_attr( $settings['default'] ); ?>" style="background-color: <?php
1007 - echo esc_attr( $value ); ?>;"></div>
1008 - <input type="text" class="merchant-color-input" name="merchant[<?php
1009 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
1010 - echo esc_attr( $value ); ?>"/>
1011 - </div>
1012 - <?php
1013 - }
1014 -
1015 - /**
1016 - * Field: Gallery
1017 - */
1018 - public static function gallery( $settings, $value ) {
1019 - $settings = wp_parse_args( $settings, array(
1020 - 'label' => esc_html__( 'Select Images', 'merchant' ),
1021 - ) );
1022 -
1023 - $images = ( ! empty( $value ) ) ? explode( ',', $value ) : array();
1024 -
1025 -
1026 - echo '<div class="merchant-gallery-images">';
1027 -
1028 - if ( ! empty( $images ) ) :
1029 -
1030 - foreach ( $images as $image_id ) :
1031 -
1032 - $image = wp_get_attachment_image_src( $image_id, 'thumbnail' );
1033 -
1034 - if ( ! empty( $image ) && ! empty( $image[0] ) ) :
1035 -
1036 - printf( '<div class="merchant-gallery-image" data-item-id="%s">', esc_attr( $image_id ) );
1037 -
1038 - echo '<i class="merchant-gallery-remove dashicons dashicons-no-alt"></i>';
1039 -
1040 - printf( '<img src="%s" />', esc_url( $image[0] ) );
1041 -
1042 - echo '</div>';
1043 -
1044 - endif;
1045 -
1046 - endforeach;
1047 -
1048 - endif;
1049 -
1050 - echo '</div>';
1051 -
1052 - ?>
1053 - <a href="#" class="merchant-gallery-button"><?php
1054 - echo esc_html( $settings['label'] ); ?></a>
1055 - <input type="hidden" class="merchant-gallery-input" name="merchant[<?php
1056 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
1057 - echo esc_attr( $value ); ?>"/>
1058 - <?php
1059 - }
1060 -
1061 - /**
1062 - * Field: Upload
1063 - */
1064 - public static function upload( $settings, $value ) {
1065 - $settings = wp_parse_args( $settings, array(
1066 - 'label' => esc_html__( 'Select Image', 'merchant' ),
1067 - ) );
1068 -
1069 - echo '<div class="merchant-upload-wrapper">';
1070 -
1071 - if ( ! empty( $value ) ) :
1072 -
1073 - $image = wp_get_attachment_image_src( $value, 'thumbnail' );
1074 -
1075 - if ( ! empty( $image ) && ! empty( $image[0] ) ) :
1076 -
1077 - echo '<div class="merchant-upload-image">';
1078 - echo '<i class="merchant-upload-remove dashicons dashicons-no-alt"></i>';
1079 - printf( '<img src="%s" />', esc_url( $image[0] ) );
1080 - echo '</div>';
1081 -
1082 - endif;
1083 -
1084 - endif;
1085 -
1086 - echo '</div>';
1087 -
1088 - ?>
1089 - <a href="#" class="merchant-upload-button"><?php
1090 - echo esc_html( $settings['label'] ); ?></a>
1091 - <input type="hidden" class="merchant-upload-input" name="merchant[<?php
1092 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
1093 - echo esc_attr( $value ); ?>"/>
1094 - <?php
1095 - }
1096 -
1097 - /**
1098 - * Field: Warning
1099 - */
1100 - public static function warning( $settings ) {
1101 - echo wp_kses_post( $settings['content'] );
1102 - }
1103 -
1104 - /**
1105 - * Field: Warning
1106 - */
1107 - public static function info( $settings ) {
1108 - echo wp_kses_post( $settings['content'] );
1109 - }
1110 -
1111 - /**
1112 - * Field: Divider
1113 - */
1114 - public static function divider() {
1115 - }
1116 -
1117 - /**
1118 - * Field: Content
1119 - */
1120 - public static function content( $settings ) {
1121 - echo wp_kses_post( $settings['content'] );
1122 - }
1123 -
1124 - /**
1125 - * Field: Sortable
1126 - */
1127 - public static function sortable( $settings, $value ) {
1128 - ?>
1129 - <div class="merchant-sortable">
1130 - <ul class="merchant-sortable-list ui-sortable">
1131 - <?php
1132 - foreach ( $value as $option_key ) :
1133 - $option_val = $settings['options'][ $option_key ];
1134 -
1135 - if ( in_array( $option_key, $value, true ) ) :
1136 - ?>
1137 - <li class="merchant-sortable-item" data-value="<?php
1138 - echo esc_attr( $option_key ); ?>">
1139 - <i class='dashicons dashicons-menu'></i>
1140 - <i class="dashicons dashicons-visibility visibility"></i>
1141 - <?php
1142 - echo esc_html( $option_val ); ?>
1143 - </li>
1144 - <?php
1145 - endif; ?>
1146 - <?php
1147 - endforeach; ?>
1148 -
1149 - <?php
1150 - foreach ( $settings['options'] as $option_key => $option_val ) :
1151 - if ( ! in_array( $option_key, $value, true ) ) :
1152 - $invisible = ! in_array( $option_key, $value, true ) ? ' invisible' : '';
1153 -
1154 - ?>
1155 - <li class="merchant-sortable-item<?php
1156 - echo esc_attr( $invisible ); ?>" data-value="<?php
1157 - echo esc_attr( $option_key ); ?>">
1158 - <i class='dashicons dashicons-menu'></i>
1159 - <i class="dashicons dashicons-visibility visibility"></i>
1160 - <?php
1161 - echo esc_html( $option_val ); ?>
1162 - </li>
1163 - <?php
1164 - endif; ?>
1165 - <?php
1166 - endforeach; ?>
1167 - </ul>
1168 -
1169 - <input class="merchant-sortable-input" type="hidden" name="merchant[<?php
1170 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
1171 - echo esc_attr( wp_json_encode( $value ) ); ?>"/>
1172 - </div>
1173 - <?php
1174 - }
1175 -
1176 - /**
1177 - * Field: Sortable Repeater.
1178 - */
1179 - public static function sortable_repeater( $settings, $value ) {
1180 - ?>
1181 - <div class="merchant-sortable-repeater-control<?php
1182 - echo isset( $settings['sorting'] ) && false === $settings['sorting'] ? ' disable-sorting' : ''; ?>">
1183 - <div class="merchant-sortable-repeater sortable regular-field">
1184 - <div class="repeater">
1185 - <input type="text" value="" class="repeater-input"/><span class="dashicons dashicons-menu"></span><a class="customize-control-sortable-repeater-delete"
1186 - href="#"><span
1187 - class="dashicons dashicons-no-alt"></span></a>
1188 - </div>
1189 - </div>
1190 - <button class="button customize-control-sortable-repeater-add" type="button"><?php
1191 - echo esc_html( $settings['button_label'] ); ?></button>
1192 - <input class="merchant-sortable-repeater-input" type="hidden" name="merchant[<?php
1193 - echo esc_attr( $settings['id'] ); ?>]" value="<?php
1194 - echo esc_attr( wp_json_encode( $value ) ); ?>"/>
1195 - </div>
1196 - <?php
1197 - }
1198 -
1199 - /**
1200 - * Field: Flexible Content.
1201 - *
1202 - * @param array $settings
1203 - * @param mixed $value
1204 - *
1205 - * @return void
1206 - */
1207 - public static function flexible_content( $settings, $value ) {
1208 - $values = ( is_array( $value ) && ! empty( $value ) ) ? $value : array();
1209 - $empty = empty( $values ) ? 'empty' : '';
1210 -
1211 - $settings = wp_parse_args( $settings, array(
1212 - 'sorting' => false,
1213 - 'style' => 'default',
1214 - ) );
1215 -
1216 - $classes = array(
1217 - 'merchant-flexible-content-control',
1218 - "{$settings['style']}-style",
1219 - );
1220 -
1221 - if ( $settings['sorting'] === false ) {
1222 - $classes[] = 'disable-sorting';
1223 - }
1224 - ?>
1225 - <div class="<?php
1226 - echo esc_attr( implode( ' ', $classes ) ); ?>"
1227 - data-id="<?php
1228 - echo esc_attr( $settings['id'] ) ?>">
1229 -
1230 - <div class="layouts" data-id="<?php
1231 - echo esc_attr( $settings['id'] ) ?>">
1232 -
1233 - <?php
1234 - foreach ( $settings['layouts'] as $layout_type => $layout ) : ?>
1235 -
1236 - <div class="layout" data-type="<?php
1237 - echo esc_attr( $layout_type ) ?>">
1238 - <div class="layout-header">
1239 - <div class="layout-count">1</div>
1240 - <div class="layout-title">
1241 - <?php
1242 - echo esc_html( $layout['title'] ) ?>
1243 - </div>
1244 - <div class="layout-actions">
1245 - <span class="customize-control-flexible-content-move dashicons dashicons-menu"></span>
1246 - <a class="customize-control-flexible-content-delete" href="#">
1247 - <span class="dashicons dashicons-no-alt"></span>
1248 - </a>
1249 - </div>
1250 - </div>
1251 - <div class="layout-body">
1252 - <?php
1253 - foreach ( $layout['fields'] as $sub_field ) :
1254 - $classes = array( 'layout-field' );
1255 -
1256 - if ( isset( $sub_field['classes'] ) ) {
1257 - $classes = array_merge( $classes, $sub_field['classes'] );
1258 - } ?>
1259 - <div class="<?php
1260 - echo esc_attr( implode( ' ', $classes ) ); ?>">
1261 - <?php
1262 - static::replace_field( $sub_field,
1263 - '',
1264 - array(
1265 - "name=\"merchant[{$sub_field['id']}]",
1266 - 'merchant-module-page-setting-field-upload',
1267 - 'merchant-module-page-setting-field-select_ajax',
1268 - ),
1269 - array(
1270 - "data-name=\"merchant[{$settings['id']}][0][{$sub_field['id']}]",
1271 - 'merchant-module-page-setting-field-upload template',
1272 - 'merchant-module-page-setting-field-select_ajax template',
1273 - ) ) ?>
1274 - </div>
1275 - <?php
1276 - endforeach; ?>
1277 - <input type="hidden" data-name="merchant[<?php
1278 - echo esc_attr( $settings['id'] ) ?>][0][layout]" value="<?php
1279 - echo esc_attr( $layout_type ) ?>">
1280 - </div>
1281 - </div>
1282 -
1283 - <?php
1284 - endforeach; ?>
1285 -
1286 - </div>
1287 -
1288 - <div class="merchant-flexible-content <?php
1289 - echo esc_attr( $empty ); ?> sortable">
1290 -
1291 - <?php
1292 - foreach ( $values as $option_key => $option ) : ?>
1293 - <div class="layout" data-type="<?php
1294 - echo esc_attr( $option['layout'] ) ?>">
1295 - <div class="layout-header">
1296 - <div class="layout-count"><?php
1297 - echo absint( $option_key + 1 ) ?></div>
1298 - <div class="layout-title">
1299 - <?php
1300 - echo esc_html( $settings['layouts'][ $option['layout'] ]['title'] ) ?>
1301 - </div>
1302 - <div class="layout-actions">
1303 - <span class="customize-control-flexible-content-move dashicons dashicons-menu"></span>
1304 - <a class="customize-control-flexible-content-delete" href="#">
1305 - <span class="dashicons dashicons-no-alt"></span>
1306 - </a>
1307 - </div>
1308 - </div>
1309 - <div class="layout-body">
1310 - <?php
1311 - foreach ( $settings['layouts'][ $option['layout'] ]['fields'] as $sub_field ) :
1312 - $classes = array( 'layout-field' );
1313 - if ( isset( $sub_field['classes'] ) ) {
1314 - $classes = array_merge( $classes, $sub_field['classes'] );
1315 - } ?>
1316 - <div class="<?php
1317 - echo esc_attr( implode( ' ', $classes ) ) ?>">
1318 - <?php
1319 - $value = null;
1320 - if ( isset( $option[ $sub_field['id'] ] ) ) {
1321 - $value = $option[ $sub_field['id'] ];
1322 - } elseif ( isset( $sub_field['default'] ) ) {
1323 - $value = $sub_field['default'];
1324 - }
1325 - static::replace_field( $sub_field,
1326 - $value,
1327 - "name=\"merchant[{$sub_field['id']}]",
1328 - "name=\"merchant[{$settings['id']}][{$option_key}][{$sub_field['id']}]" ) ?>
1329 - </div>
1330 - <?php
1331 - endforeach; ?>
1332 - <input type="hidden" name="merchant[<?php
1333 - echo esc_attr( $settings['id'] ) ?>][<?php
1334 - echo absint( $option_key ) ?>][layout]"
1335 - value="<?php
1336 - echo esc_attr( $option['layout'] ) ?>">
1337 - </div>
1338 - </div>
1339 -
1340 - <?php
1341 - endforeach; ?>
1342 -
1343 - </div>
1344 -
1345 - <div class="customize-control-flexible-content-add-wrapper">
1346 - <div class="customize-control-flexible-content-add-list">
1347 - <?php
1348 - foreach ( $settings['layouts'] as $layout_type => $layout ) : ?>
1349 - <a href="#"
1350 - class="customize-control-flexible-content-add"
1351 - data-id="<?php
1352 - echo esc_attr( $settings['id'] ) ?>"
1353 - data-layout="<?php
1354 - echo esc_attr( $layout_type ) ?>">
1355 - <?php
1356 - echo esc_attr( $layout['title'] ) ?>
1357 - </a>
1358 - <?php
1359 - endforeach; ?>
1360 - </div>
1361 - <button class="button customize-control-flexible-content-add-button" type="button"><?php
1362 - echo esc_html( $settings['button_label'] ); ?></button>
1363 - </div>
1364 - </div>
1365 - <?php
1366 - }
1367 -
1368 - /**
1369 - * Field: Create Page.
1370 - */
1371 - public static function create_page( $settings, $value ) {
1372 - $page_id = get_option( $settings['option_name'] );
1373 -
1374 - echo '<div class="merchant-create-page-control">';
1375 -
1376 - if ( $page_id && post_exists( get_the_title( $page_id ) ) && 'publish' === get_post_status( $page_id ) ) {
1377 - echo wp_kses_post(
1378 - sprintf( /* translators: 1: link to edit page */
1379 - __( '<p class="merchant-module-page-setting-field-desc mrc-mt-0">Your page is created!</p><p class="merchant-module-page-setting-field-desc">Click <a href="%1$s" target="_blank">here</a> if you want to edit the page.</p><p class="merchant-module-page-setting-field-desc mrc-mb-0">To display the page in your theme header area, assign the page to the primary menu by clicking <a href="%2$s" target="_blank">here</a></p>',
1380 - 'merchant' ),
1381 - get_admin_url() . 'post.php?post=' . $page_id . '&action=edit',
1382 - get_admin_url() . 'nav-menus.php'
1383 - )
1384 - );
1385 - } else {
1386 - echo '<div class="merchant-create-page-control-create-message">';
1387 - echo wp_kses_post(
1388 - '<p class="merchant-module-page-setting-field-desc mrc-mt-0">'.
1389 - sprintf( /* translators: 1: page name */
1390 - __( 'It looks like you haven\'t created a <strong>%1$s</strong> page yet. Click the below button to create the page.',
1391 - 'merchant' ),
1392 - $settings['page_title']
1393 - ). '</p>'
1394 - );
1395 - echo '</div>';
1396 - echo '<div class="merchant-create-page-control-success-message" style="display: none;">';
1397 - echo wp_kses_post(
1398 - sprintf( /* translators: 1: link to edit page */
1399 - __( '<p class="merchant-module-page-setting-field-desc">Page created with success!</p><p class="merchant-module-page-setting-field-desc">Click <a href="%1$s" target="_blank">here</a> if you want to edit the page.</p><p class="merchant-module-page-setting-field-desc mrc-mb-0">To display the page in your theme header area, assign the page to the primary menu by clicking <a href="%2$s" target="_blank">here</a></p>',
1400 - 'merchant' ),
1401 - get_admin_url() . 'post.php?post=&action=edit',
1402 - get_admin_url() . 'nav-menus.php'
1403 - )
1404 - );
1405 - echo '</div>';
1406 - echo wp_kses_post(
1407 - sprintf( /* translators: 1: page title, 2: page meta key, 3: page meta value, 4: option name, 5: nonce, 6: loading text, 7: success text */
1408 - __( '<a href="#" class="merchant-create-page-control-button button-tertiary" data-page-title="%2$s" data-page-meta-key="%3$s" data-page-meta-value="%4$s" data-option-name="%5$s" data-nonce="%6$s" data-creating-text="%7$s" data-created-text="%8$s">%1$s</a>',
1409 - 'merchant' ),
1410 - __( 'Create Page', 'merchant' ),
1411 - $settings['page_title'],
1412 - $settings['page_meta_key'],
1413 - $settings['page_meta_value'],
1414 - $settings['option_name'],
1415 - wp_create_nonce( 'customize-create-page-control-nonce' ),
1416 - __( 'Creating...', 'merchant' ),
1417 - __( 'Created!', 'merchant' )
1418 - )
1419 - );
1420 - }
1421 -
1422 - echo '</div>';
1423 - }
1424 -
1425 - public static function dimensions( $settings, $value ) {
1426 - $settings = wp_parse_args( $settings, array(
1427 - 'units' => array(
1428 - 'px' => 'px',
1429 - 'rem' => 'rem',
1430 - 'em' => 'em',
1431 - 'vw' => 'vw',
1432 - 'vh' => 'vh',
1433 - '%' => '%',
1434 - ),
1435 - 'dimensions' => array(
1436 - 'top',
1437 - 'right',
1438 - 'bottom',
1439 - 'left',
1440 - ),
1441 - ) );
1442 - $default_value = array(
1443 - 'unit' => reset( $settings['units'] ),
1444 - );
1445 - foreach ( $settings['dimensions'] as $dimension ) {
1446 - $default_value[ $dimension ] = 0;
1447 - }
1448 - $value = wp_parse_args( $value, $default_value );
1449 - ?>
1450 - <div class="merchant-module-page-settings-unit">
1451 - <select name="merchant[<?php
1452 - echo esc_attr( $settings['id'] ); ?>][unit]">
1453 - <?php
1454 - foreach ( $settings['units'] as $key => $option ) : ?>
1455 - <option value="<?php
1456 - echo esc_attr( $key ); ?>" <?php
1457 - selected( $value['unit'], $key, true ); ?>><?php
1458 - echo esc_html( $option ); ?></option>
1459 - <?php
1460 - endforeach; ?>
1461 - </select>
1462 - </div>
1463 - <div class="merchant-module-page-settings-dimensions">
1464 - <?php
1465 - foreach ( $settings['dimensions'] as $dimension ) : ?>
1466 - <div>
1467 - <input id="merchant-<?php
1468 - echo esc_attr( $settings['id'] ); ?>-<?php
1469 - echo esc_attr( $dimension ) ?>"
1470 - type="number"
1471 - name="merchant[<?php
1472 - echo esc_attr( $settings['id'] ); ?>][<?php
1473 - echo esc_attr( $dimension ) ?>]"
1474 - value="<?php
1475 - echo esc_attr( $value[ $dimension ] ); ?>"/>
1476 - <label for="merchant-<?php
1477 - echo esc_attr( $settings['id'] ); ?>-<?php
1478 - echo esc_attr( $dimension ) ?>">
1479 - <?php
1480 - echo esc_html( ucfirst( $dimension ) ); ?>
1481 - </label>
1482 - </div>
1483 - <?php
1484 - endforeach; ?>
1485 - </div>
1486 - <?php
1487 - }
1488 -
1489 - public static function responsive_dimensions( $settings, $value ) {
1490 - $settings = wp_parse_args( $settings, array(
1491 - 'units' => array(
1492 - 'px' => 'px',
1493 - 'rem' => 'rem',
1494 - 'em' => 'em',
1495 - 'vw' => 'vw',
1496 - 'vh' => 'vh',
1497 - '%' => '%',
1498 - ),
1499 - 'dimensions' => array(
1500 - 'top',
1501 - 'right',
1502 - 'bottom',
1503 - 'left',
1504 - ),
1505 - 'devices' => array(
1506 - 'desktop' => 'dashicons-desktop',
1507 - 'tablet' => 'dashicons-tablet',
1508 - 'mobile' => 'dashicons-smartphone',
1509 - ),
1510 - ) );
1511 - $default_values = array();
1512 - foreach ( $settings['devices'] as $device => $icon ) {
1513 - $default_values[ $device ]['unit'] = reset( $settings['units'] );
1514 -
1515 - foreach ( $settings['dimensions'] as $dimension ) {
1516 - $default_values[ $device ][ $dimension ] = 0;
1517 - }
1518 - }
1519 - $value = wp_parse_args( $value, $default_values );
1520 - ?>
1521 - <div class="merchant-module-page-settings-responsive">
1522 - <ul class="merchant-module-page-settings-devices">
1523 - <?php
1524 - foreach ( $settings['devices'] as $device => $icon ) : ?>
1525 - <li class="<?php
1526 - echo esc_attr( $device ); ?>">
1527 - <button type="button" class="preview-<?php
1528 - echo esc_attr( $device ); ?> <?php
1529 - echo $device === key( $settings['devices'] ) ? 'active' : '' ?>"
1530 - data-device="<?php
1531 - echo esc_attr( $device ); ?>">
1532 - <i class="dashicons <?php
1533 - echo esc_attr( $icon ); ?>"></i>
1534 - </button>
1535 - </li>
1536 - <?php
1537 - endforeach; ?>
1538 - </ul>
1539 - <?php
1540 - foreach ( $settings['devices'] as $device => $icon ) : ?>
1541 - <div class="merchant-module-page-settings-device-container <?php
1542 - echo $device === key( $settings['devices'] ) ? 'active' : '' ?>" data-device="<?php
1543 - echo esc_attr( $device ); ?>">
1544 - <div class="merchant-module-page-settings-unit">
1545 - <select name="merchant[<?php
1546 - echo esc_attr( $settings['id'] ); ?>][<?php
1547 - echo esc_attr( $device ) ?>][unit]">
1548 - <?php
1549 - foreach ( $settings['units'] as $key => $option ) : ?>
1550 - <option value="<?php
1551 - echo esc_attr( $key ); ?>" <?php
1552 - selected( $value[ esc_attr( $device ) ]['unit'], $key, true ); ?>><?php
1553 - echo esc_html( $option ); ?></option>
1554 - <?php
1555 - endforeach; ?>
1556 - </select>
1557 - </div>
1558 - <div class="merchant-module-page-settings-dimensions">
1559 - <?php
1560 - foreach ( $settings['dimensions'] as $dimension ) : ?>
1561 - <div>
1562 - <input id="merchant-<?php
1563 - echo esc_attr( $settings['id'] ); ?>-<?php
1564 - echo esc_attr( $device ) ?>-<?php
1565 - echo esc_attr( $dimension ) ?>"
1566 - type="number"
1567 - name="merchant[<?php
1568 - echo esc_attr( $settings['id'] ); ?>][<?php
1569 - echo esc_attr( $device ) ?>][<?php
1570 - echo esc_attr( $dimension ) ?>]"
1571 - value="<?php
1572 - echo esc_attr( $value[ $device ][ $dimension ] ); ?>"/>
1573 - <label for="merchant-<?php
1574 - echo esc_attr( $settings['id'] ); ?>-<?php
1575 - echo esc_attr( $device ) ?>-<?php
1576 - echo esc_attr( $dimension ) ?>">
1577 - <?php
1578 - echo esc_html( ucfirst( $dimension ) ); ?>
1579 - </label>
1580 - </div>
1581 - <?php
1582 - endforeach; ?>
1583 - </div>
1584 - </div>
1585 - <?php
1586 - endforeach; ?>
1587 - </div>
1588 -
1589 - <?php
1590 - }
1591 -
1592 - /**
1593 - * Field: Custom callback.
1594 - */
1595 - public static function custom_callback( $settings, $value ) {
1596 - if ( ! empty( $settings['class_name'] ) && ! empty( $settings['callback_name'] ) ) {
1597 - return call_user_func( array( $settings['class_name'], $settings['callback_name'] ), $settings, $value );
1598 - }
1599 -
1600 - if ( ! empty( $settings['callback_name'] ) ) {
1601 - return call_user_func( $settings['callback_name'], $settings, $value );
1602 - }
1603 -
1604 - return false;
1605 - }
1606 - }
1607 -
1608 - Merchant_Admin_Options::instance();
1609 -}
1 +<?php
2 +/**
3 + * Merchant Admin Options.
4 + *
5 + * Thin orchestrator that manages module settings. Delegates rendering
6 + * to {@see Merchant_Settings_Renderer}, saving to {@see Merchant_Settings_Saver},
7 + * asset enqueueing to {@see Merchant_Admin_Assets}, and Select2 data
8 + * to {@see Merchant_Select2_Choices}.
9 + *
10 + * @package Merchant
11 + * @since 1.0
12 + */
13 +
14 +if ( ! defined( 'ABSPATH' ) ) {
15 + exit; // Exit if accessed directly
16 +}
17 +
18 +if ( ! class_exists( 'Merchant_Admin_Options' ) ) {
19 + /**
20 + * Merchant_Admin_Options
21 + *
22 + * Orchestrates the Merchant admin settings panel. Core responsibilities:
23 + * - CRUD operations for module settings (`get`, `set`, `delete`, `get_all`)
24 + * - Wiring admin hooks (assets, cache, cleanup, Pro activation)
25 + * - Backward-compatible facades that delegate to extracted classes
26 + *
27 + * This class is a singleton; use {@see Merchant_Admin_Options::instance()} to retrieve it.
28 + *
29 + * @since 1.0
30 + */
31 + class Merchant_Admin_Options {
32 +
33 + /**
34 + * The single class instance.
35 + *
36 + * @since 1.0
37 + * @var Merchant_Admin_Options|null
38 + */
39 + private static $instance = null;
40 +
41 + /**
42 + * Get the singleton instance.
43 + *
44 + * @since 1.0
45 + *
46 + * @return Merchant_Admin_Options
47 + */
48 + public static function instance() {
49 + if ( is_null( self::$instance ) ) {
50 + self::$instance = new self();
51 + }
52 +
53 + return self::$instance;
54 + }
55 +
56 + /**
57 + * Constructor.
58 + *
59 + * Registers admin hooks for script enqueueing, cache clearance,
60 + * legacy data cleanup, and Pro plugin activation.
61 + *
62 + * @since 1.0
63 + */
64 + public function __construct() {
65 + $assets = new Merchant_Admin_Assets();
66 + $choices = new Merchant_Select2_Choices();
67 +
68 + add_action( 'admin_enqueue_scripts', array( $assets, 'enqueue_scripts' ) );
69 + add_action( 'clean_user_cache', array( $choices, 'clear_customer_choices_cache' ), 10, 2 );
70 +
71 + add_action( 'admin_init', array( $this, 'delete_module_data' ) );
72 + add_action( 'admin_init', array( $this, 'activate_pro_plugin' ) );
73 + }
74 +
75 + // ──────────────────────────────────────────────────────
76 + // CRUD — core orchestrator responsibility.
77 + // ──────────────────────────────────────────────────────
78 +
79 + /**
80 + * Get a single module setting value.
81 + *
82 + * Retrieves the value of a specific setting for a given module
83 + * from the `merchant` option. Falls back to `$default_val` if
84 + * the setting does not exist.
85 + *
86 + * @since 1.0
87 + *
88 + * @param string $module The module ID (e.g. 'buy-x-get-y').
89 + * @param string $setting The setting key within the module.
90 + * @param mixed $default_val The default value if the setting is not found.
91 + *
92 + * @return mixed The setting value, filtered via `merchant_get_option`.
93 + */
94 + public static function get( $module, $setting, $default_val ) {
95 + $options = get_option( 'merchant', array() );
96 +
97 + $value = $default_val;
98 +
99 + if ( isset( $options[ $module ][ $setting ] ) ) {
100 + $value = $options[ $module ][ $setting ];
101 + }
102 +
103 + /**
104 + * Hook: merchant_get_option filter.
105 + * Fires after getting module option.
106 + *
107 + * @param mixed $value Option value.
108 + * @param string $module Module ID.
109 + * @param string $setting Setting ID.
110 + * @param mixed $default_val Default value.
111 + *
112 + * @since 1.9.3
113 + */
114 + return apply_filters( 'merchant_get_option', $value, $module, $setting, $default_val );
115 + }
116 +
117 + /**
118 + * Set a single module setting value.
119 + *
120 + * @since 1.0
121 + *
122 + * @param string $module The module ID.
123 + * @param string $setting The setting key.
124 + * @param mixed $value The value to store.
125 + *
126 + * @return void
127 + */
128 + public static function set( $module, $setting, $value ) {
129 + $options = get_option( 'merchant', array() );
130 + $options[ $module ][ $setting ] = $value;
131 + update_option( 'merchant', $options );
132 + }
133 +
134 + /**
135 + * Delete a single module setting.
136 + *
137 + * @since 1.0
138 + *
139 + * @param string $module The module ID.
140 + * @param string $setting The setting key to remove.
141 + *
142 + * @return void
143 + */
144 + public static function delete( $module, $setting ) {
145 + $options = get_option( 'merchant', array() );
146 + unset( $options[ $module ][ $setting ] );
147 + update_option( 'merchant', $options );
148 + }
149 +
150 + /**
151 + * Get all settings for a module.
152 + *
153 + * @since 1.0
154 + *
155 + * @param string $module The module ID.
156 + *
157 + * @return array All settings for the module.
158 + */
159 + public static function get_all( $module ) {
160 + $options = get_option( 'merchant', array() );
161 + $value = array();
162 +
163 + if ( isset( $options[ $module ] ) ) {
164 + $value = $options[ $module ];
165 + }
166 +
167 + return $value;
168 + }
169 +
170 + // ──────────────────────────────────────────────────────
171 + // Delegation facades — backward compatibility.
172 + // ──────────────────────────────────────────────────────
173 +
174 + /**
175 + * Create and render a module settings panel.
176 + *
177 + * @since 1.0
178 + * @see Merchant_Settings_Renderer::create()
179 + *
180 + * @param array $settings Module settings configuration.
181 + *
182 + * @return void
183 + */
184 + public static function create( $settings ) {
185 + Merchant_Settings_Renderer::create( $settings );
186 + }
187 +
188 + /**
189 + * Render a single field.
190 + *
191 + * @since 1.0
192 + * @see Merchant_Settings_Renderer::field()
193 + *
194 + * @param array $settings The field configuration array.
195 + * @param mixed $value The current saved value.
196 + * @param string $module_id The module ID.
197 + *
198 + * @return void
199 + */
200 + public static function field( $settings, $value, $module_id = '' ) {
201 + Merchant_Settings_Renderer::field( $settings, $value, $module_id );
202 + }
203 +
204 + /**
205 + * Render a disabled (pro-gated) field.
206 + *
207 + * @since 1.0
208 + * @see Merchant_Settings_Renderer::disabled_field()
209 + *
210 + * @param array $settings Field settings.
211 + * @param mixed $value Field value.
212 + * @param string $module_id Module ID.
213 + *
214 + * @return void
215 + */
216 + public static function disabled_field( $settings, $value, $module_id = '' ) {
217 + Merchant_Settings_Renderer::disabled_field( $settings, $value, $module_id );
218 + }
219 +
220 + /**
221 + * Save module options from a form submission.
222 + *
223 + * @since 1.0
224 + * @see Merchant_Settings_Saver::save_options()
225 + *
226 + * @param array $settings Module settings configuration.
227 + *
228 + * @return void
229 + */
230 + public static function save_options( $settings ) {
231 + Merchant_Settings_Saver::save_options( $settings );
232 + }
233 +
234 + /**
235 + * Sanitize options.
236 + *
237 + * @since 1.9.3
238 + * @see Merchant_Settings_Saver::sanitize()
239 + *
240 + * @param array $field The field configuration.
241 + * @param mixed $value The raw submitted value.
242 + *
243 + * @return mixed The sanitized value.
244 + */
245 + public static function sanitize( $field, $value ) {
246 + return Merchant_Settings_Saver::sanitize( $field, $value );
247 + }
248 +
249 + /**
250 + * Get product category choices for Select2.
251 + *
252 + * @since 1.9.3
253 + * @see Merchant_Select2_Choices::get_category_select2_choices()
254 + *
255 + * @return array Formatted category choices.
256 + */
257 + public static function get_category_select2_choices() {
258 + return Merchant_Select2_Choices::get_category_select2_choices();
259 + }
260 +
261 + /**
262 + * Get product tag choices for Select2.
263 + *
264 + * @since 1.9.3
265 + * @see Merchant_Select2_Choices::get_tag_select2_choices()
266 + *
267 + * @return array Formatted tag choices.
268 + */
269 + public static function get_tag_select2_choices() {
270 + return Merchant_Select2_Choices::get_tag_select2_choices();
271 + }
272 +
273 + /**
274 + * Get product brand choices for Select2.
275 + *
276 + * @since 1.9.3
277 + * @see Merchant_Select2_Choices::get_brand_select2_choices()
278 + *
279 + * @return array Formatted brand choices.
280 + */
281 + public static function get_brand_select2_choices() {
282 + return Merchant_Select2_Choices::get_brand_select2_choices();
283 + }
284 +
285 + /**
286 + * Get user role choices for Select2.
287 + *
288 + * @since 1.9.3
289 + * @see Merchant_Select2_Choices::get_user_roles_select2_choices()
290 + *
291 + * @return array Formatted role choices.
292 + */
293 + public static function get_user_roles_select2_choices() {
294 + return Merchant_Select2_Choices::get_user_roles_select2_choices();
295 + }
296 +
297 + /**
298 + * Get weekday choices, Monday first, keyed by day name.
299 + *
300 + * @since 2.3.2
301 + * @see Merchant_Select2_Choices::get_weekday_choices()
302 + *
303 + * @return array Day name => translated label.
304 + */
305 + public static function get_weekday_choices() {
306 + return Merchant_Select2_Choices::get_weekday_choices();
307 + }
308 +
309 + /**
310 + * Get shipping zone choices for Select2.
311 + *
312 + * @since 2.3.2
313 + * @see Merchant_Select2_Choices::get_shipping_zone_select2_choices()
314 + *
315 + * @return array Formatted zone choices.
316 + */
317 + public static function get_shipping_zone_select2_choices() {
318 + return Merchant_Select2_Choices::get_shipping_zone_select2_choices();
319 + }
320 +
321 + /**
322 + * Get registered shipping method choices for Select2.
323 + *
324 + * @since 2.3.2
325 + * @see Merchant_Select2_Choices::get_shipping_method_select2_choices()
326 + *
327 + * @return array Formatted method choices.
328 + */
329 + public static function get_shipping_method_select2_choices() {
330 + return Merchant_Select2_Choices::get_shipping_method_select2_choices();
331 + }
332 +
333 + /**
334 + * Get enabled payment gateway choices for Select2.
335 + *
336 + * @since 2.3.2
337 + * @see Merchant_Select2_Choices::get_payment_gateway_select2_choices()
338 + *
339 + * @return array Formatted gateway choices.
340 + */
341 + public static function get_payment_gateway_select2_choices() {
342 + return Merchant_Select2_Choices::get_payment_gateway_select2_choices();
343 + }
344 +
345 + /**
346 + * Get customer user choices for Select2.
347 + *
348 + * @since 1.9.3
349 + * @see Merchant_Select2_Choices::get_customers_select2_choices()
350 + *
351 + * @return array Formatted customer choices.
352 + */
353 + public static function get_customers_select2_choices() {
354 + return Merchant_Select2_Choices::get_customers_select2_choices();
355 + }
356 +
357 + // ──────────────────────────────────────────────────────
358 + // Admin hooks — small one-off actions.
359 + // ──────────────────────────────────────────────────────
360 +
361 + /**
362 + * Delete stale module data from the database.
363 + *
364 + * Cleans up data for removed modules (e.g., the deprecated
365 + * `code-snippets` module). Hooked to `admin_init`.
366 + *
367 + * @since 1.9.3
368 + *
369 + * @return void
370 + */
371 + public function delete_module_data() {
372 + $options = get_option( 'merchant', array() );
373 +
374 + if ( isset( $options['code-snippets'] ) ) {
375 + unset( $options['code-snippets'] );
376 + update_option( 'merchant', $options );
377 + }
378 + }
379 +
380 + /**
381 + * Activate the Merchant Pro plugin.
382 + *
383 + * Handles the `merchant_activate_pro` admin action: verifies
384 + * nonce and capabilities, activates the Pro plugin, and
385 + * redirects back to the originating Merchant page.
386 + *
387 + * @since 1.0
388 + *
389 + * @return void
390 + */
391 + public function activate_pro_plugin() {
392 + if ( ! isset( $_GET['action'] ) || 'merchant_activate_pro' !== $_GET['action'] ) {
393 + return;
394 + }
395 +
396 + if (
397 + ! isset( $_GET['nonce'] )
398 + || ! wp_verify_nonce(
399 + sanitize_text_field( wp_unslash( $_GET['nonce'] ) ),
400 + 'merchant_activate_pro'
401 + )
402 + ) {
403 + return;
404 + }
405 +
406 + if ( ! current_user_can( 'activate_plugins' ) ) {
407 + return;
408 + }
409 +
410 + $result = activate_plugin( 'merchant-pro/merchant-pro.php' );
411 +
412 + if ( is_wp_error( $result ) ) {
413 + wp_die( esc_html( $result->get_error_message() ) );
414 + }
415 +
416 + wp_safe_redirect( $this->get_safe_merchant_redirect_url() );
417 + exit;
418 + }
419 +
420 + /**
421 + * Get a safe redirect URL pointing to a Merchant admin page.
422 + *
423 + * Validates the HTTP referer is a Merchant page. Falls back
424 + * to the main Merchant dashboard if the referer is invalid
425 + * or points to a non-Merchant page.
426 + *
427 + * @since 1.9.3
428 + *
429 + * @return string Safe redirect URL.
430 + */
431 + private function get_safe_merchant_redirect_url() {
432 + $fallback_url = admin_url( 'admin.php?page=merchant' );
433 + $referer = wp_get_referer();
434 + $redirect_to = wp_validate_redirect( $referer, $fallback_url );
435 +
436 + if ( $redirect_to === $fallback_url ) {
437 + return $fallback_url;
438 + }
439 +
440 + $parsed_url = wp_parse_url( $redirect_to );
441 + $query_params = array();
442 + parse_str( $parsed_url['query'] ?? '', $query_params );
443 +
444 + if ( empty( $query_params['page'] ) || strpos( $query_params['page'], 'merchant' ) !== 0 ) {
445 + return $fallback_url;
446 + }
447 +
448 + return $redirect_to;
449 + }
450 + }
451 +
452 + Merchant_Admin_Options::instance();
453 +}