PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.26.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.26.1
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / models / fields / FrmFieldCombo.php

FrmFieldCombo.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.26.1, at classes/models/fields/FrmFieldCombo.php

546 lines 12.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Combo field - Field contains sub fields
4 *
5 * @package Formidable
6 *
7 * @since 4.11
8 */
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 die( 'You are not allowed to call this page directly.' );
12 }
13
14 class FrmFieldCombo extends FrmFieldType {
15
16 /**
17 * Does the html for this field label need to include "for"?
18 *
19 * @var bool
20 *
21 * @since 3.0
22 */
23 protected $has_for_label = false;
24
25 /**
26 * Sub fields.
27 *
28 * @var array
29 */
30 protected $sub_fields = array();
31
32 /**
33 * This is used to check if field is combo field.
34 *
35 * @var bool
36 */
37 public $is_combo_field = true;
38
39 /**
40 * Gets ALL subfields.
41 *
42 * @return array
43 */
44 public function get_sub_fields() {
45 return $this->sub_fields;
46 }
47
48 /**
49 * Registers sub fields.
50 *
51 * @param array $sub_fields Sub fields. Accepts array or array or array of string.
52 *
53 * @return void
54 */
55 protected function register_sub_fields( array $sub_fields ) {
56 $defaults = $this->get_default_sub_field();
57
58 foreach ( $sub_fields as $name => $sub_field ) {
59 if ( empty( $sub_field ) ) {
60 continue;
61 }
62
63 if ( is_array( $sub_field ) ) {
64 $sub_field = wp_parse_args( $sub_field, $defaults );
65 $sub_field['name'] = $name;
66 $this->sub_fields[ $name ] = $sub_field;
67 continue;
68 }
69
70 if ( is_string( $sub_field ) ) {
71 $this->sub_fields[ $name ] = wp_parse_args(
72 array(
73 'name' => $name,
74 'label' => $sub_field,
75 ),
76 $defaults
77 );
78 }
79 }//end foreach
80 }
81
82 /**
83 * Set the aria-invalid attribute for subfields.
84 *
85 * @since 6.16.3
86 *
87 * @param array $shortcode_atts
88 * @param array $args
89 *
90 * @return void
91 */
92 public function set_aria_invalid_error( &$shortcode_atts, $args ) {
93 foreach ( $this->get_sub_fields() as $sub_field ) {
94 $shortcode_atts[ 'aria-invalid-' . $sub_field['name'] ] = isset( $args['errors'][ 'field' . $this->field_id . '-' . $sub_field['name'] ] ) ? 'true' : 'false';
95 }
96 }
97
98 /**
99 * Gets default sub field.
100 *
101 * @return array
102 */
103 protected function get_default_sub_field() {
104 return array(
105 'type' => 'text',
106 'label' => '',
107 'classes' => '',
108 'wrapper_classes' => '',
109 'options' => array(
110 'default_value',
111 'placeholder',
112 'desc',
113 ),
114 'optional' => false,
115 'atts' => array(),
116 );
117 }
118
119 /**
120 * Registers extra options for saving.
121 *
122 * @return array
123 */
124 protected function extra_field_opts() {
125 $extra_options = parent::extra_field_opts();
126
127 // Register for sub field options.
128 foreach ( $this->sub_fields as $key => $sub_field ) {
129 if ( empty( $sub_field['options'] ) || ! is_array( $sub_field['options'] ) ) {
130 continue;
131 }
132
133 foreach ( $sub_field['options'] as $option ) {
134 if ( 'default_value' === $option ) {
135 // We parse default value from field column.
136 continue;
137 }
138
139 if ( is_string( $option ) ) {
140 $extra_options[ $key . '_' . $option ] = '';
141 } elseif ( ! empty( $option['name'] ) ) {
142 $extra_options[ $key . '_' . $option['name'] ] = '';
143 }
144 }
145 }
146
147 return $extra_options;
148 }
149
150 /**
151 * Include the settings for placeholder, default value, and sub labels for each
152 * of the individual field labels.
153 *
154 * @since 4.0
155 *
156 * @param array $args Includes 'field', 'display'.
157 *
158 * @return void
159 */
160 public function show_after_default( $args ) {
161 $field = (array) $args['field'];
162 $default_value = $this->get_default_value();
163 $processed_sub_fields = $this->get_processed_sub_fields();
164
165 foreach ( $this->sub_fields as $name => $sub_field ) {
166 $sub_field['name'] = $name;
167 $wrapper_classes = 'frm_grid_container frm_sub_field_options frm_sub_field_options-' . $sub_field['name'];
168
169 if ( ! isset( $processed_sub_fields[ $name ] ) ) {
170 // Options for this subfield should be hidden.
171 $wrapper_classes .= ' frm_hidden';
172 }
173
174 include FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/combo-field/sub-field-options.php';
175 }
176 }
177
178 /**
179 * Gets default value of field.
180 * This should return an array of default value of sub fields.
181 *
182 * @return array
183 */
184 protected function get_default_value() {
185 $default_value = $this->get_field_column( 'default_value' );
186
187 if ( is_array( $default_value ) ) {
188 return $default_value;
189 }
190
191 if ( is_object( $default_value ) ) {
192 return (array) $default_value;
193 }
194
195 if ( ! $default_value ) {
196 $default_value = array();
197
198 foreach ( $this->sub_fields as $name => $sub_field ) {
199 $default_value[ $name ] = '';
200 }
201
202 return $default_value;
203 }
204
205 // We store default value as JSON string in db.
206 return json_decode( $default_value, true );
207 }
208
209 /**
210 * Gets labels for built-in options of fields or sub fields.
211 *
212 * @return array
213 */
214 protected function get_built_in_option_labels() {
215 return array(
216 'default_value' => __( 'Default Value', 'formidable' ),
217 'placeholder' => __( 'Placeholder Text', 'formidable' ),
218 'desc' => __( 'Description', 'formidable' ),
219 );
220 }
221
222 /**
223 * Which built-in settings this field supports?
224 *
225 * @return array
226 */
227 protected function field_settings_for_type() {
228 $settings = array(
229 'description' => false,
230 'default' => false,
231 // Don't use the regular placeholder option.
232 'clear_on_focus' => false,
233 'logic' => true,
234 'visibility' => true,
235 );
236
237 return $settings;
238 }
239
240 /**
241 * Shows field on the form builder.
242 *
243 * @param string $name Field name.
244 *
245 * @return void
246 */
247 public function show_on_form_builder( $name = '' ) {
248 $field = FrmFieldsHelper::setup_edit_vars( $this->field );
249
250 $field['default_value'] = $this->get_default_value();
251 $field['value'] = $field['default_value'];
252
253 $field_name = $this->html_name( $name );
254
255 $this->load_field_output( compact( 'field', 'field_name' ) );
256 }
257
258 /**
259 * Gets processed sub fields.
260 * This should return the list of sub fields after sorting or show/hide based of some options.
261 *
262 * @return array
263 */
264 protected function get_processed_sub_fields() {
265 return $this->sub_fields;
266 }
267
268 /**
269 * Shows field in the frontend.
270 *
271 * @param array $args Arguments.
272 * @param array $shortcode_atts Shortcode attributes.
273 *
274 * @return string
275 */
276 public function front_field_input( $args, $shortcode_atts ) {
277 $field = (array) $this->field;
278
279 $field['default_value'] = $this->get_default_value();
280
281 if ( empty( $field['value'] ) ) {
282 $field['value'] = $field['default_value'];
283 }
284
285 $args['field'] = $field;
286 $args['shortcode_atts'] = $shortcode_atts;
287
288 ob_start();
289 $this->load_field_output( $args );
290 $input_html = ob_get_clean();
291
292 return $input_html;
293 }
294
295 /**
296 * Loads field output.
297 *
298 * @param array $args {
299 * Arguments.
300 *
301 * @type array $field Field array.
302 * @type string $html_id HTML ID.
303 * @type string $field_name Field name attribute.
304 * @type array $shortcode_atts Shortcode attributes.
305 * @type array $errors Field errors.
306 * @type bool $remove_names Remove name attribute or not.
307 * }
308 *
309 * @return void
310 */
311 protected function load_field_output( $args ) {
312 if ( empty( $args['field'] ) ) {
313 return;
314 }
315
316 $this->process_args_for_field_output( $args );
317
318 $include_paths = array(
319 FrmAppHelper::plugin_path() . "/classes/views/frm-fields/front-end/{$args['field']['type']}-field/{$args['field']['type']}-field.php",
320 FrmAppHelper::plugin_path() . '/classes/views/frm-fields/front-end/combo-field/combo-field.php',
321 );
322
323 foreach ( $include_paths as $include_path ) {
324 if ( file_exists( $include_path ) ) {
325 include $include_path;
326 return;
327 }
328 }
329 }
330
331 /**
332 * Loads processed args for field output.
333 *
334 * @param array $args {
335 * Arguments.
336 *
337 * @type array $field Field array.
338 * @type string $html_id HTML ID.
339 * @type string $field_name Field name attribute.
340 * @type array $shortcode_atts Shortcode attributes.
341 * @type array $errors Field errors.
342 * @type bool $remove_names Remove name attribute or not.
343 * }
344 *
345 * @return void
346 */
347 protected function process_args_for_field_output( &$args ) {
348 $args['field'] = (array) $args['field'];
349
350 if ( ! isset( $args['html_id'] ) ) {
351 $args['html_id'] = $this->html_id();
352 }
353
354 if ( ! isset( $args['field_name'] ) ) {
355 $args['field_name'] = $this->html_name( $args['field']['name'] );
356 }
357
358 $args['sub_fields'] = $this->get_processed_sub_fields();
359
360 if ( ! isset( $args['shortcode_atts'] ) ) {
361 $args['shortcode_atts'] = array();
362 }
363
364 if ( ! isset( $args['errors'] ) ) {
365 $args['errors'] = array();
366 }
367 }
368
369 /**
370 * Prints sub field input atts.
371 *
372 * @param array $args Arguments. Includes `field`, `sub_field`.
373 *
374 * @return void
375 */
376 protected function print_input_atts( $args ) {
377 $field = $args['field'];
378 $sub_field = $args['sub_field'];
379
380 // Placeholder.
381 if ( in_array( 'placeholder', $sub_field['options'], true ) ) {
382 $placeholders = FrmField::get_option( $field, 'placeholder' );
383
384 if ( ! empty( $placeholders[ $sub_field['name'] ] ) ) {
385 $field['placeholder'] = $placeholders[ $sub_field['name'] ];
386 }
387 }
388
389 // Add optional class.
390 $classes = $sub_field['classes'] ?? '';
391
392 if ( is_array( $classes ) ) {
393 $classes = implode( ' ', $classes );
394 }
395
396 if ( ! empty( $sub_field['optional'] ) ) {
397 $classes .= ' frm_optional';
398 }
399
400 if ( $classes ) {
401 $field['input_class'] = esc_attr( $classes );
402 }
403
404 // Fake it to avoid printing frm-val attribute.
405 $field['default_value'] = '';
406
407 if ( ! empty( $sub_field['name'] ) ) {
408 $field['subfield_name'] = $sub_field['name'];
409 }
410 do_action( 'frm_field_input_html', $field );
411
412 // Print custom attributes.
413 if ( ! empty( $sub_field['atts'] ) && is_array( $sub_field['atts'] ) ) {
414 foreach ( $sub_field['atts'] as $att_name => $att_value ) {
415 echo esc_attr( trim( $att_name ) ) . '="' . esc_attr( trim( $att_value ) ) . '" ';
416 }
417 }
418 }
419
420 /**
421 * Validate field.
422 *
423 * @param array $args Arguments. Includes `errors`, `value`.
424 *
425 * @return array Errors array.
426 */
427 public function validate( $args ) {
428 $errors = $args['errors'] ?? array();
429
430 if ( ! $this->field->required ) {
431 return $errors;
432 }
433
434 if ( class_exists( 'FrmProEntryMeta' ) && FrmProEntryMeta::skip_required_validation( $this->field ) ) {
435 return $errors;
436 }
437
438 if ( class_exists( 'FrmProFieldsHelper' ) && ! FrmProFieldsHelper::is_field_visible_to_user( $this->field ) ) {
439 return $errors;
440 }
441
442 $blank_msg = FrmFieldsHelper::get_error_msg( $this->field, 'blank' );
443
444 $sub_fields = $this->get_processed_sub_fields();
445
446 // Validate not empty.
447 foreach ( $sub_fields as $name => $sub_field ) {
448 if ( empty( $sub_field['optional'] ) && empty( $args['value'][ $name ] ) ) {
449 $errors[ 'field' . $args['id'] . '-' . $name ] = '';
450 $errors[ 'field' . $args['id'] ] = $blank_msg;
451 }
452 }
453
454 return $errors;
455 }
456
457 /**
458 * Gets export headings.
459 *
460 * @return array
461 */
462 public function get_export_headings() {
463 $headings = array();
464 $field_id = $this->field->id ?? $this->field['id'];
465 $field_name = $this->field->name ?? $this->field['name'];
466 $field_key = $this->field->field_key ?? $this->field['field_key'];
467 $sub_fields = $this->get_processed_sub_fields();
468
469 foreach ( $sub_fields as $name => $sub_field ) {
470 $headings[ $field_id . '_' . $name ] = $field_name . ' (' . $field_key . ') - ' . $sub_field['label'];
471 }
472
473 return $headings;
474 }
475
476 /**
477 * Get a list of all field settings that should be translated
478 * on a multilingual site.
479 *
480 * @since 3.06.01
481 *
482 * @return array
483 */
484 public function translatable_strings() {
485 $strings = parent::translatable_strings();
486
487 foreach ( $this->sub_fields as $name => $sub_field ) {
488 if ( in_array( 'desc', $sub_field['options'], true ) ) {
489 $strings[] = $name . '_desc';
490 }
491 }
492
493 return $strings;
494 }
495
496 /**
497 * Checks if should print hidden subfields and hide them. This is useful to use js to show or hide sub fields.
498 *
499 * @return bool
500 */
501 protected function should_print_hidden_sub_fields() {
502 return false;
503 }
504
505 /**
506 * Gets inputs container attributes.
507 *
508 * @return array
509 */
510 protected function get_inputs_container_attrs() {
511 return array(
512 'class' => 'frm_combo_inputs_container',
513 'id' => 'frm_combo_inputs_container_' . $this->field_id,
514 );
515 }
516
517 /**
518 * Gets subfield input attributes.
519 *
520 * @since 6.26
521 *
522 * @param array $sub_field Subfield data.
523 * @param array $args Field output args. See {@see FrmFieldCombo::load_field_output()}.
524 *
525 * @return array
526 */
527 protected function get_sub_field_input_attrs( $sub_field, $args ) {
528 $attrs = array(
529 'type' => $sub_field['type'],
530 'id' => $args['html_id'] . '_' . $sub_field['name'],
531 'value' => '',
532 );
533
534 if ( ! empty( $args['field']['value'][ $sub_field['name'] ] ) ) {
535 $attrs['value'] = $args['field']['value'][ $sub_field['name'] ];
536 $attrs['data-frmval'] = $args['field']['value'][ $sub_field['name'] ];
537 }
538
539 if ( empty( $args['remove_names'] ) ) {
540 $attrs['name'] = $args['field_name'] . '[' . $sub_field['name'] . ']';
541 }
542
543 return $attrs;
544 }
545 }
546