PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 1.10.0
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v1.10.0
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
merchant / admin / classes / class-merchant-admin-options.php

class-merchant-admin-options.php in Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant 1.10.0, at admin/classes/class-merchant-admin-options.php

2,676 lines 100.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 add_action( 'wp_ajax_merchant_admin_products_search', array( $this, 'products_search' ) );
40
41 add_action( 'clean_user_cache', array( $this, 'clear_customer_choices_cache' ), 10, 2 );
42 }
43
44 /**
45 * Enqueue scripts.
46 */
47 public function enqueue_scripts() {
48 if (
49 isset( $_GET['page'] ) && 'merchant' === $_GET['page'] // phpcs:ignore WordPress.Security.NonceVerification.Recommended
50 && isset( $_GET['module'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
51 ) {
52 wp_enqueue_script( 'merchant-select2', MERCHANT_URI . 'assets/vendor/select2/select2.full.min.js', array( 'jquery' ), '4.0.13', true );
53 wp_enqueue_style( 'merchant-select2', MERCHANT_URI . 'assets/vendor/select2/select2.min.css', array(), '4.0.13', 'all' );
54
55 wp_localize_script( 'merchant-select2', 'merchant_admin_options', array(
56 'ajaxurl' => admin_url( 'admin-ajax.php' ),
57 'ajaxnonce' => wp_create_nonce( 'merchant_admin_options' ),
58 'product_delete_confirmation_message' => esc_html__( 'Are you sure you want to remove this product?', 'merchant' ),
59 ) );
60
61 wp_enqueue_style('date-picker', MERCHANT_URI . 'assets/vendor/air-datepicker/air-datepicker.css', array(), MERCHANT_VERSION, 'all' );
62 wp_enqueue_script('date-picker', MERCHANT_URI . 'assets/vendor/air-datepicker/air-datepicker.js', array( 'jquery' ), MERCHANT_VERSION, true );
63 wp_localize_script( 'date-picker', 'merchant_datepicker_locale', array(
64 wp_json_encode(
65 array(
66 'days' => array(
67 esc_html__( 'Sunday', 'merchant' ),
68 esc_html__( 'Monday', 'merchant' ),
69 esc_html__( 'Tuesday', 'merchant' ),
70 esc_html__( 'Wednesday', 'merchant' ),
71 esc_html__( 'Thursday', 'merchant' ),
72 esc_html__( 'Friday', 'merchant' ),
73 esc_html__( 'Saturday', 'merchant' ),
74 ),
75 'daysShort' => array(
76 esc_html__( 'Sun', 'merchant' ),
77 esc_html__( 'Mon', 'merchant' ),
78 esc_html__( 'Tue', 'merchant' ),
79 esc_html__( 'Wed', 'merchant' ),
80 esc_html__( 'Thu', 'merchant' ),
81 esc_html__( 'Fri', 'merchant' ),
82 esc_html__( 'Sat', 'merchant' ),
83 ),
84 'daysMin' => array(
85 esc_html__( 'Su', 'merchant' ),
86 esc_html__( 'Mo', 'merchant' ),
87 esc_html__( 'Tu', 'merchant' ),
88 esc_html__( 'We', 'merchant' ),
89 esc_html__( 'Th', 'merchant' ),
90 esc_html__( 'Fr', 'merchant' ),
91 esc_html__( 'Sa', 'merchant' ),
92 ),
93 'months' => array(
94 esc_html__( 'January', 'merchant' ),
95 esc_html__( 'February', 'merchant' ),
96 esc_html__( 'March', 'merchant' ),
97 esc_html__( 'April', 'merchant' ),
98 esc_html__( 'May', 'merchant' ),
99 esc_html__( 'June', 'merchant' ),
100 esc_html__( 'July', 'merchant' ),
101 esc_html__( 'August', 'merchant' ),
102 esc_html__( 'September', 'merchant' ),
103 esc_html__( 'October', 'merchant' ),
104 esc_html__( 'November', 'merchant' ),
105 esc_html__( 'December', 'merchant' ),
106 ),
107 'monthsShort' => array(
108 esc_html__( 'Jan', 'merchant' ),
109 esc_html__( 'Feb', 'merchant' ),
110 esc_html__( 'Mar', 'merchant' ),
111 esc_html__( 'Apr', 'merchant' ),
112 esc_html__( 'May', 'merchant' ),
113 esc_html__( 'Jun', 'merchant' ),
114 esc_html__( 'Jul', 'merchant' ),
115 esc_html__( 'Aug', 'merchant' ),
116 esc_html__( 'Sep', 'merchant' ),
117 esc_html__( 'Oct', 'merchant' ),
118 esc_html__( 'Nov', 'merchant' ),
119 esc_html__( 'Dec', 'merchant' ),
120 ),
121 'clear' => esc_html__( 'Clear', 'merchant' ),
122 )
123 ),
124 ) );
125 }
126 }
127
128 /**
129 * Ajax callbacks.
130 */
131 public function create_page_control_ajax_callback() {
132 check_ajax_referer( 'customize-create-page-control-nonce', 'nonce' );
133
134 // Check current user capabilities
135 if ( ! current_user_can( 'manage_options' ) ) {
136 wp_send_json_error( 'You are not allowed to do this.' );
137 }
138
139 $page_title = isset( $_POST['page_title'] ) ? sanitize_text_field( $_POST['page_title'] ) : '';
140 $page_meta_key = isset( $_POST['page_meta_key'] ) ? sanitize_text_field( $_POST['page_meta_key'] ) : '';
141 $page_meta_value = isset( $_POST['page_meta_value'] ) ? sanitize_text_field( $_POST['page_meta_value'] ) : '';
142 $option_name = isset( $_POST['option_name'] ) ? sanitize_text_field( $_POST['option_name'] ) : '';
143
144 $meta_input = array();
145 if ( $page_meta_key && $page_meta_value ) {
146 $meta_input = array(
147 $page_meta_key => $page_meta_value,
148 );
149 }
150
151 $postarr = array(
152 'post_type' => 'page',
153 'post_status' => 'publish',
154 'post_title' => $page_title,
155 'post_content' => '',
156 'meta_input' => $meta_input,
157 );
158
159 $page_id = wp_insert_post( $postarr );
160
161 if ( ! is_wp_error( $page_id ) ) {
162 if ( $option_name ) {
163 update_option( $option_name, $page_id );
164 }
165
166 wp_send_json( array(
167 'status' => 'success',
168 'page_id' => $page_id,
169 ) );
170 } else {
171 wp_send_json( array(
172 'status' => 'error',
173 ) );
174 }
175 }
176
177 /**
178 * Select content ajax callback.
179 *
180 */
181 public function select_content_ajax() {
182 $term = ( isset( $_GET['term'] ) ) ? sanitize_text_field( wp_unslash( $_GET['term'] ) ) : '';
183 $nonce = ( isset( $_GET['nonce'] ) ) ? sanitize_text_field( wp_unslash( $_GET['nonce'] ) ) : '';
184 $source = ( isset( $_GET['source'] ) ) ? sanitize_text_field( wp_unslash( $_GET['source'] ) ) : '';
185
186 // Check current user capabilities
187 if ( ! current_user_can( 'manage_options' ) ) {
188 wp_send_json_error( 'You are not allowed to do this.' );
189 }
190
191 if ( ! empty( $term ) && ! empty( $source ) && ! empty( $nonce ) && wp_verify_nonce( $nonce, 'merchant_admin_options' ) ) {
192 $options = array();
193
194 switch ( $source ) {
195 case 'post':
196 case 'product':
197 $query = new WP_Query( array(
198 's' => $term,
199 'post_type' => $source,
200 'post_status' => 'publish',
201 'posts_per_page' => 25,
202 'order' => 'DESC',
203 ) );
204
205 if ( ! empty( $query->posts ) ) {
206 foreach ( $query->posts as $post ) {
207 $options[] = array(
208 'id' => $post->ID,
209 'text' => $post->post_title,
210 );
211 }
212 }
213
214 break;
215
216 case 'user':
217 $query = new WP_User_Query( array(
218 'search' => '*' . $term . '*',
219 'search_columns' => array( 'user_login', 'user_nicename', 'user_email', 'user_url' ),
220 'number' => 25,
221 ) );
222
223 if ( ! empty( $query->results ) ) {
224 foreach ( $query->results as $user ) {
225 $options[] = array(
226 'id' => $user->ID,
227 'text' => $user->display_name,
228 );
229 }
230 }
231
232 break;
233 }
234
235 wp_send_json_success( $options );
236 } else {
237 wp_send_json_error();
238 }
239 }
240
241 /**
242 * Get option.
243 */
244 public static function get( $module, $setting, $default_val ) {
245 $options = get_option( 'merchant', array() );
246
247 $value = $default_val;
248
249 if ( isset( $options[ $module ][ $setting ] ) ) {
250 $value = $options[ $module ][ $setting ];
251 }
252
253 /**
254 * Hook: merchant_get_option filter.
255 * Fires after getting module option.
256 *
257 * @param mixed $value Option value.
258 * @param string $module Module ID.
259 * @param string $setting Setting ID.
260 * @param mixed $default_val Default value.
261 *
262 * @since 1.9.3
263 */
264 return apply_filters( 'merchant_get_option', $value, $module, $setting, $default_val );
265 }
266
267 /**
268 * Set option.
269 */
270 public static function set( $module, $setting, $value ) {
271 $options = get_option( 'merchant', array() );
272 $options[ $module ][ $setting ] = $value;
273 update_option( 'merchant', $options );
274 }
275
276 /**
277 * Delete option.
278 */
279 public static function delete( $module, $setting ) {
280 $options = get_option( 'merchant', array() );
281 unset( $options[ $module ][ $setting ] );
282 update_option( 'merchant', $options );
283 }
284
285 /**
286 * Get all options.
287 */
288 public static function get_all( $module ) {
289 $options = get_option( 'merchant', array() );
290 $value = array();
291
292 if ( isset( $options[ $module ] ) ) {
293 $value = $options[ $module ];
294 }
295
296 return $value;
297 }
298
299 /**
300 * Create options.
301 */
302 public static function create( $settings ) {
303 $module_id = ( isset( $_GET['module'] ) ) ? sanitize_text_field( wp_unslash( $_GET['module'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
304
305 /**
306 * Hook: merchant_module_settings
307 *
308 * @param array $settings Module settings.
309 * @param string $module_id Module ID.
310 *
311 * @since 1.0
312 */
313 $settings = apply_filters( 'merchant_module_settings', $settings, $module_id );
314
315 self::save_options( $settings );
316
317 $options = get_option( 'merchant', array() );
318 ?>
319 <div class="merchant-module-page-settings">
320 <div class="merchant-module-page-setting-box">
321 <?php
322 if ( ! empty( $settings['title'] ) ) : ?>
323 <div class="merchant-module-page-setting-title">
324 <?php
325 echo esc_html( $settings['title'] ); ?>
326 <?php
327 if ( ! empty( $settings['subtitle'] ) ) : ?>
328 <div class="merchant-module-page-setting-subtitle"><?php
329 echo esc_html( $settings['subtitle'] ); ?></div>
330 <?php
331 endif; ?>
332 </div>
333 <?php
334 endif; ?>
335 <div class="merchant-module-page-setting-fields">
336 <?php
337
338 if ( ! empty( $settings['fields'] ) ) {
339 foreach ( $settings['fields'] as $field ) {
340 $value = null;
341
342 if ( isset( $field['default'] ) ) {
343 $value = $field['default'];
344 }
345
346 if ( isset( $field['id'] ) && isset( $options[ $settings['module'] ] ) && isset( $options[ $settings['module'] ][ $field['id'] ] ) ) {
347 $value = $options[ $settings['module'] ][ $field['id'] ];
348 }
349
350 $current_module = Merchant_Admin_Modules::get_module_info( $settings['module'] );
351 $is_pro_module = ! merchant_is_pro_active() && isset( $current_module['pro'] ) && $current_module['pro'] === true;
352 $is_pro_field = ! merchant_is_pro_active() && isset( $field['pro'] ) && $field['pro'] === true;
353
354 if ( $is_pro_module || $is_pro_field ) {
355 self::disabled_field( $field, $value );
356 } else {
357 self::field( $field, $value, $module_id );
358 }
359 }
360 }
361 ?>
362 </div>
363 </div>
364 </div>
365 <?php
366 }
367
368 /**
369 * Save options.
370 */
371 public static function save_options( $settings ) {
372 $save = ( isset( $_POST['merchant_save'] ) ) ? sanitize_text_field( wp_unslash( $_POST['merchant_save'] ) ) : '';
373 $reset = ( isset( $_POST['merchant_reset'] ) ) ? sanitize_text_field( wp_unslash( $_POST['merchant_reset'] ) ) : '';
374 $nonce = ( isset( $_POST['merchant_nonce'] ) ) ? sanitize_text_field( wp_unslash( $_POST['merchant_nonce'] ) ) : '';
375
376 if ( ! wp_verify_nonce( $nonce, 'merchant_nonce' ) ) {
377 return;
378 }
379
380 if ( ! current_user_can( 'manage_options' ) ) {
381 return;
382 }
383
384 $options = get_option( 'merchant', array() );
385
386 if ( ! empty( $save ) ) {
387 if ( ! empty( $settings['fields'] ) ) {
388 foreach ( $settings['fields'] as $field ) {
389 if ( ! isset( $field['id'] ) ) {
390 continue;
391 }
392
393 if ( ! merchant_is_pro_active() && isset( $field['pro'] ) && $field['pro'] === true ) {
394 continue;
395 }
396
397 $value = null;
398
399 if ( isset( $_POST['merchant'] ) && isset( $_POST['merchant'][ $field['id'] ] ) ) {
400 if ( 'textarea_code' === $field['type'] ) {
401 $value = wp_kses( $_POST['merchant'][ $field['id'] ], merchant_kses_allowed_tags_for_code_snippets() );
402 } elseif ( 'textarea_multiline' === $field['type'] ) {
403 $value = sanitize_textarea_field( $_POST['merchant'][ $field['id'] ] );
404 } elseif ( is_array( $_POST['merchant'][ $field['id'] ] ) ) {
405 $value = array_filter( map_deep( wp_unslash( $_POST['merchant'][ $field['id'] ] ), 'sanitize_text_field' ) );
406 } else {
407 $value = sanitize_text_field( wp_unslash( $_POST['merchant'][ $field['id'] ] ) );
408 }
409 }
410
411 $options[ $settings['module'] ][ $field['id'] ] = self::sanitize( $field, $value );
412 }
413 }
414 } elseif ( ! empty( $reset ) ) {
415 $options[ $settings['module'] ] = array();
416 }
417
418 update_option( 'merchant', $options );
419
420 /**
421 * Hook: merchant_options_saved, fired after saving module options.
422 *
423 * @param string $module module ID.
424 * @param array $options module options.
425 *
426 * @since 1.9.3
427 */
428 do_action( 'merchant_options_saved', $settings['module'], $options[ $settings['module'] ] );
429
430 /**
431 * Hook: merchant_options_saved, fired after saving specific module options.
432 *
433 * @param array $options module options.
434 *
435 * @since 1.9.3
436 */
437 do_action( "merchant_options_saved_{$settings['module']}", $options[ $settings['module'] ] );
438 }
439
440 /**
441 * Sanitize options.
442 */
443 public static function sanitize( $field, $value ) {
444 // Callback for custom sanitize methods.
445 if ( ! empty( $field['sanitize'] ) && is_callable( $field['sanitize'] ) ) {
446 return call_user_func( $field['sanitize'], $value );
447 }
448
449 switch ( $field['type'] ) {
450 case 'text':
451 case 'color':
452 case 'number':
453 case 'select_size_chart':
454 $value = sanitize_text_field( $value );
455 break;
456
457 case 'textarea':
458 $value = sanitize_textarea_field( $value );
459 break;
460
461 case 'textarea_code':
462 $value = $value;
463 break;
464
465 case 'checkbox_multiple':
466 if ( is_array( $value ) && ! empty( $value ) ) {
467 $value = array_filter( array_map( 'sanitize_text_field', $value ) );
468 } else {
469 $value = array();
470 }
471 break;
472
473 case 'checkbox':
474 case 'switcher':
475 $value = ( '1' === $value ) ? 1 : 0;
476 break;
477
478 case 'range':
479 case 'number':
480 $value = absint( $value );
481 break;
482 case 'select_ajax':
483 if ( is_array( $value ) && ! empty( $value ) ) {
484 $value = array_filter( array_map( 'sanitize_text_field', $value ) );
485 } elseif ( is_string( $value ) ) {
486 $value = sanitize_text_field( $value );
487 } else {
488 $value = isset( $field['multiple'] ) && $field['multiple'] === false ? '' : array();
489 }
490 break;
491 case 'radio':
492 case 'radio_alt':
493 case 'select':
494 case 'choices':
495 case 'buttons':
496 case 'buttons_alt':
497 case 'buttons_content':
498 $value = ( in_array( $value, array_keys( $field['options'] ), true ) ) ? sanitize_key( $value ) : '';
499 break;
500
501 case 'hook_select':
502 $value = is_array( $value ) ? $value : array();
503
504 foreach ( $value as $key => $val ) {
505 if ( $key === 'hook_name' ) {
506 $value[ $key ] = in_array( $val, array_keys( $field['options'] ), true ) ? sanitize_key( $val ) : '';
507 } else {
508 $value[ $key ] = (int) $val;
509 }
510 }
511
512 break;
513
514 case 'code-editor':
515 $value = wp_kses_post( $value );
516 break;
517
518 case 'sortable':
519 $values = json_decode( $value );
520 $value = array();
521
522 foreach ( $values as $val ) {
523 if ( in_array( $val, array_keys( $field['options'] ), true ) ) {
524 $value[] = sanitize_key( $val );
525 }
526 }
527 break;
528 case 'dimensions':
529 $values = is_array( $value ) ? $value : array();
530
531 foreach ( $values as $key => $val ) {
532 if ( $key === 'unit' ) {
533 $value[ $key ] = sanitize_key( $value[ $key ] );
534 } else {
535 $value[ $key ] = absint( $value[ $key ] );
536 }
537 }
538 break;
539 case 'responsive_dimensions':
540 $values = is_array( $value ) ? $value : array();
541
542 foreach ( $values as $device => $device_fields ) {
543 foreach ( $device_fields as $device_field => $device_field_val ) {
544 if ( $device_field === 'unit' ) {
545 $value[ $device ][ $device_field ] = sanitize_key( $device_field_val );
546 } else {
547 $value[ $device ][ $device_field ] = absint( $device_field_val );
548 }
549 }
550 }
551 break;
552
553 case 'sortable_repeater':
554 $values = json_decode( $value );
555 $value = array_map( 'sanitize_text_field', $values );
556 break;
557 case 'flexible_content':
558 $value = ! is_array( $value ) || empty( $value ) ? array() : $value;
559
560 $value = array_map( function ( $sub_fields ) use ( $field ) {
561 foreach ( $sub_fields as $sub_field => $value ) {
562 if ( $sub_field === 'layout' ) {
563 $sub_fields[ $sub_field ] = sanitize_text_field( $value );
564 } else {
565 $layout_field = array_filter( $field['layouts'][ $sub_fields['layout'] ]['fields'], function ( $layout_field ) use ( $sub_field ) {
566 return $layout_field['id'] === $sub_field;
567 } );
568
569
570 $sub_fields[ $sub_field ] = self::sanitize( reset( $layout_field ), $value );
571 }
572 }
573
574 return $sub_fields;
575 }, $value );
576
577 break;
578 }
579
580 return $value;
581 }
582
583 /**
584 * Field
585 */
586 public static function field( $settings, $value, $module_id = '') {
587
588 if ( ! empty( $settings['type'] ) ) {
589 $type = $settings['type'];
590
591 $id = ( ! empty( $settings['id'] ) ) ? $settings['id'] : '';
592 $class = ( ! empty( $settings['class'] ) ) ? ' ' . $settings['class'] : '';
593 $condition = ( ! empty( $settings['condition'] ) ) ? $settings['condition'] : array();
594 $conditions = ( ! empty( $settings['conditions'] ) ) ? $settings['conditions'] : ''; //Docs here: https://github.com/athemes/Merchant/pull/133
595 $default = ( ! empty( $settings['default'] ) ) ? $settings['default'] : null;
596 $is_upsell = ! merchant_is_pro_active() && isset( $settings['pro'] ) && $settings['pro'] === true;
597
598 if ( ! $value && ( 0 !== $value && '0' !== $value ) ) {
599 if ( $type === 'checkbox_multiple' ) {
600 $value = is_array( $value ) ? $value : (array) $default;
601 } else {
602 $value = $default;
603 }
604 }
605
606 $wrapper_classes = array( 'merchant-module-page-setting-field' );
607 $wrapper_classes[] = 'merchant-module-page-setting-field-' . $type;
608
609 if ( ! empty( $class ) ) {
610 $wrapper_classes[] = $class;
611 }
612
613 /**
614 * Hook 'merchant_admin_module_field_wrapper_classes'
615 *
616 * @since 1.9.3
617 */
618 $wrapper_classes = apply_filters( 'merchant_admin_module_field_wrapper_classes', $wrapper_classes, $settings, $value, $module_id );
619
620 echo '<div class="'. esc_attr( implode( ' ', $wrapper_classes ) ) .'" data-id="'
621 . esc_attr( $id ) . '" data-type="' . esc_attr( $type ) . '" data-condition="' . esc_attr( wp_json_encode( $condition ) ) .
622 '" data-conditions="' . ( $conditions ? esc_attr( wp_json_encode( $conditions ) ) : "" ) . '">';
623 if ( ! empty( $settings['title'] ) ) {
624 ?>
625 <div class="merchant-module-page-setting-field-title<?php echo esc_attr( $is_upsell ? ' merchant-module-page-setting-field-title__has-upsell' : '' ); ?>">
626 <?php echo esc_html( $settings['title'] ); ?>
627
628 <?php if ( $is_upsell ) : ?>
629 <a href="<?php echo esc_url( 'https://athemes.com/merchant-upgrade?utm_source=plugin_dashboard&utm_medium=merchant_dashboard&utm_campaign=Merchant' ); ?>" class="merchant-module-pro-upsell" target="_blank">
630 <span class="merchant-pro-badge merchant-pro-tooltip" data-tooltip-message="<?php echo esc_attr__( 'This option is only available on Merchant Pro', 'merchant' ); ?>">
631 <svg width="28" height="16" viewBox="0 0 28 16" fill="none" xmlns="http://www.w3.org/2000/svg">
632 <path d="M7.41309 8.90723H5.58203V7.85254H7.41309C7.71257 7.85254 7.95508 7.80371 8.14062 7.70605C8.32943 7.60514 8.46777 7.46842 8.55566 7.2959C8.64355 7.12012 8.6875 6.91992 8.6875 6.69531C8.6875 6.47721 8.64355 6.27376 8.55566 6.08496C8.46777 5.89616 8.32943 5.74316 8.14062 5.62598C7.95508 5.50879 7.71257 5.4502 7.41309 5.4502H6.02148V11.5H4.67871V4.39062H7.41309C7.96647 4.39062 8.43848 4.48991 8.8291 4.68848C9.22298 4.88379 9.52246 5.1556 9.72754 5.50391C9.93587 5.84896 10.04 6.24284 10.04 6.68555C10.04 7.14453 9.93587 7.54004 9.72754 7.87207C9.52246 8.2041 9.22298 8.45964 8.8291 8.63867C8.43848 8.81771 7.96647 8.90723 7.41309 8.90723ZM11.0947 4.39062H13.6777C14.2181 4.39062 14.682 4.47201 15.0693 4.63477C15.4567 4.79753 15.7546 5.03841 15.9629 5.35742C16.1712 5.67643 16.2754 6.06868 16.2754 6.53418C16.2754 6.90202 16.2103 7.22103 16.0801 7.49121C15.9499 7.76139 15.766 7.98763 15.5283 8.16992C15.2939 8.35221 15.0173 8.49544 14.6982 8.59961L14.2783 8.81445H11.998L11.9883 7.75488H13.6924C13.9691 7.75488 14.1986 7.70605 14.3809 7.6084C14.5632 7.51074 14.6999 7.37565 14.791 7.20312C14.8854 7.0306 14.9326 6.83366 14.9326 6.6123C14.9326 6.37467 14.887 6.1696 14.7959 5.99707C14.7048 5.82129 14.5664 5.6862 14.3809 5.5918C14.1953 5.4974 13.9609 5.4502 13.6777 5.4502H12.4375V11.5H11.0947V4.39062ZM15.1084 11.5L13.4629 8.31641L14.8838 8.31152L16.5488 11.4316V11.5H15.1084ZM23.209 7.76465V8.13086C23.209 8.66797 23.1374 9.15137 22.9941 9.58105C22.8509 10.0075 22.6475 10.3704 22.3838 10.6699C22.1201 10.9694 21.806 11.1989 21.4414 11.3584C21.0768 11.5179 20.6715 11.5977 20.2256 11.5977C19.7861 11.5977 19.3825 11.5179 19.0146 11.3584C18.6501 11.1989 18.3343 10.9694 18.0674 10.6699C17.8005 10.3704 17.5938 10.0075 17.4473 9.58105C17.3008 9.15137 17.2275 8.66797 17.2275 8.13086V7.76465C17.2275 7.22428 17.3008 6.74089 17.4473 6.31445C17.5938 5.88802 17.7988 5.52507 18.0625 5.22559C18.3262 4.92285 18.6403 4.69173 19.0049 4.53223C19.3727 4.37272 19.7764 4.29297 20.2158 4.29297C20.6618 4.29297 21.0671 4.37272 21.4316 4.53223C21.7962 4.69173 22.1104 4.92285 22.374 5.22559C22.641 5.52507 22.846 5.88802 22.9893 6.31445C23.1357 6.74089 23.209 7.22428 23.209 7.76465ZM21.8516 8.13086V7.75488C21.8516 7.36751 21.8158 7.02734 21.7441 6.73438C21.6725 6.43815 21.5667 6.18913 21.4268 5.9873C21.2868 5.78548 21.1143 5.63411 20.9092 5.5332C20.7041 5.42904 20.473 5.37695 20.2158 5.37695C19.9554 5.37695 19.7243 5.42904 19.5225 5.5332C19.3239 5.63411 19.1546 5.78548 19.0146 5.9873C18.8747 6.18913 18.7673 6.43815 18.6924 6.73438C18.6208 7.02734 18.585 7.36751 18.585 7.75488V8.13086C18.585 8.51497 18.6208 8.85514 18.6924 9.15137C18.7673 9.44759 18.8747 9.69824 19.0146 9.90332C19.1579 10.1051 19.3304 10.2581 19.5322 10.3623C19.734 10.4665 19.9652 10.5186 20.2256 10.5186C20.486 10.5186 20.7171 10.4665 20.9189 10.3623C21.1208 10.2581 21.29 10.1051 21.4268 9.90332C21.5667 9.69824 21.6725 9.44759 21.7441 9.15137C21.8158 8.85514 21.8516 8.51497 21.8516 8.13086Z" fill="#3858E9"/>
633 <rect x="0.5" y="1" width="27" height="14" rx="1.5" stroke="#3858E9"/>
634 </svg>
635 </span>
636 </a>
637 <?php endif; ?>
638 </div>
639 <?php
640 }
641
642 echo '<div class="merchant-module-page-setting-field-inner merchant-field-' . esc_attr( $id ) . '">';
643 if ( method_exists( 'Merchant_Admin_Options', $type ) ) {
644 call_user_func( array( 'Merchant_Admin_Options', $type ), $settings, $value, $module_id );
645 } else {
646 esc_html_e( 'Field not found!', 'merchant' );
647 }
648 echo '</div>';
649
650 $hidden_desc = $settings['hidden_desc'] ?? '';
651
652 /**
653 * Hook 'merchant_admin_module_field_hidden_description'
654 *
655 * @since 1.9.3
656 */
657 $hidden_desc = apply_filters( 'merchant_admin_module_field_hidden_description', $hidden_desc, $settings, $value, $module_id );
658
659 $desc = ( ! empty( $settings['desc'] ) ) ? $settings['desc'] : '';
660
661 /**
662 * Hook 'merchant_admin_module_field_description'
663 *
664 * @since 1.9.3
665 */
666 $desc = apply_filters( 'merchant_admin_module_field_description', $desc, $settings, $value, $module_id );
667
668 if ( ! empty( $desc ) ) {
669 $hidden_desc_html = '';
670 if ( ! empty( $hidden_desc ) ) {
671 $hidden_desc_html = '<div class="merchant-module-page-setting-field-hidden-desc-trigger" data-show-text="' . esc_html__( 'Show more', 'merchant' ) . '" data-hidden-text="' . esc_html__( 'Show less', 'merchant' ) . '"><span>' . esc_html__( 'Show more', 'merchant' ) . '</span>';
672 $hidden_desc_html .= '<img src="' . esc_url( MERCHANT_URI . '/assets/images/arrow-down.svg' ) . '" alt="Merchant" />';
673 $hidden_desc_html .= '</div>';
674 }
675
676 printf( '<div class="merchant-module-page-setting-field-desc' . esc_attr( $hidden_desc ? ' merchant-module-page-setting-field-desc-has-hidden-desc' : '' ) .'">%s%s</div>', wp_kses_post( $desc ), wp_kses_post( $hidden_desc_html ) );
677 }
678
679 if ( ! empty( $hidden_desc ) ) {
680 printf( '<div class="merchant-module-page-setting-field-hidden-desc">%s</div>', wp_kses_post( nl2br( $hidden_desc ) ) );
681 }
682
683 echo '</div>';
684 }
685 }
686
687 /**
688 * Disabled field
689 *
690 * @param array $settings
691 * @param mixed $value
692 *
693 * @return void
694 */
695 public static function disabled_field( $settings, $value, $module_id = '') {
696 static::replace_field(
697 $settings,
698 $value,
699 array(
700 '<input ',
701 '<select ',
702 'merchant-module-page-setting-field-inner',
703 ),
704 array(
705 '<input disabled ',
706 '<select disabled ',
707 'merchant-module-page-setting-field-inner disabled',
708 ),
709 $module_id
710 );
711 }
712
713 /**
714 * Modified field.
715 *
716 * @param $settings
717 * @param $value
718 * @param $search
719 * @param $replace
720 *
721 * @return void
722 */
723 public static function replace_field( $settings, $value, $search, $replace, $module_id = '') {
724 ob_start();
725 self::field( $settings, $value, $module_id );
726 $field = ob_get_clean();
727
728 echo wp_kses( str_replace( $search, $replace, $field ), merchant_kses_allowed_tags( array( 'all' ) ) );
729 }
730
731 /**
732 * Field: Text
733 */
734 public static function text( $settings, $value, $module_id = '' ) {
735 ?>
736 <input type="text" name="merchant[<?php
737 echo esc_attr( $settings['id'] ); ?>]" value="<?php
738 echo esc_attr( $value ); ?>" placeholder="<?php
739 echo esc_attr( $settings['placeholder'] ?? '' ); ?>"/>
740 <?php
741 }
742
743 /**
744 * Field: Text (readonly)
745 */
746 public static function text_readonly( $settings, $value, $module_id = '' ) {
747 ?>
748 <input type="text" value="<?php
749 echo esc_attr( $value ); ?>" readonly/>
750 <?php
751 }
752
753 /**
754 * Field: Number
755 */
756 public static function number( $settings, $value, $module_id = '' ) {
757 ?>
758 <input type="number" name="merchant[<?php
759 echo esc_attr( $settings['id'] ); ?>]" value="<?php
760 echo esc_attr( $value ); ?>"<?php
761 echo isset( $settings['step'] ) ? ' step="' . esc_attr( $settings['step'] ) . '"' : '';
762 echo isset( $settings['max'] ) ? ' max="' . esc_attr( $settings['max'] ) . '"' : '';
763 echo isset( $settings['min'] ) ? ' min="' . esc_attr( $settings['min'] ) . '"' : '' ?>
764 placeholder="<?php echo esc_attr( $settings['placeholder'] ?? '' ); ?>"/>
765 <?php
766 }
767
768 /**
769 * Field: Textarea
770 */
771 public static function textarea( $settings, $value, $module_id = '' ) {
772 $value = ( $value ) ? $value : '';
773 ?>
774 <textarea name="merchant[<?php
775 echo esc_attr( $settings['id'] ); ?>]"><?php
776 echo wp_kses_post( $value ); ?></textarea>
777 <?php
778 }
779
780 /**
781 * Field: Textarea
782 */
783 public static function textarea_multiline( $settings, $value, $module_id = '' ) {
784 $value = ( $value ) ? $value : '';
785 ?>
786 <textarea name="merchant[<?php
787 echo esc_attr( $settings['id'] ); ?>]"><?php
788 echo wp_kses_post( $value ); ?></textarea>
789 <?php
790 }
791
792 /**
793 * Field: Textarea Code Snippet.
794 */
795 public static function textarea_code( $settings, $value, $module_id = '' ) {
796 $value = ( $value ) ? $value : '';
797 ?>
798 <textarea name="merchant[<?php
799 echo esc_attr( $settings['id'] ); ?>]"><?php
800 echo wp_kses( $value, merchant_kses_allowed_tags_for_code_snippets() ); ?></textarea>
801 <?php
802 }
803
804 /**
805 * Field: Checkbox
806 */
807 public static function checkbox( $settings, $value, $module_id = '' ) {
808 ?>
809 <div>
810 <label>
811 <input type="checkbox" name="merchant[<?php
812 echo esc_attr( $settings['id'] ); ?>]" value="1" <?php
813 checked( $value, 1, true ); ?> />
814 <?php
815 if ( ! empty( $settings['label'] ) ) : ?>
816 <span><?php
817 echo esc_html( $settings['label'] ); ?></span>
818 <?php
819 endif; ?>
820 </label>
821 </div>
822 <?php
823 }
824
825 /**
826 * Field: Checkbox multiple
827 */
828 public static function checkbox_multiple( $settings, $value ) {
829 if ( ! empty( $settings['options'] ) ) : ?>
830 <?php
831 foreach ( $settings['options'] as $key => $option ) : ?>
832 <label>
833 <input
834 type="checkbox" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>][]"
835 value="<?php echo esc_attr( $key ); ?>"
836 <?php checked( in_array( $key, $value, true ), true ); ?>
837 />
838 <span><?php echo esc_html( $option ); ?></span>
839 </label>
840 <?php
841 endforeach; ?>
842 <?php
843 endif;
844 }
845
846 /**
847 * Field: Switcher
848 */
849 public static function switcher( $settings, $value, $module_id = '' ) {
850 ?>
851 <div class="merchant-toggle-switch">
852 <input type="checkbox" id="<?php
853 echo esc_attr( $settings['id'] ); ?>" name="merchant[<?php
854 echo esc_attr( $settings['id'] ); ?>]" value="1" <?php
855 checked( $value, 1, true ); ?>
856 class="toggle-switch-checkbox"/>
857 <label class="toggle-switch-label" for="<?php
858 echo esc_attr( $settings['id'] ); ?>">
859 <span class="toggle-switch-inner"></span>
860 <span class="toggle-switch-switch"></span>
861 </label>
862 <?php
863 if ( ! empty( $settings['label'] ) ) : ?>
864 <span><?php
865 echo esc_html( $settings['label'] ); ?></span>
866 <?php
867 endif; ?>
868 </div>
869 <?php
870 }
871
872 /**
873 * Field: Radio
874 */
875 public static function radio( $settings, $value, $module_id = '' ) {
876 ?>
877 <?php
878 if ( ! empty( $settings['options'] ) ) : ?>
879 <?php
880 foreach ( $settings['options'] as $key => $option ) : ?>
881 <label>
882 <input type="radio" name="merchant[<?php
883 echo esc_attr( $settings['id'] ); ?>]" value="<?php
884 echo esc_attr( $key ); ?>" <?php
885 checked( $value, $key, true ); ?>/>
886 <span><?php
887 echo esc_html( $option ); ?></span>
888 </label>
889 <?php
890 endforeach; ?>
891 <?php
892 endif; ?>
893 <?php
894 }
895
896 /**
897 * Field: Image picker
898 */
899 public static function image_picker( $settings, $value, $module_id = '' ) {
900 ?>
901 <div class="merchant-image-picker">
902 <?php
903 if ( ! empty( $settings['options'] ) ) : ?>
904 <?php
905 foreach ( $settings['options'] as $key => $option ) : ?>
906 <label>
907 <input type="radio" name="merchant[<?php
908 echo esc_attr( $settings['id'] ); ?>]" value="<?php
909 echo esc_attr( $key ); ?>" <?php
910 checked( $value, $key, true ); ?>/>
911 <?php
912 if ( isset( $option['image'] ) ) { ?>
913 <img src="<?php
914 echo esc_url( $option['image'] ) ?>" alt="">
915 <?php
916 } ?>
917 <?php
918 if ( isset( $option['title'] ) ) { ?>
919 <span class="tool-tip-text"><?php
920 echo esc_html( $option['title'] ) ?></span>
921 <?php
922 } ?>
923 </label>
924 <?php
925 endforeach; ?>
926 <?php
927 endif; ?>
928 </div>
929 <?php
930 }
931
932 /**
933 * Field: Radio Alt
934 */
935 public static function radio_alt( $settings, $value, $module_id = '' ) {
936 ?>
937 <?php
938 if ( ! empty( $settings['options'] ) ) : ?>
939 <?php
940 foreach ( $settings['options'] as $key => $option ) : ?>
941 <div>
942 <label>
943 <input type="radio" name="merchant[<?php
944 echo esc_attr( $settings['id'] ); ?>]" value="<?php
945 echo esc_attr( $key ); ?>" <?php
946 checked( $value, $key, true ); ?>/>
947 <span><?php
948 echo esc_html( $option['title'] ); ?></span>
949 </label>
950 <p><?php
951 echo esc_html( $option['desc'] ); ?></p>
952 </div>
953 <?php
954 endforeach; ?>
955 <?php
956 endif; ?>
957 <?php
958 }
959
960 /**
961 * Field: Choices
962 */
963 public static function choices( $settings, $value, $module_id = '' ) {
964 ?>
965 <div class="merchant-choices merchant-choices-<?php
966 echo esc_attr( $settings['id'] ) ?>">
967 <?php
968 if ( ! empty( $settings['options'] ) ) : ?>
969 <?php
970 foreach ( $settings['options'] as $key => $option ) : ?>
971 <label>
972 <input type="radio" name="merchant[<?php
973 echo esc_attr( $settings['id'] ); ?>]" value="<?php
974 echo esc_attr( $key ); ?>" <?php
975 checked( $value, $key, true ); ?>/>
976 <?php
977 if ( ! empty( $option['svg'] ) ) : ?>
978 <span class="merchant-svg">
979 <?php
980 echo wp_kses( Merchant_SVG_Icons::get_svg_icon( $option['svg'] ), merchant_kses_allowed_tags( array(), false ) ); ?>
981
982 <?php
983 if ( ! empty( $option['label'] ) ) : ?>
984 <span class="merchant-tooltip"><?php
985 echo esc_html( $option['label'] ); ?></span>
986 <?php
987 endif; ?>
988 </span>
989 <?php
990 else : ?>
991 <figure>
992 <?php if ( ! empty( $option['image'] ) ) :
993 $title = $option['title'] ?? '';
994 ?>
995 <img src="<?php echo esc_url( sprintf( $option['image'], MERCHANT_URI . 'assets/images' ) ); ?>" alt="<?php echo esc_attr( $title ); ?>" title="<?php echo esc_attr( $title ); ?>"/>
996 <?php
997 else : ?>
998 <img src="<?php
999 echo esc_url( sprintf( $option, MERCHANT_URI . 'assets/images' ) ); ?>"/>
1000 <?php
1001 endif; ?>
1002 <?php
1003 if ( ! empty( $option['label'] ) ) : ?>
1004 <span class="merchant-tooltip"><?php
1005 echo esc_html( $option['label'] ); ?></span>
1006 <?php
1007 endif; ?>
1008 </figure>
1009 <?php
1010 endif; ?>
1011 </label>
1012 <?php
1013 endforeach; ?>
1014 <?php
1015 endif; ?>
1016 </div>
1017 <?php
1018 }
1019
1020 /**
1021 * Field: Select
1022 */
1023 public static function select( $settings, $value, $module_id = '' ) {
1024 ?>
1025 <?php
1026 if ( ! empty( $settings['options'] ) ) : ?>
1027 <select name="merchant[<?php
1028 echo esc_attr( $settings['id'] ); ?>]">
1029 <?php
1030 foreach ( $settings['options'] as $key => $option ) : ?>
1031 <option value="<?php
1032 echo esc_attr( $key ); ?>" <?php
1033 selected( $value, $key, true ); ?>><?php
1034 echo esc_html( $option ); ?></option>
1035 <?php
1036 endforeach; ?>
1037 </select>
1038 <?php
1039 endif; ?>
1040 <?php
1041 }
1042
1043 /**
1044 * Field: Hook Select
1045 */
1046 public static function hook_select( $settings, $value, $module_id = '' ) {
1047 $hook_name = isset( $value['hook_name'] ) ? $value['hook_name'] : '';
1048 $hook_priority = isset( $value['hook_priority'] ) ? $value['hook_priority'] : '';
1049
1050 ?>
1051 <div class="merchant-module-page-setting-field-hook_select-wrapper">
1052 <div class="merchant-module-page-setting-field-select">
1053 <select name="merchant[<?php
1054 echo esc_attr( $settings['id'] ); ?>][hook_name]">
1055 <?php
1056 if ( ! empty( $settings['options'] ) ) : ?>
1057 <?php
1058 foreach ( $settings['options'] as $key => $option ) : ?>
1059 <option value="<?php
1060 echo esc_attr( $key ); ?>" <?php
1061 selected( $hook_name, $key, true ); ?>><?php
1062 echo esc_html( $option ); ?></option>
1063 <?php
1064 endforeach; ?>
1065 <?php
1066 endif; ?>
1067 </select>
1068 </div>
1069 <?php
1070
1071 if ( isset( $settings['order'] ) && true === $settings['order'] ) {
1072 ?>
1073 <div class="merchant-module-page-setting-field-number">
1074 <input type="number" name="merchant[<?php
1075 echo esc_attr( $settings['id'] ); ?>][hook_priority]" value="<?php
1076 echo esc_attr( $hook_priority ); ?>"/>
1077 </div>
1078 <?php
1079 } ?>
1080 </div>
1081
1082 <?php
1083 }
1084
1085 /**
1086 * Field: Select ajax
1087 *
1088 * @param $settings
1089 * @param $value
1090 *
1091 * @return void
1092 */
1093 public static function select_ajax( $settings, $value, $module_id = '' ) {
1094 $settings = wp_parse_args( $settings, array(
1095 'source' => 'post',
1096 ) );
1097
1098 $ids = ( is_array( $value ) && ! empty( $value ) ) ? $value : (array) $value;
1099
1100 if ( isset( $settings['multiple'] ) ) {
1101 $multiple = $settings['multiple'] === true ? 'multiple' : '';
1102 } else {
1103 $multiple = 'multiple';
1104 }
1105
1106 $placeholder = $settings['placeholder'] ?? '';
1107 ?>
1108 <select
1109 name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]<?php echo esc_attr( $multiple ? '[]' : '' ); ?>"
1110 <?php echo esc_attr( $multiple ); ?>
1111 data-source="<?php echo esc_attr( $settings['source'] ); ?>"
1112 data-placeholder="<?php echo esc_attr( $placeholder ); ?>">
1113 <?php
1114 if ( ! empty( $ids ) ) {
1115 foreach ( $ids as $id ) {
1116 switch ( $settings['source'] ) {
1117 case 'post':
1118 case 'product':
1119 $post = get_post( $id );
1120
1121 if ( ! empty( $post ) ) {
1122 echo '<option value="' . esc_attr( $post->ID ) . '" selected>' . esc_html( $post->post_title ) . '</option>';
1123 }
1124 break;
1125 case 'user':
1126 $user = get_user_by( 'ID', $id );
1127 if( $user ) {
1128 echo '<option value="' . esc_attr( $user->ID ) . '" selected>' . esc_html( $user->display_name ) . '</option>';
1129 }
1130 break;
1131 case 'options':
1132 }
1133 }
1134 }
1135 if ( $settings['source'] === 'options' ) {
1136 $value = ! empty( $value ) ? $value : '';
1137
1138 foreach ( $settings['options'] as $option ) {
1139 if ( isset( $option['options'] ) ) {
1140 echo '<optgroup label="' . esc_attr( $option['text'] ) . '">';
1141
1142 foreach ( $option['options'] as $child_option ) {
1143 $selected_value = is_array( $value ) ? in_array( $child_option['id'], $value, true ) : $child_option['id'];
1144 echo '<option value="' . esc_attr( $child_option['id'] ) . '" ' . selected( $selected_value, is_array( $value ) ? true : $value, false ) . '>' . esc_html( $child_option['text'] ) . '</option>';
1145 }
1146
1147 echo '</optgroup>';
1148 } else {
1149 $selected_value = is_array( $value ) ? in_array( $option['id'], $value, true ) : $option['id'];
1150 echo '<option value="' . esc_attr( $option['id'] ) . '" ' . selected( $selected_value, is_array( $value ) ? true : $value, false ) . '>' . esc_html( $option['text'] ) . '</option>';
1151 }
1152 }
1153 } ?>
1154 </select>
1155 <?php
1156 }
1157
1158 /**
1159 * Field: Info Block
1160 *
1161 * @return void
1162 */
1163 public static function info_block( $settings, $value, $module_id = '' ) {
1164 ?>
1165 <div class="merchant-info-block">
1166 <i class="dashicons dashicons-info"></i>
1167 <p><?php
1168 echo ! empty( $settings['description'] ) ? esc_html( $settings['description'] ) : ''; ?><?php
1169 if ( ! empty( $settings['button_text'] ) && ! empty( $settings['button_link'] ) ) {
1170 printf( '<a href="%s" target="_blank">%s</a>', esc_url( $settings['button_link'] ), esc_html( $settings['button_text'] ) );
1171 } ?></p>
1172 </div>
1173 <?php
1174 }
1175
1176 /**
1177 * Field: Products Selector
1178 *
1179 * @param $settings
1180 * @param $value
1181 *
1182 * @return void
1183 */
1184 public static function products_selector( $settings, $value, $module_id = '' ) {
1185 if ( ! class_exists( 'WooCommerce' ) ) {
1186 echo '<p class="merchant-notice">' . esc_html__( 'WooCommerce is not installed or activated.', 'merchant' ) . '</p>';
1187
1188 return;
1189 }
1190
1191 $ids = $value ? explode( ',', $value ) : array();
1192
1193 if ( isset( $settings['multiple'] ) ) {
1194 $multiple = $settings['multiple'] === true ? 'multiple' : 'false';
1195 } else {
1196 $multiple = 'multiple';
1197 }
1198
1199 if ( ! isset( $settings['allowed_types'] ) ) {
1200 $settings['allowed_types'] = array( 'all' );
1201 }
1202 ?>
1203
1204 <div class="merchant-products-search-container" data-multiple="<?php
1205 echo esc_attr( $multiple ); ?>">
1206 <div class="merchant-search-area">
1207 <input type="text" name="merchant-search-field" data-allowed-types="<?php
1208 echo esc_attr( implode( ',', $settings['allowed_types'] ) ) ?>" placeholder="<?php
1209 esc_attr_e( 'Search products', 'merchant' ); ?>" class="merchant-search-field">
1210 <span class="merchant-searching"><?php
1211 esc_html_e( 'Searching...', 'merchant' ); ?></span>
1212 <img src="<?php echo esc_url( MERCHANT_URI . 'assets/images/admin/products-search-icon.svg' ); ?>" class="merchant-search-icon"
1213 alt="<?php esc_attr_e( 'Search icon', 'merchant' ); ?>">
1214 <div class="merchant-selections-products-preview"></div>
1215 </div>
1216 <div class="merchant-selected-products-preview">
1217 <ul>
1218 <?php
1219 if ( ! empty( $ids ) ) {
1220 foreach ( $ids as $product_id ) {
1221 $product = wc_get_product( $product_id );
1222 if ( $product ) {
1223 self::product_data_li( $product );
1224 }
1225 }
1226 }
1227 ?>
1228 </ul>
1229 </div>
1230 <input type="hidden" name="merchant[<?php
1231 echo esc_attr( $settings['id'] ); ?>]" class="merchant-selected-products" value="<?php
1232 echo esc_attr( $value ) ?>">
1233 </div>
1234 <?php
1235 }
1236
1237 public static function product_data_li( $product, $search = false, $hierarchy = false ) {
1238 $product_id = $product->get_id();
1239 $product_sku = $product->get_sku();
1240 $product_name = $product->get_name();
1241 $edit_link = get_edit_post_link( $product_id );
1242 if ( $product->is_type( 'variation' ) ) {
1243 $edit_link = get_edit_post_link( $product->get_parent_id() );
1244 }
1245
1246 /**
1247 * Filter product image.
1248 *
1249 * @since 1.9.1
1250 */
1251 $product_image = apply_filters(
1252 'merchant_product_item_product_image',
1253 '<span class="img">' . $product->get_image( array( 30, 30 ) ) . '</span>',
1254 $product
1255 );
1256
1257 $price = $product->get_price();
1258 $key = $product_id . '_' . $product_sku;
1259
1260 /**
1261 * Filter the product bundle item product info.
1262 *
1263 * @param string $product_info The product bundle item product info.
1264 * @param WC_Product $product The product object.
1265 *
1266 * @since 1.9.0
1267 */
1268 $product_info = apply_filters( 'merchant_pro_product_bundle_item_product_info', $product->get_type() . '<br/>#' . $product_id, $product );
1269 if ( $search ) {
1270 $remove_btn = '<span class="remove hint--left" aria-label="' . esc_html__( 'Add', 'merchant' ) . '">+</span>';
1271 } else {
1272 $remove_btn = '<span class="remove hint--left" aria-label="' . esc_html__( 'Remove', 'merchant' ) . '">×</span>';
1273 }
1274
1275 $item_class = 'product-item';
1276 if( $hierarchy && $product->is_type( 'variation' ) ) {
1277 $item_class .= ' hierarchy-style';
1278 }
1279
1280 echo '<li class="' . esc_attr( $item_class ) . '" data-key="' . esc_attr( $key ) . '" data-name="' . esc_attr( $product_name ) . '" data-sku="'
1281 . esc_attr( $product_sku ) . '" data-id="' . esc_attr( $product_id ) . '" data-price="' . esc_attr( $price ) . '">'
1282 . wp_kses( $product_image, array(
1283 'span' => array(
1284 'class' => true,
1285 ),
1286 'img' => array(
1287 'src' => true,
1288 'alt' => true,
1289 'decoding' => true,
1290 'srcset' => true,
1291 'loading' => true,
1292 'sizes' => true,
1293 'class' => true,
1294 'width' => true,
1295 'height' => true,
1296 ),
1297 ) ) . '<span class="data">'
1298 . '<span class="name">' . esc_html( $product_name ) . '</span><span class="info">' . wp_kses( $product->get_price_html(), array(
1299 'span' => array(
1300 'class' => true,
1301 ),
1302 'del' => array(
1303 'aria-hidden' => true,
1304 ),
1305 'ins' => array(),
1306 'bdi' => array(),
1307
1308 ) ) . '</span> ' . ( $product->is_sold_individually()
1309 ? '<span class="info">' . esc_html__( 'sold individually', 'merchant' ) . '</span> ' : '' ) . '</span>'
1310 . '<span class="type"><a href="' . esc_url( $edit_link ) . '" target="_blank">' . wp_kses_post( $product_info ) . '</a></span> ' . wp_kses( $remove_btn, array(
1311 'span' => array(
1312 'class' => true,
1313 'aria-label' => true,
1314 ),
1315 ) );
1316
1317 echo '</li>';
1318 }
1319
1320 public function products_search() {
1321 check_ajax_referer( 'merchant_admin_options', 'nonce' );
1322
1323 if ( ! isset( $_POST['keyword'] ) || empty( $_POST['keyword'] ) ) {
1324 exit();
1325 }
1326
1327 $types = array( 'simple', 'variable' ); // limit search to product types
1328
1329 if ( isset( $_POST['product_types'] ) || ! empty( $_POST['product_types'] ) ) {
1330 $types = explode( ',', sanitize_text_field( $_POST['product_types'] ) );
1331 }
1332
1333 $hierarchy = false;
1334 if (
1335 in_array( 'all', $types, true )
1336 || ( in_array( 'variation', $types, true ) && in_array( 'variable', $types, true ) )
1337 ) {
1338 $hierarchy = true;
1339 }
1340
1341 $added_ids = isset( $_POST['ids'] ) ? explode( ',', sanitize_text_field( $_POST['ids'] ) ) : array();
1342 $keyword = sanitize_text_field( $_POST['keyword'] );
1343 if ( is_numeric( $keyword ) ) {
1344 // search by id
1345 $query_args = array(
1346 'p' => absint( $keyword ),
1347 'post_type' => 'product',
1348 );
1349 } else {
1350 $query_args = array(
1351 'post_type' => 'product',
1352 'post_status' => array( 'publish', 'private' ),
1353 's' => $keyword,
1354 'posts_per_page' => 10,
1355 );
1356
1357 if ( ! empty( $types ) && ! in_array( 'all', $types, true ) ) {
1358 $product_types = $types;
1359
1360 if ( in_array( 'variation', $types, true ) ) {
1361 $product_types[] = 'variable';
1362 }
1363
1364 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
1365 $query_args['tax_query'] = array(
1366 array(
1367 'taxonomy' => 'product_type',
1368 'field' => 'slug',
1369 'terms' => $product_types,
1370 ),
1371 );
1372 }
1373
1374 $query_args['post__not_in'] = array_map( 'absint', $added_ids );
1375 }
1376
1377 // Filter by category slugs.
1378 $categories = array_map( 'sanitize_text_field', $_POST['categories'] ?? array() );
1379 if ( is_array( $categories ) && ! empty( $categories ) ) {
1380 $query_args['tax_query'][] = array(
1381 'taxonomy' => 'product_cat',
1382 'field' => 'slug',
1383 'terms' => $categories,
1384 'operator' => 'IN',
1385 );
1386 }
1387
1388 $query = new WP_Query( $query_args );
1389
1390 if ( $query->have_posts() ) {
1391 echo '<ul>';
1392
1393 while ( $query->have_posts() ) {
1394 $query->the_post();
1395 $_product = wc_get_product( get_the_ID() );
1396
1397 if ( ! $_product ) {
1398 continue;
1399 }
1400
1401 if (
1402 ! $_product->is_type( 'variable' )
1403 || in_array( 'variable', $types, true )
1404 || in_array( 'all', $types, true )
1405 ) {
1406 self::product_data_li( $_product, array( 'qty' => 1 ), true, $hierarchy );
1407 }
1408
1409 if (
1410 $_product->is_type( 'variable' )
1411 && (
1412 empty( $types )
1413 || in_array( 'all', $types, true )
1414 || in_array( 'variation', $types, true )
1415 )
1416 ) {
1417 // show all children
1418 $children = $_product->get_children();
1419
1420 if ( is_array( $children ) && count( $children ) > 0 ) {
1421 foreach ( $children as $child ) {
1422 $child_product = wc_get_product( $child );
1423 /**
1424 * @var WC_Product_Variation $child_product
1425 */
1426 if ( ! $this->are_variation_attributes_set( $child_product ) ) {
1427 // Don't display variations that don't have all attributes set.
1428 continue;
1429 }
1430 self::product_data_li( $child_product, true, $hierarchy );
1431 }
1432 }
1433 }
1434 }
1435
1436 echo '</ul>';
1437 wp_reset_postdata();
1438 } else {
1439 // translators: %s is the search keyword
1440 echo wp_kses( '<ul><span>' . sprintf( esc_html__( 'No results found for "%s"', 'merchant' ), $keyword ) . '</span></ul>', array(
1441 'ul' => array(),
1442 'span' => array(),
1443 ) );
1444 }
1445
1446 exit;
1447 }
1448
1449 /**
1450 * Check if all variation attributes are set.
1451 *
1452 * @param $variation WC_Product_Variation variation product object
1453 *
1454 * @return bool
1455 */
1456 public function are_variation_attributes_set( $variation ) {
1457 // Check if the product is a variation and has attributes
1458 if ( $variation && $variation->is_type( 'variation' ) ) {
1459 // Get the variation attributes
1460 $variation_attributes = $variation->get_variation_attributes();
1461
1462 // Check if all variation attributes are set
1463 foreach ( $variation_attributes as $attribute => $value ) {
1464 if ( empty( $value ) ) {
1465 return false; // At least one attribute is not set
1466 }
1467 }
1468
1469 return true; // All variation attributes are set
1470 }
1471
1472 return false; // Not a valid variation product
1473 }
1474
1475 /**
1476 * Field: Select Size Chart
1477 */
1478 public static function select_size_chart( $settings, $value, $module_id = '' ) {
1479 $options = array(
1480 '' => esc_html__( 'Default', 'merchant' ),
1481 );
1482
1483 $posts = get_posts( array(
1484 'post_type' => 'merchant_size_chart',
1485 'posts_per_page' => - 1,
1486 'post_status' => 'publish',
1487 ) );
1488
1489 if ( ! is_wp_error( $posts ) && ! empty( $posts ) ) {
1490 foreach ( $posts as $_post ) {
1491 $options[ $_post->ID ] = $_post->post_title;
1492 }
1493 }
1494
1495 ?>
1496 <?php
1497 if ( ! empty( $options ) ) : ?>
1498 <select name="merchant[<?php
1499 echo esc_attr( $settings['id'] ); ?>]">
1500 <?php
1501 foreach ( $options as $key => $option ) : ?>
1502 <option value="<?php
1503 echo esc_attr( $key ); ?>" <?php
1504 selected( $value, $key, true ); ?>><?php
1505 echo esc_html( $option ); ?></option>
1506 <?php
1507 endforeach; ?>
1508 </select>
1509 <?php
1510 endif; ?>
1511 <?php
1512 }
1513
1514 /**
1515 * Field: Buttons
1516 */
1517 public static function buttons( $settings, $value, $module_id = '' ) {
1518 ?>
1519 <div class="merchant-buttons">
1520 <?php
1521 if ( ! empty( $settings['options'] ) ) : ?>
1522 <?php
1523 foreach ( $settings['options'] as $key => $option ) : ?>
1524 <label class="merchant-button-<?php
1525 echo esc_attr( $key ); ?>"">
1526 <input type="radio" name="merchant[<?php
1527 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1528 echo esc_attr( $key ); ?>" <?php
1529 checked( $value, $key, true ); ?>/>
1530 <span><?php
1531 echo esc_html( $option ); ?></span>
1532 </label>
1533 <?php
1534 endforeach; ?>
1535 <?php
1536 endif; ?>
1537 </div>
1538 <?php
1539 }
1540
1541 /**
1542 * Field: Buttons Alt
1543 */
1544 public static function buttons_alt( $settings, $value, $module_id = '' ) {
1545 ?>
1546 <div class="merchant-buttons">
1547 <?php
1548 if ( ! empty( $settings['options'] ) ) : ?>
1549 <?php
1550 foreach ( $settings['options'] as $key => $option ) : ?>
1551 <label class="merchant-button-<?php
1552 echo esc_attr( $key ); ?>">
1553 <input type="radio" name="merchant[<?php
1554 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1555 echo esc_attr( $key ); ?>" <?php
1556 checked( $value, $key, true ); ?>/>
1557 <span><?php
1558 echo esc_html( $option ); ?></span>
1559 </label>
1560 <?php
1561 endforeach; ?>
1562 <?php
1563 endif; ?>
1564 </div>
1565 <?php
1566 }
1567
1568 /**
1569 * Field: Buttons Content
1570 */
1571 public static function buttons_content( $settings, $value, $module_id = '' ) {
1572 ?>
1573 <div class="merchant-buttons-content">
1574 <?php
1575 if ( ! empty( $settings['options'] ) ) : ?>
1576 <?php
1577 foreach ( $settings['options'] as $key => $option ) : ?>
1578 <label class="merchant-button-content-<?php echo esc_attr( $key ); ?>">
1579 <input
1580 type="radio"
1581 name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]"
1582 value="<?php echo esc_attr( $key ); ?>"
1583 <?php checked( $value, $key, true ); ?>
1584 />
1585
1586 <span class="merchant-buttons-inner-content">
1587 <?php if ( $option['icon'] ) : ?>
1588 <img src="<?php echo esc_url( $option['icon'] ); ?>" alt="">
1589 <?php endif; ?>
1590 <span>
1591 <span><?php echo esc_html( $option['title'] ?? '' ); ?></span>
1592 <span><?php echo esc_html( $option['desc'] ?? '' ); ?></span>
1593 </span>
1594 </span>
1595 </label>
1596 <?php
1597 endforeach; ?>
1598 <?php
1599 endif; ?>
1600 </div>
1601 <?php
1602 }
1603
1604 /**
1605 * Field: Range
1606 */
1607 public static function range( $settings, $value, $module_id = '' ) {
1608 $settings = wp_parse_args( $settings, array(
1609 'min' => '',
1610 'max' => '',
1611 'step' => '',
1612 'unit' => '',
1613 ) );
1614
1615 ?>
1616 <div class="merchant-range">
1617 <input type="range" class="merchant-range-input" name="" min="<?php
1618 echo esc_attr( $settings['min'] ); ?>" max="<?php
1619 echo esc_attr( $settings['max'] ); ?>"
1620 step="<?php
1621 echo esc_attr( $settings['step'] ); ?>" value="<?php
1622 echo esc_attr( $value ); ?>"/>
1623 <input type="number" class="merchant-range-number-input" name="merchant[<?php
1624 echo esc_attr( $settings['id'] ); ?>]" min="<?php
1625 echo esc_attr( $settings['min'] ); ?>"
1626 max="<?php
1627 echo esc_attr( $settings['max'] ); ?>" step="<?php
1628 echo esc_attr( $settings['step'] ); ?>" value="<?php
1629 echo esc_attr( $value ); ?>"/>
1630 <?php
1631 if ( ! empty( $settings['unit'] ) ) : ?>
1632 <span class="merchant-range-unit"><?php
1633 echo esc_html( $settings['unit'] ); ?></span>
1634 <?php
1635 endif; ?>
1636 </div>
1637 <?php
1638 }
1639
1640 /**
1641 * Field: Color
1642 */
1643 public static function color( $settings, $value, $module_id = '' ) {
1644 $settings = wp_parse_args( $settings, array(
1645 'default' => '#212121',
1646 ) );
1647
1648 ?>
1649 <div class="merchant-color">
1650 <div class="merchant-color-picker" data-default-color="<?php
1651 echo esc_attr( $settings['default'] ); ?>" style="background-color: <?php
1652 echo esc_attr( $value ); ?>;"></div>
1653 <input type="text" class="merchant-color-input" name="merchant[<?php
1654 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1655 echo esc_attr( $value ); ?>"/>
1656 </div>
1657 <?php
1658 }
1659
1660 /**
1661 * Field: Gallery
1662 */
1663 public static function gallery( $settings, $value, $module_id = '' ) {
1664 $settings = wp_parse_args( $settings, array(
1665 'label' => esc_html__( 'Select Images', 'merchant' ),
1666 ) );
1667
1668 $images = ( ! empty( $value ) ) ? explode( ',', $value ) : array();
1669
1670
1671 echo '<div class="merchant-gallery-images">';
1672
1673 if ( ! empty( $images ) ) :
1674
1675 foreach ( $images as $image_id ) :
1676
1677 $image = wp_get_attachment_image_src( $image_id, 'thumbnail' );
1678
1679 if ( ! empty( $image ) && ! empty( $image[0] ) ) :
1680
1681 printf( '<div class="merchant-gallery-image" data-item-id="%s">', esc_attr( $image_id ) );
1682
1683 echo '<i class="merchant-gallery-remove dashicons dashicons-no-alt"></i>';
1684
1685 printf( '<img src="%s" />', esc_url( $image[0] ) );
1686
1687 echo '</div>';
1688
1689 endif;
1690
1691 endforeach;
1692
1693 endif;
1694
1695 echo '</div>';
1696
1697 ?>
1698 <a href="#" class="merchant-gallery-button"><?php
1699 echo esc_html( $settings['label'] ); ?></a>
1700 <input type="hidden" class="merchant-gallery-input" name="merchant[<?php
1701 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1702 echo esc_attr( $value ); ?>"/>
1703 <?php
1704 }
1705
1706 /**
1707 * Field: Upload
1708 */
1709 public static function upload( $settings, $value, $module_id = '' ) {
1710 $settings = wp_parse_args( $settings, array(
1711 'label' => esc_html__( 'Select Image', 'merchant' ),
1712 ) );
1713
1714 echo '<div class="merchant-upload-wrapper">';
1715 if ( ! empty( $value ) ) :
1716 $image = wp_get_attachment_image_src( $value, 'thumbnail' );
1717 if ( ! empty( $image ) && ! empty( $image[0] ) ) :
1718 echo '<div class="merchant-upload-image">';
1719 echo '<i class="merchant-upload-remove dashicons dashicons-no-alt"></i>';
1720 printf( '<img src="%s" />', esc_url( $image[0] ) );
1721 echo '</div>';
1722 endif;
1723 endif;
1724 echo '</div>';
1725
1726 $drag_drop = $settings['drag_drop'] ?? false;
1727 ?>
1728 <div class="merchant-upload-button-wrapper<?php echo esc_attr( $drag_drop ? ' merchant-upload-button-drag-drop' : '' ); ?>">
1729 <?php if ( $drag_drop ) : ?>
1730 <img src="<?php echo esc_url( esc_url( MERCHANT_URI . '/assets/images/upload-icon.svg' ) ); ?>" alt="<?php echo esc_attr__( 'Upload image', 'merchant' ); ?>"/>
1731 <?php endif; ?>
1732 <a href="#" class="merchant-upload-button"><?php echo esc_html( $settings['label'] ?? '' ); ?></a>
1733 </div>
1734 <input type="hidden" class="merchant-upload-input" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $value ); ?>"/>
1735 <?php
1736 }
1737
1738 /**
1739 * Field: Warning
1740 */
1741 public static function warning( $settings ) {
1742 echo wp_kses_post( $settings['content'] );
1743 }
1744
1745 /**
1746 * Field: Warning
1747 */
1748 public static function info( $settings ) {
1749 echo wp_kses_post( $settings['content'] );
1750 }
1751
1752 /**
1753 * Field: Divider
1754 */
1755 public static function divider() {
1756 }
1757
1758 /**
1759 * Field: Content
1760 */
1761 public static function content( $settings ) {
1762 echo wp_kses_post( $settings['content'] );
1763 }
1764
1765 /**
1766 * Field: Sortable
1767 */
1768 public static function sortable( $settings, $value, $module_id = '' ) {
1769 ?>
1770 <div class="merchant-sortable">
1771 <ul class="merchant-sortable-list ui-sortable">
1772 <?php
1773 foreach ( $value as $option_key ) :
1774 $option_val = $settings['options'][ $option_key ];
1775
1776 if ( in_array( $option_key, $value, true ) ) :
1777 ?>
1778 <li class="merchant-sortable-item" data-value="<?php
1779 echo esc_attr( $option_key ); ?>">
1780 <i class='dashicons dashicons-menu'></i>
1781 <i class="dashicons dashicons-visibility visibility"></i>
1782 <?php
1783 echo esc_html( $option_val ); ?>
1784 </li>
1785 <?php
1786 endif; ?>
1787 <?php
1788 endforeach; ?>
1789
1790 <?php
1791 foreach ( $settings['options'] as $option_key => $option_val ) :
1792 if ( ! in_array( $option_key, $value, true ) ) :
1793 $invisible = ! in_array( $option_key, $value, true ) ? ' invisible' : '';
1794
1795 ?>
1796 <li class="merchant-sortable-item<?php
1797 echo esc_attr( $invisible ); ?>" data-value="<?php
1798 echo esc_attr( $option_key ); ?>">
1799 <i class='dashicons dashicons-menu'></i>
1800 <i class="dashicons dashicons-visibility visibility"></i>
1801 <?php
1802 echo esc_html( $option_val ); ?>
1803 </li>
1804 <?php
1805 endif; ?>
1806 <?php
1807 endforeach; ?>
1808 </ul>
1809
1810 <input class="merchant-sortable-input" type="hidden" name="merchant[<?php
1811 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1812 echo esc_attr( wp_json_encode( $value ) ); ?>"/>
1813 </div>
1814 <?php
1815 }
1816
1817 /**
1818 * Field: Sortable Repeater.
1819 */
1820 public static function sortable_repeater( $settings, $value, $module_id = '' ) {
1821 ?>
1822 <div class="merchant-sortable-repeater-control<?php
1823 echo isset( $settings['sorting'] ) && false === $settings['sorting'] ? ' disable-sorting' : ''; ?>">
1824 <div class="merchant-sortable-repeater sortable regular-field">
1825 <div class="repeater">
1826 <input type="text" value="" class="repeater-input"/><span class="dashicons dashicons-menu"></span><a class="customize-control-sortable-repeater-delete"
1827 href="#"><span
1828 class="dashicons dashicons-no-alt"></span></a>
1829 </div>
1830 </div>
1831 <button class="button customize-control-sortable-repeater-add" type="button"><?php
1832 echo esc_html( $settings['button_label'] ); ?></button>
1833 <input class="merchant-sortable-repeater-input" type="hidden" name="merchant[<?php
1834 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1835 echo esc_attr( wp_json_encode( $value ) ); ?>"/>
1836 </div>
1837 <?php
1838 }
1839
1840 public static function wc_coupons( $settings, $value ) {
1841 $coupons = get_posts( array(
1842 'posts_per_page' => - 1,
1843 'orderby' => 'title',
1844 'order' => 'asc',
1845 'post_type' => 'shop_coupon',
1846 'post_status' => 'publish',
1847 ) );
1848 if ( $coupons ) {
1849 ?>
1850 <div class="merchant-wc-coupon-selector merchant-<?php
1851 echo esc_attr( $settings['id'] ) ?>">
1852 <?php
1853 echo '<select name="merchant[' . esc_attr( $settings['id'] ) . ']">';
1854 echo '<option value="">' . esc_html__( 'Select a coupon', 'merchant' ) . '</option>';
1855
1856 foreach ( $coupons as $coupon ) {
1857 $coupon_code = strtolower( $coupon->post_title );
1858
1859 echo '<option value="' . esc_attr( $coupon_code ) . '"' . selected( esc_attr( $coupon_code ), $value, false ) . '>';
1860 echo esc_html( $coupon_code );
1861 echo '</option>';
1862 }
1863
1864 echo '</select>';
1865 echo '<a href="' . esc_url( admin_url( 'edit.php?post_type=shop_coupon' ) ) . '" target="_blank" style="margin-left: 10px;">' . esc_html__( 'Manage coupons',
1866 'merchant' ) . '</a>';
1867 ?>
1868 </div>
1869 <?php
1870 } else {
1871 echo '<div style="color: red;">';
1872 echo wp_kses_post(
1873 sprintf(
1874 /* Translators: 1. Coupon admin url 2. Link target attribute value */
1875 __( 'No coupons found! <a href="%1$s" target="%2$s">Create a new coupon</a>', 'merchant' ),
1876 admin_url( 'post-new.php?post_type=shop_coupon' ),
1877 '_blank'
1878 )
1879 );
1880 echo '</div>';
1881 echo '<input type="hidden" name="merchant[' . esc_attr( $settings['id'] ) . ']" value="" />';
1882 }
1883 }
1884
1885 /**
1886 * Field: Date Time.
1887 *
1888 * @param $settings array field settings.
1889 * @param $value string field value.
1890 * @param $module_id string module id.
1891 *
1892 * @return void
1893 */
1894 public static function date_time( $settings, $value, $module_id = '' ) {
1895 // All options are documented here: https://air-datepicker.com/docs
1896 $options = array(
1897 'dateFormat' => 'MM-dd-yyyy',
1898 'timepicker' => true,
1899 'timeFormat' => 'hh:mm AA',
1900 'minDate' => 'today',
1901 'timeZone' => wp_timezone_string(),
1902 );
1903 if ( isset( $settings['options'] ) ) {
1904 $settings['options'] = wp_parse_args( $settings['options'], $options );
1905 } else {
1906 $settings['options'] = $options;
1907 }
1908 ?>
1909 <div class="merchant-datetime-field" data-options="<?php echo esc_attr( wp_json_encode( $settings['options'] ) ); ?>">
1910 <input type="text" name="merchant[<?php
1911 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1912 echo esc_attr( $value ); ?>" placeholder="<?php
1913 echo isset( $settings['placeholder'] ) ? esc_attr( $settings['placeholder'] ) : ''; ?>"/>
1914 </div>
1915 <?php
1916 }
1917
1918 /**
1919 * Field: Flexible Content.
1920 *
1921 * @param array $settings
1922 * @param mixed $value
1923 *
1924 * @return void
1925 */
1926 public static function flexible_content( $settings, $value, $module_id = '' ) {
1927 $values = ( is_array( $value ) && ! empty( $value ) ) ? $value : array();
1928 $empty = empty( $values ) ? 'empty' : '';
1929
1930 $settings = wp_parse_args( $settings, array(
1931 'sorting' => false,
1932 'style' => 'default',
1933 'accordion' => false,
1934 ) );
1935
1936 $classes = array(
1937 'merchant-flexible-content-control',
1938 "{$settings['style']}-style",
1939 );
1940
1941 $has_sorting = (bool) ( $settings['sorting'] ?? true );
1942 if ( ! $has_sorting ) {
1943 $classes[] = 'disable-sorting';
1944 }
1945
1946 $has_accordion = (bool) ( $settings['accordion'] ?? false );
1947 if ( $has_accordion ) {
1948 $classes[] = 'has-accordion';
1949 }
1950
1951 $has_duplicate = (bool) ( $settings['duplicate'] ?? false );
1952 if ( $has_duplicate ) {
1953 $classes[] = 'has-duplicate';
1954 }
1955 ?>
1956 <div class="<?php
1957 echo esc_attr( implode( ' ', $classes ) ); ?>"
1958 data-id="<?php
1959 echo esc_attr( $settings['id'] ) ?>">
1960
1961 <div class="layouts" data-id="<?php echo esc_attr( $settings['id'] ) ?>">
1962 <?php foreach ( $settings['layouts'] as $layout_type => $layout ) : ?>
1963 <div class="layout" data-type="<?php echo esc_attr( $layout_type ) ?>">
1964 <div class="layout__inner">
1965 <?php if ( $has_sorting ) : ?>
1966 <span class="customize-control-flexible-content-move">
1967 <svg xmlns="http://www.w3.org/2000/svg" width="10" height="14" viewBox="0 0 10 14" fill="none">
1968 <path d="M1.75 0.5C1.19772 0.5 0.75 0.947715 0.75 1.5V2.5C0.75 3.05228 1.19772 3.5 1.75 3.5H2.75C3.30228 3.5 3.75 3.05228 3.75 2.5V1.5C3.75 0.947715 3.30228 0.5 2.75 0.5H1.75Z" fill="#4A4A4A"/>
1969 <path d="M1.75 5.5C1.19772 5.5 0.75 5.94772 0.75 6.5V7.5C0.75 8.05228 1.19772 8.5 1.75 8.5H2.75C3.30228 8.5 3.75 8.05228 3.75 7.5V6.5C3.75 5.94772 3.30228 5.5 2.75 5.5H1.75Z" fill="#4A4A4A"/>
1970 <path d="M0.75 11.5C0.75 10.9477 1.19772 10.5 1.75 10.5H2.75C3.30228 10.5 3.75 10.9477 3.75 11.5V12.5C3.75 13.0523 3.30228 13.5 2.75 13.5H1.75C1.19772 13.5 0.75 13.0523 0.75 12.5V11.5Z" fill="#4A4A4A"/>
1971 <path d="M7.25 0.5C6.69772 0.5 6.25 0.947715 6.25 1.5V2.5C6.25 3.05228 6.69772 3.5 7.25 3.5H8.25C8.80228 3.5 9.25 3.05228 9.25 2.5V1.5C9.25 0.947715 8.80228 0.5 8.25 0.5H7.25Z" fill="#4A4A4A"/>
1972 <path d="M6.25 6.5C6.25 5.94772 6.69772 5.5 7.25 5.5H8.25C8.80228 5.5 9.25 5.94772 9.25 6.5V7.5C9.25 8.05228 8.80228 8.5 8.25 8.5H7.25C6.69772 8.5 6.25 8.05228 6.25 7.5V6.5Z" fill="#4A4A4A"/>
1973 <path d="M7.25 10.5C6.69772 10.5 6.25 10.9477 6.25 11.5V12.5C6.25 13.0523 6.69772 13.5 7.25 13.5H8.25C8.80228 13.5 9.25 13.0523 9.25 12.5V11.5C9.25 10.9477 8.80228 10.5 8.25 10.5H7.25Z" fill="#4A4A4A"/>
1974 </svg>
1975 </span>
1976 <?php endif; ?>
1977 <div class="layout-header">
1978 <div class="layout-count">1</div>
1979 <div class="layout-title"<?php
1980 if ( isset( $layout['title-field'] ) && ! empty( $layout['title-field'] ) ) {
1981 echo ' data-title-field="' . esc_attr( $layout['title-field'] ) . '"';
1982 } ?>>
1983 <?php
1984 echo esc_html( $layout['title'] ) ?>
1985 </div>
1986 <div class="layout-toggle">
1987 <?php if ( $has_accordion ) : ?>
1988 <span class="customize-control-flexible-content-accordion">
1989 <svg xmlns="http://www.w3.org/2000/svg" width="10" height="7" viewBox="0 0 10 7" fill="none">
1990 <path fill-rule="evenodd" clip-rule="evenodd" d="M0.71967 0.732854C1.01256 0.43996 1.48744 0.43996 1.78033 0.732854L5.25 4.20252L8.71967 0.732854C9.01256 0.43996 9.48744 0.43996 9.78033 0.732854C10.0732 1.02575 10.0732 1.50062 9.78033 1.79351L5.78033 5.79351C5.48744 6.08641 5.01256 6.08641 4.71967 5.79351L0.71967 1.79351C0.426777 1.50062 0.426777 1.02575 0.71967 0.732854Z" fill="#4A4A4A"/>
1991 </svg>
1992 </span>
1993 <?php endif; ?>
1994 </div>
1995 </div>
1996 <div class="layout-body">
1997 <?php
1998 foreach ( $layout['fields'] as $sub_field ) :
1999 $classes = array( 'layout-field' );
2000
2001 if ( isset( $sub_field['classes'] ) ) {
2002 $classes = array_merge( $classes, $sub_field['classes'] );
2003 } ?>
2004 <div class="<?php
2005 echo esc_attr( implode( ' ', $classes ) ); ?>">
2006 <?php
2007 if ( 'fields_group' === $sub_field['type'] ) {
2008 static::fields_group( $sub_field, $value, $module_id, true, array(
2009 'id' => $settings['id'],
2010 'option_key' => 0,
2011 'value' => $value,
2012 ) );
2013 } else {
2014 static::replace_field(
2015 $sub_field,
2016 '',
2017 array(
2018 "name=\"merchant[{$sub_field['id']}]",
2019 'merchant-module-page-setting-field-upload',
2020 'merchant-module-page-setting-field-select_ajax',
2021 ),
2022 array(
2023 "data-name=\"merchant[{$settings['id']}][0][{$sub_field['id']}]",
2024 'merchant-module-page-setting-field-upload template',
2025 'merchant-module-page-setting-field-select_ajax template',
2026 ),
2027 $module_id
2028 );
2029 }
2030 ?>
2031 </div>
2032 <?php
2033 endforeach; ?>
2034 <input type="hidden" data-name="merchant[<?php
2035 echo esc_attr( $settings['id'] ) ?>][0][layout]" value="<?php
2036 echo esc_attr( $layout_type ) ?>">
2037 </div>
2038 <?php self::print_flexible_layout_actions( $settings, $layout_type ); ?>
2039 </div>
2040 </div>
2041 <?php
2042 endforeach; ?>
2043 </div>
2044
2045 <div class="merchant-flexible-content <?php echo esc_attr( $empty ); ?> sortable">
2046 <?php
2047 foreach ( $values as $option_key => $option ) : ?>
2048 <div class="layout" data-type="<?php echo esc_attr( $option['layout'] ) ?>">
2049 <div class="layout__inner">
2050 <?php if ( $has_sorting ) : ?>
2051 <span class="customize-control-flexible-content-move">
2052 <svg xmlns="http://www.w3.org/2000/svg" width="10" height="14" viewBox="0 0 10 14" fill="none">
2053 <path d="M1.75 0.5C1.19772 0.5 0.75 0.947715 0.75 1.5V2.5C0.75 3.05228 1.19772 3.5 1.75 3.5H2.75C3.30228 3.5 3.75 3.05228 3.75 2.5V1.5C3.75 0.947715 3.30228 0.5 2.75 0.5H1.75Z" fill="#4A4A4A"/>
2054 <path d="M1.75 5.5C1.19772 5.5 0.75 5.94772 0.75 6.5V7.5C0.75 8.05228 1.19772 8.5 1.75 8.5H2.75C3.30228 8.5 3.75 8.05228 3.75 7.5V6.5C3.75 5.94772 3.30228 5.5 2.75 5.5H1.75Z" fill="#4A4A4A"/>
2055 <path d="M0.75 11.5C0.75 10.9477 1.19772 10.5 1.75 10.5H2.75C3.30228 10.5 3.75 10.9477 3.75 11.5V12.5C3.75 13.0523 3.30228 13.5 2.75 13.5H1.75C1.19772 13.5 0.75 13.0523 0.75 12.5V11.5Z" fill="#4A4A4A"/>
2056 <path d="M7.25 0.5C6.69772 0.5 6.25 0.947715 6.25 1.5V2.5C6.25 3.05228 6.69772 3.5 7.25 3.5H8.25C8.80228 3.5 9.25 3.05228 9.25 2.5V1.5C9.25 0.947715 8.80228 0.5 8.25 0.5H7.25Z" fill="#4A4A4A"/>
2057 <path d="M6.25 6.5C6.25 5.94772 6.69772 5.5 7.25 5.5H8.25C8.80228 5.5 9.25 5.94772 9.25 6.5V7.5C9.25 8.05228 8.80228 8.5 8.25 8.5H7.25C6.69772 8.5 6.25 8.05228 6.25 7.5V6.5Z" fill="#4A4A4A"/>
2058 <path d="M7.25 10.5C6.69772 10.5 6.25 10.9477 6.25 11.5V12.5C6.25 13.0523 6.69772 13.5 7.25 13.5H8.25C8.80228 13.5 9.25 13.0523 9.25 12.5V11.5C9.25 10.9477 8.80228 10.5 8.25 10.5H7.25Z" fill="#4A4A4A"/>
2059 </svg>
2060 </span>
2061 <?php endif; ?>
2062 <div class="layout-header">
2063 <div class="layout-count"><?php
2064 echo absint( $option_key + 1 ) ?></div>
2065 <div class="layout-title"<?php
2066 if ( isset( $layout['title-field'] ) && ! empty( $layout['title-field'] ) ) {
2067 echo ' data-title-field="' . esc_attr( $layout['title-field'] ) . '"';
2068 } ?>>
2069 <?php
2070 echo isset( $settings['layouts'][ $option['layout'] ]['title'] ) ? esc_html( $settings['layouts'][ $option['layout'] ]['title'] ) : '' ?>
2071 </div>
2072 <div class="layout-toggle">
2073 <?php if ( $has_accordion ) : ?>
2074 <span class="customize-control-flexible-content-accordion">
2075 <svg xmlns="http://www.w3.org/2000/svg" width="10" height="7" viewBox="0 0 10 7" fill="none">
2076 <path fill-rule="evenodd" clip-rule="evenodd" d="M0.71967 0.732854C1.01256 0.43996 1.48744 0.43996 1.78033 0.732854L5.25 4.20252L8.71967 0.732854C9.01256 0.43996 9.48744 0.43996 9.78033 0.732854C10.0732 1.02575 10.0732 1.50062 9.78033 1.79351L5.78033 5.79351C5.48744 6.08641 5.01256 6.08641 4.71967 5.79351L0.71967 1.79351C0.426777 1.50062 0.426777 1.02575 0.71967 0.732854Z" fill="#4A4A4A"/>
2077 </svg>
2078 </span>
2079 <?php endif; ?>
2080 </div>
2081 </div>
2082 <div class="layout-body">
2083 <?php
2084 foreach ( $settings['layouts'][ $option['layout'] ]['fields'] as $sub_field ) :
2085 $classes = array( 'layout-field' );
2086 if ( isset( $sub_field['classes'] ) ) {
2087 $classes = array_merge( $classes, $sub_field['classes'] );
2088 } ?>
2089 <div class="<?php
2090 echo esc_attr( implode( ' ', $classes ) ) ?>">
2091 <?php
2092 $value = null;
2093 if ( isset( $option[ $sub_field['id'] ] ) ) {
2094 $value = $option[ $sub_field['id'] ];
2095 } elseif ( isset( $sub_field['default'] ) ) {
2096 $value = $sub_field['default'];
2097 }
2098
2099 if ( 'fields_group' === $sub_field['type'] ) {
2100 static::fields_group( $sub_field, $value, $module_id, true, array(
2101 'id' => $settings['id'],
2102 'option_key' => $option_key,
2103 'value' => $option,
2104 ) );
2105 } else {
2106 static::replace_field(
2107 $sub_field,
2108 $value,
2109 "name=\"merchant[{$sub_field['id']}]",
2110 "name=\"merchant[{$settings['id']}][{$option_key}][{$sub_field['id']}]",
2111 $module_id
2112 );
2113 }
2114 ?>
2115 </div>
2116 <?php
2117 endforeach; ?>
2118 <input type="hidden" name="merchant[<?php
2119 echo esc_attr( $settings['id'] ) ?>][<?php
2120 echo absint( $option_key ) ?>][layout]"
2121 value="<?php
2122 echo esc_attr( $option['layout'] ) ?>">
2123 </div>
2124 <?php self::print_flexible_layout_actions( $settings, $layout_type ); ?>
2125 </div>
2126 </div>
2127 <?php
2128 endforeach; ?>
2129 </div>
2130
2131 <div class="customize-control-flexible-content-add-wrapper">
2132 <div class="customize-control-flexible-content-add-list">
2133 <?php
2134 foreach ( $settings['layouts'] as $layout_type => $layout ) : ?>
2135 <a href="#"
2136 class="customize-control-flexible-content-add"
2137 data-id="<?php
2138 echo esc_attr( $settings['id'] ) ?>"
2139 data-layout="<?php
2140 echo esc_attr( $layout_type ) ?>">
2141 <?php
2142 echo esc_attr( $layout['title'] ) ?>
2143 </a>
2144 <?php
2145 endforeach; ?>
2146 </div>
2147 <button class="button customize-control-flexible-content-add-button" type="button"><?php
2148 echo esc_html( $settings['button_label'] ); ?></button>
2149 </div>
2150 </div>
2151 <?php
2152 }
2153
2154 /**
2155 * Field: Group.
2156 *
2157 * @param $settings array field settings.
2158 * @param $value mixed field value.
2159 * @param $module_id string module id.
2160 * @param $inside_flexible boolean is inside flexible content.
2161 * @param $args array extra arguments to be passed if inside flexible content.
2162 *
2163 * @return void
2164 */
2165 public static function fields_group( $settings, $value, $module_id = '', $inside_flexible = false, $args = array() ) {
2166 $control_field_status = ! empty( $settings['display_status'] ) && $settings['display_status'] === true;
2167 $accordion = ! empty( $settings['accordion'] ) && $settings['accordion'] === true;
2168 $state = ! empty( $settings['state'] ) && $settings['state'] === 'open';
2169 ?>
2170 <div class="merchant-group-field<?php
2171 echo $accordion ? ' has-accordion' : '';
2172 echo $control_field_status ? ' has-flag' : '';
2173 echo $state ? ' open' : '';
2174 echo ' merchant-group-field-' . esc_attr( $settings['id'] ) ?>" data-id="<?php
2175 echo esc_attr( $settings['id'] ) ?>">
2176 <div class="title-area<?php
2177 echo $accordion ? ' accordion-style' : '' ?>">
2178 <?php
2179 if ( ! empty( $settings['title'] ) ) {
2180 printf( '<div class="merchant-module-page-setting-field-title">%s<span class="field-status hidden"></span></div>', esc_html( $settings['title'] ) );
2181 }
2182 if ( ! empty( $settings['sub-desc'] ) ) {
2183 printf( '<div class="merchant-module-page-setting-field-desc">%s</div>', wp_kses_post( $settings['sub-desc'] ) );
2184 }
2185 if ( $accordion ) {
2186 ?>
2187 <span class="accordion-icon dashicons dashicons-arrow-down-alt2"></span>
2188 <?php
2189 }
2190 ?>
2191 </div>
2192 <div class="merchant-group-fields-container">
2193 <?php
2194 if ( $control_field_status ) {
2195 /**
2196 * Field: Status.
2197 *
2198 * @since 1.9.12
2199 */
2200 $status = apply_filters(
2201 'merchant_group_status_field',
2202 array(
2203 'id' => $settings['id'] . '_status',
2204 'type' => 'select',
2205 'title' => esc_html__( 'Status', 'merchant' ),
2206 'options' => array(
2207 'inactive' => esc_html__( 'Inactive', 'merchant' ),
2208 'active' => esc_html__( 'Active', 'merchant' ),
2209 ),
2210 'default' => isset( $settings['default'] ) ? $settings['default'] : 'active',
2211 ),
2212 $settings,
2213 $value,
2214 $module_id
2215 );
2216 if ( $inside_flexible ) {
2217 static::replace_field(
2218 $status,
2219 isset( $args['value'][$settings['id']][ $status['id'] ] ) ? $args['value'][$settings['id']][ $status['id'] ] : $status['default'] ?? '',
2220 "name=\"merchant[{$status['id']}]",
2221 "name=\"merchant[{$args['id']}][{$args['option_key']}][{$settings['id']}][{$status['id']}]\" data-name=\"merchant[{$args['id']}][0][{$settings['id']}][{$status['id']}]",
2222 $module_id
2223 );
2224 } else {
2225 static::replace_field(
2226 $status,
2227 isset( $value[ $status['id'] ] ) ? $value[ $status['id'] ] : '',
2228 "name=\"merchant[{$status['id']}]",
2229 "name=\"merchant[{$settings['id']}][{$status['id']}]",
2230 $module_id
2231 );
2232 }
2233 }
2234
2235 foreach ( $settings['fields'] as $field ) {
2236 if ( $inside_flexible ) {
2237 static::replace_field(
2238 $field,
2239 isset( $args['value'][$settings['id']][ $field['id'] ] ) ? $args['value'][$settings['id']][ $field['id'] ] : $field['default'] ?? '',
2240 "name=\"merchant[{$field['id']}]",
2241 "name=\"merchant[{$args['id']}][{$args['option_key']}][{$settings['id']}][{$field['id']}]\" data-name=\"merchant[{$args['id']}][0][{$settings['id']}][{$field['id']}]",
2242 $module_id
2243 );
2244 } else {
2245 static::replace_field(
2246 $field,
2247 isset( $value[ $field['id'] ] ) ? $value[ $field['id'] ] : '',
2248 "name=\"merchant[{$field['id']}]",
2249 "name=\"merchant[{$settings['id']}][{$field['id']}]",
2250 $module_id
2251 );
2252 }
2253 } ?>
2254 </div>
2255 </div>
2256 <?php
2257 }
2258
2259 /**
2260 * Field: Create Page.
2261 */
2262 public static function create_page( $settings, $value, $module_id = '' ) {
2263 $page_id = get_option( $settings['option_name'] );
2264
2265 echo '<div class="merchant-create-page-control">';
2266
2267 if ( $page_id && post_exists( get_the_title( $page_id ) ) && 'publish' === get_post_status( $page_id ) ) {
2268 echo wp_kses_post(
2269 sprintf( /* translators: 1: link to edit page */
2270 __( '<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>',
2271 'merchant' ),
2272 get_admin_url() . 'post.php?post=' . $page_id . '&action=edit',
2273 get_admin_url() . 'nav-menus.php'
2274 )
2275 );
2276 } else {
2277 echo '<div class="merchant-create-page-control-create-message">';
2278 echo wp_kses_post(
2279 '<p class="merchant-module-page-setting-field-desc mrc-mt-0">'.
2280 sprintf( /* translators: 1: page name */
2281 __( 'It looks like you haven\'t created a <strong>%1$s</strong> page yet. Click the below button to create the page.',
2282 'merchant' ),
2283 $settings['page_title']
2284 ). '</p>'
2285 );
2286 echo '</div>';
2287 echo '<div class="merchant-create-page-control-success-message" style="display: none;">';
2288 echo wp_kses_post(
2289 sprintf( /* translators: 1: link to edit page */
2290 __( '<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>',
2291 'merchant' ),
2292 get_admin_url() . 'post.php?post=&action=edit',
2293 get_admin_url() . 'nav-menus.php'
2294 )
2295 );
2296 echo '</div>';
2297 echo wp_kses_post(
2298 sprintf( /* translators: 1: page title, 2: page meta key, 3: page meta value, 4: option name, 5: nonce, 6: loading text, 7: success text */
2299 __( '<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>',
2300 'merchant' ),
2301 __( 'Create Page', 'merchant' ),
2302 $settings['page_title'],
2303 $settings['page_meta_key'],
2304 $settings['page_meta_value'],
2305 $settings['option_name'],
2306 wp_create_nonce( 'customize-create-page-control-nonce' ),
2307 __( 'Creating...', 'merchant' ),
2308 __( 'Created!', 'merchant' )
2309 )
2310 );
2311 }
2312
2313 echo '</div>';
2314 }
2315
2316 public static function dimensions( $settings, $value, $module_id = '' ) {
2317 $settings = wp_parse_args( $settings, array(
2318 'units' => array(
2319 'px' => 'px',
2320 'rem' => 'rem',
2321 'em' => 'em',
2322 'vw' => 'vw',
2323 'vh' => 'vh',
2324 '%' => '%',
2325 ),
2326 'dimensions' => array(
2327 'top',
2328 'right',
2329 'bottom',
2330 'left',
2331 ),
2332 ) );
2333 $default_value = array(
2334 'unit' => reset( $settings['units'] ),
2335 );
2336 foreach ( $settings['dimensions'] as $dimension ) {
2337 $default_value[ $dimension ] = 0;
2338 }
2339 $value = wp_parse_args( $value, $default_value );
2340 ?>
2341 <div class="merchant-module-page-settings-unit">
2342 <select name="merchant[<?php
2343 echo esc_attr( $settings['id'] ); ?>][unit]">
2344 <?php
2345 foreach ( $settings['units'] as $key => $option ) : ?>
2346 <option value="<?php
2347 echo esc_attr( $key ); ?>" <?php
2348 selected( $value['unit'], $key, true ); ?>><?php
2349 echo esc_html( $option ); ?></option>
2350 <?php
2351 endforeach; ?>
2352 </select>
2353 </div>
2354 <div class="merchant-module-page-settings-dimensions">
2355 <?php
2356 foreach ( $settings['dimensions'] as $dimension ) : ?>
2357 <div>
2358 <input id="merchant-<?php
2359 echo esc_attr( $settings['id'] ); ?>-<?php
2360 echo esc_attr( $dimension ) ?>"
2361 type="number"
2362 name="merchant[<?php
2363 echo esc_attr( $settings['id'] ); ?>][<?php
2364 echo esc_attr( $dimension ) ?>]"
2365 value="<?php
2366 echo esc_attr( $value[ $dimension ] ); ?>"/>
2367 <label for="merchant-<?php
2368 echo esc_attr( $settings['id'] ); ?>-<?php
2369 echo esc_attr( $dimension ) ?>">
2370 <?php
2371 echo esc_html( ucfirst( $dimension ) ); ?>
2372 </label>
2373 </div>
2374 <?php
2375 endforeach; ?>
2376 </div>
2377 <?php
2378 }
2379
2380 public static function responsive_dimensions( $settings, $value, $module_id = '' ) {
2381 $settings = wp_parse_args( $settings, array(
2382 'units' => array(
2383 'px' => 'px',
2384 'rem' => 'rem',
2385 'em' => 'em',
2386 'vw' => 'vw',
2387 'vh' => 'vh',
2388 '%' => '%',
2389 ),
2390 'dimensions' => array(
2391 'top',
2392 'right',
2393 'bottom',
2394 'left',
2395 ),
2396 'devices' => array(
2397 'desktop' => 'dashicons-desktop',
2398 'tablet' => 'dashicons-tablet',
2399 'mobile' => 'dashicons-smartphone',
2400 ),
2401 ) );
2402 $default_values = array();
2403 foreach ( $settings['devices'] as $device => $icon ) {
2404 $default_values[ $device ]['unit'] = reset( $settings['units'] );
2405
2406 foreach ( $settings['dimensions'] as $dimension ) {
2407 $default_values[ $device ][ $dimension ] = 0;
2408 }
2409 }
2410 $value = wp_parse_args( $value, $default_values );
2411 ?>
2412 <div class="merchant-module-page-settings-responsive">
2413 <ul class="merchant-module-page-settings-devices">
2414 <?php
2415 foreach ( $settings['devices'] as $device => $icon ) : ?>
2416 <li class="<?php
2417 echo esc_attr( $device ); ?>">
2418 <button type="button" class="preview-<?php
2419 echo esc_attr( $device ); ?> <?php
2420 echo $device === key( $settings['devices'] ) ? 'active' : '' ?>"
2421 data-device="<?php
2422 echo esc_attr( $device ); ?>">
2423 <i class="dashicons <?php
2424 echo esc_attr( $icon ); ?>"></i>
2425 </button>
2426 </li>
2427 <?php
2428 endforeach; ?>
2429 </ul>
2430 <?php
2431 foreach ( $settings['devices'] as $device => $icon ) : ?>
2432 <div class="merchant-module-page-settings-device-container <?php
2433 echo $device === key( $settings['devices'] ) ? 'active' : '' ?>" data-device="<?php
2434 echo esc_attr( $device ); ?>">
2435 <div class="merchant-module-page-settings-unit">
2436 <select name="merchant[<?php
2437 echo esc_attr( $settings['id'] ); ?>][<?php
2438 echo esc_attr( $device ) ?>][unit]">
2439 <?php
2440 foreach ( $settings['units'] as $key => $option ) : ?>
2441 <option value="<?php
2442 echo esc_attr( $key ); ?>" <?php
2443 selected( $value[ esc_attr( $device ) ]['unit'], $key, true ); ?>><?php
2444 echo esc_html( $option ); ?></option>
2445 <?php
2446 endforeach; ?>
2447 </select>
2448 </div>
2449 <div class="merchant-module-page-settings-dimensions">
2450 <?php
2451 foreach ( $settings['dimensions'] as $dimension ) : ?>
2452 <div>
2453 <input id="merchant-<?php
2454 echo esc_attr( $settings['id'] ); ?>-<?php
2455 echo esc_attr( $device ) ?>-<?php
2456 echo esc_attr( $dimension ) ?>"
2457 type="number"
2458 name="merchant[<?php
2459 echo esc_attr( $settings['id'] ); ?>][<?php
2460 echo esc_attr( $device ) ?>][<?php
2461 echo esc_attr( $dimension ) ?>]"
2462 value="<?php
2463 echo esc_attr( $value[ $device ][ $dimension ] ); ?>"/>
2464 <label for="merchant-<?php
2465 echo esc_attr( $settings['id'] ); ?>-<?php
2466 echo esc_attr( $device ) ?>-<?php
2467 echo esc_attr( $dimension ) ?>">
2468 <?php
2469 echo esc_html( ucfirst( $dimension ) ); ?>
2470 </label>
2471 </div>
2472 <?php
2473 endforeach; ?>
2474 </div>
2475 </div>
2476 <?php
2477 endforeach; ?>
2478 </div>
2479
2480 <?php
2481 }
2482
2483 /**
2484 * Field: Custom callback.
2485 */
2486 public static function custom_callback( $settings, $value, $module_id = '' ) {
2487 if ( ! empty( $settings['class_name'] ) && ! empty( $settings['callback_name'] ) ) {
2488 return call_user_func( array( $settings['class_name'], $settings['callback_name'] ), $settings, $value );
2489 }
2490
2491 if ( ! empty( $settings['callback_name'] ) ) {
2492 return call_user_func( $settings['callback_name'], $settings, $value );
2493 }
2494
2495 return false;
2496 }
2497
2498 private static function print_flexible_layout_actions( $settings, $layout_type ) {
2499 $has_duplicate = ! empty( $settings['duplicate'] );
2500 $has_accordion = ! empty( $settings['accordion'] );
2501 ?>
2502 <div class="layout-actions<?php echo $has_accordion ? esc_attr( ' layout-actions-has_accordion' ) : ' layout-actions-no_accordion'; ?>">
2503 <a href="#" class="layout-actions__toggle">
2504 <svg xmlns="http://www.w3.org/2000/svg" width="14" height="4" viewBox="0 0 14 4" fill="none">
2505 <path d="M1.5 0.763184C2.32843 0.763183 3 1.43476 3 2.26318C3 3.09161 2.32843 3.76318 1.5 3.76318C0.671573 3.76318 -2.93554e-08 3.09161 -6.55671e-08 2.26318C-1.01779e-07 1.43476 0.671573 0.763184 1.5 0.763184Z" fill="#4A4A4A"/>
2506 <path d="M7 0.763183C7.82843 0.763183 8.5 1.43476 8.5 2.26318C8.5 3.09161 7.82843 3.76318 7 3.76318C6.17157 3.76318 5.5 3.09161 5.5 2.26318C5.5 1.43476 6.17157 0.763183 7 0.763183Z" fill="#4A4A4A"/>
2507 <path d="M12.5 0.763183C13.3284 0.763183 14 1.43476 14 2.26318C14 3.09161 13.3284 3.76318 12.5 3.76318C11.6716 3.76318 11 3.09161 11 2.26318C11 1.43476 11.6716 0.763183 12.5 0.763183Z" fill="#4A4A4A"/>
2508 </svg>
2509 </a>
2510 <div class="layout-actions__inner" style="display: none;">
2511 <?php if ( $has_duplicate ) : ?>
2512 <a
2513 href="#"
2514 class="customize-control-flexible-content-duplicate"
2515 data-id="<?php echo esc_attr( $settings['id'] ); ?>"
2516 data-layout="<?php echo esc_attr( $layout_type ); ?>"
2517 title="<?php echo esc_attr__( 'Duplicate', 'merchant' ); ?>">
2518 <svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" viewBox="0 0 19 22" fill="none">
2519 <path fill-rule="evenodd" clip-rule="evenodd" d="M2 1.76318H13C13.2761 1.76318 13.5 1.98704 13.5 2.26318V13.2632C13.5 13.5393 13.2761 13.7632 13 13.7632H2C1.72386 13.7632 1.5 13.5393 1.5 13.2632V2.26318C1.5 1.98704 1.72386 1.76318 2 1.76318ZM0 2.26318C0 1.15861 0.895431 0.263184 2 0.263184H13C14.1046 0.263184 15 1.15861 15 2.26318V13.2632C15 14.3678 14.1046 15.2632 13 15.2632H2C0.89543 15.2632 0 14.3678 0 13.2632V2.26318ZM17 5.26318V16.0132C17 16.7035 16.4404 17.2632 15.75 17.2632H3V18.7632H15.75C17.2688 18.7632 18.5 17.532 18.5 16.0132V5.26318H17Z" fill="#757575"/>
2520 </svg>
2521 <span><?php echo esc_html__( 'Duplicate', 'merchant' ); ?></span>
2522 </a>
2523 <?php endif; ?>
2524
2525 <a class="customize-control-flexible-content-delete" href="#">
2526 <svg xmlns="http://www.w3.org/2000/svg" width="14" height="17" viewBox="0 0 14 17" fill="none">
2527 <path fill-rule="evenodd" clip-rule="evenodd" d="M7 0.263184C5.18578 0.263184 3.67247 1.55151 3.32502 3.26318H0V4.76318H1.2699L2.08782 13.7602C2.21659 15.1767 3.40421 16.2613 4.82652 16.2613H9.17366C10.596 16.2613 11.7836 15.1767 11.9124 13.7602L12.7303 4.76318H14V3.26318H10.675C10.3275 1.5515 8.81422 0.263184 7 0.263184ZM7 1.76318C6.02034 1.76318 5.18691 2.38929 4.87803 3.26318H9.12197C8.81309 2.38929 7.97966 1.76318 7 1.76318ZM11.2241 4.76318H2.77609L3.58166 13.6244C3.64019 14.2683 4.18002 14.7613 4.82652 14.7613H9.17366C9.82017 14.7613 10.36 14.2683 10.4185 13.6244L11.2241 4.76318Z" fill="#757575"/>
2528 </svg>
2529 <span><?php echo esc_html__( 'Delete', 'merchant' ); ?></span>
2530 </a>
2531 </div>
2532 </div>
2533 <?php
2534 }
2535
2536 /**
2537 * Get category choices for select2
2538 *
2539 * @return array
2540 */
2541 public static function get_category_select2_choices() {
2542 $choices = array();
2543 $categories = merchant_get_product_categories();
2544
2545 if ( is_array( $categories ) && ! empty( $categories ) ) {
2546 $choices = self::build_category_select2_choices( $categories );
2547 }
2548
2549 return $choices;
2550 }
2551
2552 /**
2553 * Build Select2 choices for hierarchical categories.
2554 *
2555 * @param $categories
2556 * @param $level
2557 *
2558 * @return array
2559 */
2560 private static function build_category_select2_choices( $categories, $level = 0 ) {
2561 $choices = array();
2562
2563 foreach ( $categories as $cat ) {
2564 $indent = str_repeat( '&nbsp;', $level * 4 ); // Use non-breaking spaces for indentation
2565
2566 $choices[] = array(
2567 'id' => esc_attr( $cat['slug'] ?? '' ),
2568 'text' => esc_html( $indent . ( $cat['name'] ?? '' ) ),
2569 );
2570
2571 if ( ! empty( $cat['children'] ) ) {
2572 $choices = array_merge( $choices, self::build_category_select2_choices( $cat['children'], $level + 1 ) );
2573 }
2574 }
2575
2576 return $choices;
2577 }
2578
2579 /**
2580 * Get Tag choices for select2
2581 *
2582 * @return array
2583 */
2584 public static function get_tag_select2_choices() {
2585 $choices = array();
2586 $tags = merchant_get_product_tags();
2587
2588 if ( is_array( $tags ) && ! empty( $tags ) ) {
2589 foreach ( $tags as $slug => $name ) {
2590 $choices[] = array(
2591 'id' => esc_attr( $slug ),
2592 'text' => esc_html( $name ),
2593 );
2594 }
2595 }
2596
2597 return $choices;
2598 }
2599
2600 /**
2601 * Get User Roles choices for select2
2602 *
2603 * @return array
2604 */
2605 public static function get_user_roles_select2_choices() {
2606 $choices = array();
2607 $user_roles = get_editable_roles();
2608
2609 if ( ! empty( $user_roles ) ) {
2610 foreach ( $user_roles as $role_id => $role_data ) {
2611 $choices[] = array(
2612 'id' => $role_id,
2613 'text' => $role_data['name'],
2614 );
2615 }
2616 }
2617
2618 return $choices;
2619 }
2620
2621 /**
2622 * Get Customers choices for select2.
2623 *
2624 * @return array
2625 */
2626 public static function get_customers_select2_choices() {
2627 $cache_key = 'customers_select2_choices';
2628 $choices = get_transient( $cache_key );
2629
2630 if ( ! empty( $choices ) && is_array( $choices ) ) {
2631 return $choices;
2632 }
2633
2634 // Get users with the 'customer' role
2635 $customer_users = get_users(
2636 array(
2637 'role' => 'customer',
2638 'fields' => array( 'ID', 'display_name' ),
2639 )
2640 );
2641
2642 $choices = array();
2643 if ( ! empty( $customer_users ) ) {
2644 foreach ( $customer_users as $user ) {
2645 $choices[] = array(
2646 'id' => $user->ID,
2647 'text' => $user->display_name,
2648 );
2649 }
2650 }
2651
2652 // Cache the choices with no expiration. Will be cleared using `clear_customer_choices_cache`
2653 set_transient( $cache_key, $choices );
2654
2655 return $choices;
2656 }
2657
2658 /**
2659 * Clear customers cache when a customer is created/deleted/updated.
2660 *
2661 * @param $user_id
2662 * @param $user
2663 *
2664 * @return void
2665 */
2666 public function clear_customer_choices_cache( $user_id, $user ) {
2667 $user_roles = $user->roles ?? array();
2668 if ( in_array( 'customer', $user_roles, true ) ) {
2669 delete_transient( 'customers_select2_choices' );
2670 }
2671 }
2672 }
2673
2674 Merchant_Admin_Options::instance();
2675 }
2676