PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.35
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.35
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.35, at classes/models/fields/FrmFieldCombo.php

543 lines 12.7 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 ( ! $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 return 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
238 /**
239 * Shows field on the form builder.
240 *
241 * @param string $name Field name.
242 *
243 * @return void
244 */
245 public function show_on_form_builder( $name = '' ) {
246 $field = FrmFieldsHelper::setup_edit_vars( $this->field );
247
248 $field['default_value'] = $this->get_default_value();
249 $field['value'] = $field['default_value'];
250
251 $field_name = $this->html_name( $name );
252
253 $this->load_field_output( compact( 'field', 'field_name' ) );
254 }
255
256 /**
257 * Gets processed sub fields.
258 * This should return the list of sub fields after sorting or show/hide based of some options.
259 *
260 * @return array
261 */
262 protected function get_processed_sub_fields() {
263 return $this->sub_fields;
264 }
265
266 /**
267 * Shows field in the frontend.
268 *
269 * @param array $args Arguments.
270 * @param array $shortcode_atts Shortcode attributes.
271 *
272 * @return string
273 */
274 public function front_field_input( $args, $shortcode_atts ) {
275 $field = (array) $this->field;
276
277 $field['default_value'] = $this->get_default_value();
278
279 if ( empty( $field['value'] ) ) {
280 $field['value'] = $field['default_value'];
281 }
282
283 $args['field'] = $field;
284 $args['shortcode_atts'] = $shortcode_atts;
285
286 ob_start();
287 $this->load_field_output( $args );
288
289 return ob_get_clean();
290 }
291
292 /**
293 * Loads field output.
294 *
295 * @param array $args {
296 * Arguments.
297 *
298 * @type array $field Field array.
299 * @type string $html_id HTML ID.
300 * @type string $field_name Field name attribute.
301 * @type array $shortcode_atts Shortcode attributes.
302 * @type array $errors Field errors.
303 * @type bool $remove_names Remove name attribute or not.
304 * }
305 *
306 * @return void
307 */
308 protected function load_field_output( $args ) {
309 if ( empty( $args['field'] ) ) {
310 return;
311 }
312
313 $this->process_args_for_field_output( $args );
314
315 $include_paths = array(
316 FrmAppHelper::plugin_path() . "/classes/views/frm-fields/front-end/{$args['field']['type']}-field/{$args['field']['type']}-field.php",
317 FrmAppHelper::plugin_path() . '/classes/views/frm-fields/front-end/combo-field/combo-field.php',
318 );
319
320 foreach ( $include_paths as $include_path ) {
321 if ( file_exists( $include_path ) ) {
322 include $include_path;
323 return;
324 }
325 }
326 }
327
328 /**
329 * Loads processed args for field output.
330 *
331 * @param array $args {
332 * Arguments.
333 *
334 * @type array $field Field array.
335 * @type string $html_id HTML ID.
336 * @type string $field_name Field name attribute.
337 * @type array $shortcode_atts Shortcode attributes.
338 * @type array $errors Field errors.
339 * @type bool $remove_names Remove name attribute or not.
340 * }
341 *
342 * @return void
343 */
344 protected function process_args_for_field_output( &$args ) {
345 $args['field'] = (array) $args['field'];
346
347 if ( ! isset( $args['html_id'] ) ) {
348 $args['html_id'] = $this->html_id();
349 }
350
351 if ( ! isset( $args['field_name'] ) ) {
352 $args['field_name'] = $this->html_name( $args['field']['name'] );
353 }
354
355 $args['sub_fields'] = $this->get_processed_sub_fields();
356
357 if ( ! isset( $args['shortcode_atts'] ) ) {
358 $args['shortcode_atts'] = array();
359 }
360
361 if ( ! isset( $args['errors'] ) ) {
362 $args['errors'] = array();
363 }
364 }
365
366 /**
367 * Prints sub field input atts.
368 *
369 * @param array $args Arguments. Includes `field`, `sub_field`.
370 *
371 * @return void
372 */
373 protected function print_input_atts( $args ) {
374 $field = $args['field'];
375 $sub_field = $args['sub_field'];
376
377 // Placeholder.
378 if ( in_array( 'placeholder', $sub_field['options'], true ) ) {
379 $placeholders = FrmField::get_option( $field, 'placeholder' );
380
381 if ( ! empty( $placeholders[ $sub_field['name'] ] ) ) {
382 $field['placeholder'] = $placeholders[ $sub_field['name'] ];
383 }
384 }
385
386 // Add optional class.
387 $classes = $sub_field['classes'] ?? '';
388
389 if ( is_array( $classes ) ) {
390 $classes = implode( ' ', $classes );
391 }
392
393 if ( ! empty( $sub_field['optional'] ) ) {
394 $classes .= ' frm_optional';
395 }
396
397 if ( $classes ) {
398 $field['input_class'] = esc_attr( $classes );
399 }
400
401 // Fake it to avoid printing frm-val attribute.
402 $field['default_value'] = '';
403
404 if ( ! empty( $sub_field['name'] ) ) {
405 $field['subfield_name'] = $sub_field['name'];
406 }
407
408 do_action( 'frm_field_input_html', $field );
409
410 // Print custom attributes.
411 if ( empty( $sub_field['atts'] ) || ! is_array( $sub_field['atts'] ) ) {
412 return;
413 }
414
415 foreach ( $sub_field['atts'] as $att_name => $att_value ) {
416 echo esc_attr( trim( $att_name ) ) . '="' . esc_attr( trim( $att_value ) ) . '" ';
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 $blank_msg = FrmFieldsHelper::get_error_msg( $this->field, 'blank' );
439 $sub_fields = $this->get_processed_sub_fields();
440
441 // Validate not empty.
442 foreach ( $sub_fields as $name => $sub_field ) {
443 if ( ! empty( $sub_field['optional'] ) || ! empty( $args['value'][ $name ] ) ) {
444 continue;
445 }
446
447 $errors[ 'field' . $args['id'] . '-' . $name ] = '';
448 $errors[ 'field' . $args['id'] ] = $blank_msg;
449 }
450
451 return $errors;
452 }
453
454 /**
455 * Gets export headings.
456 *
457 * @return array
458 */
459 public function get_export_headings() {
460 $headings = array();
461 $field_id = is_object( $this->field ) ? $this->field->id : $this->field['id'];
462 $field_name = is_object( $this->field ) ? $this->field->name : $this->field['name'];
463 $sub_fields = $this->get_processed_sub_fields();
464
465 // Include sub-field headings.
466 foreach ( $sub_fields as $name => $sub_field ) {
467 $headings[ $field_id . '_' . $name ] = $field_name . ' - ' . $sub_field['label'];
468 }
469
470 return $headings;
471 }
472
473 /**
474 * Get a list of all field settings that should be translated
475 * on a multilingual site.
476 *
477 * @since 3.06.01
478 *
479 * @return array
480 */
481 public function translatable_strings() {
482 $strings = parent::translatable_strings();
483
484 foreach ( $this->sub_fields as $name => $sub_field ) {
485 if ( in_array( 'desc', $sub_field['options'], true ) ) {
486 $strings[] = $name . '_desc';
487 }
488 }
489
490 return $strings;
491 }
492
493 /**
494 * Checks if should print hidden subfields and hide them. This is useful to use js to show or hide sub fields.
495 *
496 * @return bool
497 */
498 protected function should_print_hidden_sub_fields() {
499 return false;
500 }
501
502 /**
503 * Gets inputs container attributes.
504 *
505 * @return array
506 */
507 public function get_inputs_container_attrs() {
508 return array(
509 'class' => 'frm_combo_inputs_container',
510 'id' => 'frm_combo_inputs_container_' . $this->field_id,
511 );
512 }
513
514 /**
515 * Gets subfield input attributes.
516 *
517 * @since 6.26
518 *
519 * @param array $sub_field Subfield data.
520 * @param array $args Field output args. See {@see FrmFieldCombo::load_field_output()}.
521 *
522 * @return array
523 */
524 protected function get_sub_field_input_attrs( $sub_field, $args ) {
525 $attrs = array(
526 'type' => $sub_field['type'],
527 'id' => $args['html_id'] . '_' . $sub_field['name'],
528 'value' => '',
529 );
530
531 if ( ! empty( $args['field']['value'][ $sub_field['name'] ] ) ) {
532 $attrs['value'] = $args['field']['value'][ $sub_field['name'] ];
533 $attrs['data-frmval'] = $args['field']['value'][ $sub_field['name'] ];
534 }
535
536 if ( empty( $args['remove_names'] ) ) {
537 $attrs['name'] = $args['field_name'] . '[' . $sub_field['name'] . ']';
538 }
539
540 return $attrs;
541 }
542 }
543