PluginProbe ʕ •ᴥ•ʔ
Advanced Custom Fields (ACF®) / 6.8.9
Advanced Custom Fields (ACF®) v6.8.9
6.8.9 6.8.8 6.8.7 6.8.6 6.8.5 6.8.4 6.8.3 6.8.2 6.8.1 5.8.5 5.8.6 5.8.7 5.8.8 5.8.9 5.9.0 5.9.1 5.9.2 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 5.9.9 6.0.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.0.6 6.0.7 6.1.0 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.1.6 6.1.7 6.1.8 6.2.0 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.6.1 6.2.7 6.2.8 6.2.9 6.3.0 6.3.1 6.3.10.2 6.3.11 6.3.12 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.6.1 6.4.0 6.4.0.1 6.4.1 6.4.2 6.4.3 6.5.0 6.5.1 6.6.0 6.6.1 6.6.2 6.7.0 6.7.1 6.7.2 6.8.0 trunk 1.0.0 1.0.2 1.0.3 1.0.5 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.1.1 2.1.3 2.1.4 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.6 3.0.7 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 3.5.8 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.8 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.8 4.3.9 4.4.0 4.4.1 4.4.10 4.4.11 4.4.12 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 5.10 5.10.1 5.10.2 5.11 5.11.1 5.11.2 5.11.3 5.11.4 5.12 5.12.1 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.6.10 5.6.2 5.6.3 5.6.4 5.6.5 5.6.6 5.6.7 5.6.8 5.6.9 5.7.0 5.7.1 5.7.10 5.7.12 5.7.13 5.7.2 5.7.3 5.7.4 5.7.5 5.7.6 5.7.7 5.7.8 5.7.9 5.8.0 5.8.1 5.8.10 5.8.11 5.8.12 5.8.13 5.8.14 5.8.2 5.8.3 5.8.4
advanced-custom-fields / includes / acf-input-functions.php
advanced-custom-fields / includes Last commit date
admin 1 month ago ajax 3 months ago api 2 weeks ago fields 4 weeks ago forms 4 weeks ago legacy 5 months ago locations 1 month ago post-types 5 months ago rest-api 4 weeks ago walkers 5 months ago acf-bidirectional-functions.php 5 months ago acf-field-functions.php 5 months ago acf-field-group-functions.php 5 months ago acf-form-functions.php 5 months ago acf-helper-functions.php 5 months ago acf-hook-functions.php 5 months ago acf-input-functions.php 5 months ago acf-internal-post-type-functions.php 5 months ago acf-meta-functions.php 2 months ago acf-post-functions.php 5 months ago acf-post-type-functions.php 5 months ago acf-taxonomy-functions.php 5 months ago acf-user-functions.php 5 months ago acf-utility-functions.php 5 months ago acf-value-functions.php 5 months ago acf-wp-functions.php 5 months ago assets.php 5 months ago class-acf-data.php 5 months ago class-acf-internal-post-type.php 5 months ago compatibility.php 5 months ago deprecated.php 5 months ago fields.php 5 months ago index.php 2 years ago l10n.php 5 months ago local-fields.php 5 months ago local-json.php 3 months ago local-meta.php 5 months ago locations.php 5 months ago loop.php 5 months ago media.php 6 days ago rest-api.php 5 months ago revisions.php 3 months ago third-party.php 5 months ago upgrades.php 2 months ago validation.php 5 months ago wpml.php 5 months ago
acf-input-functions.php
561 lines
1 <?php
2 /**
3 * @package ACF
4 * @author WP Engine
5 *
6 * © 2026 Advanced Custom Fields (ACF®). All rights reserved.
7 * "ACF" is a trademark of WP Engine.
8 * Licensed under the GNU General Public License v2 or later.
9 * https://www.gnu.org/licenses/gpl-2.0.html
10 */
11
12 /**
13 * acf_filter_attrs
14 *
15 * Filters out empty attrs from the provided array.
16 *
17 * @date 11/6/19
18 * @since 5.8.1
19 *
20 * @param array $attrs The array of attrs.
21 * @return array
22 */
23 function acf_filter_attrs( $attrs ) {
24
25 // Filter out empty attrs but allow "0" values.
26 $filtered = array_filter( $attrs, 'acf_not_empty' );
27
28 // Correct specific attributes (required="required").
29 foreach ( array( 'required', 'readonly', 'disabled', 'multiple' ) as $key ) {
30 unset( $filtered[ $key ] );
31 if ( ! empty( $attrs[ $key ] ) ) {
32 $filtered[ $key ] = $key;
33 }
34 }
35 return $filtered;
36 }
37
38 /**
39 * acf_esc_attrs
40 *
41 * Generated valid HTML from an array of attrs.
42 *
43 * @date 11/6/19
44 * @since 5.8.1
45 *
46 * @param array $attrs The array of attrs.
47 * @return string
48 */
49 function acf_esc_attrs( $attrs ) {
50 $html = '';
51
52 // Loop over attrs and validate data types.
53 foreach ( $attrs as $k => $v ) {
54
55 // String (but don't trim value).
56 if ( is_string( $v ) && ( $k !== 'value' ) ) {
57 $v = trim( $v );
58
59 // Boolean
60 } elseif ( is_bool( $v ) ) {
61 $v = $v ? 1 : 0;
62
63 // Object
64 } elseif ( is_array( $v ) || is_object( $v ) ) {
65 $v = json_encode( $v );
66 }
67
68 // Generate HTML.
69 $html .= sprintf( ' %s="%s"', esc_attr( $k ), esc_attr( $v ) );
70 }
71
72 // Return trimmed.
73 return trim( $html );
74 }
75
76
77 /**
78 * Sanitizes text content and strips out disallowed HTML.
79 *
80 * This function emulates `wp_kses_post()` with a context of "acf" for extensibility.
81 *
82 * @since 5.9.6
83 *
84 * @param string $string The string to be escaped
85 * @return string|false
86 */
87 function acf_esc_html( $string = '' ) {
88
89 if ( ! is_scalar( $string ) ) {
90 return false;
91 }
92
93 return wp_kses( (string) $string, 'acf' );
94 }
95
96 /**
97 * Private callback for the "wp_kses_allowed_html" filter used to return allowed HTML for "acf" context.
98 *
99 * @since 5.9.6
100 *
101 * @param array $tags An array of allowed tags.
102 * @param string $context The context name.
103 * @return array
104 */
105 function _acf_kses_allowed_html( $tags, $context ) {
106 global $allowedposttags;
107
108 if ( $context === 'acf' ) {
109 return $allowedposttags;
110 }
111 return $tags;
112 }
113
114 add_filter( 'wp_kses_allowed_html', '_acf_kses_allowed_html', 0, 2 );
115
116 /**
117 * acf_html_input
118 *
119 * Returns the HTML of an input.
120 *
121 * @date 13/6/19
122 * @since 5.8.1
123 *
124 * @param array $attrs The array of attrs.
125 * @return string
126 */
127 // function acf_html_input( $attrs = array() ) {
128 // return sprintf( '<input %s/>', acf_esc_attrs($attrs) );
129 // }
130
131 /**
132 * acf_hidden_input
133 *
134 * Renders the HTML of a hidden input.
135 *
136 * @date 3/02/2014
137 * @since 5.0.0
138 *
139 * @param array $attrs The array of attrs.
140 * @return string
141 */
142 function acf_hidden_input( $attrs = array() ) {
143 echo acf_get_hidden_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
144 }
145
146 /**
147 * acf_get_hidden_input
148 *
149 * Returns the HTML of a hidden input.
150 *
151 * @date 3/02/2014
152 * @since 5.0.0
153 *
154 * @param array $attrs The array of attrs.
155 * @return string
156 */
157 function acf_get_hidden_input( $attrs = array() ) {
158 return sprintf( '<input type="hidden" %s/>', acf_esc_attrs( $attrs ) );
159 }
160
161 /**
162 * acf_text_input
163 *
164 * Renders the HTML of a text input.
165 *
166 * @date 3/02/2014
167 * @since 5.0.0
168 *
169 * @param array $attrs The array of attrs.
170 * @return string
171 */
172 function acf_text_input( $attrs = array() ) {
173 echo acf_get_text_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
174 }
175
176 /**
177 * acf_get_text_input
178 *
179 * Returns the HTML of a text input.
180 *
181 * @date 3/02/2014
182 * @since 5.0.0
183 *
184 * @param array $attrs The array of attrs.
185 * @return string
186 */
187 function acf_get_text_input( $attrs = array() ) {
188 $attrs = wp_parse_args(
189 $attrs,
190 array(
191 'type' => 'text',
192 )
193 );
194 if ( isset( $attrs['value'] ) && is_string( $attrs['value'] ) ) {
195 $attrs['value'] = htmlspecialchars( $attrs['value'] );
196 }
197 return sprintf( '<input %s/>', acf_esc_attrs( $attrs ) );
198 }
199
200 /**
201 * acf_file_input
202 *
203 * Renders the HTML of a file input.
204 *
205 * @date 3/02/2014
206 * @since 5.0.0
207 *
208 * @param array $attrs The array of attrs.
209 * @return string
210 */
211 function acf_file_input( $attrs = array() ) {
212 echo acf_get_file_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
213 }
214
215 /**
216 * acf_get_file_input
217 *
218 * Returns the HTML of a file input.
219 *
220 * @date 3/02/2014
221 * @since 5.0.0
222 *
223 * @param array $attrs The array of attrs.
224 * @return string
225 */
226 function acf_get_file_input( $attrs = array() ) {
227 $field_key = isset( $attrs['key'] ) && is_string( $attrs['key'] ) ? $attrs['key'] : '';
228 $nonce_field = '';
229
230 /**
231 * If we don't have a field key (most likely because this was called by a third-party field),
232 * we have to try to guess the field key based on the field name.
233 */
234 if ( '' === $field_key ) {
235 $parts = explode( '[', $attrs['name'] );
236 if ( is_array( $parts ) && ! empty( $parts[1] ) ) {
237 // Remove the trailing `]`.
238 $field_key = substr( end( $parts ), 0, -1 );
239 }
240 }
241
242 /**
243 * We only output the nonce if we have a field key, as it's possible to render
244 * the file input without a real field. But, basic uploaders that don't have any
245 * custom logic will likely fail to upload anyway if they don't have a field key.
246 */
247 if ( '' !== $field_key ) {
248 $nonce_attrs = array(
249 'name' => 'acf[' . $field_key . '_file_nonce]',
250 'value' => wp_create_nonce( 'acf/file_uploader_nonce/' . $field_key ),
251 );
252 $nonce_field = sprintf(
253 '<input type="hidden" %s />',
254 acf_esc_attrs( $nonce_attrs )
255 );
256 }
257
258 return sprintf(
259 '<input type="file" %1$s />%2$s',
260 acf_esc_attrs( $attrs ),
261 $nonce_field
262 );
263 }
264
265 /**
266 * acf_textarea_input
267 *
268 * Renders the HTML of a textarea input.
269 *
270 * @date 3/02/2014
271 * @since 5.0.0
272 *
273 * @param array $attrs The array of attrs.
274 * @return string
275 */
276 function acf_textarea_input( $attrs = array() ) {
277 echo acf_get_textarea_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
278 }
279
280 /**
281 * acf_get_textarea_input
282 *
283 * Returns the HTML of a textarea input.
284 *
285 * @date 3/02/2014
286 * @since 5.0.0
287 *
288 * @param array $attrs The array of attrs.
289 * @return string
290 */
291 function acf_get_textarea_input( $attrs = array() ) {
292 $value = '';
293 if ( isset( $attrs['value'] ) ) {
294 $value = $attrs['value'];
295 unset( $attrs['value'] );
296 }
297 return sprintf( '<textarea %s>%s</textarea>', acf_esc_attrs( $attrs ), esc_textarea( $value ) );
298 }
299
300 /**
301 * acf_checkbox_input
302 *
303 * Renders the HTML of a checkbox input.
304 *
305 * @date 3/02/2014
306 * @since 5.0.0
307 *
308 * @param array $attrs The array of attrs.
309 * @return string
310 */
311 function acf_checkbox_input( $attrs = array() ) {
312 echo acf_get_checkbox_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
313 }
314
315 /**
316 * acf_get_checkbox_input
317 *
318 * Returns the HTML of a checkbox input.
319 *
320 * @date 3/02/2014
321 * @since 5.0.0
322 *
323 * @param array $attrs The array of attrs.
324 * @return string
325 */
326 function acf_get_checkbox_input( $attrs = array() ) {
327
328 // Allow radio or checkbox type.
329 $attrs = wp_parse_args(
330 $attrs,
331 array(
332 'type' => 'checkbox',
333 )
334 );
335
336 // Get label.
337 $label = '';
338 if ( isset( $attrs['label'] ) ) {
339 $label = $attrs['label'];
340 unset( $attrs['label'] );
341 }
342
343 // Render.
344 $checked = isset( $attrs['checked'] );
345
346 // Build label attributes array for accessibility and consistency.
347 $label_attrs = array();
348 if ( $checked ) {
349 $label_attrs['class'] = 'selected';
350 }
351
352 if ( ! empty( $attrs['button_group'] ) ) {
353 unset( $attrs['button_group'] );
354 // If tabindex is provided, use it for the label; otherwise, use checked-based default.
355 if ( isset( $attrs['tabindex'] ) ) {
356 $label_attrs['tabindex'] = (string) $attrs['tabindex'];
357 unset( $attrs['tabindex'] );
358 } else {
359 $label_attrs['tabindex'] = $checked ? '0' : '-1';
360 }
361 $label_attrs['role'] = 'radio';
362 $label_attrs['aria-checked'] = $checked ? 'true' : 'false';
363 }
364
365 return '<label' . ( acf_esc_attrs( $label_attrs ) ? ' ' . acf_esc_attrs( $label_attrs ) : '' ) . '><input ' . acf_esc_attrs( $attrs ) . '/> ' . acf_esc_html( $label ) . '</label>';
366 }
367
368 /**
369 * acf_radio_input
370 *
371 * Renders the HTML of a radio input.
372 *
373 * @date 3/02/2014
374 * @since 5.0.0
375 *
376 * @param array $attrs The array of attrs.
377 * @return string
378 */
379 function acf_radio_input( $attrs = array() ) {
380 echo acf_get_radio_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
381 }
382
383 /**
384 * acf_get_radio_input
385 *
386 * Returns the HTML of a radio input.
387 *
388 * @date 3/02/2014
389 * @since 5.0.0
390 *
391 * @param array $attrs The array of attrs.
392 * @return string
393 */
394 function acf_get_radio_input( $attrs = array() ) {
395 $attrs['type'] = 'radio';
396 return acf_get_checkbox_input( $attrs );
397 }
398
399 /**
400 * acf_select_input
401 *
402 * Renders the HTML of a select input.
403 *
404 * @date 3/02/2014
405 * @since 5.0.0
406 *
407 * @param array $attrs The array of attrs.
408 * @return string
409 */
410 function acf_select_input( $attrs = array() ) {
411 echo acf_get_select_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
412 }
413
414 /**
415 * acf_select_input
416 *
417 * Returns the HTML of a select input.
418 *
419 * @date 3/02/2014
420 * @since 5.0.0
421 *
422 * @param array $attrs The array of attrs.
423 * @return string
424 */
425 function acf_get_select_input( $attrs = array() ) {
426 $value = (array) acf_extract_var( $attrs, 'value' );
427 $choices = (array) acf_extract_var( $attrs, 'choices' );
428 return sprintf(
429 '<select %s>%s</select>',
430 acf_esc_attrs( $attrs ),
431 acf_walk_select_input( $choices, $value )
432 );
433 }
434
435 /**
436 * acf_walk_select_input
437 *
438 * Returns the HTML of a select input's choices.
439 *
440 * @date 27/6/17
441 * @since 5.6.0
442 *
443 * @param array $choices The choices to walk through.
444 * @param array $values The selected choices.
445 * @param array $depth The current walk depth.
446 * @return string
447 */
448 function acf_walk_select_input( $choices = array(), $values = array(), $depth = 0 ) {
449 $html = '';
450
451 // Sanitize values for 'selected' matching (only once).
452 if ( $depth == 0 ) {
453 $values = array_map( 'esc_attr', $values );
454 }
455
456 // Loop over choices and append to html.
457 if ( $choices ) {
458 foreach ( $choices as $value => $label ) {
459
460 // Multiple (optgroup)
461 if ( is_array( $label ) ) {
462 $html .= sprintf(
463 '<optgroup label="%s">%s</optgroup>',
464 esc_attr( $value ),
465 acf_walk_select_input( $label, $values, $depth + 1 )
466 );
467
468 // single (option)
469 } else {
470 $attrs = array(
471 'value' => $value,
472 );
473
474 // If is selected.
475 $pos = array_search( esc_attr( $value ), $values );
476 if ( $pos !== false ) {
477 $attrs['selected'] = 'selected';
478 $attrs['data-i'] = $pos;
479 }
480 $html .= sprintf( '<option %s>%s</option>', acf_esc_attrs( $attrs ), esc_html( $label ) );
481 }
482 }
483 }
484 return $html;
485 }
486
487 /**
488 * acf_clean_atts
489 *
490 * See acf_filter_attrs().
491 *
492 * @date 3/10/17
493 * @since 5.6.3
494 *
495 * @param array $attrs The array of attrs.
496 * @return string
497 */
498 function acf_clean_atts( $attrs ) {
499 return acf_filter_attrs( $attrs );
500 }
501
502 /**
503 * acf_esc_atts
504 *
505 * See acf_esc_attrs().
506 *
507 * @date 27/6/17
508 * @since 5.6.0
509 *
510 * @param array $attrs The array of attrs.
511 * @return string
512 */
513 function acf_esc_atts( $attrs ) {
514 return acf_esc_attrs( $attrs );
515 }
516
517 /**
518 * acf_esc_attr
519 *
520 * @date 13/6/19
521 * @since 5.8.1
522 * @deprecated 5.6.0
523 * @see acf_esc_attrs().
524 *
525 * @param array $attrs The array of attrs.
526 * @return string
527 */
528 function acf_esc_attr( $attrs ) {
529 return acf_esc_attrs( $attrs );
530 }
531
532 /**
533 * acf_esc_attr_e
534 *
535 * See acf_esc_attrs().
536 *
537 * @date 13/6/19
538 * @since 5.8.1
539 * @deprecated 5.6.0
540 *
541 * @param array $attrs The array of attrs.
542 */
543 function acf_esc_attr_e( $attrs ) {
544 echo acf_esc_attrs( $attrs );
545 }
546
547 /**
548 * acf_esc_atts_e
549 *
550 * See acf_esc_attrs().
551 *
552 * @date 13/6/19
553 * @since 5.8.1
554 * @deprecated 5.6.0
555 *
556 * @param array $attrs The array of attrs.
557 */
558 function acf_esc_atts_e( $attrs ) {
559 echo acf_esc_attrs( $attrs );
560 }
561