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

2,681 lines 101.1 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_textarea_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_multiline':
458 case 'textarea':
459 $value = sanitize_textarea_field( $value );
460 break;
461
462 case 'textarea_code':
463 $value = $value;
464 break;
465
466 case 'checkbox_multiple':
467 if ( is_array( $value ) && ! empty( $value ) ) {
468 $value = array_filter( array_map( 'sanitize_text_field', $value ) );
469 } else {
470 $value = array();
471 }
472 break;
473
474 case 'checkbox':
475 case 'switcher':
476 $value = ( '1' === $value ) ? 1 : 0;
477 break;
478
479 case 'range':
480 case 'number':
481 $value = absint( $value );
482 break;
483 case 'select_ajax':
484 if ( is_array( $value ) && ! empty( $value ) ) {
485 $value = array_filter( array_map( 'sanitize_text_field', $value ) );
486 } elseif ( is_string( $value ) ) {
487 $value = sanitize_text_field( $value );
488 } else {
489 $value = isset( $field['multiple'] ) && $field['multiple'] === false ? '' : array();
490 }
491 break;
492 case 'radio':
493 case 'radio_alt':
494 case 'select':
495 case 'choices':
496 case 'buttons':
497 case 'buttons_alt':
498 case 'buttons_content':
499 $value = ( in_array( $value, array_keys( $field['options'] ), true ) ) ? sanitize_key( $value ) : '';
500 break;
501
502 case 'hook_select':
503 $value = is_array( $value ) ? $value : array();
504
505 foreach ( $value as $key => $val ) {
506 if ( $key === 'hook_name' ) {
507 $value[ $key ] = in_array( $val, array_keys( $field['options'] ), true ) ? sanitize_key( $val ) : '';
508 } else {
509 $value[ $key ] = (int) $val;
510 }
511 }
512
513 break;
514
515 case 'code-editor':
516 $value = wp_kses_post( $value );
517 break;
518
519 case 'sortable':
520 $values = json_decode( $value );
521 $value = array();
522
523 foreach ( $values as $val ) {
524 if ( in_array( $val, array_keys( $field['options'] ), true ) ) {
525 $value[] = sanitize_key( $val );
526 }
527 }
528 break;
529 case 'dimensions':
530 $values = is_array( $value ) ? $value : array();
531
532 foreach ( $values as $key => $val ) {
533 if ( $key === 'unit' ) {
534 $value[ $key ] = sanitize_key( $value[ $key ] );
535 } else {
536 $value[ $key ] = absint( $value[ $key ] );
537 }
538 }
539 break;
540 case 'responsive_dimensions':
541 $values = is_array( $value ) ? $value : array();
542
543 foreach ( $values as $device => $device_fields ) {
544 foreach ( $device_fields as $device_field => $device_field_val ) {
545 if ( $device_field === 'unit' ) {
546 $value[ $device ][ $device_field ] = sanitize_key( $device_field_val );
547 } else {
548 $value[ $device ][ $device_field ] = absint( $device_field_val );
549 }
550 }
551 }
552 break;
553
554 case 'sortable_repeater':
555 $values = json_decode( $value );
556 $value = array_map( 'sanitize_text_field', $values );
557 break;
558 case 'flexible_content':
559 $value = ! is_array( $value ) || empty( $value ) ? array() : $value;
560
561 $value = array_map( function ( $sub_fields ) use ( $field ) {
562 foreach ( $sub_fields as $sub_field => $value ) {
563 if ( $sub_field === 'layout' ) {
564 $sub_fields[ $sub_field ] = sanitize_text_field( $value );
565 } else {
566 $layout_field = array_filter( $field['layouts'][ $sub_fields['layout'] ]['fields'], function ( $layout_field ) use ( $sub_field ) {
567 return $layout_field['id'] === $sub_field;
568 } );
569
570
571 $sub_fields[ $sub_field ] = self::sanitize( reset( $layout_field ), $value );
572 }
573 }
574
575 return $sub_fields;
576 }, $value );
577
578 break;
579 }
580
581 return $value;
582 }
583
584 /**
585 * Field
586 */
587 public static function field( $settings, $value, $module_id = '') {
588
589 if ( ! empty( $settings['type'] ) ) {
590 $type = $settings['type'];
591
592 $id = ( ! empty( $settings['id'] ) ) ? $settings['id'] : '';
593 $class = ( ! empty( $settings['class'] ) ) ? ' ' . $settings['class'] : '';
594 $condition = ( ! empty( $settings['condition'] ) ) ? $settings['condition'] : array();
595 $conditions = ( ! empty( $settings['conditions'] ) ) ? $settings['conditions'] : ''; //Docs here: https://github.com/athemes/Merchant/pull/133
596 $default = ( ! empty( $settings['default'] ) ) ? $settings['default'] : null;
597 $is_upsell = ! merchant_is_pro_active() && isset( $settings['pro'] ) && $settings['pro'] === true;
598
599 if ( ! $value && ( 0 !== $value && '0' !== $value ) ) {
600 if ( $type === 'checkbox_multiple' ) {
601 $value = is_array( $value ) ? $value : (array) $default;
602 } elseif ( $type === 'text' && ! empty( $module_id ) ) {
603 $value = Merchant_Option::get( $module_id, $id );
604 } else {
605 $value = $default;
606 }
607 }
608
609 $wrapper_classes = array( 'merchant-module-page-setting-field' );
610 $wrapper_classes[] = 'merchant-module-page-setting-field-' . $type;
611
612 if ( ! empty( $class ) ) {
613 $wrapper_classes[] = $class;
614 }
615
616 /**
617 * Hook 'merchant_admin_module_field_wrapper_classes'
618 *
619 * @since 1.9.3
620 */
621 $wrapper_classes = apply_filters( 'merchant_admin_module_field_wrapper_classes', $wrapper_classes, $settings, $value, $module_id );
622
623 echo '<div class="'. esc_attr( implode( ' ', $wrapper_classes ) ) .'" data-id="'
624 . esc_attr( $id ) . '" data-type="' . esc_attr( $type ) . '" data-condition="' . esc_attr( wp_json_encode( $condition ) ) .
625 '" data-conditions="' . ( $conditions ? esc_attr( wp_json_encode( $conditions ) ) : "" ) . '">';
626 if ( ! empty( $settings['title'] ) ) {
627 ?>
628 <div class="merchant-module-page-setting-field-title<?php echo esc_attr( $is_upsell ? ' merchant-module-page-setting-field-title__has-upsell' : '' ); ?>">
629 <?php echo esc_html( $settings['title'] ); ?>
630
631 <?php if ( $is_upsell ) : ?>
632 <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">
633 <span class="merchant-pro-badge merchant-pro-tooltip" data-tooltip-message="<?php echo esc_attr__( 'This option is only available on Merchant Pro', 'merchant' ); ?>">
634 <svg width="28" height="16" viewBox="0 0 28 16" fill="none" xmlns="http://www.w3.org/2000/svg">
635 <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"/>
636 <rect x="0.5" y="1" width="27" height="14" rx="1.5" stroke="#3858E9"/>
637 </svg>
638 </span>
639 </a>
640 <?php endif; ?>
641 </div>
642 <?php
643 }
644
645 echo '<div class="merchant-module-page-setting-field-inner merchant-field-' . esc_attr( $id ) . '">';
646 if ( method_exists( 'Merchant_Admin_Options', $type ) ) {
647 call_user_func( array( 'Merchant_Admin_Options', $type ), $settings, $value, $module_id );
648 } else {
649 esc_html_e( 'Field not found!', 'merchant' );
650 }
651 echo '</div>';
652
653 $hidden_desc = $settings['hidden_desc'] ?? '';
654
655 /**
656 * Hook 'merchant_admin_module_field_hidden_description'
657 *
658 * @since 1.9.3
659 */
660 $hidden_desc = apply_filters( 'merchant_admin_module_field_hidden_description', $hidden_desc, $settings, $value, $module_id );
661
662 $desc = ( ! empty( $settings['desc'] ) ) ? $settings['desc'] : '';
663
664 /**
665 * Hook 'merchant_admin_module_field_description'
666 *
667 * @since 1.9.3
668 */
669 $desc = apply_filters( 'merchant_admin_module_field_description', $desc, $settings, $value, $module_id );
670
671 if ( ! empty( $desc ) ) {
672 $hidden_desc_html = '';
673 if ( ! empty( $hidden_desc ) ) {
674 $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>';
675 $hidden_desc_html .= '<img src="' . esc_url( MERCHANT_URI . '/assets/images/arrow-down.svg' ) . '" alt="Merchant" />';
676 $hidden_desc_html .= '</div>';
677 }
678
679 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 ) );
680 }
681
682 if ( ! empty( $hidden_desc ) ) {
683 printf( '<div class="merchant-module-page-setting-field-hidden-desc">%s</div>', wp_kses_post( nl2br( $hidden_desc ) ) );
684 }
685
686 echo '</div>';
687 }
688 }
689
690 /**
691 * Disabled field
692 *
693 * @param array $settings
694 * @param mixed $value
695 *
696 * @return void
697 */
698 public static function disabled_field( $settings, $value, $module_id = '') {
699 static::replace_field(
700 $settings,
701 $value,
702 array(
703 '<input ',
704 '<select ',
705 'merchant-module-page-setting-field-inner',
706 ),
707 array(
708 '<input disabled ',
709 '<select disabled ',
710 'merchant-module-page-setting-field-inner disabled',
711 ),
712 $module_id
713 );
714 }
715
716 /**
717 * Modified field.
718 *
719 * @param $settings
720 * @param $value
721 * @param $search
722 * @param $replace
723 *
724 * @return void
725 */
726 public static function replace_field( $settings, $value, $search, $replace, $module_id = '') {
727 ob_start();
728 self::field( $settings, $value, $module_id );
729 $field = ob_get_clean();
730
731 echo wp_kses( str_replace( $search, $replace, $field ), merchant_kses_allowed_tags( array( 'all' ) ) );
732 }
733
734 /**
735 * Field: Text
736 */
737 public static function text( $settings, $value, $module_id = '' ) {
738 ?>
739 <input type="text" name="merchant[<?php
740 echo esc_attr( $settings['id'] ); ?>]" value="<?php
741 echo esc_attr( $value ); ?>" placeholder="<?php
742 echo esc_attr( $settings['placeholder'] ?? '' ); ?>"/>
743 <?php
744 }
745
746 /**
747 * Field: Text (readonly)
748 */
749 public static function text_readonly( $settings, $value, $module_id = '' ) {
750 ?>
751 <input type="text" value="<?php
752 echo esc_attr( $value ); ?>" readonly/>
753 <?php
754 }
755
756 /**
757 * Field: Number
758 */
759 public static function number( $settings, $value, $module_id = '' ) {
760 ?>
761 <input type="number" name="merchant[<?php
762 echo esc_attr( $settings['id'] ); ?>]" value="<?php
763 echo esc_attr( $value ); ?>"<?php
764 echo isset( $settings['step'] ) ? ' step="' . esc_attr( $settings['step'] ) . '"' : '';
765 echo isset( $settings['max'] ) ? ' max="' . esc_attr( $settings['max'] ) . '"' : '';
766 echo isset( $settings['min'] ) ? ' min="' . esc_attr( $settings['min'] ) . '"' : '' ?>
767 placeholder="<?php echo esc_attr( $settings['placeholder'] ?? '' ); ?>"/>
768 <?php
769 }
770
771 /**
772 * Field: Textarea
773 */
774 public static function textarea( $settings, $value, $module_id = '' ) {
775 $value = ( $value ) ? $value : '';
776 ?>
777 <textarea name="merchant[<?php
778 echo esc_attr( $settings['id'] ); ?>]"><?php
779 echo wp_kses_post( $value ); ?></textarea>
780 <?php
781 }
782
783 /**
784 * Field: Textarea
785 */
786 public static function textarea_multiline( $settings, $value, $module_id = '' ) {
787 $value = ( $value ) ? $value : '';
788 ?>
789 <textarea name="merchant[<?php
790 echo esc_attr( $settings['id'] ); ?>]"><?php
791 echo wp_kses_post( $value ); ?></textarea>
792 <?php
793 }
794
795 /**
796 * Field: Textarea Code Snippet.
797 */
798 public static function textarea_code( $settings, $value, $module_id = '' ) {
799 $value = ( $value ) ? $value : '';
800 ?>
801 <textarea name="merchant[<?php
802 echo esc_attr( $settings['id'] ); ?>]"><?php
803 echo wp_kses( $value, merchant_kses_allowed_tags_for_code_snippets() ); ?></textarea>
804 <?php
805 }
806
807 /**
808 * Field: Checkbox
809 */
810 public static function checkbox( $settings, $value, $module_id = '' ) {
811 ?>
812 <div>
813 <label>
814 <input type="checkbox" name="merchant[<?php
815 echo esc_attr( $settings['id'] ); ?>]" value="1" <?php
816 checked( $value, 1, true ); ?> />
817 <?php
818 if ( ! empty( $settings['label'] ) ) : ?>
819 <span><?php
820 echo esc_html( $settings['label'] ); ?></span>
821 <?php
822 endif; ?>
823 </label>
824 </div>
825 <?php
826 }
827
828 /**
829 * Field: Checkbox multiple
830 */
831 public static function checkbox_multiple( $settings, $value ) {
832 if ( ! empty( $settings['options'] ) ) : ?>
833 <?php
834 foreach ( $settings['options'] as $key => $option ) : ?>
835 <label>
836 <input
837 type="checkbox" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>][]"
838 value="<?php echo esc_attr( $key ); ?>"
839 <?php checked( in_array( $key, $value, true ), true ); ?>
840 />
841 <span><?php echo esc_html( $option ); ?></span>
842 </label>
843 <?php
844 endforeach; ?>
845 <?php
846 endif;
847 }
848
849 /**
850 * Field: Switcher
851 */
852 public static function switcher( $settings, $value, $module_id = '' ) {
853 ?>
854 <div class="merchant-toggle-switch">
855 <input type="checkbox" id="<?php
856 echo esc_attr( $settings['id'] ); ?>" name="merchant[<?php
857 echo esc_attr( $settings['id'] ); ?>]" value="1" <?php
858 checked( $value, 1, true ); ?>
859 class="toggle-switch-checkbox"/>
860 <label class="toggle-switch-label" for="<?php
861 echo esc_attr( $settings['id'] ); ?>">
862 <span class="toggle-switch-inner"></span>
863 <span class="toggle-switch-switch"></span>
864 </label>
865 <?php
866 if ( ! empty( $settings['label'] ) ) : ?>
867 <span><?php
868 echo esc_html( $settings['label'] ); ?></span>
869 <?php
870 endif; ?>
871 </div>
872 <?php
873 }
874
875 /**
876 * Field: Radio
877 */
878 public static function radio( $settings, $value, $module_id = '' ) {
879 ?>
880 <?php
881 if ( ! empty( $settings['options'] ) ) : ?>
882 <?php
883 foreach ( $settings['options'] as $key => $option ) : ?>
884 <label>
885 <input type="radio" name="merchant[<?php
886 echo esc_attr( $settings['id'] ); ?>]" value="<?php
887 echo esc_attr( $key ); ?>" <?php
888 checked( $value, $key, true ); ?>/>
889 <span><?php
890 echo esc_html( $option ); ?></span>
891 </label>
892 <?php
893 endforeach; ?>
894 <?php
895 endif; ?>
896 <?php
897 }
898
899 /**
900 * Field: Image picker
901 */
902 public static function image_picker( $settings, $value, $module_id = '' ) {
903 ?>
904 <div class="merchant-image-picker">
905 <?php
906 if ( ! empty( $settings['options'] ) ) : ?>
907 <?php
908 foreach ( $settings['options'] as $key => $option ) : ?>
909 <label>
910 <input type="radio" name="merchant[<?php
911 echo esc_attr( $settings['id'] ); ?>]" value="<?php
912 echo esc_attr( $key ); ?>" <?php
913 checked( $value, $key, true ); ?>/>
914 <?php
915 if ( isset( $option['image'] ) ) { ?>
916 <img src="<?php
917 echo esc_url( $option['image'] ) ?>" alt="">
918 <?php
919 } ?>
920 <?php
921 if ( isset( $option['title'] ) ) { ?>
922 <span class="tool-tip-text"><?php
923 echo esc_html( $option['title'] ) ?></span>
924 <?php
925 } ?>
926 </label>
927 <?php
928 endforeach; ?>
929 <?php
930 endif; ?>
931 </div>
932 <?php
933 }
934
935 /**
936 * Field: Radio Alt
937 */
938 public static function radio_alt( $settings, $value, $module_id = '' ) {
939 ?>
940 <?php
941 if ( ! empty( $settings['options'] ) ) : ?>
942 <?php
943 foreach ( $settings['options'] as $key => $option ) : ?>
944 <div>
945 <label>
946 <input type="radio" name="merchant[<?php
947 echo esc_attr( $settings['id'] ); ?>]" value="<?php
948 echo esc_attr( $key ); ?>" <?php
949 checked( $value, $key, true ); ?>/>
950 <span><?php
951 echo esc_html( $option['title'] ); ?></span>
952 </label>
953 <p><?php
954 echo esc_html( $option['desc'] ); ?></p>
955 </div>
956 <?php
957 endforeach; ?>
958 <?php
959 endif; ?>
960 <?php
961 }
962
963 /**
964 * Field: Choices
965 */
966 public static function choices( $settings, $value, $module_id = '' ) {
967 ?>
968 <div class="merchant-choices merchant-choices-<?php
969 echo esc_attr( $settings['id'] ) ?>">
970 <?php
971 if ( ! empty( $settings['options'] ) ) : ?>
972 <?php
973 foreach ( $settings['options'] as $key => $option ) : ?>
974 <label>
975 <input type="radio" name="merchant[<?php
976 echo esc_attr( $settings['id'] ); ?>]" value="<?php
977 echo esc_attr( $key ); ?>" <?php
978 checked( $value, $key, true ); ?>/>
979 <?php
980 if ( ! empty( $option['svg'] ) ) : ?>
981 <span class="merchant-svg">
982 <?php
983 echo wp_kses( Merchant_SVG_Icons::get_svg_icon( $option['svg'] ), merchant_kses_allowed_tags( array(), false ) ); ?>
984
985 <?php
986 if ( ! empty( $option['label'] ) ) : ?>
987 <span class="merchant-tooltip"><?php
988 echo esc_html( $option['label'] ); ?></span>
989 <?php
990 endif; ?>
991 </span>
992 <?php
993 else : ?>
994 <figure>
995 <?php if ( ! empty( $option['image'] ) ) :
996 $title = $option['title'] ?? '';
997 ?>
998 <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 ); ?>"/>
999 <?php
1000 else : ?>
1001 <img src="<?php
1002 echo esc_url( sprintf( $option, MERCHANT_URI . 'assets/images' ) ); ?>"/>
1003 <?php
1004 endif; ?>
1005 <?php
1006 if ( ! empty( $option['label'] ) ) : ?>
1007 <span class="merchant-tooltip"><?php
1008 echo esc_html( $option['label'] ); ?></span>
1009 <?php
1010 endif; ?>
1011 </figure>
1012 <?php
1013 endif; ?>
1014 </label>
1015 <?php
1016 endforeach; ?>
1017 <?php
1018 endif; ?>
1019 </div>
1020 <?php
1021 }
1022
1023 /**
1024 * Field: Select
1025 */
1026 public static function select( $settings, $value, $module_id = '' ) {
1027 ?>
1028 <?php
1029 if ( ! empty( $settings['options'] ) ) : ?>
1030 <select name="merchant[<?php
1031 echo esc_attr( $settings['id'] ); ?>]">
1032 <?php
1033 foreach ( $settings['options'] as $key => $option ) : ?>
1034 <option value="<?php
1035 echo esc_attr( $key ); ?>" <?php
1036 selected( $value, $key, true ); ?>><?php
1037 echo esc_html( $option ); ?></option>
1038 <?php
1039 endforeach; ?>
1040 </select>
1041 <?php
1042 endif; ?>
1043 <?php
1044 }
1045
1046 /**
1047 * Field: Hook Select
1048 */
1049 public static function hook_select( $settings, $value, $module_id = '' ) {
1050 $hook_name = isset( $value['hook_name'] ) ? $value['hook_name'] : '';
1051 $hook_priority = isset( $value['hook_priority'] ) ? $value['hook_priority'] : '';
1052
1053 ?>
1054 <div class="merchant-module-page-setting-field-hook_select-wrapper">
1055 <div class="merchant-module-page-setting-field-select">
1056 <select name="merchant[<?php
1057 echo esc_attr( $settings['id'] ); ?>][hook_name]">
1058 <?php
1059 if ( ! empty( $settings['options'] ) ) : ?>
1060 <?php
1061 foreach ( $settings['options'] as $key => $option ) : ?>
1062 <option value="<?php
1063 echo esc_attr( $key ); ?>" <?php
1064 selected( $hook_name, $key, true ); ?>><?php
1065 echo esc_html( $option ); ?></option>
1066 <?php
1067 endforeach; ?>
1068 <?php
1069 endif; ?>
1070 </select>
1071 </div>
1072 <?php
1073
1074 if ( isset( $settings['order'] ) && true === $settings['order'] ) {
1075 ?>
1076 <div class="merchant-module-page-setting-field-number">
1077 <input type="number" name="merchant[<?php
1078 echo esc_attr( $settings['id'] ); ?>][hook_priority]" value="<?php
1079 echo esc_attr( $hook_priority ); ?>"/>
1080 </div>
1081 <?php
1082 } ?>
1083 </div>
1084
1085 <?php
1086 }
1087
1088 /**
1089 * Field: Select ajax
1090 *
1091 * @param $settings
1092 * @param $value
1093 *
1094 * @return void
1095 */
1096 public static function select_ajax( $settings, $value, $module_id = '' ) {
1097 $settings = wp_parse_args( $settings, array(
1098 'source' => 'post',
1099 ) );
1100
1101 $ids = ( is_array( $value ) && ! empty( $value ) ) ? $value : (array) $value;
1102
1103 if ( isset( $settings['multiple'] ) ) {
1104 $multiple = $settings['multiple'] === true ? 'multiple' : '';
1105 } else {
1106 $multiple = 'multiple';
1107 }
1108
1109 $placeholder = $settings['placeholder'] ?? '';
1110 ?>
1111 <select
1112 name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]<?php echo esc_attr( $multiple ? '[]' : '' ); ?>"
1113 <?php echo esc_attr( $multiple ); ?>
1114 data-source="<?php echo esc_attr( $settings['source'] ); ?>"
1115 data-placeholder="<?php echo esc_attr( $placeholder ); ?>">
1116 <?php
1117 if ( ! empty( $ids ) ) {
1118 foreach ( $ids as $id ) {
1119 switch ( $settings['source'] ) {
1120 case 'post':
1121 case 'product':
1122 $post = get_post( $id );
1123
1124 if ( ! empty( $post ) ) {
1125 echo '<option value="' . esc_attr( $post->ID ) . '" selected>' . esc_html( $post->post_title ) . '</option>';
1126 }
1127 break;
1128 case 'user':
1129 $user = get_user_by( 'ID', $id );
1130 if( $user ) {
1131 echo '<option value="' . esc_attr( $user->ID ) . '" selected>' . esc_html( $user->display_name ) . '</option>';
1132 }
1133 break;
1134 case 'options':
1135 }
1136 }
1137 }
1138 if ( $settings['source'] === 'options' ) {
1139 $value = ! empty( $value ) ? $value : '';
1140
1141 foreach ( $settings['options'] as $option ) {
1142 if ( isset( $option['options'] ) ) {
1143 echo '<optgroup label="' . esc_attr( $option['text'] ) . '">';
1144
1145 foreach ( $option['options'] as $child_option ) {
1146 $selected_value = is_array( $value ) ? in_array( $child_option['id'], $value, true ) : $child_option['id'];
1147 echo '<option value="' . esc_attr( $child_option['id'] ) . '" ' . selected( $selected_value, is_array( $value ) ? true : $value, false ) . '>' . esc_html( $child_option['text'] ) . '</option>';
1148 }
1149
1150 echo '</optgroup>';
1151 } else {
1152 $selected_value = is_array( $value ) ? in_array( $option['id'], $value, true ) : $option['id'];
1153 echo '<option value="' . esc_attr( $option['id'] ) . '" ' . selected( $selected_value, is_array( $value ) ? true : $value, false ) . '>' . esc_html( $option['text'] ) . '</option>';
1154 }
1155 }
1156 } ?>
1157 </select>
1158 <?php
1159 }
1160
1161 /**
1162 * Field: Info Block
1163 *
1164 * @return void
1165 */
1166 public static function info_block( $settings, $value, $module_id = '' ) {
1167 ?>
1168 <div class="merchant-info-block">
1169 <i class="dashicons dashicons-info"></i>
1170 <p><?php
1171 echo ! empty( $settings['description'] ) ? esc_html( $settings['description'] ) : ''; ?><?php
1172 if ( ! empty( $settings['button_text'] ) && ! empty( $settings['button_link'] ) ) {
1173 printf( '<a href="%s" target="_blank">%s</a>', esc_url( $settings['button_link'] ), esc_html( $settings['button_text'] ) );
1174 } ?></p>
1175 </div>
1176 <?php
1177 }
1178
1179 /**
1180 * Field: Products Selector
1181 *
1182 * @param $settings
1183 * @param $value
1184 *
1185 * @return void
1186 */
1187 public static function products_selector( $settings, $value, $module_id = '' ) {
1188 if ( ! class_exists( 'WooCommerce' ) ) {
1189 echo '<p class="merchant-notice">' . esc_html__( 'WooCommerce is not installed or activated.', 'merchant' ) . '</p>';
1190
1191 return;
1192 }
1193
1194 $ids = $value ? explode( ',', $value ) : array();
1195
1196 if ( isset( $settings['multiple'] ) ) {
1197 $multiple = $settings['multiple'] === true ? 'multiple' : 'false';
1198 } else {
1199 $multiple = 'multiple';
1200 }
1201
1202 if ( ! isset( $settings['allowed_types'] ) ) {
1203 $settings['allowed_types'] = array( 'all' );
1204 }
1205 ?>
1206
1207 <div class="merchant-products-search-container" data-multiple="<?php
1208 echo esc_attr( $multiple ); ?>">
1209 <div class="merchant-search-area">
1210 <input type="text" name="merchant-search-field" data-allowed-types="<?php
1211 echo esc_attr( implode( ',', $settings['allowed_types'] ) ) ?>" placeholder="<?php
1212 esc_attr_e( 'Search products', 'merchant' ); ?>" class="merchant-search-field">
1213 <span class="merchant-searching"><?php
1214 esc_html_e( 'Searching...', 'merchant' ); ?></span>
1215 <img src="<?php echo esc_url( MERCHANT_URI . 'assets/images/admin/products-search-icon.svg' ); ?>" class="merchant-search-icon"
1216 alt="<?php esc_attr_e( 'Search icon', 'merchant' ); ?>">
1217 <div class="merchant-selections-products-preview"></div>
1218 </div>
1219 <div class="merchant-selected-products-preview">
1220 <ul>
1221 <?php
1222 if ( ! empty( $ids ) ) {
1223 foreach ( $ids as $product_id ) {
1224 $product = wc_get_product( $product_id );
1225 if ( $product ) {
1226 self::product_data_li( $product );
1227 }
1228 }
1229 }
1230 ?>
1231 </ul>
1232 </div>
1233 <input type="hidden" name="merchant[<?php
1234 echo esc_attr( $settings['id'] ); ?>]" class="merchant-selected-products" value="<?php
1235 echo esc_attr( $value ) ?>">
1236 </div>
1237 <?php
1238 }
1239
1240 public static function product_data_li( $product, $search = false, $hierarchy = false ) {
1241 $product_id = $product->get_id();
1242 $product_sku = $product->get_sku();
1243 $product_name = $product->get_name();
1244 $edit_link = get_edit_post_link( $product_id );
1245 if ( $product->is_type( 'variation' ) ) {
1246 $edit_link = get_edit_post_link( $product->get_parent_id() );
1247 }
1248
1249 /**
1250 * Filter product image.
1251 *
1252 * @since 1.9.1
1253 */
1254 $product_image = apply_filters(
1255 'merchant_product_item_product_image',
1256 '<span class="img">' . $product->get_image( array( 30, 30 ) ) . '</span>',
1257 $product
1258 );
1259
1260 $price = $product->get_price();
1261 $key = $product_id . '_' . $product_sku;
1262
1263 /**
1264 * Filter the product bundle item product info.
1265 *
1266 * @param string $product_info The product bundle item product info.
1267 * @param WC_Product $product The product object.
1268 *
1269 * @since 1.9.0
1270 */
1271 $product_info = apply_filters( 'merchant_pro_product_bundle_item_product_info', $product->get_type() . '<br/>#' . $product_id, $product );
1272 if ( $search ) {
1273 $remove_btn = '<span class="remove hint--left" aria-label="' . esc_html__( 'Add', 'merchant' ) . '">+</span>';
1274 } else {
1275 $remove_btn = '<span class="remove hint--left" aria-label="' . esc_html__( 'Remove', 'merchant' ) . '">×</span>';
1276 }
1277
1278 $item_class = 'product-item';
1279 if( $hierarchy && $product->is_type( 'variation' ) ) {
1280 $item_class .= ' hierarchy-style';
1281 }
1282
1283 echo '<li class="' . esc_attr( $item_class ) . '" data-key="' . esc_attr( $key ) . '" data-name="' . esc_attr( $product_name ) . '" data-sku="'
1284 . esc_attr( $product_sku ) . '" data-id="' . esc_attr( $product_id ) . '" data-price="' . esc_attr( $price ) . '">'
1285 . wp_kses( $product_image, array(
1286 'span' => array(
1287 'class' => true,
1288 ),
1289 'img' => array(
1290 'src' => true,
1291 'alt' => true,
1292 'decoding' => true,
1293 'srcset' => true,
1294 'loading' => true,
1295 'sizes' => true,
1296 'class' => true,
1297 'width' => true,
1298 'height' => true,
1299 ),
1300 ) ) . '<span class="data">'
1301 . '<span class="name">' . esc_html( $product_name ) . '</span><span class="info">' . wp_kses( $product->get_price_html(), array(
1302 'span' => array(
1303 'class' => true,
1304 ),
1305 'del' => array(
1306 'aria-hidden' => true,
1307 ),
1308 'ins' => array(),
1309 'bdi' => array(),
1310
1311 ) ) . '</span> ' . ( $product->is_sold_individually()
1312 ? '<span class="info">' . esc_html__( 'sold individually', 'merchant' ) . '</span> ' : '' ) . '</span>'
1313 . '<span class="type"><a href="' . esc_url( $edit_link ) . '" target="_blank">' . wp_kses_post( $product_info ) . '</a></span> ' . wp_kses( $remove_btn, array(
1314 'span' => array(
1315 'class' => true,
1316 'aria-label' => true,
1317 ),
1318 ) );
1319
1320 echo '</li>';
1321 }
1322
1323 public function products_search() {
1324 check_ajax_referer( 'merchant_admin_options', 'nonce' );
1325
1326 if ( ! isset( $_POST['keyword'] ) || empty( $_POST['keyword'] ) ) {
1327 exit();
1328 }
1329
1330 $types = array( 'simple', 'variable' ); // limit search to product types
1331
1332 if ( isset( $_POST['product_types'] ) || ! empty( $_POST['product_types'] ) ) {
1333 $types = explode( ',', sanitize_text_field( $_POST['product_types'] ) );
1334 }
1335
1336 $hierarchy = false;
1337 if (
1338 in_array( 'all', $types, true )
1339 || ( in_array( 'variation', $types, true ) && in_array( 'variable', $types, true ) )
1340 ) {
1341 $hierarchy = true;
1342 }
1343
1344 $added_ids = isset( $_POST['ids'] ) ? explode( ',', sanitize_text_field( $_POST['ids'] ) ) : array();
1345 $keyword = sanitize_text_field( $_POST['keyword'] );
1346 if ( is_numeric( $keyword ) ) {
1347 // search by id
1348 $query_args = array(
1349 'p' => absint( $keyword ),
1350 'post_type' => 'product',
1351 );
1352 } else {
1353 $query_args = array(
1354 'post_type' => 'product',
1355 'post_status' => array( 'publish', 'private' ),
1356 's' => $keyword,
1357 'posts_per_page' => 10,
1358 );
1359
1360 if ( ! empty( $types ) && ! in_array( 'all', $types, true ) ) {
1361 $product_types = $types;
1362
1363 if ( in_array( 'variation', $types, true ) ) {
1364 $product_types[] = 'variable';
1365 }
1366
1367 // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
1368 $query_args['tax_query'] = array(
1369 array(
1370 'taxonomy' => 'product_type',
1371 'field' => 'slug',
1372 'terms' => $product_types,
1373 ),
1374 );
1375 }
1376
1377 $query_args['post__not_in'] = array_map( 'absint', $added_ids );
1378 }
1379
1380 // Filter by category slugs.
1381 $categories = array_map( 'sanitize_text_field', $_POST['categories'] ?? array() );
1382 if ( is_array( $categories ) && ! empty( $categories ) ) {
1383 $query_args['tax_query'][] = array(
1384 'taxonomy' => 'product_cat',
1385 'field' => 'slug',
1386 'terms' => $categories,
1387 'operator' => 'IN',
1388 );
1389 }
1390
1391 $query = new WP_Query( $query_args );
1392
1393 if ( $query->have_posts() ) {
1394 echo '<ul>';
1395
1396 while ( $query->have_posts() ) {
1397 $query->the_post();
1398 $_product = wc_get_product( get_the_ID() );
1399
1400 if ( ! $_product ) {
1401 continue;
1402 }
1403
1404 if (
1405 ! $_product->is_type( 'variable' )
1406 || in_array( 'variable', $types, true )
1407 || in_array( 'all', $types, true )
1408 ) {
1409 self::product_data_li( $_product, array( 'qty' => 1 ), true, $hierarchy );
1410 }
1411
1412 if (
1413 $_product->is_type( 'variable' )
1414 && (
1415 empty( $types )
1416 || in_array( 'all', $types, true )
1417 || in_array( 'variation', $types, true )
1418 )
1419 ) {
1420 // show all children
1421 $children = $_product->get_children();
1422
1423 if ( is_array( $children ) && count( $children ) > 0 ) {
1424 foreach ( $children as $child ) {
1425 $child_product = wc_get_product( $child );
1426 /**
1427 * @var WC_Product_Variation $child_product
1428 */
1429 if ( ! $this->are_variation_attributes_set( $child_product ) ) {
1430 // Don't display variations that don't have all attributes set.
1431 continue;
1432 }
1433 self::product_data_li( $child_product, true, $hierarchy );
1434 }
1435 }
1436 }
1437 }
1438
1439 echo '</ul>';
1440 wp_reset_postdata();
1441 } else {
1442 // translators: %s is the search keyword
1443 echo wp_kses( '<ul><span>' . sprintf( esc_html__( 'No results found for "%s"', 'merchant' ), $keyword ) . '</span></ul>', array(
1444 'ul' => array(),
1445 'span' => array(),
1446 ) );
1447 }
1448
1449 exit;
1450 }
1451
1452 /**
1453 * Check if all variation attributes are set.
1454 *
1455 * @param $variation WC_Product_Variation variation product object
1456 *
1457 * @return bool
1458 */
1459 public function are_variation_attributes_set( $variation ) {
1460 // Check if the product is a variation and has attributes
1461 if ( $variation && $variation->is_type( 'variation' ) ) {
1462 // Get the variation attributes
1463 $variation_attributes = $variation->get_variation_attributes();
1464
1465 // Check if all variation attributes are set
1466 foreach ( $variation_attributes as $attribute => $value ) {
1467 if ( empty( $value ) ) {
1468 return false; // At least one attribute is not set
1469 }
1470 }
1471
1472 return true; // All variation attributes are set
1473 }
1474
1475 return false; // Not a valid variation product
1476 }
1477
1478 /**
1479 * Field: Select Size Chart
1480 */
1481 public static function select_size_chart( $settings, $value, $module_id = '' ) {
1482 $options = array(
1483 '' => esc_html__( 'Default', 'merchant' ),
1484 );
1485
1486 $posts = get_posts( array(
1487 'post_type' => 'merchant_size_chart',
1488 'posts_per_page' => - 1,
1489 'post_status' => 'publish',
1490 ) );
1491
1492 if ( ! is_wp_error( $posts ) && ! empty( $posts ) ) {
1493 foreach ( $posts as $_post ) {
1494 $options[ $_post->ID ] = $_post->post_title;
1495 }
1496 }
1497
1498 ?>
1499 <?php
1500 if ( ! empty( $options ) ) : ?>
1501 <select name="merchant[<?php
1502 echo esc_attr( $settings['id'] ); ?>]">
1503 <?php
1504 foreach ( $options as $key => $option ) : ?>
1505 <option value="<?php
1506 echo esc_attr( $key ); ?>" <?php
1507 selected( $value, $key, true ); ?>><?php
1508 echo esc_html( $option ); ?></option>
1509 <?php
1510 endforeach; ?>
1511 </select>
1512 <?php
1513 endif; ?>
1514 <?php
1515 }
1516
1517 /**
1518 * Field: Buttons
1519 */
1520 public static function buttons( $settings, $value, $module_id = '' ) {
1521 ?>
1522 <div class="merchant-buttons">
1523 <?php
1524 if ( ! empty( $settings['options'] ) ) : ?>
1525 <?php
1526 foreach ( $settings['options'] as $key => $option ) : ?>
1527 <label class="merchant-button-<?php
1528 echo esc_attr( $key ); ?>"">
1529 <input type="radio" name="merchant[<?php
1530 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1531 echo esc_attr( $key ); ?>" <?php
1532 checked( $value, $key, true ); ?>/>
1533 <span><?php
1534 echo esc_html( $option ); ?></span>
1535 </label>
1536 <?php
1537 endforeach; ?>
1538 <?php
1539 endif; ?>
1540 </div>
1541 <?php
1542 }
1543
1544 /**
1545 * Field: Buttons Alt
1546 */
1547 public static function buttons_alt( $settings, $value, $module_id = '' ) {
1548 ?>
1549 <div class="merchant-buttons">
1550 <?php
1551 if ( ! empty( $settings['options'] ) ) : ?>
1552 <?php
1553 foreach ( $settings['options'] as $key => $option ) : ?>
1554 <label class="merchant-button-<?php
1555 echo esc_attr( $key ); ?>">
1556 <input type="radio" name="merchant[<?php
1557 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1558 echo esc_attr( $key ); ?>" <?php
1559 checked( $value, $key, true ); ?>/>
1560 <span><?php
1561 echo esc_html( $option ); ?></span>
1562 </label>
1563 <?php
1564 endforeach; ?>
1565 <?php
1566 endif; ?>
1567 </div>
1568 <?php
1569 }
1570
1571 /**
1572 * Field: Buttons Content
1573 */
1574 public static function buttons_content( $settings, $value, $module_id = '' ) {
1575 ?>
1576 <div class="merchant-buttons-content">
1577 <?php
1578 if ( ! empty( $settings['options'] ) ) : ?>
1579 <?php
1580 foreach ( $settings['options'] as $key => $option ) : ?>
1581 <label class="merchant-button-content-<?php echo esc_attr( $key ); ?>">
1582 <input
1583 type="radio"
1584 name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]"
1585 value="<?php echo esc_attr( $key ); ?>"
1586 <?php checked( $value, $key, true ); ?>
1587 />
1588
1589 <span class="merchant-buttons-inner-content">
1590 <?php if ( $option['icon'] ) : ?>
1591 <img src="<?php echo esc_url( $option['icon'] ); ?>" alt="">
1592 <?php endif; ?>
1593 <span>
1594 <span><?php echo esc_html( $option['title'] ?? '' ); ?></span>
1595 <span><?php echo esc_html( $option['desc'] ?? '' ); ?></span>
1596 </span>
1597 </span>
1598 </label>
1599 <?php
1600 endforeach; ?>
1601 <?php
1602 endif; ?>
1603 </div>
1604 <?php
1605 }
1606
1607 /**
1608 * Field: Range
1609 */
1610 public static function range( $settings, $value, $module_id = '' ) {
1611 $settings = wp_parse_args( $settings, array(
1612 'min' => '',
1613 'max' => '',
1614 'step' => '',
1615 'unit' => '',
1616 ) );
1617
1618 ?>
1619 <div class="merchant-range">
1620 <input type="range" class="merchant-range-input" name="" min="<?php
1621 echo esc_attr( $settings['min'] ); ?>" max="<?php
1622 echo esc_attr( $settings['max'] ); ?>"
1623 step="<?php
1624 echo esc_attr( $settings['step'] ); ?>" value="<?php
1625 echo esc_attr( $value ); ?>"/>
1626 <input type="number" class="merchant-range-number-input" name="merchant[<?php
1627 echo esc_attr( $settings['id'] ); ?>]" min="<?php
1628 echo esc_attr( $settings['min'] ); ?>"
1629 max="<?php
1630 echo esc_attr( $settings['max'] ); ?>" step="<?php
1631 echo esc_attr( $settings['step'] ); ?>" value="<?php
1632 echo esc_attr( $value ); ?>"/>
1633 <?php
1634 if ( ! empty( $settings['unit'] ) ) : ?>
1635 <span class="merchant-range-unit"><?php
1636 echo esc_html( $settings['unit'] ); ?></span>
1637 <?php
1638 endif; ?>
1639 </div>
1640 <?php
1641 }
1642
1643 /**
1644 * Field: Color
1645 */
1646 public static function color( $settings, $value, $module_id = '' ) {
1647 $settings = wp_parse_args( $settings, array(
1648 'default' => '#212121',
1649 ) );
1650
1651 ?>
1652 <div class="merchant-color">
1653 <div class="merchant-color-picker" data-default-color="<?php
1654 echo esc_attr( $settings['default'] ); ?>" style="background-color: <?php
1655 echo esc_attr( $value ); ?>;"></div>
1656 <input type="text" class="merchant-color-input" name="merchant[<?php
1657 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1658 echo esc_attr( $value ); ?>"/>
1659 </div>
1660 <?php
1661 }
1662
1663 /**
1664 * Field: Gallery
1665 */
1666 public static function gallery( $settings, $value, $module_id = '' ) {
1667 $settings = wp_parse_args( $settings, array(
1668 'label' => esc_html__( 'Select Images', 'merchant' ),
1669 ) );
1670
1671 $images = ( ! empty( $value ) ) ? explode( ',', $value ) : array();
1672
1673
1674 echo '<div class="merchant-gallery-images">';
1675
1676 if ( ! empty( $images ) ) :
1677
1678 foreach ( $images as $image_id ) :
1679
1680 $image = wp_get_attachment_image_src( $image_id, 'thumbnail' );
1681
1682 if ( ! empty( $image ) && ! empty( $image[0] ) ) :
1683
1684 printf( '<div class="merchant-gallery-image" data-item-id="%s">', esc_attr( $image_id ) );
1685
1686 echo '<i class="merchant-gallery-remove dashicons dashicons-no-alt"></i>';
1687
1688 printf( '<img src="%s" />', esc_url( $image[0] ) );
1689
1690 echo '</div>';
1691
1692 endif;
1693
1694 endforeach;
1695
1696 endif;
1697
1698 echo '</div>';
1699
1700 ?>
1701 <a href="#" class="merchant-gallery-button"><?php
1702 echo esc_html( $settings['label'] ); ?></a>
1703 <input type="hidden" class="merchant-gallery-input" name="merchant[<?php
1704 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1705 echo esc_attr( $value ); ?>"/>
1706 <?php
1707 }
1708
1709 /**
1710 * Field: Upload
1711 */
1712 public static function upload( $settings, $value, $module_id = '' ) {
1713 $settings = wp_parse_args( $settings, array(
1714 'label' => esc_html__( 'Select Image', 'merchant' ),
1715 ) );
1716
1717 echo '<div class="merchant-upload-wrapper">';
1718 if ( ! empty( $value ) ) :
1719 $image = wp_get_attachment_image_src( $value, 'thumbnail' );
1720 if ( ! empty( $image ) && ! empty( $image[0] ) ) :
1721 echo '<div class="merchant-upload-image">';
1722 echo '<i class="merchant-upload-remove dashicons dashicons-no-alt"></i>';
1723 printf( '<img src="%s" />', esc_url( $image[0] ) );
1724 echo '</div>';
1725 endif;
1726 endif;
1727 echo '</div>';
1728
1729 $drag_drop = $settings['drag_drop'] ?? false;
1730 ?>
1731 <div class="merchant-upload-button-wrapper<?php echo esc_attr( $drag_drop ? ' merchant-upload-button-drag-drop' : '' ); ?>">
1732 <?php if ( $drag_drop ) : ?>
1733 <img src="<?php echo esc_url( esc_url( MERCHANT_URI . '/assets/images/upload-icon.svg' ) ); ?>" alt="<?php echo esc_attr__( 'Upload image', 'merchant' ); ?>"/>
1734 <?php endif; ?>
1735 <a href="#" class="merchant-upload-button"><?php echo esc_html( $settings['label'] ?? '' ); ?></a>
1736 </div>
1737 <input type="hidden" class="merchant-upload-input" name="merchant[<?php echo esc_attr( $settings['id'] ); ?>]" value="<?php echo esc_attr( $value ); ?>"/>
1738 <?php
1739 }
1740
1741 /**
1742 * Field: Warning
1743 */
1744 public static function warning( $settings ) {
1745 echo wp_kses_post( $settings['content'] );
1746 }
1747
1748 /**
1749 * Field: Warning
1750 */
1751 public static function info( $settings ) {
1752 echo wp_kses_post( $settings['content'] );
1753 }
1754
1755 /**
1756 * Field: Divider
1757 */
1758 public static function divider() {
1759 }
1760
1761 /**
1762 * Field: Content
1763 */
1764 public static function content( $settings ) {
1765 echo wp_kses_post( $settings['content'] );
1766 }
1767
1768 /**
1769 * Field: Sortable
1770 */
1771 public static function sortable( $settings, $value, $module_id = '' ) {
1772 ?>
1773 <div class="merchant-sortable">
1774 <ul class="merchant-sortable-list ui-sortable">
1775 <?php
1776 foreach ( $value as $option_key ) :
1777 $option_val = $settings['options'][ $option_key ];
1778
1779 if ( in_array( $option_key, $value, true ) ) :
1780 ?>
1781 <li class="merchant-sortable-item" data-value="<?php
1782 echo esc_attr( $option_key ); ?>">
1783 <i class='dashicons dashicons-menu'></i>
1784 <i class="dashicons dashicons-visibility visibility"></i>
1785 <?php
1786 echo esc_html( $option_val ); ?>
1787 </li>
1788 <?php
1789 endif; ?>
1790 <?php
1791 endforeach; ?>
1792
1793 <?php
1794 foreach ( $settings['options'] as $option_key => $option_val ) :
1795 if ( ! in_array( $option_key, $value, true ) ) :
1796 $invisible = ! in_array( $option_key, $value, true ) ? ' invisible' : '';
1797
1798 ?>
1799 <li class="merchant-sortable-item<?php
1800 echo esc_attr( $invisible ); ?>" data-value="<?php
1801 echo esc_attr( $option_key ); ?>">
1802 <i class='dashicons dashicons-menu'></i>
1803 <i class="dashicons dashicons-visibility visibility"></i>
1804 <?php
1805 echo esc_html( $option_val ); ?>
1806 </li>
1807 <?php
1808 endif; ?>
1809 <?php
1810 endforeach; ?>
1811 </ul>
1812
1813 <input class="merchant-sortable-input" type="hidden" name="merchant[<?php
1814 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1815 echo esc_attr( wp_json_encode( $value ) ); ?>"/>
1816 </div>
1817 <?php
1818 }
1819
1820 /**
1821 * Field: Sortable Repeater.
1822 */
1823 public static function sortable_repeater( $settings, $value, $module_id = '' ) {
1824 ?>
1825 <div class="merchant-sortable-repeater-control<?php
1826 echo isset( $settings['sorting'] ) && false === $settings['sorting'] ? ' disable-sorting' : ''; ?>">
1827 <div class="merchant-sortable-repeater sortable regular-field">
1828 <div class="repeater">
1829 <input type="text" value="" class="repeater-input"/><span class="dashicons dashicons-menu"></span><a class="customize-control-sortable-repeater-delete"
1830 href="#"><span
1831 class="dashicons dashicons-no-alt"></span></a>
1832 </div>
1833 </div>
1834 <button class="button customize-control-sortable-repeater-add" type="button"><?php
1835 echo esc_html( $settings['button_label'] ); ?></button>
1836 <input class="merchant-sortable-repeater-input" type="hidden" name="merchant[<?php
1837 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1838 echo esc_attr( wp_json_encode( $value ) ); ?>"/>
1839 </div>
1840 <?php
1841 }
1842
1843 public static function wc_coupons( $settings, $value ) {
1844 $coupons = get_posts( array(
1845 'posts_per_page' => - 1,
1846 'orderby' => 'title',
1847 'order' => 'asc',
1848 'post_type' => 'shop_coupon',
1849 'post_status' => 'publish',
1850 ) );
1851 if ( $coupons ) {
1852 ?>
1853 <div class="merchant-wc-coupon-selector merchant-<?php
1854 echo esc_attr( $settings['id'] ) ?>">
1855 <?php
1856 echo '<select name="merchant[' . esc_attr( $settings['id'] ) . ']">';
1857 echo '<option value="">' . esc_html__( 'Select a coupon', 'merchant' ) . '</option>';
1858
1859 foreach ( $coupons as $coupon ) {
1860 $coupon_code = strtolower( $coupon->post_title );
1861
1862 echo '<option value="' . esc_attr( $coupon_code ) . '"' . selected( esc_attr( $coupon_code ), $value, false ) . '>';
1863 echo esc_html( $coupon_code );
1864 echo '</option>';
1865 }
1866
1867 echo '</select>';
1868 echo '<a href="' . esc_url( admin_url( 'edit.php?post_type=shop_coupon' ) ) . '" target="_blank" style="margin-left: 10px;">' . esc_html__( 'Manage coupons',
1869 'merchant' ) . '</a>';
1870 ?>
1871 </div>
1872 <?php
1873 } else {
1874 echo '<div style="color: red;">';
1875 echo wp_kses_post(
1876 sprintf(
1877 /* Translators: 1. Coupon admin url 2. Link target attribute value */
1878 __( 'No coupons found! <a href="%1$s" target="%2$s">Create a new coupon</a>', 'merchant' ),
1879 admin_url( 'post-new.php?post_type=shop_coupon' ),
1880 '_blank'
1881 )
1882 );
1883 echo '</div>';
1884 echo '<input type="hidden" name="merchant[' . esc_attr( $settings['id'] ) . ']" value="" />';
1885 }
1886 }
1887
1888 /**
1889 * Field: Date Time.
1890 *
1891 * @param $settings array field settings.
1892 * @param $value string field value.
1893 * @param $module_id string module id.
1894 *
1895 * @return void
1896 */
1897 public static function date_time( $settings, $value, $module_id = '' ) {
1898 // All options are documented here: https://air-datepicker.com/docs
1899 $options = array(
1900 'dateFormat' => 'MM-dd-yyyy',
1901 'timepicker' => true,
1902 'timeFormat' => 'hh:mm AA',
1903 'minDate' => 'today',
1904 'timeZone' => wp_timezone_string(),
1905 );
1906 if ( isset( $settings['options'] ) ) {
1907 $settings['options'] = wp_parse_args( $settings['options'], $options );
1908 } else {
1909 $settings['options'] = $options;
1910 }
1911 ?>
1912 <div class="merchant-datetime-field" data-options="<?php echo esc_attr( wp_json_encode( $settings['options'] ) ); ?>">
1913 <input type="text" name="merchant[<?php
1914 echo esc_attr( $settings['id'] ); ?>]" value="<?php
1915 echo esc_attr( $value ); ?>" placeholder="<?php
1916 echo isset( $settings['placeholder'] ) ? esc_attr( $settings['placeholder'] ) : ''; ?>"/>
1917 </div>
1918 <?php
1919 }
1920
1921 /**
1922 * Field: Flexible Content.
1923 *
1924 * @param array $settings
1925 * @param mixed $value
1926 *
1927 * @return void
1928 */
1929 public static function flexible_content( $settings, $value, $module_id = '' ) {
1930 $values = ( is_array( $value ) && ! empty( $value ) ) ? $value : array();
1931 $empty = empty( $values ) ? 'empty' : '';
1932
1933 $settings = wp_parse_args( $settings, array(
1934 'sorting' => false,
1935 'style' => 'default',
1936 'accordion' => false,
1937 ) );
1938
1939 $classes = array(
1940 'merchant-flexible-content-control',
1941 "{$settings['style']}-style",
1942 );
1943
1944 $has_sorting = (bool) ( $settings['sorting'] ?? true );
1945 if ( ! $has_sorting ) {
1946 $classes[] = 'disable-sorting';
1947 }
1948
1949 $has_accordion = (bool) ( $settings['accordion'] ?? false );
1950 if ( $has_accordion ) {
1951 $classes[] = 'has-accordion';
1952 }
1953
1954 $has_duplicate = (bool) ( $settings['duplicate'] ?? false );
1955 if ( $has_duplicate ) {
1956 $classes[] = 'has-duplicate';
1957 }
1958 ?>
1959 <div class="<?php
1960 echo esc_attr( implode( ' ', $classes ) ); ?>"
1961 data-id="<?php
1962 echo esc_attr( $settings['id'] ) ?>">
1963
1964 <div class="layouts" data-id="<?php echo esc_attr( $settings['id'] ) ?>">
1965 <?php foreach ( $settings['layouts'] as $layout_type => $layout ) : ?>
1966 <div class="layout" data-type="<?php echo esc_attr( $layout_type ) ?>">
1967 <div class="layout__inner">
1968 <?php if ( $has_sorting ) : ?>
1969 <span class="customize-control-flexible-content-move">
1970 <svg xmlns="http://www.w3.org/2000/svg" width="10" height="14" viewBox="0 0 10 14" fill="none">
1971 <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"/>
1972 <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"/>
1973 <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"/>
1974 <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"/>
1975 <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"/>
1976 <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"/>
1977 </svg>
1978 </span>
1979 <?php endif; ?>
1980 <div class="layout-header">
1981 <div class="layout-count">1</div>
1982 <div class="layout-title"<?php
1983 if ( isset( $layout['title-field'] ) && ! empty( $layout['title-field'] ) ) {
1984 echo ' data-title-field="' . esc_attr( $layout['title-field'] ) . '"';
1985 } ?>>
1986 <?php
1987 echo esc_html( $layout['title'] ) ?>
1988 </div>
1989 <div class="layout-toggle">
1990 <?php if ( $has_accordion ) : ?>
1991 <span class="customize-control-flexible-content-accordion">
1992 <svg xmlns="http://www.w3.org/2000/svg" width="10" height="7" viewBox="0 0 10 7" fill="none">
1993 <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"/>
1994 </svg>
1995 </span>
1996 <?php endif; ?>
1997 </div>
1998 </div>
1999 <div class="layout-body">
2000 <?php
2001 foreach ( $layout['fields'] as $sub_field ) :
2002 $classes = array( 'layout-field' );
2003
2004 if ( isset( $sub_field['classes'] ) ) {
2005 $classes = array_merge( $classes, $sub_field['classes'] );
2006 } ?>
2007 <div class="<?php
2008 echo esc_attr( implode( ' ', $classes ) ); ?>">
2009 <?php
2010 if ( 'fields_group' === $sub_field['type'] ) {
2011 static::fields_group( $sub_field, $value, $module_id, true, array(
2012 'id' => $settings['id'],
2013 'option_key' => 0,
2014 'value' => $value,
2015 ) );
2016 } else {
2017 static::replace_field(
2018 $sub_field,
2019 $sub_field['default'] ?? '',
2020 array(
2021 "name=\"merchant[{$sub_field['id']}]",
2022 'merchant-module-page-setting-field-upload',
2023 'merchant-module-page-setting-field-select_ajax',
2024 ),
2025 array(
2026 "data-name=\"merchant[{$settings['id']}][0][{$sub_field['id']}]",
2027 'merchant-module-page-setting-field-upload template',
2028 'merchant-module-page-setting-field-select_ajax template',
2029 ),
2030 $module_id
2031 );
2032 }
2033 ?>
2034 </div>
2035 <?php
2036 endforeach; ?>
2037 <input type="hidden" data-name="merchant[<?php
2038 echo esc_attr( $settings['id'] ) ?>][0][layout]" value="<?php
2039 echo esc_attr( $layout_type ) ?>">
2040 </div>
2041 <?php self::print_flexible_layout_actions( $settings, $layout_type ); ?>
2042 </div>
2043 </div>
2044 <?php
2045 endforeach; ?>
2046 </div>
2047
2048 <div class="merchant-flexible-content <?php echo esc_attr( $empty ); ?> sortable">
2049 <?php
2050 foreach ( $values as $option_key => $option ) : ?>
2051 <div class="layout" data-type="<?php echo esc_attr( $option['layout'] ) ?>">
2052 <div class="layout__inner">
2053 <?php if ( $has_sorting ) : ?>
2054 <span class="customize-control-flexible-content-move">
2055 <svg xmlns="http://www.w3.org/2000/svg" width="10" height="14" viewBox="0 0 10 14" fill="none">
2056 <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"/>
2057 <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"/>
2058 <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"/>
2059 <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"/>
2060 <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"/>
2061 <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"/>
2062 </svg>
2063 </span>
2064 <?php endif; ?>
2065 <div class="layout-header">
2066 <div class="layout-count"><?php
2067 echo absint( $option_key + 1 ) ?></div>
2068 <div class="layout-title"<?php
2069 if ( isset( $layout['title-field'] ) && ! empty( $layout['title-field'] ) ) {
2070 echo ' data-title-field="' . esc_attr( $layout['title-field'] ) . '"';
2071 } ?>>
2072 <?php
2073 echo isset( $settings['layouts'][ $option['layout'] ]['title'] ) ? esc_html( $settings['layouts'][ $option['layout'] ]['title'] ) : '' ?>
2074 </div>
2075 <div class="layout-toggle">
2076 <?php if ( $has_accordion ) : ?>
2077 <span class="customize-control-flexible-content-accordion">
2078 <svg xmlns="http://www.w3.org/2000/svg" width="10" height="7" viewBox="0 0 10 7" fill="none">
2079 <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"/>
2080 </svg>
2081 </span>
2082 <?php endif; ?>
2083 </div>
2084 </div>
2085 <div class="layout-body">
2086 <?php
2087 foreach ( $settings['layouts'][ $option['layout'] ]['fields'] as $sub_field ) :
2088 $classes = array( 'layout-field' );
2089 if ( isset( $sub_field['classes'] ) ) {
2090 $classes = array_merge( $classes, $sub_field['classes'] );
2091 } ?>
2092 <div class="<?php
2093 echo esc_attr( implode( ' ', $classes ) ) ?>">
2094 <?php
2095 $value = null;
2096 if ( isset( $option[ $sub_field['id'] ] ) ) {
2097 $value = $option[ $sub_field['id'] ];
2098 } elseif ( isset( $sub_field['type'] ) && $sub_field['type'] === 'switcher' ) {
2099 $value = is_null( $value ) ? 0 : 1;
2100 } elseif ( isset( $sub_field['default'] ) ) {
2101 $value = $sub_field['default'];
2102 }
2103
2104 if ( 'fields_group' === $sub_field['type'] ) {
2105 static::fields_group( $sub_field, $value, $module_id, true, array(
2106 'id' => $settings['id'],
2107 'option_key' => $option_key,
2108 'value' => $option,
2109 ) );
2110 } else {
2111 static::replace_field(
2112 $sub_field,
2113 $value,
2114 "name=\"merchant[{$sub_field['id']}]",
2115 "name=\"merchant[{$settings['id']}][{$option_key}][{$sub_field['id']}]",
2116 $module_id
2117 );
2118 }
2119 ?>
2120 </div>
2121 <?php
2122 endforeach; ?>
2123 <input type="hidden" name="merchant[<?php
2124 echo esc_attr( $settings['id'] ) ?>][<?php
2125 echo absint( $option_key ) ?>][layout]"
2126 value="<?php
2127 echo esc_attr( $option['layout'] ) ?>">
2128 </div>
2129 <?php self::print_flexible_layout_actions( $settings, $layout_type ); ?>
2130 </div>
2131 </div>
2132 <?php
2133 endforeach; ?>
2134 </div>
2135
2136 <div class="customize-control-flexible-content-add-wrapper">
2137 <div class="customize-control-flexible-content-add-list">
2138 <?php
2139 foreach ( $settings['layouts'] as $layout_type => $layout ) : ?>
2140 <a href="#"
2141 class="customize-control-flexible-content-add"
2142 data-id="<?php
2143 echo esc_attr( $settings['id'] ) ?>"
2144 data-layout="<?php
2145 echo esc_attr( $layout_type ) ?>">
2146 <?php
2147 echo esc_attr( $layout['title'] ) ?>
2148 </a>
2149 <?php
2150 endforeach; ?>
2151 </div>
2152 <button class="button customize-control-flexible-content-add-button" type="button"><?php
2153 echo esc_html( $settings['button_label'] ); ?></button>
2154 </div>
2155 </div>
2156 <?php
2157 }
2158
2159 /**
2160 * Field: Group.
2161 *
2162 * @param $settings array field settings.
2163 * @param $value mixed field value.
2164 * @param $module_id string module id.
2165 * @param $inside_flexible boolean is inside flexible content.
2166 * @param $args array extra arguments to be passed if inside flexible content.
2167 *
2168 * @return void
2169 */
2170 public static function fields_group( $settings, $value, $module_id = '', $inside_flexible = false, $args = array() ) {
2171 $control_field_status = ! empty( $settings['display_status'] ) && $settings['display_status'] === true;
2172 $accordion = ! empty( $settings['accordion'] ) && $settings['accordion'] === true;
2173 $state = ! empty( $settings['state'] ) && $settings['state'] === 'open';
2174 ?>
2175 <div class="merchant-group-field<?php
2176 echo $accordion ? ' has-accordion' : '';
2177 echo $control_field_status ? ' has-flag' : '';
2178 echo $state ? ' open' : '';
2179 echo ' merchant-group-field-' . esc_attr( $settings['id'] ) ?>" data-id="<?php
2180 echo esc_attr( $settings['id'] ) ?>">
2181 <div class="title-area<?php
2182 echo $accordion ? ' accordion-style' : '' ?>">
2183 <?php
2184 if ( ! empty( $settings['title'] ) ) {
2185 printf( '<div class="merchant-module-page-setting-field-title">%s<span class="field-status hidden"></span></div>', esc_html( $settings['title'] ) );
2186 }
2187 if ( ! empty( $settings['sub-desc'] ) ) {
2188 printf( '<div class="merchant-module-page-setting-field-desc">%s</div>', wp_kses_post( $settings['sub-desc'] ) );
2189 }
2190 if ( $accordion ) {
2191 ?>
2192 <span class="accordion-icon dashicons dashicons-arrow-down-alt2"></span>
2193 <?php
2194 }
2195 ?>
2196 </div>
2197 <div class="merchant-group-fields-container">
2198 <?php
2199 if ( $control_field_status ) {
2200 /**
2201 * Field: Status.
2202 *
2203 * @since 1.9.12
2204 */
2205 $status = apply_filters(
2206 'merchant_group_status_field',
2207 array(
2208 'id' => $settings['id'] . '_status',
2209 'type' => 'select',
2210 'title' => esc_html__( 'Status', 'merchant' ),
2211 'options' => array(
2212 'inactive' => esc_html__( 'Inactive', 'merchant' ),
2213 'active' => esc_html__( 'Active', 'merchant' ),
2214 ),
2215 'default' => isset( $settings['default'] ) ? $settings['default'] : 'active',
2216 ),
2217 $settings,
2218 $value,
2219 $module_id
2220 );
2221 if ( $inside_flexible ) {
2222 static::replace_field(
2223 $status,
2224 isset( $args['value'][$settings['id']][ $status['id'] ] ) ? $args['value'][$settings['id']][ $status['id'] ] : $status['default'] ?? '',
2225 "name=\"merchant[{$status['id']}]",
2226 "name=\"merchant[{$args['id']}][{$args['option_key']}][{$settings['id']}][{$status['id']}]\" data-name=\"merchant[{$args['id']}][0][{$settings['id']}][{$status['id']}]",
2227 $module_id
2228 );
2229 } else {
2230 static::replace_field(
2231 $status,
2232 isset( $value[ $status['id'] ] ) ? $value[ $status['id'] ] : '',
2233 "name=\"merchant[{$status['id']}]",
2234 "name=\"merchant[{$settings['id']}][{$status['id']}]",
2235 $module_id
2236 );
2237 }
2238 }
2239
2240 foreach ( $settings['fields'] as $field ) {
2241 if ( $inside_flexible ) {
2242 static::replace_field(
2243 $field,
2244 isset( $args['value'][$settings['id']][ $field['id'] ] ) ? $args['value'][$settings['id']][ $field['id'] ] : ( $field['default'] ?? '' ),
2245 "name=\"merchant[{$field['id']}]",
2246 "name=\"merchant[{$args['id']}][{$args['option_key']}][{$settings['id']}][{$field['id']}]\" data-name=\"merchant[{$args['id']}][0][{$settings['id']}][{$field['id']}]",
2247 $module_id
2248 );
2249 } else {
2250 static::replace_field(
2251 $field,
2252 isset( $value[ $field['id'] ] ) ? $value[ $field['id'] ] : ( $field['default'] ?? '' ),
2253 "name=\"merchant[{$field['id']}]",
2254 "name=\"merchant[{$settings['id']}][{$field['id']}]",
2255 $module_id
2256 );
2257 }
2258 } ?>
2259 </div>
2260 </div>
2261 <?php
2262 }
2263
2264 /**
2265 * Field: Create Page.
2266 */
2267 public static function create_page( $settings, $value, $module_id = '' ) {
2268 $page_id = get_option( $settings['option_name'] );
2269
2270 echo '<div class="merchant-create-page-control">';
2271
2272 if ( $page_id && post_exists( get_the_title( $page_id ) ) && 'publish' === get_post_status( $page_id ) ) {
2273 echo wp_kses_post(
2274 sprintf( /* translators: 1: link to edit page */
2275 __( '<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>',
2276 'merchant' ),
2277 get_admin_url() . 'post.php?post=' . $page_id . '&action=edit',
2278 get_admin_url() . 'nav-menus.php'
2279 )
2280 );
2281 } else {
2282 echo '<div class="merchant-create-page-control-create-message">';
2283 echo wp_kses_post(
2284 '<p class="merchant-module-page-setting-field-desc mrc-mt-0">'.
2285 sprintf( /* translators: 1: page name */
2286 __( 'It looks like you haven\'t created a <strong>%1$s</strong> page yet. Click the below button to create the page.',
2287 'merchant' ),
2288 $settings['page_title']
2289 ). '</p>'
2290 );
2291 echo '</div>';
2292 echo '<div class="merchant-create-page-control-success-message" style="display: none;">';
2293 echo wp_kses_post(
2294 sprintf( /* translators: 1: link to edit page */
2295 __( '<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>',
2296 'merchant' ),
2297 get_admin_url() . 'post.php?post=&action=edit',
2298 get_admin_url() . 'nav-menus.php'
2299 )
2300 );
2301 echo '</div>';
2302 echo wp_kses_post(
2303 sprintf( /* translators: 1: page title, 2: page meta key, 3: page meta value, 4: option name, 5: nonce, 6: loading text, 7: success text */
2304 __( '<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>',
2305 'merchant' ),
2306 __( 'Create Page', 'merchant' ),
2307 $settings['page_title'],
2308 $settings['page_meta_key'],
2309 $settings['page_meta_value'],
2310 $settings['option_name'],
2311 wp_create_nonce( 'customize-create-page-control-nonce' ),
2312 __( 'Creating...', 'merchant' ),
2313 __( 'Created!', 'merchant' )
2314 )
2315 );
2316 }
2317
2318 echo '</div>';
2319 }
2320
2321 public static function dimensions( $settings, $value, $module_id = '' ) {
2322 $settings = wp_parse_args( $settings, array(
2323 'units' => array(
2324 'px' => 'px',
2325 'rem' => 'rem',
2326 'em' => 'em',
2327 'vw' => 'vw',
2328 'vh' => 'vh',
2329 '%' => '%',
2330 ),
2331 'dimensions' => array(
2332 'top',
2333 'right',
2334 'bottom',
2335 'left',
2336 ),
2337 ) );
2338 $default_value = array(
2339 'unit' => reset( $settings['units'] ),
2340 );
2341 foreach ( $settings['dimensions'] as $dimension ) {
2342 $default_value[ $dimension ] = 0;
2343 }
2344 $value = wp_parse_args( $value, $default_value );
2345 ?>
2346 <div class="merchant-module-page-settings-unit">
2347 <select name="merchant[<?php
2348 echo esc_attr( $settings['id'] ); ?>][unit]">
2349 <?php
2350 foreach ( $settings['units'] as $key => $option ) : ?>
2351 <option value="<?php
2352 echo esc_attr( $key ); ?>" <?php
2353 selected( $value['unit'], $key, true ); ?>><?php
2354 echo esc_html( $option ); ?></option>
2355 <?php
2356 endforeach; ?>
2357 </select>
2358 </div>
2359 <div class="merchant-module-page-settings-dimensions">
2360 <?php
2361 foreach ( $settings['dimensions'] as $dimension ) : ?>
2362 <div>
2363 <input id="merchant-<?php
2364 echo esc_attr( $settings['id'] ); ?>-<?php
2365 echo esc_attr( $dimension ) ?>"
2366 type="number"
2367 name="merchant[<?php
2368 echo esc_attr( $settings['id'] ); ?>][<?php
2369 echo esc_attr( $dimension ) ?>]"
2370 value="<?php
2371 echo esc_attr( $value[ $dimension ] ); ?>"/>
2372 <label for="merchant-<?php
2373 echo esc_attr( $settings['id'] ); ?>-<?php
2374 echo esc_attr( $dimension ) ?>">
2375 <?php
2376 echo esc_html( ucfirst( $dimension ) ); ?>
2377 </label>
2378 </div>
2379 <?php
2380 endforeach; ?>
2381 </div>
2382 <?php
2383 }
2384
2385 public static function responsive_dimensions( $settings, $value, $module_id = '' ) {
2386 $settings = wp_parse_args( $settings, array(
2387 'units' => array(
2388 'px' => 'px',
2389 'rem' => 'rem',
2390 'em' => 'em',
2391 'vw' => 'vw',
2392 'vh' => 'vh',
2393 '%' => '%',
2394 ),
2395 'dimensions' => array(
2396 'top',
2397 'right',
2398 'bottom',
2399 'left',
2400 ),
2401 'devices' => array(
2402 'desktop' => 'dashicons-desktop',
2403 'tablet' => 'dashicons-tablet',
2404 'mobile' => 'dashicons-smartphone',
2405 ),
2406 ) );
2407 $default_values = array();
2408 foreach ( $settings['devices'] as $device => $icon ) {
2409 $default_values[ $device ]['unit'] = reset( $settings['units'] );
2410
2411 foreach ( $settings['dimensions'] as $dimension ) {
2412 $default_values[ $device ][ $dimension ] = 0;
2413 }
2414 }
2415 $value = wp_parse_args( $value, $default_values );
2416 ?>
2417 <div class="merchant-module-page-settings-responsive">
2418 <ul class="merchant-module-page-settings-devices">
2419 <?php
2420 foreach ( $settings['devices'] as $device => $icon ) : ?>
2421 <li class="<?php
2422 echo esc_attr( $device ); ?>">
2423 <button type="button" class="preview-<?php
2424 echo esc_attr( $device ); ?> <?php
2425 echo $device === key( $settings['devices'] ) ? 'active' : '' ?>"
2426 data-device="<?php
2427 echo esc_attr( $device ); ?>">
2428 <i class="dashicons <?php
2429 echo esc_attr( $icon ); ?>"></i>
2430 </button>
2431 </li>
2432 <?php
2433 endforeach; ?>
2434 </ul>
2435 <?php
2436 foreach ( $settings['devices'] as $device => $icon ) : ?>
2437 <div class="merchant-module-page-settings-device-container <?php
2438 echo $device === key( $settings['devices'] ) ? 'active' : '' ?>" data-device="<?php
2439 echo esc_attr( $device ); ?>">
2440 <div class="merchant-module-page-settings-unit">
2441 <select name="merchant[<?php
2442 echo esc_attr( $settings['id'] ); ?>][<?php
2443 echo esc_attr( $device ) ?>][unit]">
2444 <?php
2445 foreach ( $settings['units'] as $key => $option ) : ?>
2446 <option value="<?php
2447 echo esc_attr( $key ); ?>" <?php
2448 selected( $value[ esc_attr( $device ) ]['unit'], $key, true ); ?>><?php
2449 echo esc_html( $option ); ?></option>
2450 <?php
2451 endforeach; ?>
2452 </select>
2453 </div>
2454 <div class="merchant-module-page-settings-dimensions">
2455 <?php
2456 foreach ( $settings['dimensions'] as $dimension ) : ?>
2457 <div>
2458 <input id="merchant-<?php
2459 echo esc_attr( $settings['id'] ); ?>-<?php
2460 echo esc_attr( $device ) ?>-<?php
2461 echo esc_attr( $dimension ) ?>"
2462 type="number"
2463 name="merchant[<?php
2464 echo esc_attr( $settings['id'] ); ?>][<?php
2465 echo esc_attr( $device ) ?>][<?php
2466 echo esc_attr( $dimension ) ?>]"
2467 value="<?php
2468 echo esc_attr( $value[ $device ][ $dimension ] ); ?>"/>
2469 <label for="merchant-<?php
2470 echo esc_attr( $settings['id'] ); ?>-<?php
2471 echo esc_attr( $device ) ?>-<?php
2472 echo esc_attr( $dimension ) ?>">
2473 <?php
2474 echo esc_html( ucfirst( $dimension ) ); ?>
2475 </label>
2476 </div>
2477 <?php
2478 endforeach; ?>
2479 </div>
2480 </div>
2481 <?php
2482 endforeach; ?>
2483 </div>
2484
2485 <?php
2486 }
2487
2488 /**
2489 * Field: Custom callback.
2490 */
2491 public static function custom_callback( $settings, $value, $module_id = '' ) {
2492 if ( ! empty( $settings['class_name'] ) && ! empty( $settings['callback_name'] ) ) {
2493 return call_user_func( array( $settings['class_name'], $settings['callback_name'] ), $settings, $value );
2494 }
2495
2496 if ( ! empty( $settings['callback_name'] ) ) {
2497 return call_user_func( $settings['callback_name'], $settings, $value );
2498 }
2499
2500 return false;
2501 }
2502
2503 private static function print_flexible_layout_actions( $settings, $layout_type ) {
2504 $has_duplicate = ! empty( $settings['duplicate'] );
2505 $has_accordion = ! empty( $settings['accordion'] );
2506 ?>
2507 <div class="layout-actions<?php echo $has_accordion ? esc_attr( ' layout-actions-has_accordion' ) : ' layout-actions-no_accordion'; ?>">
2508 <a href="#" class="layout-actions__toggle">
2509 <svg xmlns="http://www.w3.org/2000/svg" width="14" height="4" viewBox="0 0 14 4" fill="none">
2510 <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"/>
2511 <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"/>
2512 <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"/>
2513 </svg>
2514 </a>
2515 <div class="layout-actions__inner" style="display: none;">
2516 <?php if ( $has_duplicate ) : ?>
2517 <a
2518 href="#"
2519 class="customize-control-flexible-content-duplicate"
2520 data-id="<?php echo esc_attr( $settings['id'] ); ?>"
2521 data-layout="<?php echo esc_attr( $layout_type ); ?>"
2522 title="<?php echo esc_attr__( 'Duplicate', 'merchant' ); ?>">
2523 <svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" viewBox="0 0 19 22" fill="none">
2524 <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"/>
2525 </svg>
2526 <span><?php echo esc_html__( 'Duplicate', 'merchant' ); ?></span>
2527 </a>
2528 <?php endif; ?>
2529
2530 <a class="customize-control-flexible-content-delete" href="#">
2531 <svg xmlns="http://www.w3.org/2000/svg" width="14" height="17" viewBox="0 0 14 17" fill="none">
2532 <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"/>
2533 </svg>
2534 <span><?php echo esc_html__( 'Delete', 'merchant' ); ?></span>
2535 </a>
2536 </div>
2537 </div>
2538 <?php
2539 }
2540
2541 /**
2542 * Get category choices for select2
2543 *
2544 * @return array
2545 */
2546 public static function get_category_select2_choices() {
2547 $choices = array();
2548 $categories = merchant_get_product_categories();
2549
2550 if ( is_array( $categories ) && ! empty( $categories ) ) {
2551 $choices = self::build_category_select2_choices( $categories );
2552 }
2553
2554 return $choices;
2555 }
2556
2557 /**
2558 * Build Select2 choices for hierarchical categories.
2559 *
2560 * @param $categories
2561 * @param $level
2562 *
2563 * @return array
2564 */
2565 private static function build_category_select2_choices( $categories, $level = 0 ) {
2566 $choices = array();
2567
2568 foreach ( $categories as $cat ) {
2569 $indent = str_repeat( '&nbsp;', $level * 4 ); // Use non-breaking spaces for indentation
2570
2571 $choices[] = array(
2572 'id' => esc_attr( $cat['slug'] ?? '' ),
2573 'text' => esc_html( $indent . ( $cat['name'] ?? '' ) ),
2574 );
2575
2576 if ( ! empty( $cat['children'] ) ) {
2577 $choices = array_merge( $choices, self::build_category_select2_choices( $cat['children'], $level + 1 ) );
2578 }
2579 }
2580
2581 return $choices;
2582 }
2583
2584 /**
2585 * Get Tag choices for select2
2586 *
2587 * @return array
2588 */
2589 public static function get_tag_select2_choices() {
2590 $choices = array();
2591 $tags = merchant_get_product_tags();
2592
2593 if ( is_array( $tags ) && ! empty( $tags ) ) {
2594 foreach ( $tags as $slug => $name ) {
2595 $choices[] = array(
2596 'id' => esc_attr( $slug ),
2597 'text' => esc_html( $name ),
2598 );
2599 }
2600 }
2601
2602 return $choices;
2603 }
2604
2605 /**
2606 * Get User Roles choices for select2
2607 *
2608 * @return array
2609 */
2610 public static function get_user_roles_select2_choices() {
2611 $choices = array();
2612 $user_roles = get_editable_roles();
2613
2614 if ( ! empty( $user_roles ) ) {
2615 foreach ( $user_roles as $role_id => $role_data ) {
2616 $choices[] = array(
2617 'id' => $role_id,
2618 'text' => $role_data['name'],
2619 );
2620 }
2621 }
2622
2623 return $choices;
2624 }
2625
2626 /**
2627 * Get Customers choices for select2.
2628 *
2629 * @return array
2630 */
2631 public static function get_customers_select2_choices() {
2632 $cache_key = 'customers_select2_choices';
2633 $choices = get_transient( $cache_key );
2634
2635 if ( ! empty( $choices ) && is_array( $choices ) ) {
2636 return $choices;
2637 }
2638
2639 // Get users with the 'customer' role
2640 $customer_users = get_users(
2641 array(
2642 'role' => 'customer',
2643 'fields' => array( 'ID', 'display_name' ),
2644 )
2645 );
2646
2647 $choices = array();
2648 if ( ! empty( $customer_users ) ) {
2649 foreach ( $customer_users as $user ) {
2650 $choices[] = array(
2651 'id' => $user->ID,
2652 'text' => $user->display_name,
2653 );
2654 }
2655 }
2656
2657 // Cache the choices with no expiration. Will be cleared using `clear_customer_choices_cache`
2658 set_transient( $cache_key, $choices );
2659
2660 return $choices;
2661 }
2662
2663 /**
2664 * Clear customers cache when a customer is created/deleted/updated.
2665 *
2666 * @param $user_id
2667 * @param $user
2668 *
2669 * @return void
2670 */
2671 public function clear_customer_choices_cache( $user_id, $user ) {
2672 $user_roles = $user->roles ?? array();
2673 if ( in_array( 'customer', $user_roles, true ) ) {
2674 delete_transient( 'customers_select2_choices' );
2675 }
2676 }
2677 }
2678
2679 Merchant_Admin_Options::instance();
2680 }
2681