PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 2.2.8
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v2.2.8
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 / inc / classes / class-merchant-metabox.php

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

1,363 lines 48.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Metabox.
5 *
6 * @package Merchant
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit; // Exit if accessed directly
11 }
12
13 /**
14 * Metabox class.
15 *
16 */
17 if ( ! class_exists( 'Merchant_Metabox' ) ) {
18 class Merchant_Metabox {
19
20 private static $initialized = null;
21
22 /**
23 * Options.
24 *
25 */
26 public static $options = array();
27
28 /**
29 * Constructor.
30 *
31 */
32 public function __construct() {
33 if ( ! is_null( self::$initialized ) ) {
34 return;
35 }
36
37 self::$initialized = true;
38
39 add_action( 'load-post.php', array( $this, 'init_metabox' ) );
40 add_action( 'load-post-new.php', array( $this, 'init_metabox' ) );
41 add_action( 'wp_ajax_merchant_select_ajax', array( $this, 'select_content_ajax' ) );
42 }
43
44 /**
45 * Init metabox.
46 *
47 */
48 public function init_metabox() {
49 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_metabox_scripts' ) );
50 add_action( 'add_meta_boxes', array( $this, 'add_metabox' ) );
51 add_action( 'save_post', array( $this, 'save_metabox' ) );
52 }
53
54 /**
55 * Enqueue scripts.
56 *
57 */
58 public function enqueue_metabox_scripts() {
59 wp_enqueue_code_editor(
60 array(
61 'type' => 'text/html',
62 'codemirror' => array(
63 'indentUnit' => 2,
64 'tabSize' => 2,
65 ),
66 ) );
67
68 wp_enqueue_script( 'merchant-select2', MERCHANT_URI . 'assets/vendor/select2/select2.full.min.js', array( 'jquery' ), '4.0.13', true );
69 wp_enqueue_style( 'merchant-select2', MERCHANT_URI . 'assets/vendor/select2/select2.min.css', array(), '4.0.13', 'all' );
70
71 // Enqueue Air Datepicker for date_time fields
72 wp_enqueue_script( 'air-datepicker', MERCHANT_URI . 'assets/vendor/air-datepicker/air-datepicker.js', array( 'jquery' ), '3.4.0', true );
73 wp_enqueue_style( 'air-datepicker', MERCHANT_URI . 'assets/vendor/air-datepicker/air-datepicker.css', array(), '3.4.0' );
74
75 // Enqueue Pickr for color fields (CSS is bundled in metabox.min.css)
76 wp_enqueue_script( 'pickr', MERCHANT_URI . 'assets/vendor/pickr/pickr.min.js', array(), '1.8.2', true );
77
78 wp_enqueue_style( 'merchant-metabox-styles', MERCHANT_URI . 'assets/css/admin/metabox.min.css', array(), MERCHANT_VERSION );
79 wp_enqueue_script( 'merchant-metabox-scripts', MERCHANT_URI . 'assets/js/admin/merchant-metabox.min.js', array( 'jquery', 'jquery-ui-sortable', 'air-datepicker', 'pickr' ), MERCHANT_VERSION, true );
80
81 // Localize datepicker
82 $datepicker_locale = array(
83 'days' => array(
84 __( 'Sunday', 'merchant' ),
85 __( 'Monday', 'merchant' ),
86 __( 'Tuesday', 'merchant' ),
87 __( 'Wednesday', 'merchant' ),
88 __( 'Thursday', 'merchant' ),
89 __( 'Friday', 'merchant' ),
90 __( 'Saturday', 'merchant' ),
91 ),
92 'daysShort' => array(
93 __( 'Sun', 'merchant' ),
94 __( 'Mon', 'merchant' ),
95 __( 'Tue', 'merchant' ),
96 __( 'Wed', 'merchant' ),
97 __( 'Thu', 'merchant' ),
98 __( 'Fri', 'merchant' ),
99 __( 'Sat', 'merchant' ),
100 ),
101 'daysMin' => array(
102 __( 'Su', 'merchant' ),
103 __( 'Mo', 'merchant' ),
104 __( 'Tu', 'merchant' ),
105 __( 'We', 'merchant' ),
106 __( 'Th', 'merchant' ),
107 __( 'Fr', 'merchant' ),
108 __( 'Sa', 'merchant' ),
109 ),
110 'months' => array(
111 __( 'January', 'merchant' ),
112 __( 'February', 'merchant' ),
113 __( 'March', 'merchant' ),
114 __( 'April', 'merchant' ),
115 __( 'May', 'merchant' ),
116 __( 'June', 'merchant' ),
117 __( 'July', 'merchant' ),
118 __( 'August', 'merchant' ),
119 __( 'September', 'merchant' ),
120 __( 'October', 'merchant' ),
121 __( 'November', 'merchant' ),
122 __( 'December', 'merchant' ),
123 ),
124 'monthsShort' => array(
125 __( 'Jan', 'merchant' ),
126 __( 'Feb', 'merchant' ),
127 __( 'Mar', 'merchant' ),
128 __( 'Apr', 'merchant' ),
129 __( 'May', 'merchant' ),
130 __( 'Jun', 'merchant' ),
131 __( 'Jul', 'merchant' ),
132 __( 'Aug', 'merchant' ),
133 __( 'Sep', 'merchant' ),
134 __( 'Oct', 'merchant' ),
135 __( 'Nov', 'merchant' ),
136 __( 'Dec', 'merchant' ),
137 ),
138 'today' => __( 'Today', 'merchant' ),
139 'clear' => __( 'Clear', 'merchant' ),
140 );
141
142 wp_localize_script( 'merchant-metabox-scripts', 'merchant_metabox', array(
143 'ajaxurl' => admin_url( 'admin-ajax.php' ),
144 'ajaxnonce' => wp_create_nonce( 'merchant_metabox' ),
145 ) );
146
147 wp_localize_script( 'merchant-metabox-scripts', 'merchant_datepicker_locale', $datepicker_locale );
148 }
149
150 /**
151 * Select content ajax callback.
152 *
153 */
154 public function select_content_ajax() {
155 $term = ( isset( $_GET['term'] ) ) ? sanitize_text_field( wp_unslash( $_GET['term'] ) ) : '';
156 $nonce = ( isset( $_GET['nonce'] ) ) ? sanitize_text_field( wp_unslash( $_GET['nonce'] ) ) : '';
157 $source = ( isset( $_GET['source'] ) ) ? sanitize_text_field( wp_unslash( $_GET['source'] ) ) : '';
158
159 // Check current user capabilities
160 if ( ! current_user_can( 'manage_options' ) ) {
161 wp_send_json_error( 'You are not allowed to do this.' );
162 }
163
164 if ( ! empty( $term ) && ! empty( $source ) && ! empty( $nonce ) && wp_verify_nonce( $nonce, 'merchant_metabox' ) ) {
165 $options = array();
166
167 switch ( $source ) {
168 case 'post':
169 case 'product':
170 $query = new WP_Query( array(
171 's' => $term,
172 'post_type' => $source,
173 'post_status' => 'publish',
174 'posts_per_page' => 25,
175 'order' => 'DESC',
176 ) );
177
178 if ( ! empty( $query->posts ) ) {
179 foreach ( $query->posts as $post ) {
180 $options[] = array(
181 'id' => $post->ID,
182 'text' => $post->post_title,
183 );
184 }
185 }
186
187 break;
188
189 case 'user':
190 $query = new WP_User_Query( array(
191 'search' => '*' . $term . '*',
192 'search_columns' => array( 'user_login', 'user_email', 'display_name' ),
193 'number' => 25,
194 'orderby' => 'display_name',
195 'order' => 'ASC',
196 'fields' => array( 'ID', 'display_name', 'user_email' ),
197 ) );
198 $users = $query->get_results();
199 if ( ! empty( $users ) ) {
200 foreach ( $users as $user ) {
201 $options[] = array(
202 'id' => $user->ID,
203 'text' => $user->display_name . ' (' . $user->user_email . ')',
204 );
205 }
206 }
207 break;
208 }
209
210 wp_send_json_success( $options );
211 } else {
212 wp_send_json_error();
213 }
214 }
215
216 /**
217 * Options.
218 *
219 */
220 public function metabox_options() {
221 /**
222 * Hook: merchant_metabox_options
223 *
224 * @since 1.0
225 */
226 do_action( 'merchant_metabox_options', self::$options );
227
228 /**
229 * Hook: merchant_metabox_options_filter
230 *
231 * @since 1.0
232 */
233 self::$options = apply_filters( 'merchant_metabox_options_filter', self::$options );
234
235 // Set priority order
236 self::$options = wp_list_sort( self::$options, array( 'priority' => 'ASC' ), 'ASC', true );
237
238 foreach ( self::$options as $key => $value ) {
239 self::$options[ $key ]['fields'] = wp_list_sort( $value['fields'], array( 'priority' => 'ASC' ), 'ASC', true );
240 }
241
242 return self::$options;
243 }
244
245 /**
246 * Add section.
247 *
248 */
249 public function add_section( $id, $args ) {
250 if ( ! empty( $args['post_type'] ) && ! in_array( get_post_type(), $args['post_type'], true ) ) {
251 return;
252 }
253
254 if ( ! empty( $args['exclude'] ) && in_array( get_post_type(), $args['exclude'], true ) ) {
255 return;
256 }
257
258 $args = wp_parse_args( $args, array(
259 'title' => '',
260 'fields' => array(),
261 'priority' => ( count( self::$options ) + 1 ) * 10,
262 ) );
263
264 self::$options[ $id ] = $args;
265 }
266
267 /**
268 * Add field.
269 *
270 */
271 public function add_field( $id, $args ) {
272 if ( ( ! empty( $args['post_type'] ) && ! in_array( get_post_type(), $args['post_type'], true ) ) || empty( self::$options[ $args['section'] ] ) ) {
273 return;
274 }
275
276 $args = wp_parse_args( $args, array(
277 'priority' => ( count( self::$options[ $args['section'] ]['fields'] ) + 1 ) * 10,
278 ) );
279
280 self::$options[ $args['section'] ]['fields'][ $id ] = $args;
281 }
282
283 /**
284 * Add metabox.
285 *
286 */
287 public function add_metabox( $post_type ) {
288 global $post;
289
290 // Do not render the metabox on attachment post type.
291 if ( 'attachment' === $post_type ) {
292 return;
293 }
294
295 $types = get_post_types( array(
296 'public' => true,
297 ) );
298
299 if ( ! in_array( $post_type, $types, true ) ) {
300 return;
301 }
302
303 $options = $this->metabox_options();
304 if ( empty( $options ) ) {
305 return;
306 }
307
308 $metabox_title = esc_html__( 'Options', 'merchant' );
309 switch ( $post_type ) {
310 case 'post':
311 $metabox_title = esc_html__( 'Post Options', 'merchant' );
312 break;
313
314 case 'page':
315 $metabox_title = esc_html__( 'Page Options', 'merchant' );
316 break;
317
318 case 'product':
319 $metabox_title = esc_html__( 'Product Options', 'merchant' );
320 break;
321 }
322
323 // Botiga theme compatibility:
324 // Do not render the metabox in the Botiga templates builder.
325 if ( class_exists( 'Botiga_Modules' ) && Botiga_Modules::is_module_active( 'templates' ) ) {
326 unset( $types['athemes_hf'] );
327 }
328
329 $title_prefix = ! defined( 'MERCHANT_AWL_ACTIVE' ) ? esc_html__( 'Merchant ', 'merchant' ) : '';
330
331 /**
332 * Hook: merchant_metabox_title
333 *
334 * @since 1.0
335 */
336 $metabox_title = apply_filters( 'merchant_metabox_title', $title_prefix . $metabox_title, $post_type );
337
338 add_meta_box( 'merchant_metabox', $metabox_title, array( $this, 'render_metabox_content' ), $types, 'normal', 'low' );
339 }
340
341 /**
342 * Metabox content.
343 *
344 */
345 public function render_metabox_content( $post ) {
346 $options = $this->metabox_options();
347 $post_type = get_post_type( $post );
348
349 wp_nonce_field( 'merchant_metabox', 'merchant_metabox_nonce' );
350
351 echo '<div class="merchant-metabox">';
352 $has_tabs = ( ! empty( array_filter( array_column( $options, 'title' ) ) ) ) ? true : false;
353
354 if ( ! empty( $has_tabs ) ) {
355 echo '<div class="merchant-metabox-tabs">';
356
357 $num = 0;
358 foreach ( $options as $option ) {
359 if ( ! empty( $option['title'] ) ) {
360 $active = ( 0 === $num ) ? ' active' : '';
361 echo '<a href="#" class="merchant-metabox-tab' . esc_attr( $active ) . '">' . esc_html( $option['title'] ) . '</a>';
362
363 ++$num;
364 }
365 }
366
367 echo '</div>';
368 }
369
370 echo '<div class="merchant-metabox-contents">';
371
372 $num = 0;
373 foreach ( $options as $option ) {
374 $active = ( 0 === $num ) ? ' active' : '';
375 echo '<div class="merchant-metabox-content' . esc_attr( $active ) . '">';
376
377 if ( ! empty( $option['title'] ) ) {
378 echo '<h4 class="merchant-metabox-content-title">' . esc_html( $option['title'] ) . '</h4>';
379 }
380
381 if ( ! empty( $option['fields'] ) ) {
382 foreach ( $option['fields'] as $field_id => $field ) {
383 $separator = ( ! empty( $field['separator'] ) ) ? $field['separator'] : 'after';
384 $classes = array();
385 $classes[] = 'merchant-metabox-field';
386 $classes[] = 'merchant-metabox-field-separator-' . $separator;
387 $classes[] = 'merchant-metabox-field-' . $field['type'];
388
389 if ( ! empty( $field['class'] ) ) {
390 $classes[] = $field['class'];
391 }
392
393 if ( ! empty( $field['inline'] ) ) {
394 $classes[] = 'merchant-metabox-field-inline';
395 }
396
397 // Build data attributes array
398 $data_attrs = array();
399
400 // Handle old simple dependency (data-depend-on)
401 if ( ! empty( $field['depend'] ) ) {
402 $depend_meta = get_post_meta( $post->ID, $field['depend'], true );
403
404 if ( empty( $depend_meta ) ) {
405 $classes[] = 'merchant-metabox-field-hidden';
406 }
407
408 $data_attrs[] = 'data-depend-on="' . esc_attr( $field['depend'] ) . '"';
409 }
410
411 // Handle new enhanced conditions (data-conditions)
412 if ( ! empty( $field['conditions'] ) ) {
413 $data_attrs[] = "data-conditions='" . esc_attr( wp_json_encode( $field['conditions'] ) ) . "'";
414
415 // Check if field should be initially hidden based on conditions
416 if ( $this->should_hide_field( $field['conditions'], $post->ID ) ) {
417 $classes[] = 'merchant-metabox-field-hidden';
418 }
419 }
420
421 // Output the field wrapper with all data attributes
422 echo '<div class="' . esc_attr( join( ' ', $classes ) ) . '"';
423 if ( ! empty( $data_attrs ) ) {
424 echo ' ' . wp_kses_post( implode( ' ', $data_attrs ) );
425 }
426 echo '>';
427
428 if ( isset( $field['title'] ) || isset( $field['subtitle'] ) ) {
429 echo '<div class="merchant-metabox-field-title">';
430
431 if ( ! empty( $field['title'] ) ) {
432 echo '<h4>' . wp_kses_post( $field['title'] ) . '</h4>';
433 }
434
435 if ( ! empty( $field['subtitle'] ) ) {
436 echo '<small class="merchant-metabox-field-subtitle">' . wp_kses_post( $field['subtitle'] ) . '</small>';
437 }
438
439 echo '</div>';
440 }
441
442 echo '<div class="merchant-metabox-field-content">';
443
444 $meta = get_post_meta( $post->ID, $field_id, false );
445 $default = ( isset( $field['default'] ) ) ? $field['default'] : null;
446 $value = ( isset( $meta[0] ) ) ? $meta[0] : $default;
447
448 $this->get_field( $field_id, $field, $value );
449
450 if ( ! empty( $field['desc'] ) ) {
451 echo '<div class="merchant-metabox-field-description">' . wp_kses_post( $field['desc'] ) . '</div>';
452 }
453
454 echo '</div>';
455
456 echo '</div>';
457 }
458 }
459
460 echo '</div>';
461
462 ++$num;
463 }
464
465 echo '</div>';
466 echo '</div>';
467 }
468
469 /**
470 * Save metabox.
471 *
472 */
473 public function save_metabox( $post_id ) {
474 if ( ! isset( $_POST['merchant_metabox_nonce'] ) ) {
475 return $post_id;
476 }
477
478 $nonce = sanitize_key( wp_unslash( $_POST['merchant_metabox_nonce'] ) );
479 if ( ! wp_verify_nonce( $nonce, 'merchant_metabox' ) ) {
480 return $post_id;
481 }
482
483 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
484 return $post_id;
485 }
486
487 if ( ! current_user_can( 'edit_page', $post_id ) ) {
488 return $post_id;
489 }
490
491 $options = $this->metabox_options();
492 if ( empty( $options ) ) {
493 return $post_id;
494 }
495
496 foreach ( $options as $option ) {
497 if ( ! empty( $option['fields'] ) ) {
498 foreach ( $option['fields'] as $field_id => $field ) {
499 if ( $field['type'] === 'content' ) {
500 continue;
501 }
502
503 $value = $this->sanitize( $field, $field_id, $_POST );
504
505 update_post_meta( $post_id, $field_id, $value );
506 }
507 }
508 }
509 }
510
511 /**
512 * Sanitize.
513 *
514 */
515 public function sanitize( $field, $field_id, $post_data ) {
516 $value = isset( $post_data[ $field_id ] ) ? wp_unslash( $post_data[ $field_id ] ) : null;
517
518 switch ( $field['type'] ) {
519 case 'text':
520 case 'coupons':
521 case 'sidebar-select':
522 case 'size-chart-select':
523 return sanitize_text_field( $value );
524 break;
525
526 case 'textarea':
527 return sanitize_textarea_field( $value );
528 break;
529
530 case 'checkbox':
531 case 'switcher':
532 return ( '1' === $value ) ? 1 : 0;
533 break;
534
535 case 'range':
536 case 'number':
537 return absint( $value );
538 break;
539
540 case 'select':
541 if ( isset( $field['multiple'] ) && $field['multiple'] && is_array( $value ) ) {
542 return array_filter( array_map( 'sanitize_key', $value ) );
543 }
544 return ( in_array( $value, array_keys( $field['options'] ), true ) ) ? sanitize_key( $value ) : '';
545 break;
546
547 case 'choices':
548 return ( in_array( $value, array_keys( $field['options'] ), true ) ) ? sanitize_key( $value ) : '';
549 break;
550
551 case 'wc-attributes':
552 case 'select-ajax':
553 return ( is_array( $value ) && ! empty( $value ) ) ? array_filter( array_map( 'sanitize_text_field', $value ) ) : array();
554 break;
555
556 case 'repeater':
557 case 'uploads':
558 case 'size-chart':
559 return ( is_array( $value ) && ! empty( $value ) ) ? array_filter( map_deep( $value, 'sanitize_text_field' ) ) : array();
560 break;
561
562 case 'wp-editor':
563 return wp_kses_post( $value );
564 break;
565
566 case 'date_time':
567 case 'color':
568 case 'radio':
569 return sanitize_text_field( $value );
570 break;
571
572 case 'flexible-content':
573 return is_array( $value ) && ! empty( $value ) ? array_map( function ( $sub_fields ) use ( $field ) {
574 foreach ( $sub_fields as $sub_field => $value ) {
575 $sub_fields[ $sub_field ] = $this->sanitize( $field['layouts'][ $sub_fields['type'] ]['fields'][ $sub_field ], $sub_field, $sub_fields );
576 }
577
578 return $sub_fields;
579 }, $value ) : array();
580 break;
581 }
582
583 return $value;
584 }
585
586 /**
587 * Get field.
588 *
589 */
590 public function get_field( $field_id, $field, $value ) {
591 switch ( $field['type'] ) {
592 case 'text':
593 if ( isset( $field['append'] ) || isset( $field['prepend'] ) ) {
594 echo '<div class="merchant-metabox-field-input-container">';
595 if ( isset( $field['prepend'] ) ) {
596 echo '<div class="merchant-metabox-field-prepend">' . esc_attr( $field['prepend'] ) . '</div>';
597 }
598 echo '<input type="text" name="' . esc_attr( $field_id ) . '" value="' . esc_attr( $value ) . '"';
599 if ( isset( $field['placeholder'] ) ) {
600 echo ' placeholder="' . esc_attr( $field['placeholder'] ) . '"';
601 }
602 echo ' />';
603
604 if ( isset( $field['append'] ) ) {
605 echo '<div class="merchant-metabox-field-append">' . esc_attr( $field['append'] ) . '</div>';
606 }
607 echo '</div>';
608 } else {
609 echo '<input type="text" name="' . esc_attr( $field_id ) . '" value="' . esc_attr( $value ) . '"';
610 if ( isset( $field['placeholder'] ) ) {
611 echo ' placeholder="' . esc_attr( $field['placeholder'] ) . '"';
612 }
613 echo ' />';
614 }
615 break;
616
617 case 'number':
618 $style = '';
619 $step = 'any';
620 if ( isset( $field['style'] ) && ! empty( $field['style'] ) ) {
621 $style = 'style="' . esc_attr( str_replace( array( '&', '=' ), array( '; ', ': ' ), http_build_query( $field['style'] ) ) ) . '"';
622 }
623 if ( isset( $field['step'] ) && ! empty( $field['step'] ) ) {
624 $step = $field['step'];
625 }
626 if ( isset( $field['append'] ) || isset( $field['prepend'] ) ) {
627 echo '<div class="merchant-metabox-field-input-container">';
628 if ( isset( $field['prepend'] ) ) {
629 echo '<div class="merchant-metabox-field-prepend">' . esc_attr( $field['prepend'] ) . '</div>';
630 }
631 echo '<input step="' . esc_attr( $step ) . '" type="number" name="' . esc_attr( $field_id ) . '" value="' . esc_attr( $value ) . '" ' . wp_kses_post( $style ) . ' />';
632 if ( isset( $field['append'] ) ) {
633 echo '<div class="merchant-metabox-field-append">' . esc_attr( $field['append'] ) . '</div>';
634 }
635 echo '</div>';
636 } else {
637 echo '<input step="' . esc_attr( $step ) . '" type="number" '.' name="' . esc_attr( $field_id ) . '" value="' . esc_attr( $value ) . '" ' . wp_kses_post( $style ) . ' />';
638 }
639 break;
640
641 case 'textarea':
642 echo '<textarea name="' . esc_attr( $field_id ) . '">' . esc_textarea( $value ) . '</textarea>';
643 break;
644
645 case 'checkbox':
646 case 'switcher':
647 $field = wp_parse_args( $field, array(
648 'label' => '',
649 ) );
650
651 echo '<label>';
652 echo '<input type="checkbox" name="' . esc_attr( $field_id ) . '" value="1"' . checked( $value, true, false ) . ' />';
653
654 if ( 'switcher' === $field['type'] ) {
655 echo '<i></i>';
656 }
657
658 if ( ! empty( $field['label'] ) ) {
659 echo '<span>' . esc_html( $field['label'] ) . '</span>';
660 }
661 echo '</label>';
662 break;
663
664 case 'select':
665 $multiple = ( isset( $field['multiple'] ) && $field['multiple'] ) ? ' multiple' : '';
666 $name = $field_id . ( $multiple ? '[]' : '' );
667
668 echo '<select name="' . esc_attr( $name ) . '"' . esc_attr( $multiple ) . '>';
669
670 foreach ( $field['options'] as $key => $option ) {
671 $is_selected = is_array( $value ) ? in_array( $key, $value, true ) : ( (string) $key === (string) $value );
672 echo '<option value="' . esc_attr( $key ) . '"' . selected( $is_selected, true, false ) . '>' . esc_html( $option ) . '</option>';
673 }
674
675 echo '</select>';
676 break;
677
678 case 'select-ajax':
679 $field = wp_parse_args( $field, array(
680 'source' => 'post',
681 ) );
682 $ids = ( is_array( $value ) && ! empty( $value ) ) ? $value : (array) $value;
683 if ( isset( $field['multiple'] ) ) {
684 $multiple = $field['multiple'] === true ? 'multiple' : '';
685 } else {
686 $multiple = 'multiple';
687 }
688
689 echo '<select name="' . esc_attr( $field_id ) . '[]" ' . esc_attr( $multiple ) . ' data-source="' . esc_attr( $field['source'] ) . '">';
690
691 if ( ! empty( $ids ) ) {
692 foreach ( $ids as $id ) {
693 switch ( $field['source'] ) {
694 case 'post':
695 case 'product':
696 $post = get_post( $id );
697
698 if ( ! empty( $post ) ) {
699 echo '<option value="' . esc_attr( $post->ID ) . '" selected>' . esc_html( $post->post_title ) . '</option>';
700 }
701 break;
702
703 case 'user':
704 $user = get_user_by( 'id', $id );
705
706 if ( ! empty( $user ) ) {
707 echo '<option value="' . esc_attr( $user->ID ) . '" selected>' . esc_html( $user->display_name ) . ' (' . esc_html( $user->user_email ) . ')</option>';
708 }
709 break;
710 }
711 }
712 }
713
714 echo '</select>';
715 break;
716
717 case 'wc-attributes':
718 $attributes = wp_list_pluck( wc_get_attribute_taxonomies(), 'attribute_label', 'attribute_id' );
719 $values = ( is_array( $value ) && ! empty( $value ) ) ? $value : array();
720
721 if ( ! empty( $attributes ) ) {
722 echo '<div class="merchant-metabox-field-attributes">';
723 echo '<ul class="merchant-sortable">';
724
725 $selected_attributes = array();
726 foreach ( $values as $id ) {
727 if ( isset( $attributes[ $id ] ) ) {
728 $selected_attributes[ $id ] = $attributes[ $id ];
729 unset( $attributes[ $id ] );
730 }
731 }
732
733 $attributes = array_replace( $selected_attributes, $attributes );
734 foreach ( $attributes as $attribute_id => $attribute_label ) {
735 // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
736 $checked = ( in_array( $attribute_id, $values ) ) ? ' checked' : '';
737
738 echo '<li class="merchant-sortable-item">';
739 echo '<label>';
740 echo '<input type="checkbox" name="' . esc_attr( $field_id ) . '[]" value="' . esc_attr( $attribute_id ) . '"' . esc_attr( $checked ) . ' />';
741 echo '<span>' . esc_html( $attribute_label ) . '</span>';
742 echo '</label>';
743 echo '<span class="merchant-sortable-move dashicons dashicons-menu"></span>';
744 echo '</li>';
745 }
746
747 echo '</ul>';
748 echo '</div>';
749 }
750
751 break;
752
753 case 'choices':
754 echo '<div class="merchant-metabox-field-choices-images">';
755
756 foreach ( $field['options'] as $key => $option ) {
757 echo '<label>';
758 echo '<input type="radio" name="' . esc_attr( $field_id ) . '" value="' . esc_attr( $key ) . '"' . checked( $value, $key, false ) . ' />';
759 echo '<figure><img src="' . esc_url( sprintf( $option['image'],
760 MERCHANT_URI ) ) . '" title="' . esc_attr( $option['label'] ) . '" alt="' . esc_attr( $option['label'] ) . '" /></figure>';
761 echo '</label>';
762 }
763 echo '</div>';
764 break;
765
766 case 'date_time':
767 $field = wp_parse_args( $field, array(
768 'options' => array(),
769 'placeholder' => '',
770 ) );
771
772 // Set default options to match admin settings framework
773 $default_options = array(
774 'dateFormat' => 'MM-dd-yyyy',
775 'timepicker' => true,
776 'timeFormat' => 'hh:mm AA',
777 'minDate' => 'today',
778 'timeZone' => wp_timezone_string(),
779 );
780
781 $options = wp_parse_args( $field['options'], $default_options );
782
783 echo '<div class="merchant-metabox-datetime-field" data-options="' . esc_attr( wp_json_encode( $options ) ) . '">';
784 echo '<input type="text" name="' . esc_attr( $field_id ) . '" value="' . esc_attr( $value ) . '" placeholder="' . esc_attr( $field['placeholder'] ) . '" />';
785 echo '</div>';
786 break;
787
788 case 'color':
789 $field = wp_parse_args( $field, array(
790 'default' => '#212121',
791 ) );
792
793 echo '<div class="merchant-metabox-color-field">';
794 echo '<div class="merchant-color-picker" data-default-color="' . esc_attr( $field['default'] ) . '" style="background-color: ' . esc_attr( $value ? $value : $field['default'] ) . ';"></div>';
795 echo '<input type="text" class="merchant-color-input" name="' . esc_attr( $field_id ) . '" value="' . esc_attr( $value ) . '" />';
796 echo '</div>';
797 break;
798
799 case 'radio':
800 $field = wp_parse_args( $field, array(
801 'options' => array(),
802 ) );
803
804 echo '<div class="merchant-metabox-radio-field">';
805 foreach ( $field['options'] as $option_key => $option_label ) {
806 echo '<label>';
807 echo '<input type="radio" name="' . esc_attr( $field_id ) . '" value="' . esc_attr( $option_key ) . '"' . checked( $value, $option_key, false ) . ' /> ';
808 echo esc_html( $option_label );
809 echo '</label><br/>';
810 }
811 echo '</div>';
812 break;
813
814 case 'repeater':
815 $field = wp_parse_args( $field, array(
816 'button' => '',
817 ) );
818
819 echo '<div class="merchant-metabox-field-repeater-content" data-id="' . esc_attr( $field_id ) . '">';
820 $values = ( is_array( $value ) && ! empty( $value ) ) ? $value : array();
821
822 echo '<ul class="merchant-metabox-field-repeater-list">';
823 echo '<li class="merchant-metabox-field-repeater-list-item hidden">';
824 if ( isset( $field['fields'] ) ) {
825 echo '<div class="merchant-metabox-field-repeater-list-item-fields">';
826 foreach ( $field['fields'] as $sub_field_id => $sub_field ) {
827 echo '<div class="merchant-metabox-field-repeater-list-item-field">';
828 if ( isset( $sub_field['title'] ) ) {
829 echo '<span class="merchant-metabox-field-repeater-list-item-field-title">' . esc_html( $sub_field['title'] ) . '</span>';
830 }
831 echo '<div class="merchant-metabox-field-repeater-list-item-field-input" data-id="' . esc_attr( $sub_field_id ) . '">';
832 if ( $sub_field['type'] === 'text' ) {
833 echo '<input type="text" name="" value="" data-name="' . esc_attr( $field_id ) . '[0][' . esc_attr( $sub_field_id ) . ']" />';
834 }
835 if ( $sub_field['type'] === 'number' ) {
836 echo '<input type="number" name="" value="" data-name="' . esc_attr( $field_id ) . '[0][' . esc_attr( $sub_field_id ) . ']" />';
837 }
838 echo '</div>';
839 echo '</div>';
840 }
841 echo '</div>';
842 } else {
843 echo '<input type="text" name="" value="" data-name="' . esc_attr( $field_id ) . '[]" />';
844 }
845 echo '<span class="merchant-metabox-field-repeater-move dashicons dashicons-menu"></span>';
846 echo '<span class="merchant-metabox-field-repeater-remove dashicons dashicons-trash"></span>';
847 echo '</li>';
848
849 foreach ( $values as $key => $value ) {
850 echo '<li class="merchant-metabox-field-repeater-list-item">';
851 if ( isset( $field['fields'] ) ) {
852 echo '<div class="merchant-metabox-field-repeater-list-item-fields">';
853 foreach ( $field['fields'] as $sub_field_id => $sub_field ) {
854 echo '<div class="merchant-metabox-field-repeater-list-item-field">';
855 if ( isset( $sub_field['title'] ) ) {
856 echo '<span class="merchant-metabox-field-repeater-list-item-field-title">' . esc_attr( $sub_field['title'] ) . '</span>';
857 }
858 echo '<div class="merchant-metabox-field-repeater-list-item-field-input" data-id="' . esc_attr( $sub_field_id ) . '">';
859 if ( $sub_field['type'] === 'text' ) {
860 echo '<input type="text" name="' . esc_attr( $field_id ) . '[' . esc_attr( $key ) . '][' . esc_attr( $sub_field_id ) . ']" value="' . esc_attr( $value[ $sub_field_id ] ) . '" />';
861 }
862 if ( $sub_field['type'] === 'number' ) {
863 echo '<input type="number" name="' . esc_attr( $field_id ) . '[' . esc_attr( $key ) . '][' . esc_attr( $sub_field_id ) . ']" value="' . esc_attr( $value[ $sub_field_id ] ) . '" />';
864 }
865 echo '</div>';
866 echo '</div>';
867 }
868 echo '</div>';
869 } else {
870 echo '<input type="text" name="' . esc_attr( $field_id ) . '[]" value="' . esc_attr( $value ) . '" />';
871 }
872
873 echo '<span class="merchant-metabox-field-repeater-move dashicons dashicons-menu"></span>';
874 echo '<span class="merchant-metabox-field-repeater-remove dashicons dashicons-trash"></span>';
875 echo '</li>';
876 }
877 echo '</ul>';
878 echo '<button class="merchant-metabox-field-repeater-add button button-primary">' . esc_html( $field['button'] ) . '</button>';
879 echo '</div>';
880
881 break;
882
883 case 'media':
884 $placeholder = class_exists( 'Woocommerce' ) ? wc_placeholder_img_src( 'thumbnail' ) : MERCHANT_URI . '/assets/placeholder.svg';
885 $hidden_class = ( empty( $value ) ) ? ' hidden' : '';
886
887 if ( ! empty( $value ) ) {
888 $attachment = wp_get_attachment_image_src( $value, 'thumbnail' );
889 $thumbnail = ( is_array( $attachment ) && ! empty( $attachment[0] ) ) ? $attachment[0] : $placeholder;
890 } else {
891 $thumbnail = $placeholder;
892 }
893
894 echo '<div class="merchant-metabox-field-media-content">';
895 echo '<figure class="merchant-metabox-field-media-preview">';
896 echo '<img src="' . esc_url( $thumbnail ) . '" data-placeholder="' . esc_url( $placeholder ) . '" />';
897 echo '</figure>';
898
899 echo '<div class="merchant-metabox-field-media-button">';
900 echo '<a href="#" class="merchant-metabox-field-media-upload button">' . esc_html__( 'Upload/Add Image', 'merchant' ) . '</a>';
901 echo '<a href="#" class="merchant-metabox-field-media-remove merchant-button-remove button' . esc_attr( $hidden_class ) . '">' . esc_html__( 'Remove Image', 'merchant' ) . '</a>';
902 echo '<input type="hidden" name="' . esc_attr( $field_id ) . '" value="' . esc_attr( $value ) . '" class="merchant-metabox-field-media-input" />';
903 echo '</div>';
904 echo '</div>';
905
906 break;
907
908 case 'uploads':
909 $field = wp_parse_args( $field, array(
910 'button' => '',
911 'library' => 'image',
912 ) );
913
914 $enable_thumb = isset( $field['enable_thumb'] ) && $field['enable_thumb'];
915
916 echo '<div class="merchant-metabox-field-uploads-content">';
917 $values = ( is_array( $value ) && ! empty( $value ) ) ? $value : array();
918 $name = 'video' === $field['library'] ? $field_id . '[0][src]' : $field_id . '[]';
919 $thumb_name = $field_id . '[0][thumb]';
920
921 echo '<ul class="merchant-metabox-field-uploads-list" data-library="' . esc_attr( $field['library'] ) . '">';
922 echo '<li class="merchant-metabox-field-uploads-list-item hidden">';
923
924 if ( 'video' === $field['library'] || $enable_thumb ) {
925 echo '<div class="merchant-metabox-field-uploads-thumbnail">';
926 echo '<a href="#" class="merchant-metabox-field-uploads-thumbnail-remove dashicons dashicons-dismiss" style="display:none"></a>';
927 echo '<a href="#" class="merchant-metabox-field-uploads-thumbnail-upload"><span>+</span></a>';
928 echo '<input type="hidden" name="" value="" data-name="' . esc_attr( $thumb_name ) . '" />';
929 echo '</div>';
930 }
931
932 echo '<input type="text" name="" value="" data-name="' . esc_attr( $name ) . '" />';
933 echo '<button class="merchant-metabox-field-uploads-upload button">' . esc_html__( 'Upload', 'merchant' ) . '</button>';
934 echo '<span class="merchant-metabox-field-uploads-move dashicons dashicons-menu"></span>';
935 echo '<span class="merchant-metabox-field-uploads-remove dashicons dashicons-trash"></span>';
936 echo '</li>';
937
938 foreach ( $values as $key => $value ) {
939 $item_name = 'video' === $field['library'] || $enable_thumb ? str_replace( '0', $key, $name ) : $name;
940 $item_value = is_array( $value ) ? ( isset( $value['src'] ) ? $value['src'] : '' ) : $value;
941
942 echo '<li class="merchant-metabox-field-uploads-list-item">';
943 if ( 'video' === $field['library'] || $enable_thumb ) {
944 $item_thumb = is_array( $value ) && isset( $value['thumb'] ) ? $value['thumb'] : '';
945 $item_thumb_name = str_replace( '0', $key, $thumb_name );
946
947 echo '<div class="merchant-metabox-field-uploads-thumbnail">';
948 echo '<a href="#" class="merchant-metabox-field-uploads-thumbnail-remove dashicons dashicons-dismiss" ' . ( empty( $item_thumb ) ? 'style="display: none"' : '' ) . '></a>';
949 echo '<a href="#" class="merchant-metabox-field-uploads-thumbnail-upload">';
950 echo empty( $item_thumb )
951 ? '<span>+</span>'
952 : '<img src="' . esc_url( wp_get_attachment_thumb_url( $item_thumb ) ) . '" /><span style="display: none">+</span>';
953 echo '</a>';
954 echo '<input type="hidden" name="' . esc_attr( $item_thumb_name ) . '" value="' . absint( $item_thumb ) . '" />';
955 echo '</div>';
956 }
957 echo '<input type="text" name="' . esc_attr( $item_name ) . '" value="' . esc_attr( $item_value ) . '" />';
958
959 echo '<button class="merchant-metabox-field-uploads-upload button">' . esc_html__( 'Upload', 'merchant' ) . '</button>';
960 echo '<span class="merchant-metabox-field-uploads-move dashicons dashicons-menu"></span>';
961 echo '<span class="merchant-metabox-field-uploads-remove dashicons dashicons-trash"></span>';
962 echo '</li>';
963 }
964
965 echo '</ul>';
966 echo '<button class="merchant-metabox-field-uploads-add button button-primary">' . esc_html( $field['button'] ) . '</button>';
967 echo '</div>';
968
969 break;
970
971 case 'size-chart':
972 $field = wp_parse_args( $field, array(
973 'button' => '',
974 ) );
975
976 echo '<div class="merchant-metabox-field-size-chart-content">';
977 echo '<ul>';
978 echo '<li class="hidden">';
979 echo '<table>';
980 echo '<thead>';
981 echo '<tr>';
982 echo '<td colspan="100%">';
983 echo '<label>';
984 echo '<strong>' . esc_html__( 'Chart Name', 'merchant' ) . ':</strong>';
985 echo '<input type="text" value="" data-name="' . esc_attr( $field_id ) . '[0][name]" />';
986 echo '</label>';
987 echo '</td>';
988 echo '</tr>';
989 echo '</thead>';
990 echo '<tbody>';
991 echo '<tr>';
992 for ( $a = 0; $a < 4; $a ++ ) {
993 echo '<td><div class="merchant-buttons"><a href="#" class="merchant-add-col">+</a><a href="#" class="merchant-del-col">-</a></div></td>';
994 }
995 echo '<td><a href="#" class="merchant-duplicate" title="' . esc_attr__( 'Duplicate', 'merchant' ) . '"><i class="dashicons dashicons-admin-page"></i></td>';
996 echo '</tr>';
997 for ( $b = 0; $b < 4; $b ++ ) {
998 echo '<tr>';
999 for ( $c = 0; $c < 4; $c ++ ) {
1000 echo '<td><input type="text" value="" data-name="' . esc_attr( $field_id ) . '[0][sizes][0][0]" /></td>';
1001 }
1002 echo '<td><div class="merchant-buttons"><a href="#" class="merchant-add-row">+</a><a href="#" class="merchant-del-row">-</a></div></td>';
1003 echo '</tr>';
1004 }
1005 echo '</tbody>';
1006 echo '<tfoot>';
1007 echo '<tr>';
1008 echo '<td colspan="100%">';
1009 echo '<a href="#" class="merchant-remove button button-primary">' . esc_html__( 'Remove', 'merchant' ) . '</a>';
1010 echo '</td>';
1011 echo '</tr>';
1012 echo '</tfoot>';
1013 echo '</table>';
1014 echo '</li>';
1015 $tabs = ( is_array( $value ) && ! empty( $value ) ) ? $value : array();
1016 if ( ! empty( $tabs ) ) {
1017 foreach ( $tabs as $tab_key => $tab ) {
1018 $name = ( ! empty( $tab['name'] ) ) ? $tab['name'] : '';
1019 $sizes = ( ! empty( $tab['sizes'] ) ) ? $tab['sizes'] : array();
1020 echo '<li>';
1021 echo '<table>';
1022 echo '<thead>';
1023 echo '<tr>';
1024 echo '<td colspan="100%">';
1025 echo '<label>';
1026 echo '<strong>' . esc_html__( 'Chart Name', 'merchant' ) . ':</strong>';
1027 echo '<input type="text" value="' . esc_attr( $name ) . '" name="' . esc_attr( $field_id . '[' . $tab_key . '][name]' ) . '" />';
1028 echo '</label>';
1029 echo '</td>';
1030 echo '</tr>';
1031 echo '</thead>';
1032 echo '<tbody>';
1033 foreach ( $sizes as $row_key => $rows ) {
1034 if ( 0 === $row_key ) {
1035 echo '<tr>';
1036 for ( $i = 0; $i < count( $rows ); $i ++ ) {
1037 echo '<td><div class="merchant-buttons"><a href="#" class="merchant-add-col">+</a><a href="#" class="merchant-del-col">-</a></div></td>';
1038 }
1039 echo '<td><a href="#" class="merchant-duplicate" title="' . esc_attr__( 'Duplicate', 'merchant' ) . '"><i class="dashicons dashicons-admin-page"></i></td>';
1040 echo '</tr>';
1041 }
1042 echo '<tr>';
1043 foreach ( $rows as $col_key => $col ) {
1044 echo '<td><input type="text" name="' . esc_attr( $field_id . '[' . $tab_key . '][sizes][' . $row_key . '][' . $col_key . ']' ) . '" value="' . esc_attr( $col ) . '" /></td>';
1045 }
1046 echo '<td><div class="merchant-buttons"><a href="#" class="merchant-add-row">+</a><a href="#" class="merchant-del-row">-</a></div></td>';
1047 echo '</tr>';
1048 }
1049 echo '</tbody>';
1050 echo '<tfoot>';
1051 echo '<tr>';
1052 echo '<td colspan="100%">';
1053 echo '<a href="#" class="merchant-remove button button-primary">' . esc_html__( 'Remove', 'merchant' ) . '</a>';
1054 echo '</td>';
1055 echo '</tr>';
1056 echo '</tfoot>';
1057 echo '</table>';
1058 echo '</li>';
1059 }
1060 }
1061 echo '</ul>';
1062 echo '<button class="merchant-add button button-primary">' . esc_html__( 'Add Size Chart', 'merchant' ) . '</button>';
1063 echo '</div>';
1064
1065 break;
1066
1067 case 'size-chart-select':
1068 $options = array();
1069 $posts = get_posts( array(
1070 'post_type' => 'merchant_size_chart',
1071 'posts_per_page' => - 1,
1072 'post_status' => 'publish',
1073 ) );
1074
1075 if ( ! is_wp_error( $posts ) && ! empty( $posts ) ) {
1076 foreach ( $posts as $_post ) {
1077 $options[ $_post->ID ] = $_post->post_title;
1078 }
1079 }
1080
1081 echo '<select name="' . esc_attr( $field_id ) . '">';
1082 echo '<option value="">' . esc_html__( 'Select a size chart', 'merchant' ) . '</option>';
1083
1084 foreach ( $options as $key => $option ) {
1085 echo '<option value="' . esc_attr( $key ) . '"' . selected( $key, $value, false ) . '>' . esc_html( $option ) . '</option>';
1086 }
1087 echo '</select>';
1088
1089 break;
1090
1091 case 'sidebar-select':
1092 global $wp_registered_sidebars;
1093
1094 $options = array();
1095 if ( ! empty( $wp_registered_sidebars ) ) {
1096 foreach ( $wp_registered_sidebars as $sidebar ) {
1097 $options[ $sidebar['id'] ] = $sidebar['name'];
1098 }
1099 }
1100
1101 echo '<select name="' . esc_attr( $field_id ) . '">';
1102 echo '<option value="">' . esc_html__( 'Default', 'merchant' ) . '</option>';
1103
1104 foreach ( $options as $key => $option ) {
1105 echo '<option value="' . esc_attr( $key ) . '"' . selected( $key, $value, false ) . '>' . esc_html( $option ) . '</option>';
1106 }
1107 echo '</select>';
1108
1109 break;
1110
1111 case 'wp-editor':
1112 $field = wp_parse_args( $field, array(
1113 'height' => 150,
1114 ) );
1115
1116 wp_editor( $value, $field_id, array(
1117 'editor_height' => $field['height'],
1118 ) );
1119
1120 break;
1121
1122 case 'code-editor':
1123 echo '<textarea name="' . esc_attr( $field_id ) . '">' . esc_textarea( $value ) . '</textarea>';
1124 break;
1125
1126 case 'coupons':
1127 $coupons = get_posts( array(
1128 'posts_per_page' => - 1,
1129 'orderby' => 'title',
1130 'order' => 'asc',
1131 'post_type' => 'shop_coupon',
1132 'post_status' => 'publish',
1133 ) );
1134 if ( $coupons ) {
1135 echo '<select name="' . esc_attr( $field_id ) . '">';
1136 echo '<option value="">' . esc_html__( 'Select a coupon', 'merchant' ) . '</option>';
1137
1138 foreach ( $coupons as $coupon ) {
1139 $coupon_code = strtolower( $coupon->post_title );
1140
1141 echo '<option value="' . esc_attr( $coupon_code ) . '"' . selected( esc_attr( $coupon_code ), $value, false ) . '>';
1142 echo esc_html( $coupon_code );
1143 echo '</option>';
1144 }
1145
1146 echo '</select>';
1147 echo '<a href="' . esc_url( admin_url( 'edit.php?post_type=shop_coupon' ) ) . '" target="_blank" style="margin-left: 10px;">' . esc_html__( 'Manage coupons',
1148 'merchant' ) . '</a>';
1149 } else {
1150 echo '<div style="color: red;">';
1151 echo wp_kses_post(
1152 sprintf(
1153 /* Translators: 1. Coupon admin url 2. Link target attribute value */
1154 __( 'No coupons found! <a href="%1$s" target="%2$s">Create a new coupon</a>', 'merchant' ),
1155 admin_url( 'post-new.php?post_type=shop_coupon' ),
1156 '_blank'
1157 )
1158 );
1159 echo '</div>';
1160 echo '<input type="hidden" name="' . esc_attr( $field_id ) . '" value="" />';
1161 }
1162 break;
1163
1164 case 'range':
1165 $min = isset( $field['min'] ) ? $field['min'] : 0;
1166 $max = isset( $field['max'] ) ? $field['max'] : 100;
1167 $step = isset( $field['step'] ) ? $field['step'] : 1;
1168 $unit = isset( $field['unit'] ) ? $field['unit'] : '';
1169 ?>
1170 <div class="merchant-range">
1171 <input type="range" class="merchant-range-input" min="<?php echo esc_attr( $min ); ?>" max="<?php echo esc_attr( $max ); ?>" step="<?php echo esc_attr( $step ); ?>" value="<?php echo esc_attr( $value ); ?>" />
1172 <input type="number" class="merchant-range-number-input" name="<?php echo esc_attr( $field_id ); ?>" min="<?php echo esc_attr( $min ); ?>" max="<?php echo esc_attr( $max ); ?>" step="<?php echo esc_attr( $step ); ?>" value="<?php echo esc_attr( $value ); ?>" />
1173 <?php if ( ! empty( $unit ) ) : ?>
1174 <span class="merchant-range-unit"><?php echo esc_html( $unit ); ?></span>
1175 <?php endif; ?>
1176 </div>
1177 <?php
1178 break;
1179 case 'flexible-content':
1180 $field = wp_parse_args( $field, array(
1181 'button' => '',
1182 ) );
1183 $values = ( is_array( $value ) && ! empty( $value ) ) ? $value : array();
1184
1185 $empty = empty( $values ) ? 'empty' : '';
1186
1187 echo '<ul data-id="' . esc_attr( $field_id ) . '" class="merchant-metabox-field-flexible-content-list ' . esc_attr( $empty ) . '">';
1188
1189 ob_start();
1190 echo '<li class="merchant-metabox-field-flexible-content-item">';
1191 foreach ( $field['layouts'] as $layout_type => $layout ) {
1192 echo '<div data-layout="' . esc_attr( $layout_type ) . '">';
1193 echo '<div class="merchant-metabox-field-flexible-content-item-header">';
1194 echo '<div class="merchant-metabox-field-flexible-content-item-count">0</div>';
1195 echo '<div class="merchant-metabox-field-flexible-content-item-title">' . esc_html( $layout['title'] ) . '</div>';
1196 echo '<div class="merchant-metabox-field-flexible-content-item-actions">';
1197 echo '<span class="merchant-metabox-field-flexible-content-move dashicons dashicons-menu"></span>';
1198 echo '<span class="merchant-metabox-field-flexible-content-remove dashicons dashicons-trash"></span>';
1199 echo '</div>';
1200 echo '</div>';
1201 echo '<div class="merchant-metabox-field-flexible-content-item-content">';
1202 foreach ( $layout['fields'] as $sub_field_key => $sub_field ) {
1203 $sub_field_classes = array( 'merchant-metabox-field-flexible-content-item-' . esc_attr( $sub_field['type'] ) );
1204 $sub_field_id = $field_id . '[0][' . $sub_field_key . ']';
1205 $sub_field_value = '';
1206 if ( $sub_field['type'] === 'select-ajax' ) {
1207 $sub_field_classes[] = 'merchant-metabox-field-flexible-content-select-ajax-clone';
1208 $sub_field_value = array();
1209 $sub_field = wp_parse_args( $sub_field, array(
1210 'source' => 'post',
1211 ) );
1212 }
1213 echo '<div class="' . esc_attr( implode( ' ', $sub_field_classes ) ) . '">';
1214 echo '<label>';
1215 echo esc_html( $sub_field['title'] );
1216 echo '</label>';
1217 echo '<div class="merchant-metabox-field-flexible-content-item-field" data-id="' . esc_attr( $sub_field_key ) . '">';
1218 $this->get_field( $sub_field_id, $sub_field, $sub_field_value );
1219 echo '</div>';
1220 echo '</div>';
1221 }
1222 echo '</div>';
1223 echo '<input type="hidden" name="' . esc_attr( $field_id ) . '[0][layout]" value="' . esc_attr( $layout_type ) . '">';
1224 echo '</div>';
1225 }
1226 echo '</li>';
1227 $sub_fields = ob_get_clean();
1228
1229 echo wp_kses( str_replace( 'name=', 'data-name=', $sub_fields ), merchant_kses_allowed_tags( array( 'all' ) ) );
1230
1231 foreach ( $values as $value_key => $value ) {
1232 echo '<li class="merchant-metabox-field-flexible-content-item">';
1233 echo '<div class="merchant-metabox-field-flexible-content-item-header">';
1234 echo '<div class="merchant-metabox-field-flexible-content-item-count">' . esc_html( ( $value_key + 1 ) ) . '</div>';
1235 echo '<div class="merchant-metabox-field-flexible-content-item-title">' . esc_html( $field['layouts'][ $value['layout'] ]['title'] ) . '</div>';
1236 echo '<div class="merchant-metabox-field-flexible-content-item-actions">';
1237 echo '<span class="merchant-metabox-field-flexible-content-move dashicons dashicons-menu"></span>';
1238 echo '<span class="merchant-metabox-field-flexible-content-remove dashicons dashicons-trash"></span>';
1239 echo '</div>';
1240 echo '</div>';
1241 echo '<div class="merchant-metabox-field-flexible-content-item-content">';
1242 foreach ( $field['layouts'][ $value['layout'] ]['fields'] as $sub_field_key => $sub_field ) {
1243 $sub_field_classes = array( 'merchant-metabox-field-flexible-content-' . esc_attr( $sub_field['type'] ) );
1244 $sub_field_id = $field_id . '[' . $value_key . '][' . $sub_field_key . ']';
1245 $sub_field_value = isset( $value[ $sub_field_key ] ) ? $value[ $sub_field_key ] : '';
1246 if ( $sub_field['type'] === 'select-ajax' ) {
1247 $sub_field_classes[] = 'merchant-metabox-field-flexible-content-select-ajax';
1248 $sub_field_value = empty( $sub_field_value ) ? array() : $sub_field_value;
1249 $sub_field = wp_parse_args( $sub_field, array(
1250 'source' => 'post',
1251 ) );
1252 }
1253 echo '<div class="' . esc_attr( implode( ' ', $sub_field_classes ) ) . '">';
1254 echo '<label>';
1255 echo esc_html( $sub_field['title'] );
1256 echo '</label>';
1257 echo '<div class="merchant-metabox-field-flexible-content-' . esc_attr( $sub_field['type'] ) . '-field" data-id="' . esc_attr( $sub_field_key ) . '">';
1258 $this->get_field( $sub_field_id, $sub_field, $sub_field_value );
1259 echo '</div>';
1260 echo '</div>';
1261 }
1262 echo '</div>';
1263 echo '<input type="hidden" name="' . esc_attr( $field_id ) . '[' . esc_attr( $value_key ) . '][layout]" value="' . esc_attr( $value['layout'] ) . '">';
1264 echo '</li>';
1265 }
1266
1267 echo '</ul>';
1268 echo '<div class="merchant-metabox-field-flexible-content-add-wrapper">';
1269 echo '<div class="merchant-metabox-field-flexible-content-add-list">';
1270 foreach ( $field['layouts'] as $layout_type => $layout ) {
1271 echo '<a class="merchant-metabox-field-flexible-content-add" data-id="' . esc_attr( $field_id ) . '" data-layout="' . esc_attr( $layout_type ) . '" href="#">' . esc_html( $layout['title'] ) . '</a>';
1272 }
1273 echo '</div>';
1274 echo '<button class="merchant-metabox-field-flexible-content-add-button button button-primary">' . esc_html( $field['button'] ) . '</button>';
1275 echo '</div>';
1276
1277 break;
1278 }
1279 }
1280
1281 /**
1282 * Evaluate if a field should be hidden based on conditions.
1283 *
1284 * @param array $conditions Conditions array with 'relation' and 'terms'.
1285 * @param int $post_id Post ID.
1286 * @return bool True if field should be hidden, false otherwise.
1287 */
1288 private function should_hide_field( $conditions, $post_id ) {
1289 if ( empty( $conditions['terms'] ) || ! is_array( $conditions['terms'] ) ) {
1290 return false;
1291 }
1292
1293 $operator = isset( $conditions['relation'] ) ? $conditions['relation'] : 'AND';
1294 $results = array();
1295
1296 foreach ( $conditions['terms'] as $term ) {
1297 if ( ! is_array( $term ) || count( $term ) < 3 ) {
1298 continue;
1299 }
1300
1301 $field_name = $term[0];
1302 $comparison = $term[1];
1303 $target_value = $term[2];
1304
1305 // Get the actual field value from post meta
1306 $meta_value = get_post_meta( $post_id, $field_name, true );
1307
1308 $passed = false;
1309
1310 // Cast to strings to ensure consistent comparison with JavaScript.
1311 // Switcher values are saved as integers (1/0) but conditions check against strings ('1'/'0').
1312 $meta_value_str = is_array( $meta_value ) ? $meta_value : (string) $meta_value;
1313 $target_value_str = (string) $target_value;
1314
1315 // Evaluate condition based on comparison operator
1316 switch ( $comparison ) {
1317 case '==':
1318 if ( is_array( $meta_value_str ) ) {
1319 $passed = in_array( $target_value_str, array_map( 'strval', $meta_value_str ), true );
1320 } else {
1321 $passed = $meta_value_str === $target_value_str;
1322 }
1323 break;
1324 case '!=':
1325 if ( is_array( $meta_value_str ) ) {
1326 $passed = ! in_array( $target_value_str, array_map( 'strval', $meta_value_str ), true );
1327 } else {
1328 $passed = $meta_value_str !== $target_value_str;
1329 }
1330 break;
1331 case 'any':
1332 $allowed_values = explode( '|', $target_value_str );
1333 if ( is_array( $meta_value_str ) ) {
1334 $passed = count( array_intersect( array_map( 'strval', $meta_value_str ), $allowed_values ) ) > 0;
1335 } else {
1336 $passed = in_array( $meta_value_str, $allowed_values, true );
1337 }
1338 break;
1339 case 'not_any':
1340 $disallowed_values = explode( '|', $target_value_str );
1341 if ( is_array( $meta_value_str ) ) {
1342 $passed = count( array_intersect( array_map( 'strval', $meta_value_str ), $disallowed_values ) ) === 0;
1343 } else {
1344 $passed = ! in_array( $meta_value_str, $disallowed_values, true );
1345 }
1346 break;
1347 }
1348
1349 $results[] = $passed;
1350 }
1351
1352 // Combine results based on operator
1353 if ( $operator === 'OR' ) {
1354 // For OR, at least one must be true (if all false, hide)
1355 return ! in_array( true, $results, true );
1356 } else {
1357 // For AND, all must be true (if any false, hide)
1358 return in_array( false, $results, true );
1359 }
1360 }
1361 }
1362 }
1363