PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / trunk
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More vtrunk
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
← All changes | classes/models/fields/FrmFieldName.php +141 -24 6.4.2 → trunk View file →
@@ -2,8 +2,9 @@
2 2 /**
3 3 * Name field
4 4 *
5 5 * @package Formidable
6 + *
6 7 * @since 4.11
7 8 */
8 9
9 10 if ( ! defined( 'ABSPATH' ) ) {
@@ -12,11 +13,19 @@
12 13
13 14 class FrmFieldName extends FrmFieldCombo {
14 15
15 16 /**
17 + * Track the first name field ID in forms.
18 + *
19 + * @var array Array with keys are form ID and values are name field IDs.
20 + */
21 + private static $first_name_field_ids = array();
22 +
23 + /**
16 24 * Field name.
17 25 *
18 26 * @var string
27 + *
19 28 * @since 3.0
20 29 */
21 30 protected $type = 'name';
22 31
@@ -23,20 +32,25 @@
23 32 /**
24 33 * Could this field hold email values?
25 34 *
26 35 * @var bool
36 + *
27 37 * @since 3.0
28 38 */
29 39 protected $holds_email_values = true;
30 40
31 - public function __construct( $field = '', $type = '' ) {
41 + /**
42 + * @param array|int|object $field
43 + * @param string $type
44 + */
45 + public function __construct( $field = 0, $type = '' ) {
32 46 parent::__construct( $field, $type );
33 47
34 48 $this->register_sub_fields(
35 49 array(
36 - 'first' => __( 'First', 'formidable' ),
37 - 'middle' => __( 'Middle', 'formidable' ),
38 - 'last' => __( 'Last', 'formidable' ),
50 + 'first' => __( 'First Name', 'formidable' ),
51 + 'middle' => __( 'Middle Name', 'formidable' ),
52 + 'last' => __( 'Last Name', 'formidable' ),
39 53 )
40 54 );
41 55 }
42 56
@@ -46,14 +60,12 @@
46 60 *
47 61 * @return array
48 62 */
49 63 protected function get_processed_sub_fields() {
50 - $name_layout = $this->get_name_layout();
51 - $names = explode( '_', $name_layout );
52 - $col_class = 'frm' . intval( 12 / count( $names ) );
64 + $names = explode( '_', $this->get_name_layout() );
65 + $col_class = 'frm' . intval( 12 / count( $names ) );
66 + $result = array();
53 67
54 - $result = array();
55 -
56 68 foreach ( $names as $name ) {
57 69 if ( empty( $this->sub_fields[ $name ] ) ) {
58 70 continue;
59 71 }
@@ -78,12 +90,9 @@
78 90 * @return string
79 91 */
80 92 protected function get_name_layout() {
81 93 $name_layout = FrmField::get_option( $this->field, 'name_layout' );
82 - if ( ! $name_layout ) {
83 - $name_layout = 'first_last';
84 - }
85 - return $name_layout;
94 + return $name_layout ? $name_layout : 'first_last';
86 95 }
87 96
88 97 /**
89 98 * Gets extra field options.
@@ -124,8 +133,9 @@
124 133 * This also handles the shortcode output. Support [id], [id show=first], [id show=last], [id show=middle].
125 134 *
126 135 * @param mixed $value Field value before processing.
127 136 * @param array $atts Shortcode attributes.
137 + *
128 138 * @return string Most of cases, this will return string.
129 139 */
130 140 protected function prepare_display_value( $value, $atts ) {
131 141 if ( ! is_array( $value ) ) {
@@ -131,12 +141,10 @@
131 141 if ( ! is_array( $value ) ) {
132 142 return $value;
133 143 }
134 144
135 - $name_layout = $this->get_name_layout();
136 -
137 145 if ( ! empty( $atts['show'] ) ) {
138 - return isset( $value[ $atts['show'] ] ) ? $value[ $atts['show'] ] : '';
146 + return $value[ $atts['show'] ] ?? '';
139 147 }
140 148
141 149 $value = wp_parse_args(
142 150 $value,
@@ -146,9 +154,9 @@
146 154 'last' => '',
147 155 )
148 156 );
149 157
150 - switch ( $name_layout ) {
158 + switch ( $this->get_name_layout() ) {
151 159 case 'last_first':
152 160 $value = $value['last'] . ' ' . $value['first'];
153 161 break;
154 162
@@ -165,8 +173,10 @@
165 173
166 174 /**
167 175 * @since 4.0.04
168 176 *
177 + * @param array|string $value
178 + *
169 179 * @return void
170 180 */
171 181 public function sanitize_value( &$value ) {
172 182 FrmAppHelper::sanitize_value( 'sanitize_text_field', $value );
@@ -175,8 +185,9 @@
175 185 /**
176 186 * Validate field.
177 187 *
178 188 * @param array $args Arguments. Includes `errors`, `value`.
189 + *
179 190 * @return array Errors array.
180 191 */
181 192 public function validate( $args ) {
182 193 /**
@@ -206,15 +217,17 @@
206 217 protected function process_args_for_field_output( &$args ) {
207 218 parent::process_args_for_field_output( $args );
208 219
209 220 // Show all subfields in form builder then use JS to show or hide them.
210 - if ( $this->should_print_hidden_sub_fields() && count( $args['sub_fields'] ) !== count( $this->sub_fields ) ) {
211 - $hidden_fields = array_diff_key( $this->sub_fields, $args['sub_fields'] );
212 - $args['sub_fields'] = $this->sub_fields;
221 + if ( ! $this->should_print_hidden_sub_fields() || count( $args['sub_fields'] ) === count( $this->sub_fields ) ) {
222 + return;
223 + }
213 224
214 - foreach ( $hidden_fields as $name => $hidden_field ) {
215 - $args['sub_fields'][ $name ]['wrapper_classes'] .= ' frm_hidden';
216 - }
225 + $hidden_fields = array_diff_key( $this->sub_fields, $args['sub_fields'] );
226 + $args['sub_fields'] = $this->sub_fields;
227 +
228 + foreach ( $hidden_fields as $name => $hidden_field ) {
229 + $args['sub_fields'][ $name ]['wrapper_classes'] .= ' frm_hidden';
217 230 }
218 231 }
219 232
220 233 /**
@@ -231,11 +244,115 @@
231 244 * Gets inputs container attributes.
232 245 *
233 246 * @return array
234 247 */
235 - protected function get_inputs_container_attrs() {
248 + public function get_inputs_container_attrs() {
236 249 $attrs = parent::get_inputs_container_attrs();
237 250
238 251 $attrs['data-name-layout'] = $this->get_name_layout();
252 + return $attrs;
253 + }
254 +
255 + /**
256 + * Maybe show a warning if a name field is using a description that is not descriptive enough.
257 + * Prior to version 6.16, First and Last were the default values, but this has been updated to
258 + * improve accessibility.
259 + *
260 + * @since 6.16
261 + *
262 + * @param array $args
263 + *
264 + * @return void
265 + */
266 + public function show_after_default( $args ) {
267 + echo '<div class="frm-mt-xs">';
268 + parent::show_after_default( $args );
269 + echo '</div>';
270 +
271 + /**
272 + * @var array $field
273 + */
274 + $field = $args['field'];
275 +
276 + $show_warning = false;
277 +
278 + foreach ( $this->sub_fields as $sub_field ) {
279 + $description = FrmField::get_option( $field, $sub_field['name'] . '_desc' );
280 +
281 + if ( in_array( $description, array( 'First', 'Last' ), true ) ) {
282 + $show_warning = true;
283 + break;
284 + }
285 + }
286 +
287 + if ( ! $show_warning ) {
288 + return;
289 + }
290 + // phpcs:disable Generic.WhiteSpace.ScopeIndent
291 + ?>
292 + <div class="frm_warning_style">
293 + <?php
294 + FrmAppHelper::icon_by_class( 'frmfont frm_alert_icon', array( 'style' => 'width:24px' ) );
295 + echo ' ';
296 + esc_html_e( 'Subfield descriptions are read by screen readers. Enhance accessibility by using complete labels, like "First Name" instead of "First".', 'formidable' );
297 + ?>
298 + </div>
299 + <?php
300 + // phpcs:enable Generic.WhiteSpace.ScopeIndent
301 + }
302 +
303 + /**
304 + * Tracks the first name field ID in a form.
305 + *
306 + * @since 6.26
307 + *
308 + * @param object[] $fields Array of fields in a form.
309 + *
310 + * @return void
311 + */
312 + public static function track_first_name_field( $fields ) {
313 + foreach ( $fields as $field ) {
314 + if ( 'name' === $field->type ) {
315 + self::$first_name_field_ids[ $field->form_id ] = $field->id;
316 + return;
317 + }
318 + }
319 + }
320 +
321 + /**
322 + * Gets subfield input attributes.
323 + *
324 + * @since 6.26
325 + *
326 + * @param array $sub_field Subfield data.
327 + * @param array $args Field output args. See {@see FrmFieldCombo::load_field_output()}.
328 + *
329 + * @return array
330 + */
331 + protected function get_sub_field_input_attrs( $sub_field, $args ) {
332 + $attrs = parent::get_sub_field_input_attrs( $sub_field, $args );
333 + $form_id = (int) ( is_array( $args['field'] ) ? $args['field']['form_id'] : $args['field']->form_id );
334 +
335 + if ( ! self::$first_name_field_ids || empty( self::$first_name_field_ids[ $form_id ] ) ) {
336 + return $attrs;
337 + }
338 +
339 + $parent_form_id = (int) FrmField::get_option( $args['field'], 'parent_form_id' );
340 +
341 + if ( $form_id !== $parent_form_id ) {
342 + // Do not add autocomplete attribute to a name field inside repeater.
343 + return $attrs;
344 + }
345 +
346 + $field_id = (int) ( is_array( $args['field'] ) ? $args['field']['id'] : $args['field']->id );
347 +
348 + if ( intval( self::$first_name_field_ids[ $form_id ] ) === $field_id ) {
349 + if ( 'first' === $sub_field['name'] ) {
350 + $attrs['autocomplete'] = 'given-name';
351 + } elseif ( 'last' === $sub_field['name'] ) {
352 + $attrs['autocomplete'] = 'family-name';
353 + }
354 + }
355 +
239 356 return $attrs;
240 357 }
241 358 }