PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / trunk
Secure Custom Fields vtrunk
6.9.1 6.9.0 6.8.9 6.8.7 6.8.8 6.8.6 6.8.4 6.8.5 trunk 6.4.0-beta1 6.4.0-beta2 6.4.1 6.4.1-beta3 6.4.1-beta4 6.4.1-beta5 6.4.1-beta6 6.4.1-beta7 6.4.2 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.5.6 6.5.7 6.6.0 6.7.0 6.7.1 6.8.0 6.8.1 6.8.2 6.8.3
secure-custom-fields / includes / acf-input-functions.php
secure-custom-fields / includes Last commit date
Blocks 1 week ago Datastore 1 month ago Meta 1 year ago abilities 1 week ago admin 1 week ago ajax 1 month ago api 11 hours ago fields 11 hours ago forms 11 hours ago legacy 1 year ago locations 1 year ago post-types 2 months ago rest-api 1 week ago walkers 1 year ago acf-bidirectional-functions.php 1 year ago acf-field-functions.php 2 months ago acf-field-group-functions.php 7 months ago acf-form-functions.php 1 year ago acf-helper-functions.php 1 year ago acf-hook-functions.php 1 year ago acf-input-functions.php 7 months ago acf-internal-post-type-functions.php 7 months ago acf-meta-functions.php 2 weeks ago acf-post-functions.php 1 year ago acf-post-type-functions.php 1 year ago acf-taxonomy-functions.php 1 year ago acf-user-functions.php 1 week ago acf-utility-functions.php 1 year ago acf-value-functions.php 1 year ago acf-wp-functions.php 11 hours ago assets.php 1 week ago blocks-auto-inline-editing.php 2 months ago blocks.php 3 weeks ago class-acf-data.php 10 months ago class-acf-internal-post-type.php 1 week ago class-acf-options-page.php 1 year ago class-acf-site-health.php 3 months ago class-scf-json-schema-validator.php 6 months ago class-scf-schema-builder.php 2 months ago compatibility.php 1 year ago datastore.php 1 month ago deprecated.php 1 year ago fields.php 10 months ago index.php 1 year ago l10n.php 1 year ago local-fields.php 1 year ago local-json.php 1 month ago local-meta.php 1 year ago locations.php 1 year ago loop.php 10 months ago media.php 1 year ago rest-api.php 10 months ago revisions.php 1 month ago scf-ui-options-page-functions.php 1 year ago third-party.php 7 months ago upgrades.php 2 weeks ago validation.php 10 months ago wpml.php 1 year ago
acf-input-functions.php
552 lines
1 <?php
2
3 /**
4 * acf_filter_attrs
5 *
6 * Filters out empty attrs from the provided array.
7 *
8 * @date 11/6/19
9 * @since ACF 5.8.1
10 *
11 * @param array $attrs The array of attrs.
12 * @return array
13 */
14 function acf_filter_attrs( $attrs ) {
15
16 // Filter out empty attrs but allow "0" values.
17 $filtered = array_filter( $attrs, 'acf_not_empty' );
18
19 // Correct specific attributes (required="required").
20 foreach ( array( 'required', 'readonly', 'disabled', 'multiple' ) as $key ) {
21 unset( $filtered[ $key ] );
22 if ( ! empty( $attrs[ $key ] ) ) {
23 $filtered[ $key ] = $key;
24 }
25 }
26 return $filtered;
27 }
28
29 /**
30 * acf_esc_attrs
31 *
32 * Generated valid HTML from an array of attrs.
33 *
34 * @date 11/6/19
35 * @since ACF 5.8.1
36 *
37 * @param array $attrs The array of attrs.
38 * @return string
39 */
40 function acf_esc_attrs( $attrs ) {
41 $html = '';
42
43 // Loop over attrs and validate data types.
44 foreach ( $attrs as $k => $v ) {
45
46 // String (but don't trim value).
47 if ( is_string( $v ) && ( $k !== 'value' ) ) {
48 $v = trim( $v );
49
50 // Boolean
51 } elseif ( is_bool( $v ) ) {
52 $v = $v ? 1 : 0;
53
54 // Object
55 } elseif ( is_array( $v ) || is_object( $v ) ) {
56 $v = json_encode( $v );
57 }
58
59 // Generate HTML.
60 $html .= sprintf( ' %s="%s"', esc_attr( $k ), esc_attr( $v ) );
61 }
62
63 // Return trimmed.
64 return trim( $html );
65 }
66
67
68 /**
69 * Sanitizes text content and strips out disallowed HTML.
70 *
71 * This function emulates `wp_kses_post()` with a context of "acf" for extensibility.
72 *
73 * @since ACF 5.9.6
74 *
75 * @param string $string The string to be escaped
76 * @return string|false
77 */
78 function acf_esc_html( $string = '' ) {
79
80 if ( ! is_scalar( $string ) ) {
81 return false;
82 }
83
84 return wp_kses( (string) $string, 'acf' );
85 }
86
87 /**
88 * Private callback for the "wp_kses_allowed_html" filter used to return allowed HTML for "acf" context.
89 *
90 * @since ACF 5.9.6
91 *
92 * @param array $tags An array of allowed tags.
93 * @param string $context The context name.
94 * @return array
95 */
96 function _acf_kses_allowed_html( $tags, $context ) {
97 global $allowedposttags;
98
99 if ( $context === 'acf' ) {
100 return $allowedposttags;
101 }
102 return $tags;
103 }
104
105 add_filter( 'wp_kses_allowed_html', '_acf_kses_allowed_html', 0, 2 );
106
107 /**
108 * acf_html_input
109 *
110 * Returns the HTML of an input.
111 *
112 * @date 13/6/19
113 * @since ACF 5.8.1
114 *
115 * @param array $attrs The array of attrs.
116 * @return string
117 */
118 // function acf_html_input( $attrs = array() ) {
119 // return sprintf( '<input %s/>', acf_esc_attrs($attrs) );
120 // }
121
122 /**
123 * acf_hidden_input
124 *
125 * Renders the HTML of a hidden input.
126 *
127 * @date 3/02/2014
128 * @since ACF 5.0.0
129 *
130 * @param array $attrs The array of attrs.
131 * @return void echos out value.
132 */
133 function acf_hidden_input( $attrs = array() ) {
134 echo acf_get_hidden_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
135 }
136
137 /**
138 * acf_get_hidden_input
139 *
140 * Returns the HTML of a hidden input.
141 *
142 * @date 3/02/2014
143 * @since ACF 5.0.0
144 *
145 * @param array $attrs The array of attrs.
146 * @return string
147 */
148 function acf_get_hidden_input( $attrs = array() ) {
149 return sprintf( '<input type="hidden" %s/>', acf_esc_attrs( $attrs ) );
150 }
151
152 /**
153 * acf_text_input
154 *
155 * Renders the HTML of a text input.
156 *
157 * @date 3/02/2014
158 * @since ACF 5.0.0
159 *
160 * @param array $attrs The array of attrs.
161 * @return void echos out value.
162 */
163 function acf_text_input( $attrs = array() ) {
164 echo acf_get_text_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
165 }
166
167 /**
168 * acf_get_text_input
169 *
170 * Returns the HTML of a text input.
171 *
172 * @date 3/02/2014
173 * @since ACF 5.0.0
174 *
175 * @param array $attrs The array of attrs.
176 * @return string
177 */
178 function acf_get_text_input( $attrs = array() ) {
179 $attrs = wp_parse_args(
180 $attrs,
181 array(
182 'type' => 'text',
183 )
184 );
185 if ( isset( $attrs['value'] ) && is_string( $attrs['value'] ) ) {
186 $attrs['value'] = htmlspecialchars( $attrs['value'] );
187 }
188 return sprintf( '<input %s/>', acf_esc_attrs( $attrs ) );
189 }
190
191 /**
192 * acf_file_input
193 *
194 * Renders the HTML of a file input.
195 *
196 * @date 3/02/2014
197 * @since ACF 5.0.0
198 *
199 * @param array $attrs The array of attrs.
200 * @return void echos out value.
201 */
202 function acf_file_input( $attrs = array() ) {
203 echo acf_get_file_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
204 }
205
206 /**
207 * acf_get_file_input
208 *
209 * Returns the HTML of a file input.
210 *
211 * @date 3/02/2014
212 * @since ACF 5.0.0
213 *
214 * @param array $attrs The array of attrs.
215 * @return string
216 */
217 function acf_get_file_input( $attrs = array() ) {
218 $field_key = isset( $attrs['key'] ) && is_string( $attrs['key'] ) ? $attrs['key'] : '';
219 $nonce_field = '';
220
221 /**
222 * If we don't have a field key (most likely because this was called by a third-party field),
223 * we have to try to guess the field key based on the field name.
224 */
225 if ( '' === $field_key ) {
226 $parts = explode( '[', $attrs['name'] );
227 if ( is_array( $parts ) && ! empty( $parts[1] ) ) {
228 // Remove the trailing `]`.
229 $field_key = substr( end( $parts ), 0, -1 );
230 }
231 }
232
233 /**
234 * We only output the nonce if we have a field key, as it's possible to render
235 * the file input without a real field. But, basic uploaders that don't have any
236 * custom logic will likely fail to upload anyway if they don't have a field key.
237 */
238 if ( '' !== $field_key ) {
239 $nonce_attrs = array(
240 'name' => 'acf[' . $field_key . '_file_nonce]',
241 'value' => wp_create_nonce( 'acf/file_uploader_nonce/' . $field_key ),
242 );
243 $nonce_field = sprintf(
244 '<input type="hidden" %s />',
245 acf_esc_attrs( $nonce_attrs )
246 );
247 }
248
249 return sprintf(
250 '<input type="file" %1$s />%2$s',
251 acf_esc_attrs( $attrs ),
252 $nonce_field
253 );
254 }
255
256 /**
257 * acf_textarea_input
258 *
259 * Renders the HTML of a textarea input.
260 *
261 * @date 3/02/2014
262 * @since ACF 5.0.0
263 *
264 * @param array $attrs The array of attrs.
265 * @return void echos out value.
266 */
267 function acf_textarea_input( $attrs = array() ) {
268 echo acf_get_textarea_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
269 }
270
271 /**
272 * acf_get_textarea_input
273 *
274 * Returns the HTML of a textarea input.
275 *
276 * @date 3/02/2014
277 * @since ACF 5.0.0
278 *
279 * @param array $attrs The array of attrs.
280 * @return string
281 */
282 function acf_get_textarea_input( $attrs = array() ) {
283 $value = '';
284 if ( isset( $attrs['value'] ) ) {
285 $value = $attrs['value'];
286 unset( $attrs['value'] );
287 }
288 return sprintf( '<textarea %s>%s</textarea>', acf_esc_attrs( $attrs ), esc_textarea( $value ) );
289 }
290
291 /**
292 * acf_checkbox_input
293 *
294 * Renders the HTML of a checkbox input.
295 *
296 * @date 3/02/2014
297 * @since ACF 5.0.0
298 *
299 * @param array $attrs The array of attrs.
300 * @return void echos out value.
301 */
302 function acf_checkbox_input( $attrs = array() ) {
303 echo acf_get_checkbox_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
304 }
305
306 /**
307 * acf_get_checkbox_input
308 *
309 * Returns the HTML of a checkbox input.
310 *
311 * @date 3/02/2014
312 * @since ACF 5.0.0
313 *
314 * @param array $attrs The array of attrs.
315 * @return string
316 */
317 function acf_get_checkbox_input( $attrs = array() ) {
318
319 // Allow radio or checkbox type.
320 $attrs = wp_parse_args(
321 $attrs,
322 array(
323 'type' => 'checkbox',
324 )
325 );
326
327 // Get label.
328 $label = '';
329 if ( isset( $attrs['label'] ) ) {
330 $label = $attrs['label'];
331 unset( $attrs['label'] );
332 }
333
334 // Render.
335 $checked = isset( $attrs['checked'] );
336
337 // Build label attributes array for accessibility and consistency.
338 $label_attrs = array();
339 if ( $checked ) {
340 $label_attrs['class'] = 'selected';
341 }
342
343 if ( ! empty( $attrs['button_group'] ) ) {
344 unset( $attrs['button_group'] );
345 // If tabindex is provided, use it for the label; otherwise, use checked-based default.
346 if ( isset( $attrs['tabindex'] ) ) {
347 $label_attrs['tabindex'] = (string) $attrs['tabindex'];
348 unset( $attrs['tabindex'] );
349 } else {
350 $label_attrs['tabindex'] = $checked ? '0' : '-1';
351 }
352 $label_attrs['role'] = 'radio';
353 $label_attrs['aria-checked'] = $checked ? 'true' : 'false';
354 }
355
356 return '<label' . ( acf_esc_attrs( $label_attrs ) ? ' ' . acf_esc_attrs( $label_attrs ) : '' ) . '><input ' . acf_esc_attrs( $attrs ) . '/> ' . acf_esc_html( $label ) . '</label>';
357 }
358
359 /**
360 * acf_radio_input
361 *
362 * Renders the HTML of a radio input.
363 *
364 * @date 3/02/2014
365 * @since ACF 5.0.0
366 *
367 * @param array $attrs The array of attrs.
368 * @return void echos out value.
369 */
370 function acf_radio_input( $attrs = array() ) {
371 echo acf_get_radio_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
372 }
373
374 /**
375 * acf_get_radio_input
376 *
377 * Returns the HTML of a radio input.
378 *
379 * @date 3/02/2014
380 * @since ACF 5.0.0
381 *
382 * @param array $attrs The array of attrs.
383 * @return string
384 */
385 function acf_get_radio_input( $attrs = array() ) {
386 $attrs['type'] = 'radio';
387 return acf_get_checkbox_input( $attrs );
388 }
389
390 /**
391 * acf_select_input
392 *
393 * Renders the HTML of a select input.
394 *
395 * @date 3/02/2014
396 * @since ACF 5.0.0
397 *
398 * @param array $attrs The array of attrs.
399 * @return void
400 */
401 function acf_select_input( $attrs = array() ) {
402 echo acf_get_select_input( $attrs ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by input generation function.
403 }
404
405 /**
406 * acf_select_input
407 *
408 * Returns the HTML of a select input.
409 *
410 * @date 3/02/2014
411 * @since ACF 5.0.0
412 *
413 * @param array $attrs The array of attrs.
414 * @return string
415 */
416 function acf_get_select_input( $attrs = array() ) {
417 $value = (array) acf_extract_var( $attrs, 'value' );
418 $choices = (array) acf_extract_var( $attrs, 'choices' );
419 return sprintf(
420 '<select %s>%s</select>',
421 acf_esc_attrs( $attrs ),
422 acf_walk_select_input( $choices, $value )
423 );
424 }
425
426 /**
427 * acf_walk_select_input
428 *
429 * Returns the HTML of a select input's choices.
430 *
431 * @date 27/6/17
432 * @since ACF 5.6.0
433 *
434 * @param array $choices The choices to walk through.
435 * @param array $values The selected choices.
436 * @param array $depth The current walk depth.
437 * @return string
438 */
439 function acf_walk_select_input( $choices = array(), $values = array(), $depth = 0 ) {
440 $html = '';
441
442 // Sanitize values for 'selected' matching (only once).
443 if ( $depth == 0 ) {
444 $values = array_map( 'esc_attr', $values );
445 }
446
447 // Loop over choices and append to html.
448 if ( $choices ) {
449 foreach ( $choices as $value => $label ) {
450
451 // Multiple (optgroup)
452 if ( is_array( $label ) ) {
453 $html .= sprintf(
454 '<optgroup label="%s">%s</optgroup>',
455 esc_attr( $value ),
456 acf_walk_select_input( $label, $values, $depth + 1 )
457 );
458
459 // single (option)
460 } else {
461 $attrs = array(
462 'value' => $value,
463 );
464
465 // If is selected.
466 $pos = array_search( esc_attr( $value ), $values );
467 if ( $pos !== false ) {
468 $attrs['selected'] = 'selected';
469 $attrs['data-i'] = $pos;
470 }
471 $html .= sprintf( '<option %s>%s</option>', acf_esc_attrs( $attrs ), esc_html( $label ) );
472 }
473 }
474 }
475 return $html;
476 }
477
478 /**
479 * acf_clean_atts
480 *
481 * See acf_filter_attrs().
482 *
483 * @date 3/10/17
484 * @since ACF 5.6.3
485 *
486 * @param array $attrs The array of attrs.
487 * @return string
488 */
489 function acf_clean_atts( $attrs ) {
490 return acf_filter_attrs( $attrs );
491 }
492
493 /**
494 * acf_esc_atts
495 *
496 * See acf_esc_attrs().
497 *
498 * @date 27/6/17
499 * @since ACF 5.6.0
500 *
501 * @param array $attrs The array of attrs.
502 * @return string
503 */
504 function acf_esc_atts( $attrs ) {
505 return acf_esc_attrs( $attrs );
506 }
507
508 /**
509 * acf_esc_attr
510 *
511 * @date 13/6/19
512 * @since ACF 5.8.1
513 * @deprecated 5.6.0
514 * @see acf_esc_attrs().
515 *
516 * @param array $attrs The array of attrs.
517 * @return string
518 */
519 function acf_esc_attr( $attrs ) {
520 return acf_esc_attrs( $attrs );
521 }
522
523 /**
524 * acf_esc_attr_e
525 *
526 * See acf_esc_attrs().
527 *
528 * @date 13/6/19
529 * @since ACF 5.8.1
530 * @deprecated 5.6.0
531 *
532 * @param array $attrs The array of attrs.
533 */
534 function acf_esc_attr_e( $attrs ) {
535 echo acf_esc_attrs( $attrs );
536 }
537
538 /**
539 * acf_esc_atts_e
540 *
541 * See acf_esc_attrs().
542 *
543 * @date 13/6/19
544 * @since ACF 5.8.1
545 * @deprecated 5.6.0
546 *
547 * @param array $attrs The array of attrs.
548 */
549 function acf_esc_atts_e( $attrs ) {
550 echo acf_esc_attrs( $attrs );
551 }
552