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

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