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

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