PluginProbe ʕ •ᴥ•ʔ
WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More / 1.9.9.4
WPForms – Easy Form Builder for WordPress – Contact Forms, Payment Forms, Surveys, & More v1.9.9.4
1.10.1.1 1.10.1 1.10.0.5 trunk 1.1.4 1.1.4.2 1.1.5 1.1.5.1 1.1.6 1.1.6.1 1.1.7 1.1.7.1 1.1.7.2 1.1.8 1.1.8.1 1.1.8.2 1.1.8.3 1.1.8.4 1.10.0.1 1.10.0.2 1.10.0.3 1.10.0.4 1.2.0 1.2.0.1 1.2.1 1.2.2 1.2.2.1 1.2.2.2 1.2.3 1.2.3.1 1.2.3.2 1.2.4 1.2.4.1 1.2.5 1.2.5.1 1.2.6 1.2.7 1.2.8 1.2.8.1 1.2.9 1.3.0 1.3.1 1.3.1.1 1.3.1.2 1.3.2 1.3.3 1.3.5 1.3.6 1.3.6.1 1.3.6.2 1.3.7.2 1.3.7.3 1.3.7.4 1.3.8 1.3.9.1 1.4.0.1 1.4.1.1 1.4.2 1.4.2.1 1.4.2.2 1.4.3 1.4.4 1.4.4.1 1.4.5 1.4.5.1 1.4.5.2 1.4.5.3 1.4.6 1.4.7.1 1.4.7.2 1.4.8.1 1.4.9 1.5.0.1 1.5.0.3 1.5.0.4 1.5.1 1.5.1.1 1.5.1.3 1.5.2.1 1.5.2.2 1.5.2.3 1.5.3 1.5.3.1 1.5.4.1 1.5.4.2 1.5.5 1.5.5.1 1.5.6 1.5.6.2 1.5.7 1.5.8.2 1.5.9.1 1.5.9.4 1.5.9.5 1.6.0.1 1.6.0.2 1.6.1 1.6.2.2 1.6.2.3 1.6.3.1 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.7 1.6.7.1 1.6.7.2 1.6.7.3 1.6.8 1.6.8.1 1.6.9 1.7.0 1.7.1.1 1.7.1.2 1.7.2 1.7.2.1 1.7.3 1.7.4 1.7.4.1 1.7.4.2 1.7.5.1 1.7.5.2 1.7.5.3 1.7.5.5 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.7.9.1 1.8.0.1 1.8.0.2 1.8.1.1 1.8.1.2 1.8.1.3 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.3.1 1.8.4 1.8.4.1 1.8.5.2 1.8.5.3 1.8.5.4 1.8.6.2 1.8.6.3 1.8.6.4 1.8.7.2 1.8.8.2 1.8.8.3 1.8.9.1 1.8.9.2 1.8.9.4 1.8.9.5 1.8.9.6 1.9.0.1 1.9.0.2 1.9.0.3 1.9.0.4 1.9.1.1 1.9.1.2 1.9.1.3 1.9.1.4 1.9.1.5 1.9.1.6 1.9.2.1 1.9.2.2 1.9.2.3 1.9.3.1 1.9.3.2 1.9.4.1 1.9.4.2 1.9.5 1.9.5.1 1.9.5.2 1.9.6 1.9.6.1 1.9.6.2 1.9.7.1 1.9.7.2 1.9.7.3 1.9.8.1 1.9.8.2 1.9.8.4 1.9.8.7 1.9.9.2 1.9.9.3 1.9.9.4
wpforms-lite / includes / fields / class-select.php
wpforms-lite / includes / fields Last commit date
class-base.php 4 months ago class-checkbox.php 6 months ago class-email.php 8 months ago class-gdpr-checkbox.php 8 months ago class-internal-information.php 10 months ago class-name.php 10 months ago class-number-slider.php 1 year ago class-number.php 1 year ago class-radio.php 6 months ago class-select.php 5 months ago class-text.php 1 year ago class-textarea.php 1 year ago
class-select.php
796 lines
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 // phpcs:disable Generic.Commenting.DocComment.MissingShort
8 /** @noinspection PhpIllegalPsrClassPathInspection */
9 /** @noinspection AutoloadingIssuesInspection */
10 // phpcs:enable Generic.Commenting.DocComment.MissingShort
11
12 /**
13 * Dropdown field.
14 *
15 * @since 1.0.0
16 */
17 class WPForms_Field_Select extends WPForms_Field {
18
19 /**
20 * The 'Choices JS' version.
21 *
22 * @since 1.6.3
23 */
24 public const CHOICES_VERSION = '10.2.0';
25
26 /**
27 * Classic (old) style.
28 *
29 * @since 1.6.1
30 *
31 * @var string
32 */
33 public const STYLE_CLASSIC = 'classic';
34
35 /**
36 * Modern style.
37 *
38 * @since 1.6.1
39 *
40 * @var string
41 */
42 public const STYLE_MODERN = 'modern';
43
44 /**
45 * Primary class constructor.
46 *
47 * @since 1.0.0
48 */
49 public function init() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
50
51 // Define field type information.
52 $this->name = esc_html__( 'Dropdown', 'wpforms-lite' );
53 $this->keywords = esc_html__( 'choice', 'wpforms-lite' );
54 $this->type = 'select';
55 $this->icon = 'fa-caret-square-o-down';
56 $this->order = 70;
57 $this->defaults = [
58 1 => [
59 'label' => esc_html__( 'First Choice', 'wpforms-lite' ),
60 'value' => '',
61 'default' => '',
62 ],
63 2 => [
64 'label' => esc_html__( 'Second Choice', 'wpforms-lite' ),
65 'value' => '',
66 'default' => '',
67 ],
68 3 => [
69 'label' => esc_html__( 'Third Choice', 'wpforms-lite' ),
70 'value' => '',
71 'default' => '',
72 ],
73 ];
74
75 $this->default_settings = [
76 'choices' => $this->defaults,
77 ];
78
79 // Define additional field properties.
80 add_filter( 'wpforms_field_properties_' . $this->type, [ $this, 'field_properties' ], 5, 3 );
81
82 // Form frontend CSS enqueues.
83 add_action( 'wpforms_frontend_css', [ $this, 'enqueue_frontend_css' ] );
84
85 // Form frontend JS enqueues.
86 add_action( 'wpforms_frontend_js', [ $this, 'enqueue_frontend_js' ] );
87
88 add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_block_editor_assets' ] );
89 }
90
91 /**
92 * Define additional field properties.
93 *
94 * @since 1.5.0
95 *
96 * @param array $properties Field properties.
97 * @param array $field Field settings.
98 * @param array $form_data Form data and settings.
99 *
100 * @return array
101 */
102 public function field_properties( $properties, $field, $form_data ) {
103
104 // Remove primary input.
105 unset( $properties['inputs']['primary'] );
106
107 // Define data.
108 $form_id = absint( $form_data['id'] );
109 $field_id = wpforms_validate_field_id( $field['id'] );
110 $choices = $field['choices'];
111 $dynamic = wpforms_get_field_dynamic_choices( $field, $form_id, $form_data );
112
113 if ( $dynamic !== false ) {
114 $choices = $dynamic;
115 $field['show_values'] = true;
116 }
117
118 // Set options container (<select>) properties.
119 $properties['input_container'] = [
120 'class' => [],
121 'data' => [],
122 'id' => "wpforms-{$form_id}-field_{$field_id}",
123 'attr' => [
124 'name' => "wpforms[fields][{$field_id}]",
125 ],
126 ];
127
128 // Set properties.
129 foreach ( $choices as $key => $choice ) {
130
131 // Used for dynamic choices.
132 $depth = isset( $choice['depth'] ) ? absint( $choice['depth'] ) : 1;
133
134 $properties['inputs'][ $key ] = [
135 'container' => [
136 'attr' => [],
137 'class' => [ "choice-{$key}", "depth-{$depth}" ],
138 'data' => [],
139 'id' => '',
140 ],
141 'label' => [
142 'attr' => [
143 'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}",
144 ],
145 'class' => [ 'wpforms-field-label-inline' ],
146 'data' => [],
147 'id' => '',
148 'text' => $choice['label'],
149 ],
150 'attr' => [
151 'name' => "wpforms[fields][{$field_id}]",
152 'value' => isset( $field['show_values'] ) ? $choice['value'] : $choice['label'],
153 ],
154 'class' => [],
155 'data' => [],
156 'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}",
157 'required' => ! empty( $field['required'] ) ? 'required' : '',
158 'default' => isset( $choice['default'] ),
159 ];
160 }
161
162 // Add a class that changes the field size.
163 if ( ! empty( $field['size'] ) ) {
164 $properties['input_container']['class'][] = 'wpforms-field-' . esc_attr( $field['size'] );
165 }
166
167 // Required class for pagebreak validation.
168 if ( ! empty( $field['required'] ) ) {
169 $properties['input_container']['class'][] = 'wpforms-field-required';
170 }
171
172 // Add additional class for container.
173 if (
174 ! empty( $field['style'] ) &&
175 in_array( $field['style'], [ self::STYLE_CLASSIC, self::STYLE_MODERN ], true )
176 ) {
177 $properties['container']['class'][] = "wpforms-field-select-style-{$field['style']}";
178 }
179
180 return $properties;
181 }
182
183 /**
184 * Field options panel inside the builder.
185 *
186 * @since 1.0.0
187 *
188 * @param array $field Field settings.
189 *
190 * @noinspection HtmlUnknownTarget*/
191 public function field_options( $field ) {
192 /*
193 * Basic field options.
194 */
195
196 // Options open markup.
197 $this->field_option(
198 'basic-options',
199 $field,
200 [
201 'markup' => 'open',
202 ]
203 );
204
205 // Label.
206 $this->field_option( 'label', $field );
207
208 // Choices.
209 $this->field_option( 'choices', $field );
210
211 // AI Feature.
212 $this->field_option(
213 'ai_modal_button',
214 $field,
215 [
216 'value' => esc_html__( 'Generate Choices', 'wpforms-lite' ),
217 'type' => 'choices',
218 ]
219 );
220
221 // Description.
222 $this->field_option( 'description', $field );
223
224 // Required toggle.
225 $this->field_option( 'required', $field );
226
227 // Options close markup.
228 $this->field_option(
229 'basic-options',
230 $field,
231 [
232 'markup' => 'close',
233 ]
234 );
235
236 /*
237 * Advanced field options.
238 */
239
240 // Options open markup.
241 $this->field_option(
242 'advanced-options',
243 $field,
244 [
245 'markup' => 'open',
246 ]
247 );
248
249 // Show Values toggle option. This option will only show if already used
250 // or if manually enabled by a filter.
251 if ( ! empty( $field['show_values'] ) || wpforms_show_fields_options_setting() ) {
252 $show_values = $this->field_element(
253 'toggle',
254 $field,
255 [
256 'slug' => 'show_values',
257 'value' => $field['show_values'] ?? '0',
258 'desc' => esc_html__( 'Show Values', 'wpforms-lite' ),
259 'tooltip' => esc_html__( 'Check this option to manually set form field values.', 'wpforms-lite' ),
260 ],
261 false
262 );
263
264 $this->field_element(
265 'row',
266 $field,
267 [
268 'slug' => 'show_values',
269 'content' => $show_values,
270 ]
271 );
272 }
273
274 // Multiple options selection.
275 $fld = $this->field_element(
276 'toggle',
277 $field,
278 [
279 'slug' => 'multiple',
280 'value' => ! empty( $field['multiple'] ),
281 'desc' => esc_html__( 'Multiple Options Selection', 'wpforms-lite' ),
282 'tooltip' => esc_html__( 'Allow users to select multiple choices in this field.', 'wpforms-lite' ) . '<br>' .
283 sprintf(
284 wp_kses( /* translators: %s - URL to WPForms.com doc article. */
285 esc_html__( 'For details, including how this looks and works for your site\'s visitors, please check out <a href="%s" target="_blank" rel="noopener noreferrer">our doc</a>.', 'wpforms-lite' ),
286 [
287 'a' => [
288 'href' => [],
289 'target' => [],
290 'rel' => [],
291 ],
292 ]
293 ),
294 esc_url( wpforms_utm_link( 'https://wpforms.com/docs/how-to-allow-multiple-selections-to-a-dropdown-field-in-wpforms/', 'Field Options', 'Multiple Options Selection Documentation' ) )
295 ),
296 ],
297 false
298 );
299
300 $this->field_element(
301 'row',
302 $field,
303 [
304 'slug' => 'multiple',
305 'content' => $fld,
306 ]
307 );
308
309 // Style.
310 $lbl = $this->field_element(
311 'label',
312 $field,
313 [
314 'slug' => 'style',
315 'value' => esc_html__( 'Style', 'wpforms-lite' ),
316 'tooltip' => esc_html__( 'Classic style is the default one generated by your browser. Modern has a fresh look and displays all selected options in a single row.', 'wpforms-lite' ),
317 ],
318 false
319 );
320
321 $fld = $this->field_element(
322 'select',
323 $field,
324 [
325 'slug' => 'style',
326 'value' => ! empty( $field['style'] ) ? $field['style'] : self::STYLE_CLASSIC,
327 'options' => [
328 self::STYLE_CLASSIC => esc_html__( 'Classic', 'wpforms-lite' ),
329 self::STYLE_MODERN => esc_html__( 'Modern', 'wpforms-lite' ),
330 ],
331 ],
332 false
333 );
334
335 $this->field_element(
336 'row',
337 $field,
338 [
339 'slug' => 'style',
340 'content' => $lbl . $fld,
341 ]
342 );
343
344 // Size.
345 $this->field_option( 'size', $field );
346
347 // Placeholder.
348 $this->field_option( 'placeholder', $field );
349
350 // Dynamic choice auto-populating toggle.
351 $this->field_option( 'dynamic_choices', $field );
352
353 // Dynamic choice source.
354 $this->field_option( 'dynamic_choices_source', $field );
355
356 // Custom CSS classes.
357 $this->field_option( 'css', $field );
358
359 // Hide label.
360 $this->field_option( 'label_hide', $field );
361
362 // Options close markup.
363 $this->field_option(
364 'advanced-options',
365 $field,
366 [
367 'markup' => 'close',
368 ]
369 );
370 }
371
372 /**
373 * Field preview inside the builder.
374 *
375 * @since 1.0.0
376 * @since 1.6.1 Added a `Modern` style select support.
377 *
378 * @param array $field Field settings.
379 */
380 public function field_preview( $field ) {
381
382 $args = [];
383
384 // Label.
385 $this->field_preview_option( 'label', $field );
386
387 // Prepare arguments.
388 $args['modern'] = false;
389
390 if (
391 ! empty( $field['style'] ) &&
392 $field['style'] === self::STYLE_MODERN
393 ) {
394 $args['modern'] = true;
395 $args['class'] = 'choicesjs-select';
396 }
397
398 // Choices.
399 $this->field_preview_option( 'choices', $field, $args );
400
401 // Description.
402 $this->field_preview_option( 'description', $field );
403 }
404
405 /**
406 * Field display on the form front-end and admin entry edit page.
407 *
408 * @since 1.0.0
409 * @since 1.5.0 Converted to a new format, where all the data are taken not from $deprecated, but field properties.
410 * @since 1.6.1 Added multiple select support.
411 *
412 * @param array $field Field data and settings.
413 * @param array $deprecated Deprecated array of field attributes.
414 * @param array $form_data Form data and settings.
415 *
416 * @noinspection HtmlUnknownAttribute
417 */
418 public function field_display( $field, $deprecated, $form_data ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
419
420 $container = $field['properties']['input_container'];
421 $field_placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : '';
422 $is_multiple = ! empty( $field['multiple'] );
423 $is_modern = ! empty( $field['style'] ) && $field['style'] === self::STYLE_MODERN;
424 $choices = $field['properties']['inputs'];
425
426 // Do not display the field with empty choices on the frontend.
427 if ( ! $choices && ! is_admin() ) {
428 return;
429 }
430
431 // Display a warning message on the Entry Edit page.
432 if ( ! $choices && is_admin() ) {
433 $this->display_empty_dynamic_choices_message( $field );
434
435 return;
436 }
437
438 if ( ! empty( $field['properties']['input_container']['class'] ) && in_array( 'wpforms-field-required', $field['properties']['input_container']['class'], true ) ) {
439 $container['attr']['required'] = 'required';
440 }
441
442 // If it's multiple select.
443 if ( $is_multiple ) {
444 $container['attr']['multiple'] = 'multiple';
445
446 // Change a name attribute.
447 if ( ! empty( $container['attr']['name'] ) ) {
448 $container['attr']['name'] .= '[]';
449 }
450 }
451
452 // Add a class for Choices.js initialization.
453 if ( $is_modern ) {
454 $container['class'][] = 'choicesjs-select';
455
456 // Add a size-class to the data attribute - it is used when Choices.js is initialized.
457 if ( ! empty( $field['size'] ) ) {
458 $container['data']['size-class'] = 'wpforms-field-row wpforms-field-' . sanitize_html_class( $field['size'] );
459 }
460
461 $container['data']['search-enabled'] = $this->is_choicesjs_search_enabled( count( $choices ) );
462 }
463
464 $has_default = false;
465
466 // Check to see if any of the options were selected by default.
467 foreach ( $choices as $choice ) {
468 if ( ! empty( $choice['default'] ) ) {
469 $has_default = true;
470
471 break;
472 }
473 }
474
475 // Preselect default if no other choices were marked as default.
476 printf(
477 '<select %s>',
478 wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] )
479 );
480
481 // Optional placeholder.
482 if ( ! empty( $field_placeholder ) || $is_modern ) {
483 printf(
484 '<option value="" class="placeholder" disabled %s>%s</option>',
485 selected( false, $has_default || $is_multiple, false ),
486 esc_html( $field_placeholder )
487 );
488 }
489
490 // Build the select options.
491 foreach ( $choices as $key => $choice ) {
492 $label = $this->get_choices_label( $choice['label']['text'] ?? '', $key, $field );
493 $value = isset( $choice['attr']['value'] ) && ! wpforms_is_empty_string( $choice['attr']['value'] ) ? $choice['attr']['value'] : $label;
494 $data = $choice['container']['data'] ?? [];
495 $data_html = '';
496
497 if ( ! empty( $data ) ) {
498 $data_html = wpforms_html_attributes( '', '', $data );
499 }
500
501 $selected = $choice['attr']['selected'] ?? false;
502 $selected_html = $selected ? ' selected="selected"' : '';
503
504 // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
505 printf(
506 '<option value="%1$s" %2$s class="%3$s" %4$s %5$s>%6$s</option>',
507 esc_attr( $value ),
508 selected( true, ! empty( $choice['default'] ), false ),
509 esc_attr( implode( ' ', $choice['container']['class'] ) ),
510 $data_html,
511 $selected_html,
512 wp_kses(
513 $label,
514 [
515 'span' => [
516 'class' => [],
517 ],
518 ]
519 )
520 );
521 // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
522 }
523
524 echo '</select>';
525 }
526
527 /**
528 * Validate field.
529 *
530 * @since 1.8.2
531 *
532 * @param int $field_id Field ID.
533 * @param string|array $field_submit Submitted field value (raw data).
534 * @param array $form_data Form data and settings.
535 */
536 public function validate( $field_id, $field_submit, $form_data ) {
537
538 $field = $form_data['fields'][ $field_id ];
539
540 // Skip validation if the field is dynamic and choices are empty.
541 if ( $this->is_dynamic_choices_empty( $field, $form_data ) ) {
542 return;
543 }
544
545 parent::validate( $field_id, $field_submit, $form_data );
546 }
547
548 /**
549 * Format and sanitize field.
550 *
551 * @since 1.0.2
552 * @since 1.6.1 Added support for multiple values.
553 *
554 * @param int $field_id Field ID.
555 * @param string|array $field_submit Submitted field value (selected option).
556 * @param array $form_data Form data and settings.
557 */
558 public function format( $field_id, $field_submit, $form_data ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh, Generic.Metrics.NestingLevel.MaxExceeded
559
560 $field = $form_data['fields'][ $field_id ];
561 $dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false;
562 $multiple = ! empty( $field['multiple'] );
563 $name = sanitize_text_field( $field['label'] );
564 $value = [];
565
566 // Convert the submitted field value to array.
567 if ( ! is_array( $field_submit ) ) {
568 $field_submit = [ $field_submit ];
569 }
570
571 $value_raw = wpforms_sanitize_array_combine( $field_submit );
572
573 $data = [
574 'name' => $name,
575 'value' => '',
576 'value_raw' => $value_raw,
577 'id' => wpforms_validate_field_id( $field_id ),
578 'type' => $this->type,
579 ];
580
581 if ( $dynamic === 'post_type' && ! empty( $field['dynamic_post_type'] ) ) {
582
583 // Dynamic population is enabled using post type (like for a `Checkboxes` field).
584 $value_raw = implode( ',', array_map( 'absint', $field_submit ) );
585 $data['value_raw'] = $value_raw;
586 $data['dynamic'] = 'post_type';
587 $data['dynamic_items'] = $value_raw;
588 $data['dynamic_post_type'] = $field['dynamic_post_type'];
589 $posts = [];
590
591 foreach ( $field_submit as $id ) {
592 $post = get_post( $id );
593
594 if ( ! empty( $post ) && ! is_wp_error( $post ) && $data['dynamic_post_type'] === $post->post_type ) {
595 $posts[] = esc_html( wpforms_get_post_title( $post ) );
596 }
597 }
598
599 $data['value'] = ! empty( $posts ) ? wpforms_sanitize_array_combine( $posts ) : '';
600
601 } elseif ( $dynamic === 'taxonomy' && ! empty( $field['dynamic_taxonomy'] ) ) {
602
603 // Dynamic population is enabled using taxonomy (like for a `Checkboxes` field).
604 $value_raw = implode( ',', array_map( 'absint', $field_submit ) );
605 $data['value_raw'] = $value_raw;
606 $data['dynamic'] = 'taxonomy';
607 $data['dynamic_items'] = $value_raw;
608 $data['dynamic_taxonomy'] = $field['dynamic_taxonomy'];
609 $terms = [];
610
611 foreach ( $field_submit as $id ) {
612 $term = get_term( $id, $field['dynamic_taxonomy'] );
613
614 if ( ! empty( $term ) && ! is_wp_error( $term ) ) {
615 $terms[] = esc_html( wpforms_get_term_name( $term ) );
616 }
617 }
618
619 $data['value'] = ! empty( $terms ) ? wpforms_sanitize_array_combine( $terms ) : '';
620
621 } else {
622
623 // Normal processing, dynamic population is off.
624
625 // If show_values is true, that means values posted are the raw values
626 // and not the labels. So we need to get the label values.
627 if ( ! empty( $field['show_values'] ) && (int) $field['show_values'] === 1 ) {
628
629 foreach ( $field_submit as $item ) {
630 foreach ( $field['choices'] as $choice ) {
631 if ( $item === $choice['value'] ) {
632 $value[] = $choice['label'];
633
634 break;
635 }
636 }
637 }
638
639 $data['value'] = ! empty( $value ) ? wpforms_sanitize_array_combine( $value ) : '';
640
641 } else {
642 $data['value'] = $value_raw;
643 }
644 }
645
646 // Backward compatibility: for single dropdown save a string, for multiple - array.
647 if ( ! $multiple && is_array( $data ) && ( 1 === count( $data ) ) ) {
648 $data = reset( $data );
649 }
650
651 // Push field details to be saved.
652 wpforms()->obj( 'process' )->fields[ $field_id ] = $data;
653 }
654
655 /**
656 * Form frontend CSS enqueues.
657 *
658 * @since 1.6.1
659 *
660 * @param array $forms Forms on the current page.
661 */
662 public function enqueue_frontend_css( $forms ) {
663
664 $has_modern_select = false;
665
666 foreach ( $forms as $form ) {
667 if ( $this->is_field_style( $form, self::STYLE_MODERN ) ) {
668 $has_modern_select = true;
669
670 break;
671 }
672 }
673
674 if ( $has_modern_select || wpforms()->obj( 'frontend' )->assets_global() ) {
675 $min = wpforms_get_min_suffix();
676
677 wp_enqueue_style(
678 'wpforms-choicesjs',
679 WPFORMS_PLUGIN_URL . "assets/css/choices{$min}.css",
680 [],
681 self::CHOICES_VERSION
682 );
683 }
684 }
685
686 /**
687 * Form frontend JS enqueues.
688 *
689 * @since 1.6.1
690 *
691 * @param array $forms Forms on the current page.
692 */
693 public function enqueue_frontend_js( $forms ) {
694
695 $has_modern_select = false;
696
697 foreach ( $forms as $form ) {
698 if ( $this->is_field_style( $form, self::STYLE_MODERN ) ) {
699 $has_modern_select = true;
700
701 break;
702 }
703 }
704
705 if ( $has_modern_select || wpforms()->obj( 'frontend' )->assets_global() ) {
706 $this->enqueue_choicesjs_once( $forms );
707 }
708 }
709
710 /**
711 * Load WPForms Gutenberg block scripts.
712 *
713 * @since 1.8.1
714 */
715 public function enqueue_block_editor_assets() {
716
717 $min = wpforms_get_min_suffix();
718
719 wp_enqueue_style(
720 'wpforms-choicesjs',
721 WPFORMS_PLUGIN_URL . "assets/css/choices{$min}.css",
722 [],
723 self::CHOICES_VERSION
724 );
725
726 $this->enqueue_choicesjs_once( [] );
727 }
728
729 /**
730 * Whether the provided form has a dropdown field with a specified style.
731 *
732 * @since 1.6.1
733 *
734 * @param array $form Form data.
735 * @param string $style Desired field style.
736 *
737 * @return bool
738 */
739 protected function is_field_style( $form, $style ) {
740
741 $is_field_style = false;
742
743 if ( empty( $form['fields'] ) ) {
744 return false;
745 }
746
747 foreach ( (array) $form['fields'] as $field ) {
748 if (
749 ! empty( $field['type'] ) &&
750 $field['type'] === $this->type &&
751 ! empty( $field['style'] ) &&
752 sanitize_key( $style ) === $field['style']
753 ) {
754 $is_field_style = true;
755
756 break;
757 }
758 }
759
760 return $is_field_style;
761 }
762
763 /**
764 * Get a field name for an ajax error message.
765 *
766 * @since 1.6.3
767 *
768 * @param string|mixed $name Field name for error triggered.
769 * @param array $field Field settings.
770 * @param array $props List of properties.
771 * @param string|string[] $error Error message.
772 *
773 * @return string
774 * @noinspection PhpMissingReturnTypeInspection
775 * @noinspection ReturnTypeCanBeDeclaredInspection
776 */
777 public function ajax_error_field_name( $name, $field, $props, $error ) {
778
779 $name = (string) $name;
780
781 if ( ! isset( $field['type'] ) || $field['type'] !== 'select' ) {
782 return $name;
783 }
784
785 if ( ! empty( $field['multiple'] ) ) {
786 $input = isset( $props['inputs'] ) ? end( $props['inputs'] ) : [];
787
788 return isset( $input['attr']['name'] ) ? $input['attr']['name'] . '[]' : '';
789 }
790
791 return $name;
792 }
793 }
794
795 new WPForms_Field_Select();
796