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 -1301 1.62.3.2 View file →
@@ -1,1301 +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 ) {
158 - $options = get_option( 'merchant', array() );
159 -
160 - $value = $default;
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 if ( ! empty( $settings['title'] ) ) : ?>
202 - <div class="merchant-module-page-setting-title">
203 - <?php echo esc_html( $settings['title'] ); ?>
204 - <?php if ( ! empty( $settings['subtitle'] ) ) : ?>
205 - <div class="merchant-module-page-setting-subtitle"><?php echo esc_html( $settings['subtitle'] ); ?></div>
206 - <?php endif; ?>
207 - </div>
208 - <?php endif; ?>
209 - <div class="merchant-module-page-setting-fields">
210 - <?php
211 -
212 - if ( ! empty( $settings['fields'] ) ) {
213 - foreach ( $settings['fields'] as $field ) {
214 - $value = null;
215 -
216 - if ( isset( $field['default'] ) ) {
217 - $value = $field['default'];
218 - }
219 -
220 - if ( isset( $field['id'] ) && isset( $options[ $settings['module'] ] ) && isset( $options[ $settings['module'] ][ $field['id'] ] ) ) {
221 - $value = $options[ $settings['module'] ][ $field['id'] ];
222 - }
223 -
224 - $module_info = Merchant_Admin_Modules::get_module_info( $settings['module'] );
225 - if ( ( $module_info && $module_info['pro'] ) && ! defined( 'MERCHANT_PRO_DIR' ) ) {
226 - self::disabled_field( $field, $value );
227 - } else {
228 - self::field( $field, $value );
229 - }
230 - }
231 - }
232 -
233 - ?>
234 - </div>
235 - </div>
236 - </div>
237 - <?php
238 - }
239 -
240 - /**
241 - * Save options.
242 - */
243 - public static function save_options( $settings ) {
244 - $save = ( isset( $_POST['merchant_save'] ) ) ? sanitize_text_field( wp_unslash( $_POST['merchant_save'] ) ) : '';
245 - $reset = ( isset( $_POST['merchant_reset'] ) ) ? sanitize_text_field( wp_unslash( $_POST['merchant_reset'] ) ) : '';
246 - $nonce = ( isset( $_POST['merchant_nonce'] ) ) ? sanitize_text_field( wp_unslash( $_POST['merchant_nonce'] ) ) : '';
247 -
248 - if ( ! wp_verify_nonce( $nonce, 'merchant_nonce' ) ) {
249 - return;
250 - }
251 -
252 - if ( ! current_user_can( 'manage_options' ) ) {
253 - return;
254 - }
255 -
256 - $options = get_option( 'merchant', array() );
257 -
258 - if ( ! empty( $save ) ) {
259 - if ( ! empty( $settings['fields'] ) ) {
260 - foreach ( $settings['fields'] as $field ) {
261 - if ( ! isset( $field['id'] ) ) {
262 - continue;
263 - }
264 -
265 - $value = null;
266 -
267 - if ( isset( $_POST['merchant'] ) && isset( $_POST['merchant'][ $field['id'] ] ) ) {
268 - if ( 'textarea_code' === $field['type'] ) {
269 - $value = wp_kses( $_POST['merchant'][ $field['id'] ], merchant_kses_allowed_tags_for_code_snippets() );
270 - } else {
271 - if ( is_array( $_POST['merchant'][ $field['id'] ] ) ) {
272 - $value = array_filter( map_deep( wp_unslash( $_POST['merchant'][ $field['id'] ] ), 'sanitize_text_field' ) );
273 - } else {
274 - $value = sanitize_text_field( wp_unslash( $_POST['merchant'][ $field['id'] ] ) );
275 - }
276 - }
277 - }
278 -
279 -
280 - $options[ $settings['module'] ][ $field['id'] ] = self::sanitize( $field, $value );
281 - }
282 - }
283 - } elseif ( ! empty( $reset ) ) {
284 - $options[ $settings['module'] ] = array();
285 - }
286 -
287 - update_option( 'merchant', $options );
288 - }
289 -
290 - /**
291 - * Sanitize options.
292 - */
293 - public static function sanitize( $field, $value ) {
294 - // Callback for custom sanitize methods.
295 - if ( ! empty( $field['sanitize'] ) && is_callable( $field['sanitize'] ) ) {
296 - return call_user_func( $field['sanitize'], $value );
297 - }
298 -
299 - switch ( $field['type'] ) {
300 - case 'text':
301 - case 'color':
302 - case 'number':
303 - case 'select_size_chart':
304 - $value = sanitize_text_field( $value );
305 - break;
306 -
307 - case 'textarea':
308 - $value = sanitize_textarea_field( $value );
309 - break;
310 -
311 - case 'textarea_code':
312 - $value = $value;
313 - break;
314 -
315 - case 'checkbox':
316 - case 'switcher':
317 - $value = ( '1' === $value ) ? 1 : 0;
318 - break;
319 -
320 - case 'range':
321 - case 'number':
322 - $value = absint( $value );
323 - break;
324 - case 'select_ajax':
325 - if ( is_array( $value ) && ! empty( $value ) ) {
326 - $value = array_filter( array_map( 'sanitize_text_field', $value ) );
327 - } elseif ( is_string( $value ) ) {
328 - $value = sanitize_text_field( $value );
329 - } else {
330 - $value = isset( $field['multiple'] ) && $field['multiple'] === false ? '' : array();
331 - }
332 - break;
333 - case 'radio':
334 - case 'radio_alt':
335 - case 'select':
336 - case 'choices':
337 - case 'buttons':
338 - case 'buttons_alt':
339 - $value = ( in_array( $value, array_keys( $field['options'] ), true ) ) ? sanitize_key( $value ) : '';
340 - break;
341 -
342 - case 'code-editor':
343 - $value = wp_kses_post( $value );
344 - break;
345 -
346 - case 'sortable':
347 - $values = json_decode( $value );
348 - $value = array();
349 -
350 - foreach ( $values as $val ) {
351 - if ( in_array( $val, array_keys( $field['options'] ), true ) ) {
352 - $value[] = sanitize_key( $val );
353 - }
354 - }
355 - break;
356 - case 'dimensions':
357 - $values = is_array( $value ) ? $value : array();
358 -
359 - foreach ( $values as $key => $val ) {
360 - if ( $key === 'unit' ) {
361 - $value[ $key ] = sanitize_key( $value[ $key ] );
362 - } else {
363 - $value[ $key ] = absint( $value[ $key ] );
364 - }
365 - }
366 - break;
367 - case 'responsive_dimensions':
368 - $values = is_array( $value ) ? $value : array();
369 -
370 - foreach ( $values as $device => $device_fields ) {
371 - foreach ( $device_fields as $device_field => $device_field_val ) {
372 - if ( $device_field === 'unit' ) {
373 - $value[ $device ][ $device_field ] = sanitize_key( $device_field_val );
374 - } else {
375 - $value[ $device ][ $device_field ] = absint( $device_field_val );
376 - }
377 - }
378 - }
379 - break;
380 -
381 - case 'sortable_repeater':
382 - $values = json_decode( $value );
383 - $value = array_map( 'sanitize_text_field', $values );
384 - break;
385 - case 'flexible_content':
386 - $value = ! is_array( $value ) || empty( $value ) ? array() : $value;
387 -
388 - $value = array_map( function ( $sub_fields ) use ( $field ) {
389 - foreach ( $sub_fields as $sub_field => $value ) {
390 - if ( $sub_field === 'layout' ) {
391 - $sub_fields[ $sub_field ] = sanitize_text_field( $value );
392 - } else {
393 - $layout_field = array_filter( $field['layouts'][ $sub_fields['layout'] ]['fields'], function ( $layout_field ) use ( $sub_field ) {
394 - return $layout_field['id'] === $sub_field;
395 - } );
396 -
397 -
398 - $sub_fields[ $sub_field ] = self::sanitize( reset( $layout_field ), $value );
399 - }
400 - }
401 -
402 - return $sub_fields;
403 - }, $value );
404 -
405 - break;
406 - }
407 -
408 - return $value;
409 - }
410 -
411 - /**
412 - * Field
413 - */
414 - public static function field( $settings, $value ) {
415 - if ( ! empty( $settings['type'] ) ) {
416 - $type = $settings['type'];
417 -
418 - $id = ( ! empty( $settings['id'] ) ) ? $settings['id'] : '';
419 - $class = ( ! empty( $settings['class'] ) ) ? ' ' . $settings['class'] : '';
420 - $condition = ( ! empty( $settings['condition'] ) ) ? $settings['condition'] : array();
421 -
422 - echo '<div class="merchant-module-page-setting-field merchant-module-page-setting-field-' . esc_attr( $type ) . '' . esc_attr( $class ) . '" data-id="' . esc_attr( $id ) . '" data-type="' . esc_attr( $type ) . '" data-condition="' . esc_attr( wp_json_encode( $condition ) ) . '">';
423 -
424 - if ( ! empty( $settings['title'] ) ) {
425 - echo sprintf( '<div class="merchant-module-page-setting-field-title">%s</div>', esc_html( $settings['title'] ) );
426 - }
427 -
428 - echo '<div class="merchant-module-page-setting-field-inner">';
429 - if ( method_exists( 'Merchant_Admin_Options', $type ) ) {
430 - call_user_func( array( 'Merchant_Admin_Options', $type ), $settings, $value );
431 - } else {
432 - esc_html_e( 'Field not found!', 'merchant' );
433 - }
434 - echo '</div>';
435 -
436 - if ( ! empty( $settings['desc'] ) ) {
437 - echo sprintf( '<div class="merchant-module-page-setting-field-desc">%s</div>', wp_kses_post( $settings['desc'] ) );
438 - }
439 -
440 - echo '</div>';
441 - }
442 - }
443 -
444 - /**
445 - * Disabled field
446 - *
447 - * @param array $settings
448 - * @param mixed $value
449 - *
450 - * @return void
451 - */
452 - public static function disabled_field( $settings, $value ) {
453 - static::replace_field(
454 - $settings,
455 - $value,
456 - array(
457 - '<input ',
458 - '<select ',
459 - 'merchant-module-page-setting-field-inner',
460 - ),
461 - array(
462 - '<input disabled ',
463 - '<select disabled ',
464 - 'merchant-module-page-setting-field-inner disabled',
465 - )
466 - );
467 - }
468 -
469 - /**
470 - * Modified field.
471 - *
472 - * @param $settings
473 - * @param $value
474 - * @param $search
475 - * @param $replace
476 - *
477 - * @return void
478 - */
479 - public static function replace_field( $settings, $value, $search, $replace ) {
480 - ob_start();
481 - self::field( $settings, $value );
482 - $field = ob_get_clean();
483 -
484 - echo wp_kses( str_replace( $search, $replace, $field ), merchant_kses_allowed_tags( array( 'all' ) ) );
485 - }
486 -
487 - /**
488 - * Field: Text
489 - */
490 - public static function text( $settings, $value ) {
491 - ?>
492 - <input type="text" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $value ); ?>"/>
493 - <?php
494 - }
495 -
496 - /**
497 - * Field: Text (readonly)
498 - */
499 - public static function text_readonly( $settings, $value ) {
500 - ?>
501 - <input type="text" value="<?php echo esc_attr( $value ); ?>" readonly/>
502 - <?php
503 - }
504 -
505 - /**
506 - * Field: Number
507 - */
508 - public static function number( $settings, $value ) {
509 - ?>
510 - <input type="number" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $value ); ?>"/>
511 - <?php
512 - }
513 -
514 - /**
515 - * Field: Textarea
516 - */
517 - public static function textarea( $settings, $value ) {
518 - $value = ( $value ) ? $value : '';
519 - ?>
520 - <textarea name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]"><?php echo wp_kses_post( $value ); ?></textarea>
521 - <?php
522 - }
523 -
524 - /**
525 - * Field: Textarea Code Snippet.
526 - */
527 - public static function textarea_code( $settings, $value ) {
528 - $value = ( $value ) ? $value : '';
529 - ?>
530 - <textarea name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]"><?php echo wp_kses( $value, merchant_kses_allowed_tags_for_code_snippets() ); ?></textarea>
531 - <?php
532 - }
533 -
534 - /**
535 - * Field: Checkbox
536 - */
537 - public static function checkbox( $settings, $value ) {
538 - ?>
539 - <div>
540 - <label>
541 - <input type="checkbox" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="1" <?php checked( $value, 1, true ); ?> />
542 - <?php if ( ! empty( $settings['label'] ) ) : ?>
543 - <span><?php echo esc_html( $settings['label'] ); ?></span>
544 - <?php endif; ?>
545 - </label>
546 - </div>
547 - <?php
548 - }
549 -
550 - /**
551 - * Field: Switcher
552 - */
553 - public static function switcher( $settings, $value ) {
554 - ?>
555 - <div class="merchant-toggle-switch">
556 - <input type="checkbox" id="<?php echo esc_attr( $settings['id'] ); ?>" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="1" <?php checked( $value, 1, true ); ?>
557 - class="toggle-switch-checkbox"/>
558 - <label class="toggle-switch-label" for="<?php echo esc_attr( $settings['id'] ); ?>">
559 - <span class="toggle-switch-inner"></span>
560 - <span class="toggle-switch-switch"></span>
561 - </label>
562 - <?php if ( ! empty( $settings['label'] ) ) : ?>
563 - <span><?php echo esc_html( $settings['label'] ); ?></span>
564 - <?php endif; ?>
565 - </div>
566 - <?php
567 - }
568 -
569 - /**
570 - * Field: Radio
571 - */
572 - public static function radio( $settings, $value ) {
573 - ?>
574 - <?php if ( ! empty( $settings['options'] ) ) : ?>
575 - <?php foreach ( $settings['options'] as $key => $option ) : ?>
576 - <label>
577 - <input type="radio" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $key ); ?>" <?php checked( $value, $key, true ); ?>/>
578 - <span><?php echo esc_html( $option ); ?></span>
579 - </label>
580 - <?php endforeach; ?>
581 - <?php endif; ?>
582 - <?php
583 - }
584 -
585 - /**
586 - * Field: Radio Alt
587 - */
588 - public static function radio_alt( $settings, $value ) {
589 - ?>
590 - <?php if ( ! empty( $settings['options'] ) ) : ?>
591 - <?php foreach ( $settings['options'] as $key => $option ) : ?>
592 - <div>
593 - <label>
594 - <input type="radio" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $key ); ?>" <?php checked( $value, $key, true ); ?>/>
595 - <span><?php echo esc_html( $option['title'] ); ?></span>
596 - </label>
597 - <p><?php echo esc_html( $option['desc'] ); ?></p>
598 - </div>
599 - <?php endforeach; ?>
600 - <?php endif; ?>
601 - <?php
602 - }
603 -
604 - /**
605 - * Field: Choices
606 - */
607 - public static function choices( $settings, $value ) {
608 - ?>
609 - <div class="merchant-choices merchant-choices-<?php echo esc_attr( $settings['id'] ) ?>">
610 - <?php if ( ! empty( $settings['options'] ) ) : ?>
611 - <?php foreach ( $settings['options'] as $key => $option ) : ?>
612 - <label>
613 - <input type="radio" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $key ); ?>" <?php checked( $value, $key, true ); ?>/>
614 - <?php if ( ! empty( $option['svg'] ) ) : ?>
615 - <span class="merchant-svg">
616 - <?php echo wp_kses( Merchant_SVG_Icons::get_svg_icon( $option['svg'] ), merchant_kses_allowed_tags( array(), false ) ); ?>
617 -
618 - <?php if ( ! empty( $option['label'] ) ) : ?>
619 - <span class="merchant-tooltip"><?php echo esc_html( $option['label'] ); ?></span>
620 - <?php endif; ?>
621 - </span>
622 - <?php else : ?>
623 - <figure>
624 - <?php if ( ! empty( $option['image'] ) ) : ?>
625 - <img src="<?php echo esc_url( sprintf( $option['image'], MERCHANT_URI . 'assets/images' ) ); ?>"/>
626 - <?php else : ?>
627 - <img src="<?php echo esc_url( sprintf( $option, MERCHANT_URI . 'assets/images' ) ); ?>"/>
628 - <?php endif; ?>
629 - <?php if ( ! empty( $option['label'] ) ) : ?>
630 - <span class="merchant-tooltip"><?php echo esc_html( $option['label'] ); ?></span>
631 - <?php endif; ?>
632 - </figure>
633 - <?php endif; ?>
634 - </label>
635 - <?php endforeach; ?>
636 - <?php endif; ?>
637 - </div>
638 - <?php
639 - }
640 -
641 - /**
642 - * Field: Select
643 - */
644 - public static function select( $settings, $value ) {
645 - ?>
646 - <?php if ( ! empty( $settings['options'] ) ) : ?>
647 - <select name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]">
648 - <?php foreach ( $settings['options'] as $key => $option ) : ?>
649 - <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $value, $key, true ); ?>><?php echo esc_html( $option ); ?></option>
650 - <?php endforeach; ?>
651 - </select>
652 - <?php endif; ?>
653 - <?php
654 - }
655 -
656 - /**
657 - * Field: Select ajax
658 - *
659 - * @param $settings
660 - * @param $value
661 - *
662 - * @return void
663 - */
664 - public static function select_ajax( $settings, $value ) {
665 - $settings = wp_parse_args( $settings, array(
666 - 'source' => 'post',
667 - ) );
668 -
669 - $ids = ( is_array( $value ) && ! empty( $value ) ) ? $value : (array) $value;
670 -
671 - if ( isset( $settings['multiple'] ) ) {
672 - $multiple = $settings['multiple'] === true ? 'multiple' : '';
673 - } else {
674 - $multiple = 'multiple';
675 - }
676 - ?>
677 - <select name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" <?php echo esc_attr( $multiple ) ?> data-source="<?php echo esc_attr( $settings['source'] ) ?>">
678 - <?php if ( ! empty( $ids ) ) {
679 - foreach ( $ids as $id ) {
680 - switch ( $settings['source'] ) {
681 - case 'post':
682 - case 'product':
683 - $post = get_post( $id );
684 -
685 - if ( ! empty( $post ) ) {
686 - echo '<option value="' . esc_attr( $post->ID ) . '" selected>' . esc_html( $post->post_title ) . '</option>';
687 - }
688 - break;
689 - case 'options':
690 - }
691 - }
692 - }
693 - if ( $settings['source'] === 'options' ) {
694 - $value = ! empty( $value ) ? $value : '';
695 -
696 - foreach ( $settings['options'] as $option ) {
697 - if ( isset( $option['options'] ) ) {
698 - echo '<optgroup label="' . esc_attr( $option['text'] ) . '">';
699 -
700 - foreach ( $option['options'] as $child_option ) {
701 - echo '<option value="' . esc_attr( $child_option['id'] ) . '" ' . selected( $child_option['id'], $value ) . '>' . esc_html( $child_option['text'] ) . '</option>';
702 - }
703 -
704 - echo '</optgroup>';
705 - } else {
706 - echo '<option value="' . esc_attr( $option['id'] ) . '" ' . selected( $option['id'], $value ) . '>' . esc_html( $option['text'] ) . '</option>';
707 - }
708 - }
709 - } ?>
710 - </select>
711 - <?php
712 - }
713 -
714 - /**
715 - * Field: Select Size Chart
716 - */
717 - public static function select_size_chart( $settings, $value ) {
718 - $options = array(
719 - '' => esc_html__( 'Default', 'merchant' ),
720 - );
721 -
722 - $posts = get_posts( array(
723 - 'post_type' => 'merchant_size_chart',
724 - 'posts_per_page' => - 1,
725 - 'post_status' => 'publish'
726 - ) );
727 -
728 - if ( ! is_wp_error( $posts ) && ! empty( $posts ) ) {
729 - foreach ( $posts as $_post ) {
730 - $options[ $_post->ID ] = $_post->post_title;
731 - }
732 - }
733 -
734 - ?>
735 - <?php if ( ! empty( $options ) ) : ?>
736 - <select name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]">
737 - <?php foreach ( $options as $key => $option ) : ?>
738 - <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $value, $key, true ); ?>><?php echo esc_html( $option ); ?></option>
739 - <?php endforeach; ?>
740 - </select>
741 - <?php endif; ?>
742 - <?php
743 - }
744 -
745 - /**
746 - * Field: Buttons
747 - */
748 - public static function buttons( $settings, $value ) {
749 - ?>
750 - <div class="merchant-buttons">
751 - <?php if ( ! empty( $settings['options'] ) ) : ?>
752 - <?php foreach ( $settings['options'] as $key => $option ) : ?>
753 - <label class="merchant-button-<?php echo esc_attr( $key ); ?>"">
754 - <input type="radio" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $key ); ?>" <?php checked( $value, $key, true ); ?>/>
755 - <span><?php echo esc_html( $option ); ?></span>
756 - </label>
757 - <?php endforeach; ?>
758 - <?php endif; ?>
759 - </div>
760 - <?php
761 - }
762 -
763 - /**
764 - * Field: Buttons Alt
765 - */
766 - public static function buttons_alt( $settings, $value ) {
767 - ?>
768 - <div class="merchant-buttons">
769 - <?php if ( ! empty( $settings['options'] ) ) : ?>
770 - <?php foreach ( $settings['options'] as $key => $option ) : ?>
771 - <label class="merchant-button-<?php echo esc_attr( $key ); ?>">
772 - <input type="radio" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $key ); ?>" <?php checked( $value, $key, true ); ?>/>
773 - <span><?php echo esc_html( $option ); ?></span>
774 - </label>
775 - <?php endforeach; ?>
776 - <?php endif; ?>
777 - </div>
778 - <?php
779 - }
780 -
781 - /**
782 - * Field: Range
783 - */
784 - public static function range( $settings, $value ) {
785 - $settings = wp_parse_args( $settings, array(
786 - 'min' => '',
787 - 'max' => '',
788 - 'step' => '',
789 - 'unit' => '',
790 - ) );
791 -
792 - ?>
793 - <div class="merchant-range">
794 - <input type="range" class="merchant-range-input" name="" min="<?php echo esc_attr( $settings['min'] ); ?>" max="<?php echo esc_attr( $settings['max'] ); ?>"
795 - step="<?php echo esc_attr( $settings['step'] ); ?>" value="<?php echo esc_attr( $value ); ?>"/>
796 - <input type="number" class="merchant-range-number-input" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" min="<?php echo esc_attr( $settings['min'] ); ?>"
797 - max="<?php echo esc_attr( $settings['max'] ); ?>" step="<?php echo esc_attr( $settings['step'] ); ?>" value="<?php echo esc_attr( $value ); ?>"/>
798 - <?php if ( ! empty( $settings['unit'] ) ) : ?>
799 - <span class="merchant-range-unit"><?php echo esc_html( $settings['unit'] ); ?></span>
800 - <?php endif; ?>
801 - </div>
802 - <?php
803 - }
804 -
805 - /**
806 - * Field: Color
807 - */
808 - public static function color( $settings, $value ) {
809 - $settings = wp_parse_args( $settings, array(
810 - 'default' => '#212121',
811 - ) );
812 -
813 - ?>
814 - <div class="merchant-color">
815 - <div class="merchant-color-picker" data-default-color="<?php echo esc_attr( $settings['default'] ); ?>" style="background-color: <?php echo esc_attr( $value ); ?>;"></div>
816 - <input type="text" class="merchant-color-input" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $value ); ?>"/>
817 - </div>
818 - <?php
819 - }
820 -
821 - /**
822 - * Field: Gallery
823 - */
824 - public static function gallery( $settings, $value ) {
825 - $settings = wp_parse_args( $settings, array(
826 - 'label' => esc_html__( 'Select Images', 'merchant' ),
827 - ) );
828 -
829 - $images = ( ! empty( $value ) ) ? explode( ',', $value ) : array();
830 -
831 -
832 - echo '<div class="merchant-gallery-images">';
833 -
834 - if ( ! empty( $images ) ) :
835 -
836 - foreach ( $images as $image_id ) :
837 -
838 - $image = wp_get_attachment_image_src( $image_id, 'thumbnail' );
839 -
840 - if ( ! empty( $image ) && ! empty( $image[0] ) ) :
841 -
842 - echo sprintf( '<div class="merchant-gallery-image" data-item-id="%s">', esc_attr( $image_id ) );
843 -
844 - echo '<i class="merchant-gallery-remove dashicons dashicons-no-alt"></i>';
845 -
846 - echo sprintf( '<img src="%s" />', esc_url( $image[0] ) );
847 -
848 - echo '</div>';
849 -
850 - endif;
851 -
852 - endforeach;
853 -
854 - endif;
855 -
856 - echo '</div>';
857 -
858 - ?>
859 - <a href="#" class="merchant-gallery-button"><?php echo esc_html( $settings['label'] ); ?></a>
860 - <input type="hidden" class="merchant-gallery-input" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $value ); ?>"/>
861 - <?php
862 - }
863 -
864 - /**
865 - * Field: Upload
866 - */
867 - public static function upload( $settings, $value ) {
868 - $settings = wp_parse_args( $settings, array(
869 - 'label' => esc_html__( 'Select Image', 'merchant' ),
870 - ) );
871 -
872 - echo '<div class="merchant-upload-wrapper">';
873 -
874 - if ( ! empty( $value ) ) :
875 -
876 - $image = wp_get_attachment_image_src( $value, 'thumbnail' );
877 -
878 - if ( ! empty( $image ) && ! empty( $image[0] ) ) :
879 -
880 - echo '<div class="merchant-upload-image">';
881 - echo '<i class="merchant-upload-remove dashicons dashicons-no-alt"></i>';
882 - echo sprintf( '<img src="%s" />', esc_url( $image[0] ) );
883 - echo '</div>';
884 -
885 - endif;
886 -
887 - endif;
888 -
889 - echo '</div>';
890 -
891 - ?>
892 - <a href="#" class="merchant-upload-button"><?php echo esc_html( $settings['label'] ); ?></a>
893 - <input type="hidden" class="merchant-upload-input" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $value ); ?>"/>
894 - <?php
895 - }
896 -
897 - /**
898 - * Field: Warning
899 - */
900 - public static function warning( $settings ) {
901 - echo wp_kses_post( $settings['content'] );
902 - }
903 -
904 - /**
905 - * Field: Divider
906 - */
907 - public static function divider() {}
908 -
909 - /**
910 - * Field: Content
911 - */
912 - public static function content( $settings ) {
913 - echo wp_kses_post( $settings['content'] );
914 - }
915 -
916 - /**
917 - * Field: Sortable
918 - */
919 - public static function sortable( $settings, $value ) {
920 - ?>
921 - <div class="merchant-sortable">
922 - <ul class="merchant-sortable-list ui-sortable">
923 - <?php
924 - foreach ( $value as $option_key ) :
925 - $option_val = $settings['options'][ $option_key ];
926 -
927 - if ( in_array( $option_key, $value ) ) :
928 - ?>
929 - <li class="merchant-sortable-item" data-value="<?php echo esc_attr( $option_key ); ?>">
930 - <i class='dashicons dashicons-menu'></i>
931 - <i class="dashicons dashicons-visibility visibility"></i>
932 - <?php echo esc_html( $option_val ); ?>
933 - </li>
934 - <?php endif; ?>
935 - <?php endforeach; ?>
936 -
937 - <?php
938 - foreach ( $settings['options'] as $option_key => $option_val ) :
939 - if ( ! in_array( $option_key, $value ) ) :
940 - $invisible = ! in_array( $option_key, $value ) ? ' invisible' : '';
941 -
942 - ?>
943 - <li class="merchant-sortable-item<?php echo esc_attr( $invisible ); ?>" data-value="<?php echo esc_attr( $option_key ); ?>">
944 - <i class='dashicons dashicons-menu'></i>
945 - <i class="dashicons dashicons-visibility visibility"></i>
946 - <?php echo esc_html( $option_val ); ?>
947 - </li>
948 - <?php endif; ?>
949 - <?php endforeach; ?>
950 - </ul>
951 -
952 - <input class="merchant-sortable-input" type="hidden" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( wp_json_encode( $value ) ); ?>"/>
953 - </div>
954 - <?php
955 - }
956 -
957 - /**
958 - * Field: Sortable Repeater.
959 - */
960 - public static function sortable_repeater( $settings, $value ) {
961 - ?>
962 - <div class="merchant-sortable-repeater-control<?php echo isset( $settings['sorting'] ) && false === $settings['sorting'] ? ' disable-sorting' : ''; ?>">
963 - <div class="merchant-sortable-repeater sortable regular-field">
964 - <div class="repeater">
965 - <input type="text" value="" class="repeater-input"/><span class="dashicons dashicons-menu"></span><a class="customize-control-sortable-repeater-delete" href="#"><span
966 - class="dashicons dashicons-no-alt"></span></a>
967 - </div>
968 - </div>
969 - <button class="button customize-control-sortable-repeater-add" type="button"><?php echo esc_html( $settings['button_label'] ); ?></button>
970 - <input class="merchant-sortable-repeater-input" type="hidden" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( wp_json_encode( $value ) ); ?>"/>
971 - </div>
972 - <?php
973 - }
974 -
975 - /**
976 - * Field: Flexible Content.
977 - *
978 - * @param array $settings
979 - * @param mixed $value
980 - *
981 - * @return void
982 - */
983 - public static function flexible_content( $settings, $value ) {
984 - $values = ( is_array( $value ) && ! empty( $value ) ) ? $value : array();
985 - $empty = empty( $values ) ? 'empty' : '';
986 -
987 - $settings = wp_parse_args( $settings, array(
988 - 'sorting' => false,
989 - 'style' => 'default'
990 - ) );
991 -
992 - $classes = array(
993 - 'merchant-flexible-content-control',
994 - "{$settings['style']}-style"
995 - );
996 -
997 - if ( $settings['sorting'] === false ) {
998 - $classes[] = 'disable-sorting';
999 - }
1000 - ?>
1001 - <div class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>"
1002 - data-id="<?php echo esc_attr( $settings['id'] ) ?>">
1003 -
1004 - <div class="layouts" data-id="<?php echo esc_attr( $settings['id'] ) ?>">
1005 -
1006 - <?php foreach ( $settings['layouts'] as $layout_type => $layout ) : ?>
1007 -
1008 - <div class="layout" data-type="<?php echo esc_attr( $layout_type ) ?>">
1009 - <div class="layout-header">
1010 - <div class="layout-count">1</div>
1011 - <div class="layout-title">
1012 - <?php echo esc_html( $layout['title'] ) ?>
1013 - </div>
1014 - <div class="layout-actions">
1015 - <span class="customize-control-flexible-content-move dashicons dashicons-menu"></span>
1016 - <a class="customize-control-flexible-content-delete" href="#">
1017 - <span class="dashicons dashicons-no-alt"></span>
1018 - </a>
1019 - </div>
1020 - </div>
1021 - <div class="layout-body">
1022 - <?php foreach ( $layout['fields'] as $sub_field ) :
1023 - $classes = array( 'layout-field' );
1024 -
1025 - if ( isset( $sub_field['classes'] ) ) {
1026 - $classes = array_merge( $classes, $sub_field['classes'] );
1027 - } ?>
1028 - <div class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>">
1029 - <?php static::replace_field( $sub_field,
1030 - '',
1031 - array(
1032 - "name=\"merchant[{$sub_field['id']}]",
1033 - 'merchant-module-page-setting-field-upload',
1034 - 'merchant-module-page-setting-field-select_ajax'
1035 - ),
1036 - array(
1037 - "data-name=\"merchant[{$settings['id']}][0][{$sub_field['id']}]",
1038 - 'merchant-module-page-setting-field-upload template',
1039 - 'merchant-module-page-setting-field-select_ajax template'
1040 - ) ) ?>
1041 - </div>
1042 - <?php endforeach; ?>
1043 - <input type="hidden" data-name="merchant[<?php echo esc_attr( $settings['id'] ) ?>][0][layout]" value="<?php echo esc_attr( $layout_type ) ?>">
1044 - </div>
1045 - </div>
1046 -
1047 - <?php endforeach; ?>
1048 -
1049 - </div>
1050 -
1051 - <div class="merchant-flexible-content <?php echo esc_attr( $empty ); ?> sortable">
1052 -
1053 - <?php foreach ( $values as $option_key => $option ) : ?>
1054 - <div class="layout" data-type="<?php echo esc_attr( $option['layout'] ) ?>">
1055 - <div class="layout-header">
1056 - <div class="layout-count"><?php echo absint( $option_key + 1 ) ?></div>
1057 - <div class="layout-title">
1058 - <?php echo esc_html( $settings['layouts'][ $option['layout'] ]['title'] ) ?>
1059 - </div>
1060 - <div class="layout-actions">
1061 - <span class="customize-control-flexible-content-move dashicons dashicons-menu"></span>
1062 - <a class="customize-control-flexible-content-delete" href="#">
1063 - <span class="dashicons dashicons-no-alt"></span>
1064 - </a>
1065 - </div>
1066 - </div>
1067 - <div class="layout-body">
1068 - <?php foreach ( $settings['layouts'][ $option['layout'] ]['fields'] as $sub_field ) :
1069 - $classes = array( 'layout-field' );
1070 -
1071 - if ( isset( $sub_field['classes'] ) ) {
1072 - $classes = array_merge( $classes, $sub_field['classes'] );
1073 - } ?>
1074 - <div class="<?php echo esc_attr( implode( ' ', $classes ) ) ?>">
1075 - <?php static::replace_field( $sub_field,
1076 - $option[ $sub_field['id'] ],
1077 - "name=\"merchant[{$sub_field['id']}]",
1078 - "name=\"merchant[{$settings['id']}][{$option_key}][{$sub_field['id']}]" ) ?>
1079 - </div>
1080 - <?php endforeach; ?>
1081 - <input type="hidden" name="merchant[<?php echo esc_attr( $settings['id'] ) ?>][<?php echo absint( $option_key ) ?>][layout]"
1082 - value="<?php echo esc_attr( $option['layout'] ) ?>">
1083 - </div>
1084 - </div>
1085 -
1086 - <?php endforeach; ?>
1087 -
1088 - </div>
1089 -
1090 - <div class="customize-control-flexible-content-add-wrapper">
1091 - <div class="customize-control-flexible-content-add-list">
1092 - <?php foreach ( $settings['layouts'] as $layout_type => $layout ) : ?>
1093 - <a href="#"
1094 - class="customize-control-flexible-content-add"
1095 - data-id="<?php echo esc_attr( $settings['id'] ) ?>"
1096 - data-layout="<?php echo esc_attr( $layout_type ) ?>">
1097 - <?php echo esc_attr( $layout['title'] ) ?>
1098 - </a>
1099 - <?php endforeach; ?>
1100 - </div>
1101 - <button class="button customize-control-flexible-content-add-button" type="button"><?php echo esc_html( $settings['button_label'] ); ?></button>
1102 - </div>
1103 - </div>
1104 - <?php
1105 - }
1106 -
1107 - /**
1108 - * Field: Create Page.
1109 - */
1110 - public static function create_page( $settings, $value ) {
1111 - $page_id = get_option( $settings['option_name'] );
1112 -
1113 - echo '<div class="merchant-create-page-control">';
1114 -
1115 - if ( $page_id && post_exists( get_the_title( $page_id ) ) && 'publish' === get_post_status( $page_id ) ) {
1116 - echo wp_kses_post(
1117 - sprintf( /* translators: 1: link to edit page */
1118 - __( '<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>',
1119 - 'merchant' ),
1120 - get_admin_url() . 'post.php?post=' . $page_id . '&action=edit',
1121 - get_admin_url() . 'nav-menus.php'
1122 - )
1123 - );
1124 - } else {
1125 - echo '<div class="merchant-create-page-control-create-message">';
1126 - echo wp_kses_post(
1127 - sprintf( /* translators: 1: page name */
1128 - __( '<p class="merchant-module-page-setting-field-desc mrc-mt-0">It looks like you haven\'t created a <strong>%1$s</strong> page yet. Click the below button to create the page.</p>',
1129 - 'merchant' ),
1130 - $settings['page_title']
1131 - )
1132 - );
1133 - echo '</div>';
1134 - echo '<div class="merchant-create-page-control-success-message" style="display: none;">';
1135 - echo wp_kses_post(
1136 - sprintf( /* translators: 1: link to edit page */
1137 - __( '<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>',
1138 - 'merchant' ),
1139 - get_admin_url() . 'post.php?post=&action=edit',
1140 - get_admin_url() . 'nav-menus.php'
1141 - )
1142 - );
1143 - echo '</div>';
1144 - echo wp_kses_post(
1145 - sprintf( /* translators: 1: page title, 2: page meta key, 3: page meta value, 4: option name, 5: nonce, 6: loading text, 7: success text */
1146 - __( '<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>',
1147 - 'merchant' ),
1148 - __( 'Create Page', 'merchant' ),
1149 - $settings['page_title'],
1150 - $settings['page_meta_key'],
1151 - $settings['page_meta_value'],
1152 - $settings['option_name'],
1153 - wp_create_nonce( 'customize-create-page-control-nonce' ),
1154 - __( 'Creating...', 'merchant' ),
1155 - __( 'Created!', 'merchant' )
1156 - )
1157 - );
1158 - }
1159 -
1160 - echo '</div>';
1161 - }
1162 -
1163 - public static function dimensions( $settings, $value ) {
1164 - $settings = wp_parse_args( $settings, array(
1165 - 'units' => array(
1166 - 'px' => 'px',
1167 - 'rem' => 'rem',
1168 - 'em' => 'em',
1169 - 'vw' => 'vw',
1170 - 'vh' => 'vh',
1171 - '%' => '%'
1172 - ),
1173 - 'dimensions' => array(
1174 - 'top',
1175 - 'right',
1176 - 'bottom',
1177 - 'left'
1178 - )
1179 - ) );
1180 - $default_value = array(
1181 - 'unit' => reset( $settings['units'] )
1182 - );
1183 - foreach ( $settings['dimensions'] as $dimension ) {
1184 - $default_value[ $dimension ] = 0;
1185 - }
1186 - $value = wp_parse_args( $value, $default_value );
1187 - ?>
1188 - <div class="merchant-module-page-settings-unit">
1189 - <select name="merchant[<?php echo esc_attr( $settings['id'] ); ?>][unit]">
1190 - <?php foreach ( $settings['units'] as $key => $option ) : ?>
1191 - <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $value['unit'], $key, true ); ?>><?php echo esc_html( $option ); ?></option>
1192 - <?php endforeach; ?>
1193 - </select>
1194 - </div>
1195 - <div class="merchant-module-page-settings-dimensions">
1196 - <?php foreach ( $settings['dimensions'] as $dimension ) : ?>
1197 - <div>
1198 - <input id="merchant-<?php echo esc_attr( $settings['id'] ); ?>-<?php echo esc_attr( $dimension ) ?>"
1199 - type="number"
1200 - name="merchant[<?php echo esc_attr( $settings['id'] ); ?>][<?php echo esc_attr( $dimension ) ?>]"
1201 - value="<?php echo esc_attr( $value[ $dimension ] ); ?>"/>
1202 - <label for="merchant-<?php echo esc_attr( $settings['id'] ); ?>-<?php echo esc_attr( $dimension ) ?>">
1203 - <?php echo esc_html( ucfirst( $dimension ) ); ?>
1204 - </label>
1205 - </div>
1206 - <?php endforeach; ?>
1207 - </div>
1208 - <?php
1209 - }
1210 -
1211 - public static function responsive_dimensions( $settings, $value ) {
1212 - $settings = wp_parse_args( $settings, array(
1213 - 'units' => array(
1214 - 'px' => 'px',
1215 - 'rem' => 'rem',
1216 - 'em' => 'em',
1217 - 'vw' => 'vw',
1218 - 'vh' => 'vh',
1219 - '%' => '%'
1220 - ),
1221 - 'dimensions' => array(
1222 - 'top',
1223 - 'right',
1224 - 'bottom',
1225 - 'left'
1226 - ),
1227 - 'devices' => array(
1228 - 'desktop' => 'dashicons-desktop',
1229 - 'tablet' => 'dashicons-tablet',
1230 - 'mobile' => 'dashicons-smartphone'
1231 - )
1232 - ) );
1233 - $default_values = array();
1234 - foreach ( $settings['devices'] as $device => $icon ) {
1235 - $default_values[ $device ]['unit'] = reset( $settings['units'] );
1236 -
1237 - foreach ( $settings['dimensions'] as $dimension ) {
1238 - $default_values[ $device ][ $dimension ] = 0;
1239 - }
1240 - }
1241 - $value = wp_parse_args( $value, $default_values );
1242 - ?>
1243 - <div class="merchant-module-page-settings-responsive">
1244 - <ul class="merchant-module-page-settings-devices">
1245 - <?php foreach ( $settings['devices'] as $device => $icon ) : ?>
1246 - <li class="<?php echo esc_attr( $device ); ?>">
1247 - <button type="button" class="preview-<?php echo esc_attr( $device ); ?> <?php echo $device === key( $settings['devices'] ) ? 'active' : '' ?>"
1248 - data-device="<?php echo esc_attr( $device ); ?>">
1249 - <i class="dashicons <?php echo esc_attr( $icon ); ?>"></i>
1250 - </button>
1251 - </li>
1252 - <?php endforeach; ?>
1253 - </ul>
1254 - <?php foreach ( $settings['devices'] as $device => $icon ) : ?>
1255 - <div class="merchant-module-page-settings-device-container <?php echo $device === key( $settings['devices'] ) ? 'active' : '' ?>" data-device="<?php echo esc_attr( $device ); ?>">
1256 - <div class="merchant-module-page-settings-unit">
1257 - <select name="merchant[<?php echo esc_attr( $settings['id'] ); ?>][<?php echo esc_attr( $device ) ?>][unit]">
1258 - <?php foreach ( $settings['units'] as $key => $option ) : ?>
1259 - <option value="<?php echo esc_attr( $key ); ?>" <?php selected( $value[ esc_attr( $device ) ]['unit'], $key, true ); ?>><?php echo esc_html( $option ); ?></option>
1260 - <?php endforeach; ?>
1261 - </select>
1262 - </div>
1263 - <div class="merchant-module-page-settings-dimensions">
1264 - <?php foreach ( $settings['dimensions'] as $dimension ) : ?>
1265 - <div>
1266 - <input id="merchant-<?php echo esc_attr( $settings['id'] ); ?>-<?php echo esc_attr( $device ) ?>-<?php echo esc_attr( $dimension ) ?>"
1267 - type="number"
1268 - name="merchant[<?php echo esc_attr( $settings['id'] ); ?>][<?php echo esc_attr( $device ) ?>][<?php echo esc_attr( $dimension ) ?>]"
1269 - value="<?php echo esc_attr( $value[ $device ][ $dimension ] ); ?>"/>
1270 - <label for="merchant-<?php echo esc_attr( $settings['id'] ); ?>-<?php echo esc_attr( $device ) ?>-<?php echo esc_attr( $dimension ) ?>">
1271 - <?php echo esc_html( ucfirst( $dimension ) ); ?>
1272 - </label>
1273 - </div>
1274 - <?php endforeach; ?>
1275 - </div>
1276 - </div>
1277 - <?php endforeach; ?>
1278 - </div>
1279 -
1280 - <?php
1281 - }
1282 -
1283 - /**
1284 - * Field: Custom callback.
1285 - */
1286 - public static function custom_callback( $settings, $value ) {
1287 - if ( ! empty( $settings['class_name'] ) && ! empty( $settings['callback_name'] ) ) {
1288 - return call_user_func( array( $settings['class_name'], $settings['callback_name'] ), $settings, $value );
1289 - }
1290 -
1291 - if ( ! empty( $settings['callback_name'] ) ) {
1292 - return call_user_func( $settings['callback_name'], $settings, $value );
1293 - }
1294 -
1295 - return false;
1296 - }
1297 -
1298 - }
1299 -
1300 - Merchant_Admin_Options::instance();
1301 -}
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 +}