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

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