PluginProbe
Listdom: AI-powered Business Directory with Classifieds Ads Listings / trunk
Listdom: AI-powered Business Directory with Classifieds Ads Listings vtrunk
6.0.0 5.9.0 5.8.1 5.8.0 5.7.0 5.6.0 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.2.0 1.2.1 1.3.0 1.3.1 1.4.0 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.8.0 1.9.0 All 75 releases
listdom / app / includes / fields.php

fields.php in Listdom: AI-powered Business Directory with Classifieds Ads Listings trunk, at app/includes/fields.php

714 lines 25.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class LSD_Fields extends LSD_Base
4 {
5 public const ATTRIBUTE_KEY_PREFIX = 'attr-';
6
7 public static function attribute_key($slug): string
8 {
9 $slug = sanitize_title((string) $slug);
10 return $slug === '' ? '' : self::ATTRIBUTE_KEY_PREFIX . $slug;
11 }
12
13 public static function attribute_slug_from_key($key): string
14 {
15 $key = (string) $key;
16
17 if (strpos($key, self::ATTRIBUTE_KEY_PREFIX) !== 0) return '';
18
19 return sanitize_title(substr($key, strlen(self::ATTRIBUTE_KEY_PREFIX)));
20 }
21
22 public static function attribute_id_from_key($key): int
23 {
24 if (is_numeric($key))
25 {
26 $term = get_term((int) $key, LSD_Base::TAX_ATTRIBUTE);
27 return $term && !is_wp_error($term) && isset($term->term_id) ? (int) $term->term_id : 0;
28 }
29
30 $slug = self::attribute_slug_from_key($key);
31 if ($slug === '') return 0;
32
33 $term = get_term_by('slug', $slug, LSD_Base::TAX_ATTRIBUTE);
34 return $term && !is_wp_error($term) && isset($term->term_id) ? (int) $term->term_id : 0;
35 }
36
37 public function titles(array $fields = []): array
38 {
39 if (empty($fields)) $fields = $this->get();
40
41 $titles = [];
42 foreach ($fields as $key => $field)
43 {
44 if (isset($field['label']))
45 {
46 $titles[$key] = $field['label'];
47 }
48 }
49
50 return $titles;
51 }
52
53 public function get()
54 {
55 $fields = [
56 'title' => ['label' => esc_html__('Listing Title', 'listdom'), 'enabled' => 1],
57 'excerpt' => ['label' => esc_html__('Listing Excerpt', 'listdom'), 'enabled' => 0],
58 'address' => ['label' => esc_html__('Address', 'listdom'), 'enabled' => 1],
59 'price' => ['label' => esc_html__('Price', 'listdom'), 'enabled' => 1],
60 'availability' => ['label' => esc_html__('Work Hours', 'listdom'), 'enabled' => 1],
61 'phone' => ['label' => esc_html__('Phone', 'listdom'), 'enabled' => 1],
62 'email' => ['label' => esc_html__('Email', 'listdom'), 'enabled' => 0],
63 'labels' => ['label' => esc_html(lsd_t_label(LSD_Base::TAX_LABEL, 'plural')), 'enabled' => 0],
64 'website' => ['label' => esc_html__('Website', 'listdom'), 'enabled' => 0],
65 'image' => ['label' => esc_html__('Featured Image', 'listdom'), 'enabled' => 0],
66 'description' => ['label' => esc_html__('Listing Description', 'listdom'), 'enabled' => 0],
67 'remark' => ['label' => esc_html__('Remark', 'listdom'), 'enabled' => 0],
68 'price_class' => ['label' => esc_html__('Price Class', 'listdom'), 'enabled' => 0],
69 'contact' => ['label' => esc_html__('Contact Address', 'listdom'), 'enabled' => 0],
70 'cta' => ['label' => esc_html__('Call to Action', 'listdom'), 'enabled' => 0],
71 'category' => ['label' => esc_html(lsd_t_label(LSD_Base::TAX_CATEGORY)), 'enabled' => 0],
72 'tags' => ['label' => esc_html(lsd_t_label(LSD_Base::TAX_TAG, 'plural')), 'enabled' => 0],
73 'locations' => ['label' => esc_html(lsd_t_label(LSD_Base::TAX_LOCATION, 'plural')), 'enabled' => 0],
74 'features' => ['label' => esc_html(lsd_t_label(LSD_Base::TAX_FEATURE, 'plural')), 'enabled' => 0],
75 'map' => ['label' => esc_html__('Map', 'listdom'), 'enabled' => 0],
76 ];
77
78 if (!LSD_Components::pricing()) unset($fields['price'], $fields['price_class']);
79 if (!LSD_Components::cta()) unset($fields['cta']);
80 if (!LSD_Components::work_hours()) unset($fields['availability']);
81 if (!LSD_Components::map()) unset($fields['address'], $fields['map']);
82
83 // Conditionally include or exclude fields based on specific class existence
84 if (class_exists(LSDADDREV::class) || class_exists(\LSDPACREV\Base::class)) $fields['review_stars'] = ['label' => esc_html__('Review Rates', 'listdom'), 'enabled' => 0];
85 if (class_exists(\LSDPACCMP\Base::class)) $fields['compare'] = ['label' => esc_html__('Compare', 'listdom'), 'enabled' => 0];
86 if (class_exists(\LSDPACFAV\Base::class)) $fields['favorite'] = ['label' => esc_html__('Favorite', 'listdom'), 'enabled' => 0];
87 if (class_exists(\LSDPACCLM\Base::class)) $fields['claim'] = ['label' => esc_html__('Claim', 'listdom'), 'enabled' => 0];
88
89 $SN = new LSD_Socials();
90 $networks = LSD_Options::socials();
91
92 foreach ($networks as $network => $values)
93 {
94 $obj = $SN->get($network, $values);
95 $fields['sn_' . $obj->key()] = ['label' => $obj->label(), 'enabled' => 0];
96 }
97
98 $attributes = LSD_Main::get_attributes();
99 if (is_array($attributes) && !empty($attributes))
100 {
101 foreach ($attributes as $attribute)
102 {
103 $type = get_term_meta($attribute->term_id, 'lsd_field_type', true);
104 if ($type == 'separator') continue;
105
106 $slug = isset($attribute->slug) ? sanitize_title($attribute->slug) : '';
107 $key = self::attribute_key($slug);
108 if ($key === '') continue;
109
110 $fields[$key] = [
111 'label' => $attribute->name,
112 'enabled' => 0,
113 'attribute_id' => (int) $attribute->term_id,
114 'attribute_slug' => $slug,
115 'legacy_key' => (string) $attribute->term_id,
116 ];
117 }
118 }
119
120 // Fetch ACF Field Groups
121 if (function_exists('acf_get_field_groups') && (class_exists(LSDADDACF::class) || class_exists(\LSDPACACF\Base::class)))
122 {
123 $field_groups = acf_get_field_groups([
124 'post_type' => LSD_Base::PTYPE_LISTING,
125 'post_status' => 'publish',
126 ]);
127
128 foreach ($field_groups as $acf_group)
129 {
130 $acf_fields = acf_get_fields($acf_group['key']);
131 if ($acf_fields)
132 {
133 foreach ($acf_fields as $acf_field)
134 {
135 $fields['acf_' . $acf_field['name']] = [
136 'label' => $acf_field['label'],
137 'enabled' => 0,
138 ];
139 }
140 }
141 }
142 }
143
144 return apply_filters('lsd_dashboard_fields', $fields);
145 }
146
147 public function content($key, LSD_Entity_Listing $listing, $skin)
148 {
149 $output = '';
150 $attribute_id = self::attribute_id_from_key($key);
151
152 if ($attribute_id > 0)
153 {
154 $att = new LSD_Entity_Attribute($attribute_id);
155 return LSD_Kses::element($att->render($att->value($listing->id())));
156 }
157
158 switch ($key)
159 {
160 case 'title':
161 $output = '<h3 class="lsd-listing-title" ' . lsd_schema()->name() . '>' .
162 LSD_Kses::element($skin->get_title_tag($listing)) .
163 '</h3>';
164 break;
165
166 case 'address':
167 $output = LSD_Kses::element($listing->get_address(false));
168 break;
169
170 case 'excerpt':
171 $output = LSD_Kses::element($listing->get_excerpt());
172 break;
173
174 case 'remark':
175 $output = LSD_Kses::element($listing->get_remark());
176 break;
177
178 case 'labels':
179 $output = LSD_Kses::element($listing->get_labels());
180 break;
181
182 case 'price':
183 if (LSD_Components::pricing()) $output = LSD_Kses::element($listing->get_price());
184 break;
185
186 case 'email':
187 $output = LSD_Kses::element($listing->get_email());
188 break;
189
190 case 'website':
191 $output = get_post_meta($listing->id(), 'lsd_' . $key, true);
192 break;
193
194 case 'price_class':
195 if (LSD_Components::pricing()) $output = LSD_Kses::element($listing->get_price_class());
196 break;
197
198 case 'image':
199 $output = LSD_Kses::element($listing->get_cover_image([390, 260], $skin->get_listing_link_method(), $skin->get_single_listing_style()));
200 break;
201
202 case 'phone':
203 $output = LSD_Kses::element($listing->get_phone());
204 break;
205
206 case 'availability':
207 if (LSD_Components::work_hours()) $output = LSD_Kses::element($listing->get_availability(true));
208 break;
209
210 case 'locations':
211 $output = LSD_Kses::element($listing->get_locations());
212 break;
213
214 case 'category':
215 $output = LSD_Kses::element($listing->get_categories(['show_color' => true, 'multiple_categories' => true]));
216 break;
217
218 case 'tags':
219 $output = LSD_Kses::element($listing->get_tags());
220 break;
221
222 case 'contact':
223 $output = get_post_meta($listing->id(), 'lsd_contact_address', true);
224 break;
225
226 case 'description':
227 $output = LSD_Kses::element($listing->get_excerpt(50));
228 break;
229
230 case 'cta':
231 if (LSD_Components::cta()) $output = '<div class="lsd-listing-cta lsd-cta-align-left">' . LSD_Kses::element($listing->get_cta('table')) . '</div>';
232 break;
233
234 case 'features':
235 $output = LSD_Kses::element($listing->get_features());
236 break;
237
238 case 'review_stars':
239 $output = LSD_Kses::element($listing->get_rate_stars());
240 break;
241
242 case 'compare':
243 $output = LSD_Kses::element($listing->get_compare_button());
244 break;
245
246 case 'claim':
247 $output = $listing->is_claimed()
248 ? '<span class="lsd-tooltip" data-lsd-tooltip="' . esc_attr__('Verified', 'listdom') . '"><i class="lsd-fe-icon fas fa-check-circle lsd-claimed-icon"></i></span>'
249 : LSD_Kses::element($listing->get_claim_button());
250 break;
251
252 case 'favorite':
253 $output = LSD_Kses::element($listing->get_favorite_button());
254 break;
255
256 case 'map':
257 $output = LSD_Kses::element($listing->get_map());
258 break;
259
260 case substr($key, 0, 3) === 'sn_':
261 $key_without_prefix = substr($key, 3);
262 $value = $listing->get_meta('lsd_' . $key_without_prefix);
263
264 if (!empty($value)) $output = '<a href="' . esc_url($value) . '" target="_blank"><i class="lsd-fe-icon fab fa-' . $key_without_prefix . '"></i></a>';
265 break;
266
267 case substr($key, 0, 4) === 'acf_':
268 $key_without_prefix = substr($key, 4);
269 $listing_id = $listing->id();
270
271 $field = acf_get_field($key_without_prefix);
272 $type = $field['type'] ?? '';
273
274 if (in_array($type, ['tab', 'accordion', 'message'])) break;
275
276 $output = self::acf(get_field_object($field['key'], $listing_id), $listing_id);
277 if (!is_string($output)) $output = is_scalar($output) ? (string) $output : '';
278 break;
279 }
280
281 return $output;
282 }
283
284 public function schema($key)
285 {
286 $output = '';
287 $attribute_id = self::attribute_id_from_key($key);
288
289 if ($attribute_id > 0) return LSD_Entity_Attribute::schema($attribute_id);
290
291 switch ($key)
292 {
293 case 'title':
294 $output = lsd_schema()->name();
295 break;
296
297 case 'address':
298 $output = lsd_schema()->address();
299 break;
300
301 case 'price':
302 if (LSD_Components::pricing()) $output = lsd_schema()->priceRange();
303 break;
304
305 case 'phone':
306 $output = lsd_schema()->telephone();
307 break;
308
309 case 'category':
310 $output = lsd_schema()->category();
311 break;
312
313 case 'excerpt':
314 case 'description':
315 $output = lsd_schema()->description();
316 break;
317
318 default:
319 $normalized = strtolower(trim((string) $key));
320 $normalized = preg_replace('/([a-z])([A-Z])/', '$1_$2', $normalized);
321 $normalized = preg_replace('/[\s\-]+/', '_', $normalized);
322 $normalized = preg_replace('/_+/', '_', $normalized);
323
324 $simplified = str_replace('_', '', $normalized);
325
326 $map = [
327 'website' => 'url',
328 'web' => 'url',
329 'site' => 'url',
330 'link' => 'url',
331 'socials' => 'sameAs',
332 'social_links' => 'sameAs',
333 'sociallinks' => 'sameAs',
334 'email' => 'email',
335 'fax' => 'faxNumber',
336 'opening_hours' => 'openingHours',
337 'openinghours' => 'openingHours',
338 ];
339
340 if (isset($map[$normalized])) $output = lsd_schema()->prop($map[$normalized]);
341 else if (isset($map[$simplified])) $output = lsd_schema()->prop($map[$simplified]);
342 break;
343 }
344
345 return $output;
346 }
347
348 public static function acf($field, $listing_id)
349 {
350 if (!is_array($field)) return '';
351
352 $type = $field['type'] ?? null;
353 $label = $field['label'] ?? null;
354 $value = $field['value'] ?? null;
355
356 if ($type === 'image')
357 {
358 if (is_array($value))
359 {
360 $title = isset($value['title']) && trim($value['title']) ? $value['title'] : $label;
361 $thumbnail = $value['sizes']['thumbnail'] ?? ($value['url'] ?? '');
362 $url = $value['url'] ?? '';
363
364 if ($thumbnail && $url) return '<a href="' . esc_url($url) . '"><img src="' . esc_url($thumbnail) . '" alt="' . esc_attr($title) . '"></a>';
365 else if ($thumbnail) return '<img src="' . esc_url($thumbnail) . '" alt="' . esc_attr($title) . '">';
366
367 return '';
368 }
369 else if (is_numeric($value))
370 {
371 $image = wp_get_attachment_image_url($value);
372 return $image ? '<img src="' . esc_url($image) . '" alt="">' : '';
373 }
374
375 return $value ? '<img src="' . esc_url($value) . '" alt="">' : '';
376 }
377 else if ($type === 'gallery' && is_array($value))
378 {
379 $output = '';
380
381 foreach ($value as $image)
382 {
383 $rendered = self::acf([
384 'type' => 'image',
385 'label' => $label,
386 'value' => $image,
387 ], $listing_id);
388
389 if (trim($rendered) !== '') $output .= '<span class="lsd-acf-gallery-item">' . $rendered . '</span>';
390 }
391
392 return $output ? '<div class="lsd-acf-gallery">' . $output . '</div>' : '';
393 }
394 else if ($type === 'checkbox' && is_array($value))
395 {
396 $items = [];
397
398 foreach ($value as $item)
399 {
400 $rendered = self::acf_choice_value($item);
401 if ($rendered !== '') $items[] = $rendered;
402 }
403
404 return implode(', ', $items);
405 }
406 else if (in_array($type, ['select', 'radio', 'button_group'], true) && is_array($value))
407 {
408 if (self::acf_is_choice_array($value))
409 {
410 return self::acf_choice_value($value);
411 }
412
413 $items = [];
414
415 foreach ($value as $item)
416 {
417 $rendered = self::acf_choice_value($item);
418 if ($rendered !== '') $items[] = $rendered;
419 }
420
421 return implode(', ', $items);
422 }
423 else if ($type === 'file' && is_array($value))
424 {
425 $url = $value['url'] ?? '';
426 if (!$url) return '';
427
428 $title = isset($value['title']) && trim($value['title']) ? $value['title'] : $url;
429 return '<a href="' . esc_url($url) . '">' . esc_html($title) . '</a>';
430 }
431 else if ($type === 'link' && is_array($value))
432 {
433 $url = $value['url'] ?? '';
434 if (!$url) return '';
435
436 $title = isset($value['title']) && trim($value['title']) ? $value['title'] : $url;
437 return '<a href="' . esc_url($url) . '">' . esc_html($title) . '</a>';
438 }
439 else if (in_array($type, ['post_object', 'page_link', 'relationship'], true))
440 {
441 if (is_array($value))
442 {
443 $items = [];
444
445 foreach ($value as $item)
446 {
447 $rendered = self::acf_linked_post_value($item);
448 if ($rendered) $items[] = $rendered;
449 }
450
451 return implode(', ', $items);
452 }
453
454 return self::acf_linked_post_value($value);
455 }
456 else if ($type === 'taxonomy')
457 {
458 if (is_array($value))
459 {
460 $items = [];
461
462 foreach ($value as $term)
463 {
464 $rendered = self::acf_term_value($term);
465 if ($rendered) $items[] = $rendered;
466 }
467
468 return implode(', ', $items);
469 }
470
471 return self::acf_term_value($value);
472 }
473 else if ($type === 'user')
474 {
475 if (is_array($value) && isset($value['display_name'])) return $value['display_name'];
476 else if (is_array($value))
477 {
478 $items = [];
479
480 foreach ($value as $user)
481 {
482 $rendered = self::acf_user_value($user);
483 if ($rendered) $items[] = $rendered;
484 }
485
486 return implode(', ', $items);
487 }
488
489 return self::acf_user_value($value);
490 }
491 else if ($type === 'google_map' && is_array($value))
492 {
493 $parts = [];
494
495 if (isset($value['address']) && trim($value['address']) !== '') $parts[] = $value['address'];
496 else
497 {
498 $lat = $value['lat'] ?? null;
499 $lng = $value['lng'] ?? null;
500
501 if ($lat !== null && $lng !== null) $parts[] = $lat . ', ' . $lng;
502 }
503
504 return implode(' ', $parts);
505 }
506 else if ($type === 'group')
507 {
508 return is_array($value)
509 ? self::acf_compound_rows($field['sub_fields'] ?? [], $value, $listing_id)
510 : '';
511 }
512 else if ($type === 'repeater')
513 {
514 return is_array($value)
515 ? self::acf_repeater_rows($field['sub_fields'] ?? [], $value, $listing_id, $label)
516 : '';
517 }
518 else if ($type === 'flexible_content' && is_array($value))
519 {
520 $output = '';
521
522 foreach ($value as $index => $row)
523 {
524 if (!is_array($row)) continue;
525
526 $layout_name = $row['acf_fc_layout'] ?? '';
527 $layout = null;
528
529 if (isset($field['layouts']) && is_array($field['layouts']))
530 {
531 foreach ($field['layouts'] as $candidate)
532 {
533 if (($candidate['name'] ?? '') === $layout_name)
534 {
535 $layout = $candidate;
536 break;
537 }
538 }
539 }
540
541 $sub_fields = $layout['sub_fields'] ?? [];
542 $rendered = self::acf_compound_rows($sub_fields, $row, $listing_id);
543
544 if (trim($rendered) === '') continue;
545
546 $layout_label = $layout['label'] ?? sprintf(esc_html__('Row %d', 'listdom'), $index + 1);
547 $output .= '<div class="lsd-acf-flexible-layout"><h6>' . esc_html($layout_label) . '</h6>' . $rendered . '</div>';
548 }
549
550 return $output ? '<div class="lsd-acf-flexible-content">' . $output . '</div>' : '';
551 }
552 else if ($type === 'clone')
553 {
554 if (isset($field['sub_fields']) && is_array($field['sub_fields']) && is_array($value))
555 {
556 return self::acf_compound_rows($field['sub_fields'], $value, $listing_id);
557 }
558
559 return '';
560 }
561 else if (in_array($type, ['gallery', 'flexible_content'], true))
562 {
563 return '';
564 }
565 else if ($type === 'icon_picker')
566 {
567 $icon = get_field($field['name'], $listing_id);
568
569 if (filter_var($icon, FILTER_VALIDATE_URL)) return '<img alt="" src="'.esc_url($icon).'">';
570 else return '<span class="dashicons '.sanitize_html_class($icon).'"></span>';
571 }
572 else if ($type === 'true_false')
573 {
574 return $value ? esc_html__('Yes', 'listdom') : esc_html__('No', 'listdom');
575 }
576 else if (!is_array($value))
577 {
578 $value = trim((string) $value) ? $value : '';
579 if (trim($value) === '') $value = get_post_meta($listing_id, $field['name'], true);
580
581 return $value;
582 }
583
584 return self::acf_fallback_value($value);
585 }
586
587 protected static function acf_compound_rows(array $sub_fields, array $values, $listing_id)
588 {
589 $output = '';
590
591 foreach ($sub_fields as $sub_field)
592 {
593 $type = $sub_field['type'] ?? '';
594 $name = $sub_field['name'] ?? '';
595 $sub_label = $sub_field['label'] ?? '';
596
597 if (in_array($type, ['tab', 'accordion', 'message'], true) || !$name) continue;
598
599 $sub_field['value'] = $values[$name] ?? null;
600 $rendered = self::acf($sub_field, $listing_id);
601
602 if (trim($rendered) === '') continue;
603
604 $output .= '<div class="lsd-acf-sub-field lsd-acf-sub-field-' . sanitize_html_class($type) . '">';
605 if ($sub_label) $output .= '<span class="lsd-attr-key">' . esc_html($sub_label) . ': </span>';
606 $output .= '<span class="lsd-attr-value">' . esc_html($rendered) . '</span>';
607 $output .= '</div>';
608 }
609
610 return $output ? '<div class="lsd-acf-compound">' . $output . '</div>' : '';
611 }
612
613 protected static function acf_repeater_rows(array $sub_fields, array $rows, $listing_id, $label = '')
614 {
615 if (!count($rows)) return '';
616
617 $output = '';
618
619 foreach ($rows as $index => $row)
620 {
621 if (!is_array($row)) continue;
622
623 $rendered = self::acf_compound_rows($sub_fields, $row, $listing_id);
624 if (trim($rendered) === '') continue;
625
626 $row_label = sprintf(esc_html__('Row %d', 'listdom'), $index + 1);
627 $output .= '<div class="lsd-acf-repeater-row"><h6>' . esc_html($row_label) . '</h6>' . $rendered . '</div>';
628 }
629
630 return $output ? '<div class="lsd-acf-repeater">' . $output . '</div>' : '';
631 }
632
633 protected static function acf_linked_post_value($value)
634 {
635 if (is_string($value) && filter_var($value, FILTER_VALIDATE_URL))
636 {
637 return '<a href="' . esc_url($value) . '">' . esc_html($value) . '</a>';
638 }
639
640 $ID = is_object($value) ? ($value->ID ?? 0) : $value;
641 $ID = absint($ID);
642
643 if (!$ID) return '';
644
645 return '<a href="' . esc_url(get_permalink($ID)) . '">' . esc_html(get_the_title($ID)) . '</a>';
646 }
647
648 protected static function acf_term_value($value)
649 {
650 if (is_object($value) && isset($value->name)) return $value->name;
651
652 $term = get_term($value);
653 return $term && !is_wp_error($term) ? $term->name : '';
654 }
655
656 protected static function acf_user_value($value)
657 {
658 if (is_object($value) && isset($value->display_name)) return $value->display_name;
659
660 $user = get_user_by('id', absint($value));
661 return $user ? $user->display_name : '';
662 }
663
664 protected static function acf_fallback_value($value)
665 {
666 if (is_scalar($value))
667 {
668 $value = (string) $value;
669 return trim($value) !== '' ? esc_html($value) : '';
670 }
671
672 if (!is_array($value) || !count($value)) return '';
673
674 $items = [];
675
676 foreach ($value as $item)
677 {
678 $rendered = self::acf_fallback_value($item);
679 if ($rendered !== '') $items[] = $rendered;
680 }
681
682 return count($items) ? implode(', ', $items) : '';
683 }
684
685 protected static function acf_choice_value($value)
686 {
687 if (is_scalar($value))
688 {
689 $value = (string) $value;
690 return trim($value) !== '' ? esc_html($value) : '';
691 }
692
693 if (!is_array($value)) return '';
694
695 if (isset($value['label']) && trim((string) $value['label']) !== '')
696 {
697 return esc_html($value['label']);
698 }
699
700 if (isset($value['value']) && !is_array($value['value']))
701 {
702 $choice = (string) $value['value'];
703 return trim($choice) !== '' ? esc_html($choice) : '';
704 }
705
706 return self::acf_fallback_value($value);
707 }
708
709 protected static function acf_is_choice_array(array $value): bool
710 {
711 return array_key_exists('label', $value) || array_key_exists('value', $value);
712 }
713 }
714