PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.9.0
Secure Custom Fields v6.9.0
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 / api / api-template.php
secure-custom-fields / includes / api Last commit date
api-helpers.php 1 week ago api-template.php 1 month ago api-term.php 1 year ago index.php 1 year ago
api-template.php
1561 lines
1 <?php
2
3 /**
4 * This function will return a custom field value for a specific field name/key + post_id.
5 * There is a 3rd parameter to turn on/off formatting. This means that an image field will not use
6 * its 'return option' to format the value but return only what was saved in the database
7 *
8 * @since ACF 3.6
9 *
10 * @param string $selector The field name or key.
11 * @param mixed $post_id The post_id of which the value is saved against.
12 * @param boolean $format_value Whether or not to format the value as described above.
13 * @param boolean $escape_html If we're formatting the value, make sure it's also HTML safe.
14 *
15 * @return mixed
16 */
17 function get_field( $selector, $post_id = false, $format_value = true, $escape_html = false ) {
18
19 // filter post_id
20 $post_id = acf_get_valid_post_id( $post_id );
21
22 // get field
23 $field = acf_maybe_get_field( $selector, $post_id );
24
25 // create dummy field
26 $dummy_field = false;
27 if ( ! $field ) {
28 $field = acf_get_valid_field(
29 array(
30 'name' => $selector,
31 'key' => '',
32 'type' => '',
33 )
34 );
35
36 // prevent formatting, flag as dummy in case $escape_html is true.
37 $format_value = false;
38 $dummy_field = true;
39 }
40
41 // get value for field
42 $value = acf_get_value( $post_id, $field );
43
44 // escape html is only compatible when formatting the value too
45 if ( ! $dummy_field && ! $format_value && $escape_html ) {
46 _doing_it_wrong( __FUNCTION__, __( 'Returning an escaped HTML value is only possible when format_value is also true. The field value has not been returned for security.', 'secure-custom-fields' ), '6.2.6' ); //phpcs:ignore -- escape not required.
47 return false;
48 }
49
50 // format value
51 if ( $format_value ) {
52 if ( $escape_html ) {
53 // return the escaped HTML version if requested.
54 if ( acf_field_type_supports( $field['type'], 'escaping_html' ) ) {
55 $value = acf_format_value( $value, $post_id, $field, true );
56 } else {
57 $new_value = acf_format_value( $value, $post_id, $field );
58 if ( is_array( $new_value ) ) {
59 $value = map_deep( $new_value, 'acf_esc_html' );
60 } else {
61 $value = acf_esc_html( $new_value );
62 }
63 }
64 } else {
65 // get value for field
66 $value = acf_format_value( $value, $post_id, $field );
67 }
68 }
69
70 // If we've built a dummy text field, we won't format the value, but they may still request it escaped. Use `acf_esc_html`
71 if ( $dummy_field && $escape_html ) {
72 if ( is_array( $value ) ) {
73 $value = map_deep( $value, 'acf_esc_html' );
74 } else {
75 $value = acf_esc_html( $value );
76 }
77 }
78
79 // return
80 return $value;
81 }
82
83 /**
84 * This function is the same as echo get_field(), but will escape the value for safe HTML output regardless of parameters.
85 *
86 * @since ACF 1.0.3
87 *
88 * @param string $selector The field name or key.
89 * @param mixed $post_id The post_id of which the value is saved against.
90 * @param boolean $format_value Enable formatting of value. Default true.
91 *
92 * @return void
93 */
94 function the_field( $selector, $post_id = false, $format_value = true ) {
95 $field = get_field_object( $selector, $post_id, $format_value, true, $format_value );
96 $value = $field ? $field['value'] : get_field( $selector, $post_id, $format_value, $format_value );
97
98 if ( is_array( $value ) ) {
99 $value = implode( ', ', $value );
100 }
101
102 // If we're not a scalar we'd throw an error, so return early for safety.
103 if ( ! is_scalar( $value ) ) {
104 return;
105 }
106
107 // If $format_value is false, we've not been able to apply field level escaping as we're giving the raw DB value. Escape the output with `acf_esc_html`.
108 if ( ! $format_value ) {
109 $value = acf_esc_html( $value );
110 }
111
112 // Get the unescaped value while we're still logging removed_unsafe_html.
113 $unescaped_value = get_field( $selector, $post_id, $format_value, false );
114 if ( is_array( $unescaped_value ) ) {
115 $unescaped_value = implode( ', ', $unescaped_value );
116 }
117
118 if ( ! is_scalar( $unescaped_value ) ) {
119 $unescaped_value = false;
120 }
121
122 $field_type = is_array( $field ) && isset( $field['type'] ) ? $field['type'] : 'text';
123 if ( apply_filters( 'acf/the_field/allow_unsafe_html', false, $selector, $post_id, $field_type, $field ) ) {
124 $value = $unescaped_value;
125 } elseif ( $unescaped_value !== false && (string) $value !== (string) $unescaped_value ) {
126 do_action( 'acf/removed_unsafe_html', __FUNCTION__, $selector, $field, $post_id );
127 }
128
129 echo $value; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped by logic above.
130 }
131
132 /**
133 * Logs instances of ACF successfully escaping unsafe HTML.
134 *
135 * @since ACF 6.2.5
136 *
137 * @param string $function The function that resulted in HTML being escaped.
138 * @param string $selector The selector (field key, name, etc.) passed to that function.
139 * @param array $field The field being queried when HTML was escaped.
140 * @param mixed $post_id The post ID the function was called on.
141 * @return void
142 */
143 function _acf_log_escaped_html( $function, $selector, $field, $post_id ) {
144 // If the notice isn't shown, no use in logging the errors.
145 if ( apply_filters( 'acf/admin/prevent_escaped_html_notice', true ) ) {
146 return;
147 }
148
149 // If the notice has been dismissed, don't log further errors.
150 if ( get_option( 'acf_escaped_html_notice_dismissed' ) ) {
151 return;
152 }
153
154 // If the field isn't set, we've output a non-ACF field, so don't log anything.
155 if ( ! is_array( $field ) ) {
156 return;
157 }
158
159 $escaped = _acf_get_escaped_html_log();
160
161 // Only store up to 100 results at a time.
162 if ( count( $escaped ) >= 100 ) {
163 return;
164 }
165
166 // Bail if we already logged an error for this field.
167 if ( isset( $escaped[ $field['key'] ] ) ) {
168 return;
169 }
170
171 $escaped[ $field['key'] ] = array(
172 'selector' => $selector,
173 'function' => $function,
174 'field' => $field['label'],
175 'post_id' => $post_id,
176 );
177
178 _acf_update_escaped_html_log( $escaped );
179 }
180 add_action( 'acf/removed_unsafe_html', '_acf_log_escaped_html', 10, 4 );
181
182 /**
183 * Returns an array of instances where HTML was altered due to escaping in the_field or a shortcode.
184 *
185 * @since ACF 6.2.5
186 *
187 * @return array
188 */
189 function _acf_get_escaped_html_log() {
190 $escaped = get_option( 'acf_escaped_html_log', array() );
191 return is_array( $escaped ) ? $escaped : array();
192 }
193
194 /**
195 * Updates the array of instances where HTML was altered due to escaping in the_field or a shortcode.
196 *
197 * @since ACF 6.2.5
198 *
199 * @param array $escaped The array of instances.
200 * @return boolean True on success, or false on failure.
201 */
202 function _acf_update_escaped_html_log( $escaped = array() ) {
203 return update_option( 'acf_escaped_html_log', (array) $escaped, false );
204 }
205
206 /**
207 * Deletes the array of instances where HTML was altered due to escaping in the_field or a shortcode.
208 * Since ACF 6.2.7, also clears the legacy `acf_will_escape_html_log` option to clean up.
209 *
210 * @since ACF 6.2.5
211 *
212 * @return boolean True on success, or false on failure.
213 */
214 function _acf_delete_escaped_html_log() {
215 delete_option( 'acf_will_escape_html_log' );
216 return delete_option( 'acf_escaped_html_log' );
217 }
218
219 /**
220 * This function will return an array containing all the field data for a given field_name.
221 *
222 * @since ACF 3.6
223 *
224 * @param string $selector The field name or key.
225 * @param mixed $post_id The post_id of which the value is saved against.
226 * @param boolean $format_value Whether to format the field value.
227 * @param boolean $load_value Whether to load the field value.
228 * @param boolean $escape_html Should the field return a HTML safe formatted value if $format_value is true.
229 *
230 * @return array|false $field
231 */
232 function get_field_object( $selector, $post_id = false, $format_value = true, $load_value = true, $escape_html = false ) {
233 // Compatibility with ACF ~4.
234 if ( is_array( $format_value ) && isset( $format_value['format_value'] ) ) {
235 $format_value = $format_value['format_value'];
236 }
237
238 $post_id = acf_get_valid_post_id( $post_id );
239 $field = acf_maybe_get_field( $selector, $post_id );
240
241 if ( ! $field ) {
242 return false;
243 }
244
245 if ( $load_value ) {
246 $field['value'] = acf_get_value( $post_id, $field );
247 }
248
249 // escape html is only compatible when formatting the value too
250 if ( ! $format_value && $escape_html ) {
251 _doing_it_wrong( __FUNCTION__, __( 'Returning an escaped HTML value is only possible when format_value is also true. The field value has not been returned for security.', 'secure-custom-fields' ), '6.2.6' ); //phpcs:ignore -- escape not required.
252 $field['value'] = false;
253 return $field;
254 }
255
256 // format value
257 if ( $load_value && $format_value ) {
258 if ( $escape_html ) {
259 // return the escaped HTML version if requested.
260 if ( acf_field_type_supports( $field['type'], 'escaping_html' ) ) {
261 $field['value'] = acf_format_value( $field['value'], $post_id, $field, true );
262 } else {
263 $new_value = acf_format_value( $field['value'], $post_id, $field );
264 if ( is_array( $new_value ) ) {
265 $field['value'] = map_deep( $new_value, 'acf_esc_html' );
266 } else {
267 $field['value'] = acf_esc_html( $new_value );
268 }
269 }
270 } else {
271 // get value for field
272 $field['value'] = acf_format_value( $field['value'], $post_id, $field );
273 }
274 }
275
276 return $field;
277 }
278
279 /**
280 * This function will return a field for the given selector.
281 * It will also review the field_reference to ensure the correct field is returned which makes it useful for the template API
282 *
283 * @since ACF 5.2.3
284 *
285 * @param $selector (mixed) identifier of field. Can be an ID, key, name or post object
286 * @param $post_id (mixed) the post_id of which the value is saved against
287 * @param $strict (boolean) if true, return a field only when a field key is found.
288 *
289 * @return $field (array)
290 */
291 function acf_maybe_get_field( $selector, $post_id = false, $strict = true ) {
292
293 // init
294 acf_init();
295
296 // Check if field key was given.
297 if ( acf_is_field_key( $selector ) ) {
298 return acf_get_field( $selector );
299 }
300
301 // Lookup field via reference.
302 $post_id = acf_get_valid_post_id( $post_id );
303 $field = acf_get_meta_field( $selector, $post_id );
304 if ( $field ) {
305 return $field;
306 }
307
308 // Lookup field loosely via name.
309 if ( ! $strict ) {
310 return acf_get_field( $selector );
311 }
312
313 // Return no result.
314 return false;
315 }
316
317 /**
318 * This function will attempt to find a sub field
319 *
320 * @since ACF 5.4.0
321 *
322 * @param $post_id (int)
323 * @return $post_id (int)
324 */
325 function acf_maybe_get_sub_field( $selectors, $post_id = false, $strict = true ) {
326
327 // bail early if not enough selectors
328 if ( ! is_array( $selectors ) || count( $selectors ) < 3 ) {
329 return false;
330 }
331
332 // vars
333 $offset = (int) acf_get_setting( 'row_index_offset' );
334 $selector = acf_extract_var( $selectors, 0 );
335 $selectors = array_values( $selectors ); // reset keys
336
337 // attempt get field
338 $field = acf_maybe_get_field( $selector, $post_id, $strict );
339
340 // bail early if no field
341 if ( ! $field ) {
342 return false;
343 }
344
345 // loop
346 for ( $j = 0; $j < count( $selectors ); $j += 2 ) {
347
348 // vars
349 $sub_i = (int) $selectors[ $j ];
350 $sub_s = $selectors[ $j + 1 ];
351 $field_name = $field['name'];
352
353 // find sub field
354 $field = acf_get_sub_field( $sub_s, $field );
355
356 // bail early if no sub field
357 if ( ! $field ) {
358 return false;
359 }
360
361 // add to name
362 $field['name'] = $field_name . '_' . ( $sub_i - $offset ) . '_' . $field['name'];
363 }
364
365 // return
366 return $field;
367 }
368
369 /**
370 * This function will return an array containing all the custom field values for a specific post_id.
371 * The function is not very elegant and wastes a lot of PHP memory / SQL queries if you are not using all the values.
372 *
373 * @since ACF 3.6
374 *
375 * @param mixed $post_id The post_id of which the value is saved against.
376 * @param boolean $format_value Whether or not to format the field value.
377 * @param boolean $escape_html Should the field return a HTML safe formatted value if $format_value is true.
378 *
379 * @return array|false Associative array where field name => field value, or false on failure.
380 */
381 function get_fields( $post_id = false, $format_value = true, $escape_html = false ) {
382
383 // escape html is only compatible when formatting the value too
384 if ( ! $format_value && $escape_html ) {
385 _doing_it_wrong( __FUNCTION__, __( 'Returning escaped HTML values is only possible when format_value is also true. The field values have not been returned for security.', 'secure-custom-fields' ), '6.2.6' ); //phpcs:ignore -- escape not required.
386 return false;
387 }
388
389 // vars
390 $fields = get_field_objects( $post_id, $format_value, true, $escape_html );
391 $meta = array();
392
393 // bail early
394 if ( ! $fields ) {
395 return false;
396 }
397
398 // populate
399 foreach ( $fields as $k => $field ) {
400 $meta[ $k ] = $field['value'];
401 }
402
403 // return
404 return $meta;
405 }
406
407
408 /**
409 * This function will return an array containing all the custom field objects for a specific post_id.
410 * The function is not very elegant and wastes a lot of PHP memory / SQL queries if you are not using all the fields / values.
411 *
412 * @since ACF 3.6
413 *
414 * @param mixed $post_id The post_id of which the value is saved against.
415 * @param boolean $format_value Whether or not to format the field value.
416 * @param boolean $load_value Whether or not to load the field value.
417 * @param boolean $escape_html Should the field return a HTML safe formatted value if $format_value is true.
418 *
419 * @return array|false Associative array where field name => field, or false on failure.
420 */
421 function get_field_objects( $post_id = false, $format_value = true, $load_value = true, $escape_html = false ) {
422
423 // init
424 acf_init();
425
426 // validate post_id
427 $post_id = acf_get_valid_post_id( $post_id );
428
429 // get meta
430 $meta = acf_get_meta( $post_id );
431
432 // bail early if no meta
433 if ( empty( $meta ) ) {
434 return false;
435 }
436
437 // escape html is only compatible when formatting the value too
438 if ( ! $format_value && $escape_html ) {
439 _doing_it_wrong( __FUNCTION__, __( 'Returning escaped HTML values is only possible when format_value is also true. The field values have not been returned for security.', 'secure-custom-fields' ), '6.2.6' ); //phpcs:ignore -- escape not required.
440 }
441
442 // populate vars
443 $fields = array();
444 foreach ( $meta as $key => $value ) {
445
446 // bail if reference key does not exist
447 if ( ! isset( $meta[ "_$key" ] ) || ( ! is_string( $meta[ "_$key" ] ) && ! is_numeric( $meta[ "_$key" ] ) ) ) {
448 continue;
449 }
450
451 // get field
452 $field = acf_get_field( $meta[ "_$key" ] );
453
454 // bail early if no field, or if the field's name is different to $key
455 // - solves problem where sub fields (and clone fields) are incorrectly allowed
456 if ( ! $field || $field['name'] !== $key ) {
457 continue;
458 }
459
460 // load value
461 if ( $load_value ) {
462 $field['value'] = acf_get_value( $post_id, $field );
463 }
464
465 // avoid returning field values when the function is called incorrectly.
466 if ( ! $format_value && $escape_html ) {
467 $field['value'] = false;
468 }
469
470 // format value
471 if ( $load_value && $format_value ) {
472 if ( $escape_html ) {
473 // return the escaped HTML version if requested.
474 if ( acf_field_type_supports( $field['type'], 'escaping_html' ) ) {
475 $field['value'] = acf_format_value( $field['value'], $post_id, $field, true );
476 } else {
477 $new_value = acf_format_value( $field['value'], $post_id, $field );
478 if ( is_array( $new_value ) ) {
479 $field['value'] = map_deep( $new_value, 'acf_esc_html' );
480 } else {
481 $field['value'] = acf_esc_html( $new_value );
482 }
483 }
484 } else {
485 // get value for field
486 $field['value'] = acf_format_value( $field['value'], $post_id, $field );
487 }
488 }
489
490 // append to $value
491 $fields[ $key ] = $field;
492 }
493
494 // no value
495 if ( empty( $fields ) ) {
496 return false;
497 }
498
499 // return
500 return $fields;
501 }
502
503
504 /**
505 * Checks if a field (such as Repeater or Flexible Content) has any rows of data to loop over.
506 * This function is intended to be used in conjunction with the_row() to step through available values.
507 *
508 * @since ACF 4.3.0
509 *
510 * @param string $selector The field name or field key.
511 * @param mixed $post_id The post ID where the value is saved. Defaults to the current post.
512 * @return boolean
513 */
514 function have_rows( $selector, $post_id = false ) {
515
516 // Validate and backup $post_id.
517 $_post_id = $post_id;
518 $post_id = acf_get_valid_post_id( $post_id );
519
520 // Vars.
521 $key = "selector={$selector}/post_id={$post_id}";
522 $active_loop = acf_get_loop( 'active' );
523 $prev_loop = acf_get_loop( 'previous' );
524 $new_loop = false;
525 $sub_field = false;
526
527 // Check if no active loop.
528 if ( ! $active_loop ) {
529 $new_loop = 'parent';
530
531 // Detect "change" compared to the active loop.
532 } elseif ( $key !== $active_loop['key'] ) {
533
534 // Find sub field and check if a sub value exists.
535 $sub_field_exists = false;
536 $sub_field = acf_get_sub_field( $selector, $active_loop['field'] );
537 if ( $sub_field ) {
538 $sub_field_exists = isset( $active_loop['value'][ $active_loop['i'] ][ $sub_field['key'] ] );
539 }
540
541 // Detect change in post_id.
542 if ( $post_id != $active_loop['post_id'] ) {
543
544 // Case: Change in $post_id was due to this being a nested loop and not specifying the $post_id.
545 // Action: Move down one level into a new loop.
546 if ( empty( $_post_id ) && $sub_field_exists ) {
547 $new_loop = 'child';
548
549 // Case: Change in $post_id was due to a nested loop ending.
550 // Action: move up one level through the loops.
551 } elseif ( $prev_loop && $prev_loop['post_id'] == $post_id ) {
552 acf_remove_loop( 'active' );
553 $active_loop = $prev_loop;
554
555 // Case: Chang in $post_id is the most obvious, used in an WP_Query loop with multiple $post objects.
556 // Action: leave this current loop alone and create a new parent loop.
557 } else {
558 $new_loop = 'parent';
559 }
560
561 // Detect change in selector.
562 } elseif ( $selector != $active_loop['selector'] ) {
563
564 // Case: Change in $field_name was due to this being a nested loop.
565 // Action: move down one level into a new loop.
566 if ( $sub_field_exists ) {
567 $new_loop = 'child';
568
569 // Case: Change in $field_name was due to a nested loop ending.
570 // Action: move up one level through the loops.
571 } elseif ( $prev_loop && $prev_loop['selector'] == $selector && $prev_loop['post_id'] == $post_id ) {
572 acf_remove_loop( 'active' );
573 $active_loop = $prev_loop;
574
575 // Case: Change in $field_name is the most obvious, this is a new loop for a different field within the $post.
576 // Action: leave this current loop alone and create a new parent loop.
577 } else {
578 $new_loop = 'parent';
579 }
580 }
581 }
582
583 // Add loop if required.
584 if ( $new_loop ) {
585 $args = array(
586 'key' => $key,
587 'selector' => $selector,
588 'post_id' => $post_id,
589 'name' => null,
590 'value' => null,
591 'field' => null,
592 'i' => -1,
593 );
594
595 // Case: Parent loop.
596 if ( $new_loop === 'parent' ) {
597 $field = get_field_object( $selector, $post_id, false );
598 if ( $field ) {
599 $args['field'] = $field;
600 $args['value'] = $field['value'];
601 $args['name'] = $field['name'];
602 unset( $args['field']['value'] );
603 }
604
605 // Case: Child loop ($sub_field must exist).
606 } else {
607 $args['field'] = $sub_field;
608 $args['value'] = $active_loop['value'][ $active_loop['i'] ][ $sub_field['key'] ];
609 $args['name'] = "{$active_loop['name']}_{$active_loop['i']}_{$sub_field['name']}";
610 $args['post_id'] = $active_loop['post_id'];
611 }
612
613 // Bail early if value is either empty or a non array.
614 if ( ! $args['value'] || ! is_array( $args['value'] ) ) {
615 return false;
616 }
617
618 // Allow for non repeatable data for Group and Clone fields.
619 if ( acf_get_field_type_prop( $args['field']['type'], 'have_rows' ) === 'single' ) {
620 $args['value'] = array( $args['value'] );
621 }
622
623 // Add loop.
624 $active_loop = acf_add_loop( $args );
625 }
626
627 // Return true if next row exists.
628 if ( $active_loop && isset( $active_loop['value'][ (int) $active_loop['i'] + 1 ] ) ) {
629 return true;
630 }
631
632 // Return false if no next row.
633 acf_remove_loop( 'active' );
634 return false;
635 }
636
637
638 /**
639 * This function will progress the global repeater or flexible content value 1 row
640 *
641 * @since ACF 4.3.0
642 *
643 * @param N/A
644 * @return (array) the current row data
645 */
646 function the_row( $format = false ) {
647
648 // vars
649 $i = acf_get_loop( 'active', 'i' );
650
651 // increase
652 ++$i;
653
654 // update
655 acf_update_loop( 'active', 'i', $i );
656
657 // return
658 return get_row( $format );
659 }
660
661 function get_row( $format = false ) {
662
663 // vars
664 $loop = acf_get_loop( 'active' );
665
666 // bail early if no loop
667 if ( ! $loop ) {
668 return false;
669 }
670
671 // get value
672 $value = acf_maybe_get( $loop['value'], $loop['i'] );
673
674 // bail early if no current value
675 // possible if get_row_layout() is called before the_row()
676 if ( ! $value ) {
677 return false;
678 }
679
680 // format
681 if ( $format ) {
682
683 // vars
684 $field = $loop['field'];
685
686 // single row
687 if ( acf_get_field_type_prop( $field['type'], 'have_rows' ) === 'single' ) {
688
689 // format value
690 $value = acf_format_value( $value, $loop['post_id'], $field );
691
692 // multiple rows
693 } else {
694
695 // format entire value
696 // - solves problem where cached value is incomplete
697 // - no performance issues here thanks to cache
698 $value = acf_format_value( $loop['value'], $loop['post_id'], $field );
699 $value = acf_maybe_get( $value, $loop['i'] );
700 }
701 }
702
703 // return
704 return $value;
705 }
706
707 function get_row_index() {
708
709 // vars
710 $i = (int) acf_get_loop( 'active', 'i' );
711 $offset = (int) acf_get_setting( 'row_index_offset' );
712
713 // return
714 return $offset + $i;
715 }
716
717 function the_row_index() {
718 echo intval( get_row_index() );
719 }
720
721
722 /**
723 * This function is used inside a 'has_sub_field' while loop to return a sub field object
724 *
725 * @since ACF 5.3.8
726 *
727 * @param $selector (string)
728 * @return (array)
729 */
730 function get_row_sub_field( $selector ) {
731
732 // vars
733 $row = acf_get_loop( 'active' );
734
735 // bail early if no row
736 if ( ! $row ) {
737 return false;
738 }
739
740 // attempt to find sub field
741 $sub_field = acf_get_sub_field( $selector, $row['field'] );
742
743 // bail early if no field
744 if ( ! $sub_field ) {
745 return false;
746 }
747
748 // update field's name based on row data
749 $sub_field['name'] = "{$row['name']}_{$row['i']}_{$sub_field['name']}";
750
751 // return
752 return $sub_field;
753 }
754
755
756 /**
757 * This function is used inside a 'has_sub_field' while loop to return a sub field value
758 *
759 * @since ACF 5.3.8
760 *
761 * @param $selector (string)
762 * @return (mixed)
763 */
764 function get_row_sub_value( $selector ) {
765
766 // vars
767 $row = acf_get_loop( 'active' );
768
769 // bail early if no row
770 if ( ! $row ) {
771 return null;
772 }
773
774 // return value
775 if ( isset( $row['value'][ $row['i'] ][ $selector ] ) ) {
776 return $row['value'][ $row['i'] ][ $selector ];
777 }
778
779 // return
780 return null;
781 }
782
783
784 /**
785 * This function will find the current loop and unset it from the global array.
786 * To be used when loop finishes or a break is used
787 *
788 * @since ACF 5.0.0
789 *
790 * @param $hard_reset (boolean) completely wipe the global variable, or just unset the active row
791 * @return (boolean)
792 */
793 function reset_rows() {
794
795 // remove last loop
796 acf_remove_loop( 'active' );
797
798 // return
799 return true;
800 }
801
802
803 /**
804 * This function is used inside a while loop to return either true or false (loop again or stop).
805 * When using a repeater or flexible content field, it will loop through the rows until
806 * there are none left or a break is detected
807 *
808 * @since ACF 1.0.3
809 *
810 * @param $field_name (string) the field name
811 * @param $post_id (mixed) the post_id of which the value is saved against
812 * @return (boolean)
813 */
814 function has_sub_field( $field_name, $post_id = false ) {
815
816 // vars
817 $r = have_rows( $field_name, $post_id );
818
819 // if has rows, progress through 1 row for the while loop to work
820 if ( $r ) {
821 the_row();
822 }
823
824 // return
825 return $r;
826 }
827
828 /**
829 * Alias of has_sub_field
830 */
831 function has_sub_fields( $field_name, $post_id = false ) {
832 return has_sub_field( $field_name, $post_id );
833 }
834
835
836 /**
837 * This function is used inside a 'has_sub_field' while loop to return a sub field value
838 *
839 * @since ACF 1.0.3
840 *
841 * @param string $selector The field name or key.
842 * @param boolean $format_value Whether or not to format the value as described above.
843 * @param boolean $escape_html If we're formatting the value, make sure it's also HTML safe.
844 *
845 * @return mixed
846 */
847 function get_sub_field( $selector = '', $format_value = true, $escape_html = false ) {
848
849 // get sub field
850 $sub_field = get_sub_field_object( $selector, $format_value, true, $escape_html );
851
852 // bail early if no sub field
853 if ( ! $sub_field ) {
854 return false;
855 }
856
857 // return
858 return $sub_field['value'];
859 }
860
861
862 /**
863 * This function is the same as echo get_sub_field(), but will escape the value for safe HTML output.
864 *
865 * @since ACF 1.0.3
866 *
867 * @param string $field_name The field name.
868 * @param boolean $format_value Enable formatting of value. When false, the field value will be escaped at this level with `acf_esc_html`. Default true.
869 *
870 * @return void
871 */
872 function the_sub_field( $field_name, $format_value = true ) {
873 $field = get_sub_field_object( $field_name, $format_value, true, $format_value );
874 $value = ( is_array( $field ) && isset( $field['value'] ) ) ? $field['value'] : false;
875
876 if ( is_array( $value ) ) {
877 $value = implode( ', ', $value );
878 }
879
880 // If we're not a scalar we'd throw an error, so return early for safety.
881 if ( ! is_scalar( $value ) ) {
882 return;
883 }
884
885 // If $format_value is false, we've not been able to apply field level escaping as we're giving the raw DB value. Escape the output with `acf_esc_html`.
886 if ( ! $format_value ) {
887 $value = acf_esc_html( $value );
888 }
889
890 $unescaped_field = get_sub_field_object( $field_name, $format_value, true, false );
891 $unescaped_value = ( is_array( $unescaped_field ) && isset( $unescaped_field['value'] ) ) ? $unescaped_field['value'] : false;
892 if ( is_array( $unescaped_value ) ) {
893 $unescaped_value = implode( ', ', $unescaped_value );
894 }
895
896 if ( ! is_scalar( $unescaped_value ) ) {
897 $unescaped_value = false;
898 }
899
900 $field_type = is_array( $field ) && isset( $field['type'] ) ? $field['type'] : 'text';
901 if ( apply_filters( 'acf/the_field/allow_unsafe_html', false, $field_name, 'sub_field', $field_type, $field ) ) {
902 $value = $unescaped_value;
903 } elseif ( $unescaped_value !== false && (string) $value !== (string) $unescaped_value ) {
904 do_action( 'acf/removed_unsafe_html', __FUNCTION__, $field_name, $field, false );
905 }
906
907 echo $value; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped inside get_sub_field_object where necessary.
908 }
909
910
911 /**
912 * This function is used inside a 'has_sub_field' while loop to return a sub field object
913 *
914 * @since ACF 3.5.8.1
915 *
916 * @param string $selector The field name or key.
917 * @param boolean $format_value Whether to format the field value.
918 * @param boolean $load_value Whether to load the field value.
919 * @param boolean $escape_html Should the field return a HTML safe formatted value.
920 *
921 * @return mixed
922 */
923 function get_sub_field_object( $selector, $format_value = true, $load_value = true, $escape_html = false ) {
924
925 $row = acf_get_loop( 'active' );
926
927 // bail early if no row
928 if ( ! $row ) {
929 return false;
930 }
931
932 // attempt to find sub field
933 $sub_field = get_row_sub_field( $selector );
934
935 // bail early if no sub field
936 if ( ! $sub_field ) {
937 return false;
938 }
939
940 // load value
941 if ( $load_value ) {
942 $sub_field['value'] = get_row_sub_value( $sub_field['key'] );
943 }
944
945 // escape html is only compatible when formatting the value too
946 if ( ! $format_value && $escape_html ) {
947 _doing_it_wrong( __FUNCTION__, __( 'Returning an escaped HTML value is only possible when format_value is also true. The field value has not been returned for security.', 'secure-custom-fields' ), '6.2.6' ); //phpcs:ignore -- escape not required.
948 $sub_field['value'] = false;
949 }
950
951 // format value
952 if ( $load_value && $format_value ) {
953 if ( $escape_html ) {
954 // return the escaped HTML version if requested.
955 if ( acf_field_type_supports( $sub_field['type'], 'escaping_html' ) ) {
956 $sub_field['value'] = acf_format_value( $sub_field['value'], $row['post_id'], $sub_field, true );
957 } else {
958 $new_value = acf_format_value( $sub_field['value'], $row['post_id'], $sub_field );
959 if ( is_array( $new_value ) ) {
960 $sub_field['value'] = map_deep( $new_value, 'acf_esc_html' );
961 } else {
962 $sub_field['value'] = acf_esc_html( $new_value );
963 }
964 }
965 } else {
966 // get value for field
967 $sub_field['value'] = acf_format_value( $sub_field['value'], $row['post_id'], $sub_field );
968 }
969 }
970
971 // return
972 return $sub_field;
973 }
974
975
976 /**
977 * This function will return a string representation of the current row layout within a 'have_rows' loop
978 *
979 * @since ACF 3.0.6
980 *
981 * @return mixed
982 */
983 function get_row_layout() {
984
985 // vars
986 $row = get_row();
987
988 // return
989 if ( isset( $row['acf_fc_layout'] ) ) {
990 return $row['acf_fc_layout'];
991 }
992
993 // return
994 return false;
995 }
996
997 /**
998 * This function is used to add basic shortcode support for the ACF plugin
999 * eg. [acf field="heading" post_id="123" format_value="1"]
1000 *
1001 * @since ACF 1.1.1
1002 *
1003 * @param array $atts The shortcode attributes.
1004 *
1005 * @return string|void
1006 */
1007 function acf_shortcode( $atts ) {
1008 // Return if the ACF shortcode is disabled.
1009 if ( ! acf_get_setting( 'enable_shortcode' ) ) {
1010 if ( is_preview() ) {
1011 return apply_filters( 'acf/shortcode/disabled_message', esc_html__( '[The ACF shortcode is disabled on this site]', 'secure-custom-fields' ) );
1012 } else {
1013 return;
1014 }
1015 }
1016
1017 if ( function_exists( 'wp_is_block_theme' ) && wp_is_block_theme() ) {
1018 // Prevent the ACF shortcode in FSE block template parts by default.
1019 if ( ! doing_filter( 'the_content' ) && ! apply_filters( 'acf/shortcode/allow_in_block_themes_outside_content', false ) ) {
1020 return;
1021 }
1022 }
1023
1024 // Limit previews of ACF shortcode data for users without publish_posts permissions.
1025 $preview_capability = apply_filters( 'acf/shortcode/preview_capability', 'publish_posts' );
1026 if ( is_preview() && ! current_user_can( $preview_capability ) ) {
1027 return apply_filters( 'acf/shortcode/preview_capability_message', esc_html__( '[ACF shortcode value disabled for preview]', 'secure-custom-fields' ) );
1028 }
1029
1030 // Mitigate issue where some AJAX requests can return ACF field data.
1031 $ajax_capability = apply_filters( 'acf/ajax/shortcode_capability', 'edit_posts' );
1032 if ( wp_doing_ajax() && ( $ajax_capability !== false ) && ! current_user_can( $ajax_capability ) ) {
1033 return;
1034 }
1035
1036 $atts = shortcode_atts(
1037 array(
1038 'field' => '',
1039 'post_id' => false,
1040 'format_value' => true,
1041 ),
1042 $atts,
1043 'acf'
1044 );
1045
1046 // Decode the post ID for filtering.
1047 $post_id = acf_get_valid_post_id( $atts['post_id'] );
1048 $decoded_post_id = acf_decode_post_id( $post_id );
1049
1050 // If we've decoded to a post, ensure the post is publicly visible.
1051 if ( $decoded_post_id['type'] === 'post' ) {
1052 if ( $atts['post_id'] !== false && ( (int) $atts['post_id'] !== (int) acf_get_valid_post_id() ) && ( ! is_post_publicly_viewable( $decoded_post_id['id'] ) ) && apply_filters( 'acf/shortcode/prevent_access_to_fields_on_non_public_posts', true ) ) {
1053 if ( is_preview() ) {
1054 return apply_filters( 'acf/shortcode/post_not_public_message', esc_html__( '[The ACF shortcode cannot display fields from non-public posts]', 'secure-custom-fields' ) );
1055 } else {
1056 return;
1057 }
1058 }
1059 }
1060
1061 $access_already_prevented = apply_filters( 'acf/prevent_access_to_unknown_fields', false );
1062 $filter_applied = false;
1063
1064 if ( ! $access_already_prevented ) {
1065 $filter_applied = true;
1066 add_filter( 'acf/prevent_access_to_unknown_fields', '__return_true' );
1067 }
1068
1069 // Try to get the field value, ensuring any non-safe HTML is stripped from wysiwyg fields via `acf_the_content`
1070 $field = get_field_object( $atts['field'], $post_id, $atts['format_value'], true, true );
1071 $value = $field ? $field['value'] : get_field( $atts['field'], $post_id, $atts['format_value'], true );
1072
1073 $field_type = is_array( $field ) && isset( $field['type'] ) ? $field['type'] : 'text';
1074
1075 // Allow config errors to show for appropriate caps checked users.
1076 $display_errors_to_user = apply_filters( 'acf/shortcode/display_admin_errors', 'manage_options' );
1077
1078 if ( ! acf_field_type_supports( $field_type, 'bindings', true ) ) {
1079 if ( is_preview() || current_user_can( $display_errors_to_user ) ) {
1080 return apply_filters( 'acf/shortcode/field_not_supported_message', '[' . esc_html__( 'The requested ACF field type does not support output in bindings or the ACF Shortcode.', 'secure-custom-fields' ) . ']' );
1081 } else {
1082 return;
1083 }
1084 }
1085
1086 if ( isset( $field['allow_in_bindings'] ) && ! $field['allow_in_bindings'] ) {
1087 if ( is_preview() || current_user_can( $display_errors_to_user ) ) {
1088 return apply_filters( 'acf/shortcode/field_not_allowed_message', '[' . esc_html__( 'The requested ACF field is not allowed to be output in bindings or the ACF Shortcode.', 'secure-custom-fields' ) . ']' );
1089 } else {
1090 return;
1091 }
1092 }
1093
1094 if ( apply_filters( 'acf/shortcode/prevent_access', false, $atts, $decoded_post_id['id'], $decoded_post_id['type'], $field_type, $field ) ) {
1095 return;
1096 }
1097
1098 if ( is_array( $value ) ) {
1099 $value = implode( ', ', $value );
1100 }
1101
1102 // Temporarily always get the unescaped version for action comparison.
1103 $unescaped_value = get_field( $atts['field'], $post_id, $atts['format_value'], false );
1104
1105 // Remove the filter preventing access to unknown filters now we've got all the values.
1106 if ( $filter_applied ) {
1107 remove_filter( 'acf/prevent_access_to_unknown_fields', '__return_true' );
1108 }
1109
1110 if ( is_array( $unescaped_value ) ) {
1111 $unescaped_value = implode( ', ', $unescaped_value );
1112 }
1113
1114 if ( ! is_scalar( $unescaped_value ) ) {
1115 $unescaped_value = false;
1116 }
1117
1118 // Handle getting the unescaped version if we're allowed unsafe html.
1119 if ( apply_filters( 'acf/shortcode/allow_unsafe_html', false, $atts, $field_type, $field ) ) {
1120 $value = $unescaped_value;
1121 } elseif ( $unescaped_value !== false && (string) $value !== (string) $unescaped_value ) {
1122 do_action( 'acf/removed_unsafe_html', __FUNCTION__, $atts['field'], $field, $post_id );
1123 }
1124
1125 return $value;
1126 }
1127 add_shortcode( 'acf', 'acf_shortcode' );
1128
1129
1130 /**
1131 * This function will update a value in the database
1132 *
1133 * @since ACF 3.1.9
1134 *
1135 * @param string $selector The field name or key.
1136 * @param mixed $value The value to save in the database.
1137 * @param mixed $post_id The post_id of which the value is saved against.
1138 *
1139 * @return boolean
1140 */
1141 function update_field( $selector, $value, $post_id = false ) {
1142
1143 // filter post_id
1144 $post_id = acf_get_valid_post_id( $post_id );
1145
1146 // get field
1147 $field = acf_maybe_get_field( $selector, $post_id, false );
1148
1149 // create dummy field
1150 if ( ! $field ) {
1151 $field = acf_get_valid_field(
1152 array(
1153 'name' => $selector,
1154 'key' => '',
1155 'type' => '',
1156 )
1157 );
1158 }
1159
1160 // save
1161 return acf_update_value( $value, $post_id, $field );
1162 }
1163
1164
1165 /**
1166 * This function will update a value of a sub field in the database
1167 *
1168 * @since ACF 5.0.0
1169 *
1170 * @param $selector (mixed) the sub field name or key, or an array of ancestors
1171 * @param $value (mixed) the value to save in the database
1172 * @param $post_id (mixed) the post_id of which the value is saved against
1173 *
1174 * @return boolean
1175 */
1176 function update_sub_field( $selector, $value, $post_id = false ) {
1177
1178 // vars
1179 $sub_field = false;
1180
1181 // get sub field
1182 if ( is_array( $selector ) ) {
1183 $post_id = acf_get_valid_post_id( $post_id );
1184 $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false );
1185 } else {
1186 $post_id = acf_get_loop( 'active', 'post_id' );
1187 $sub_field = get_row_sub_field( $selector );
1188 }
1189
1190 // bail early if no sub field
1191 if ( ! $sub_field ) {
1192 return false;
1193 }
1194
1195 // update
1196 return acf_update_value( $value, $post_id, $sub_field );
1197 }
1198
1199
1200 /**
1201 * This function will remove a value from the database
1202 *
1203 * @since ACF 3.1.9
1204 *
1205 * @param $selector (string) the field name or key
1206 * @param $post_id (mixed) the post_id of which the value is saved against
1207 *
1208 * @return boolean
1209 */
1210 function delete_field( $selector, $post_id = false ) {
1211
1212 // filter post_id
1213 $post_id = acf_get_valid_post_id( $post_id );
1214
1215 // get field
1216 $field = acf_maybe_get_field( $selector, $post_id );
1217
1218 // delete
1219 return $field ? acf_delete_value( $post_id, $field ) : false;
1220 }
1221
1222
1223 /**
1224 * This function will delete a value of a sub field in the database
1225 *
1226 * @since ACF 5.0.0
1227 *
1228 * @param $selector (mixed) the sub field name or key, or an array of ancestors
1229 * @param $value (mixed) the value to save in the database
1230 * @param $post_id (mixed) the post_id of which the value is saved against
1231 * @return (boolean)
1232 */
1233 function delete_sub_field( $selector, $post_id = false ) {
1234 return update_sub_field( $selector, null, $post_id );
1235 }
1236
1237
1238 /**
1239 * This function will add a row of data to a field
1240 *
1241 * @since ACF 5.2.3
1242 *
1243 * @param $selector (string)
1244 * @param $row (array)
1245 * @param $post_id (mixed)
1246 * @return (boolean)
1247 */
1248 function add_row( $selector, $row = false, $post_id = false ) {
1249
1250 // filter post_id
1251 $post_id = acf_get_valid_post_id( $post_id );
1252
1253 // get field
1254 $field = acf_maybe_get_field( $selector, $post_id, false );
1255
1256 // bail early if no field
1257 if ( ! $field ) {
1258 return false;
1259 }
1260
1261 // get raw value
1262 $value = acf_get_value( $post_id, $field );
1263
1264 // ensure array
1265 $value = acf_get_array( $value );
1266
1267 // append
1268 $value[] = $row;
1269
1270 // Paginated repeaters should be saved normally.
1271 $field['pagination'] = false;
1272
1273 // update value
1274 acf_update_value( $value, $post_id, $field );
1275
1276 // return
1277 return count( $value );
1278 }
1279
1280
1281 /**
1282 * This function will add a row of data to a field
1283 *
1284 * @since ACF 5.2.3
1285 *
1286 * @param $selector (string)
1287 * @param $row (array)
1288 * @param $post_id (mixed)
1289 * @return (boolean)
1290 */
1291 function add_sub_row( $selector, $row = false, $post_id = false ) {
1292
1293 // vars
1294 $sub_field = false;
1295
1296 // get sub field
1297 if ( is_array( $selector ) ) {
1298 $post_id = acf_get_valid_post_id( $post_id );
1299 $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false );
1300 } else {
1301 $post_id = acf_get_loop( 'active', 'post_id' );
1302 $sub_field = get_row_sub_field( $selector );
1303 }
1304
1305 // bail early if no sub field
1306 if ( ! $sub_field ) {
1307 return false;
1308 }
1309
1310 // get raw value
1311 $value = acf_get_value( $post_id, $sub_field );
1312
1313 // ensure array
1314 $value = acf_get_array( $value );
1315
1316 // append
1317 $value[] = $row;
1318
1319 // update
1320 acf_update_value( $value, $post_id, $sub_field );
1321
1322 // return
1323 return count( $value );
1324 }
1325
1326
1327 /**
1328 * This function will update a row of data to a field
1329 *
1330 * @since ACF 5.2.3
1331 *
1332 * @param $selector (string)
1333 * @param $i (int)
1334 * @param $row (array)
1335 * @param $post_id (mixed)
1336 * @return (boolean)
1337 */
1338 function update_row( $selector, $i = 1, $row = false, $post_id = false ) {
1339
1340 // vars
1341 $offset = (int) acf_get_setting( 'row_index_offset' );
1342 $i = (int) $i - $offset;
1343
1344 // filter post_id
1345 $post_id = acf_get_valid_post_id( $post_id );
1346
1347 // get field
1348 $field = acf_maybe_get_field( $selector, $post_id, false );
1349
1350 // bail early if no field
1351 if ( ! $field ) {
1352 return false;
1353 }
1354
1355 // get raw value
1356 $value = acf_get_value( $post_id, $field );
1357
1358 // ensure array
1359 $value = acf_get_array( $value );
1360
1361 // update
1362 $value[ $i ] = $row;
1363
1364 // update value
1365 acf_update_value( $value, $post_id, $field );
1366
1367 // return
1368 return true;
1369 }
1370
1371
1372 /**
1373 * This function will add a row of data to a field
1374 *
1375 * @since ACF 5.2.3
1376 *
1377 * @param $selector (string)
1378 * @param $row (array)
1379 * @param $post_id (mixed)
1380 * @return (boolean)
1381 */
1382 function update_sub_row( $selector, $i = 1, $row = false, $post_id = false ) {
1383
1384 // vars
1385 $sub_field = false;
1386 $offset = (int) acf_get_setting( 'row_index_offset' );
1387 $i = (int) $i - $offset;
1388
1389 // get sub field
1390 if ( is_array( $selector ) ) {
1391 $post_id = acf_get_valid_post_id( $post_id );
1392 $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false );
1393 } else {
1394 $post_id = acf_get_loop( 'active', 'post_id' );
1395 $sub_field = get_row_sub_field( $selector );
1396 }
1397
1398 // bail early if no sub field
1399 if ( ! $sub_field ) {
1400 return false;
1401 }
1402
1403 // get raw value
1404 $value = acf_get_value( $post_id, $sub_field );
1405
1406 // ensure array
1407 $value = acf_get_array( $value );
1408
1409 // append
1410 $value[ $i ] = $row;
1411
1412 // update
1413 acf_update_value( $value, $post_id, $sub_field );
1414
1415 // return
1416 return true;
1417 }
1418
1419
1420 /**
1421 * This function will delete a row of data from a field
1422 *
1423 * @since ACF 5.2.3
1424 *
1425 * @param $selector (string)
1426 * @param $i (int)
1427 * @param $post_id (mixed)
1428 * @return (boolean)
1429 */
1430 function delete_row( $selector, $i = 1, $post_id = false ) {
1431
1432 // vars
1433 $offset = (int) acf_get_setting( 'row_index_offset' );
1434 $i = (int) $i - $offset;
1435
1436 // filter post_id
1437 $post_id = acf_get_valid_post_id( $post_id );
1438
1439 // get field
1440 $field = acf_maybe_get_field( $selector, $post_id );
1441
1442 // bail early if no field
1443 if ( ! $field ) {
1444 return false;
1445 }
1446
1447 // get value
1448 $value = acf_get_value( $post_id, $field );
1449
1450 // ensure array
1451 $value = acf_get_array( $value );
1452
1453 // bail early if index doesn't exist
1454 if ( ! isset( $value[ $i ] ) ) {
1455 return false;
1456 }
1457
1458 // unset
1459 unset( $value[ $i ] );
1460
1461 // update
1462 acf_update_value( $value, $post_id, $field );
1463
1464 // return
1465 return true;
1466 }
1467
1468
1469 /**
1470 * This function will add a row of data to a field
1471 *
1472 * @since ACF 5.2.3
1473 *
1474 * @param $selector (string)
1475 * @param $row (array)
1476 * @param $post_id (mixed)
1477 * @return (boolean)
1478 */
1479 function delete_sub_row( $selector, $i = 1, $post_id = false ) {
1480
1481 // vars
1482 $sub_field = false;
1483 $offset = (int) acf_get_setting( 'row_index_offset' );
1484 $i = (int) $i - $offset;
1485
1486 // get sub field
1487 if ( is_array( $selector ) ) {
1488 $post_id = acf_get_valid_post_id( $post_id );
1489 $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false );
1490 } else {
1491 $post_id = acf_get_loop( 'active', 'post_id' );
1492 $sub_field = get_row_sub_field( $selector );
1493 }
1494
1495 // bail early if no sub field
1496 if ( ! $sub_field ) {
1497 return false;
1498 }
1499
1500 // get raw value
1501 $value = acf_get_value( $post_id, $sub_field );
1502
1503 // ensure array
1504 $value = acf_get_array( $value );
1505
1506 // bail early if index doesn't exist
1507 if ( ! isset( $value[ $i ] ) ) {
1508 return false;
1509 }
1510
1511 // append
1512 unset( $value[ $i ] );
1513
1514 // update
1515 acf_update_value( $value, $post_id, $sub_field );
1516
1517 // return
1518 return true;
1519 }
1520
1521
1522 /**
1523 * Deprecated Functions
1524 *
1525 * These functions are outdated
1526 *
1527 * @since ACF 1.0.0
1528 *
1529 * @param n/a
1530 * @return n/a
1531 */
1532 function create_field( $field ) {
1533
1534 acf_render_field( $field );
1535 }
1536
1537 function render_field( $field ) {
1538
1539 acf_render_field( $field );
1540 }
1541
1542 function reset_the_repeater_field() {
1543
1544 return reset_rows();
1545 }
1546
1547 function the_repeater_field( $field_name, $post_id = false ) {
1548
1549 return has_sub_field( $field_name, $post_id );
1550 }
1551
1552 function the_flexible_field( $field_name, $post_id = false ) {
1553
1554 return has_sub_field( $field_name, $post_id );
1555 }
1556
1557 function acf_filter_post_id( $post_id ) {
1558
1559 return acf_get_valid_post_id( $post_id );
1560 }
1561