1971 lines
34 KiB
PHP
1971 lines
34 KiB
PHP
<?php
|
|
|
|
/*
|
|
* acf_get_field_types
|
|
*
|
|
* This function will return all available field types
|
|
*
|
|
* @type function
|
|
* @date 1/10/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param n/a
|
|
* @return (array)
|
|
*/
|
|
|
|
function acf_get_field_types() {
|
|
|
|
return apply_filters('acf/get_field_types', array());
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_get_field_type_label
|
|
*
|
|
* This function will return the label of a field type
|
|
*
|
|
* @type function
|
|
* @date 1/10/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param n/a
|
|
* @return (array)
|
|
*/
|
|
|
|
function acf_get_field_type_label( $field_type ) {
|
|
|
|
// vars
|
|
$field_types = acf_get_field_types();
|
|
|
|
|
|
// loop through categories
|
|
foreach( $field_types as $category ) {
|
|
|
|
if( isset( $category[ $field_type ] ) ) {
|
|
|
|
return $category[ $field_type ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// return
|
|
return '';
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_field_type_exists
|
|
*
|
|
* This function will check if the field_type is available
|
|
*
|
|
* @type function
|
|
* @date 1/10/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $field_type (string)
|
|
* @return (boolean)
|
|
*/
|
|
|
|
function acf_field_type_exists( $field_type ) {
|
|
|
|
// vars
|
|
$label = acf_get_field_type_label( $field_type );
|
|
|
|
|
|
// return true if label exists
|
|
if( $label !== '' ) return true;
|
|
|
|
|
|
// return
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_is_field_key
|
|
*
|
|
* This function will return true or false for the given $field_key parameter
|
|
*
|
|
* @type function
|
|
* @date 6/12/2013
|
|
* @since 5.0.0
|
|
*
|
|
* @param $field_key (string)
|
|
* @return (boolean)
|
|
*/
|
|
|
|
function acf_is_field_key( $key = '' ) {
|
|
|
|
// bail early if not string
|
|
if( !is_string($key) ) return false;
|
|
|
|
|
|
// bail early if is numeric (could be numeric string '123')
|
|
if( is_numeric($key) ) return false;
|
|
|
|
|
|
// default - starts with 'field_'
|
|
if( substr($key, 0, 6) === 'field_' ) return true;
|
|
|
|
|
|
// special - allow local field key to be any string
|
|
if( acf_is_local_field($key) ) return true;
|
|
|
|
|
|
// return
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_get_valid_field
|
|
*
|
|
* This function will fill in any missing keys to the $field array making it valid
|
|
*
|
|
* @type function
|
|
* @date 28/09/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $field (array)
|
|
* @return $field (array)
|
|
*/
|
|
|
|
function acf_get_valid_field( $field = false ) {
|
|
|
|
// $field must be an array
|
|
if( !is_array($field) ) $field = array();
|
|
|
|
|
|
// bail ealry if already valid
|
|
if( !empty($field['_valid']) ) return $field;
|
|
|
|
|
|
// defaults
|
|
$field = wp_parse_args($field, array(
|
|
'ID' => 0,
|
|
'key' => '',
|
|
'label' => '',
|
|
'name' => '',
|
|
'prefix' => '',
|
|
'type' => 'text',
|
|
'value' => null,
|
|
'menu_order' => 0,
|
|
'instructions' => '',
|
|
'required' => 0,
|
|
'id' => '',
|
|
'class' => '',
|
|
'conditional_logic' => 0,
|
|
'parent' => 0,
|
|
'wrapper' => array(
|
|
'width' => '',
|
|
'class' => '',
|
|
'id' => ''
|
|
),
|
|
'_name' => '',
|
|
'_input' => '',
|
|
'_valid' => 0,
|
|
));
|
|
|
|
|
|
// _name
|
|
$field['_name'] = $field['name'];
|
|
|
|
|
|
// field specific defaults
|
|
$field = apply_filters( "acf/get_valid_field", $field );
|
|
$field = apply_filters( "acf/get_valid_field/type={$field['type']}", $field );
|
|
|
|
|
|
// field is now valid
|
|
$field['_valid'] = 1;
|
|
|
|
|
|
// translate
|
|
$field = acf_translate_field( $field );
|
|
|
|
|
|
// return
|
|
return $field;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* acf_translate_field
|
|
*
|
|
* This function will translate field's settings
|
|
*
|
|
* @type function
|
|
* @date 8/03/2016
|
|
* @since 5.3.2
|
|
*
|
|
* @param $field (array)
|
|
* @return $field
|
|
*/
|
|
|
|
function acf_translate_field( $field ) {
|
|
|
|
// vars
|
|
$l10n = acf_get_setting('l10n');
|
|
$l10n_textdomain = acf_get_setting('l10n_textdomain');
|
|
|
|
|
|
// if
|
|
if( $l10n && $l10n_textdomain ) {
|
|
|
|
// translate
|
|
$field['label'] = acf_translate( $field['label'] );
|
|
$field['instructions'] = acf_translate( $field['instructions'] );
|
|
|
|
|
|
// filters
|
|
$field = apply_filters( "acf/translate_field", $field );
|
|
$field = apply_filters( "acf/translate_field/type={$field['type']}", $field );
|
|
|
|
}
|
|
|
|
|
|
// return
|
|
return $field;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_clone_field
|
|
*
|
|
* This function will allow customization to a field when it is cloned
|
|
* Cloning a field is the act of mimicing another. Some settings may need to be altered
|
|
*
|
|
* @type function
|
|
* @date 8/03/2016
|
|
* @since 5.3.2
|
|
*
|
|
* @param $field (array)
|
|
* @return $field
|
|
*/
|
|
|
|
function acf_clone_field( $field, $clone_field ) {
|
|
|
|
// add reference
|
|
$field['_clone'] = $clone_field['key'];
|
|
|
|
|
|
// filters
|
|
$field = apply_filters( "acf/clone_field", $field, $clone_field );
|
|
$field = apply_filters( "acf/clone_field/type={$field['type']}", $field, $clone_field );
|
|
|
|
|
|
// return
|
|
return $field;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_prepare_field
|
|
*
|
|
* This function will prepare the field for input
|
|
*
|
|
* @type function
|
|
* @date 12/02/2014
|
|
* @since 5.0.0
|
|
*
|
|
* @param $field (array)
|
|
* @return $field (array)
|
|
*/
|
|
|
|
function acf_prepare_field( $field ) {
|
|
|
|
// bail early if already prepared
|
|
if( $field['_input'] ) return $field;
|
|
|
|
|
|
// _input
|
|
$field['_input'] = $field['name'];
|
|
|
|
|
|
// _input: key overrides name
|
|
if( $field['key'] ) {
|
|
|
|
$field['_input'] = $field['key'];
|
|
|
|
}
|
|
|
|
|
|
// _input: prefix prepends name
|
|
if( $field['prefix'] ) {
|
|
|
|
$field['_input'] = "{$field['prefix']}[{$field['_input']}]";
|
|
|
|
}
|
|
|
|
|
|
// add id (may be custom set)
|
|
if( !$field['id'] ) {
|
|
|
|
$field['id'] = str_replace(array('][', '[', ']'), array('-', '-', ''), $field['_input']);
|
|
|
|
}
|
|
|
|
|
|
// filter to 3rd party customization
|
|
$field = apply_filters( "acf/prepare_field", $field );
|
|
$field = apply_filters( "acf/prepare_field/type={$field['type']}", $field );
|
|
$field = apply_filters( "acf/prepare_field/name={$field['name']}", $field );
|
|
$field = apply_filters( "acf/prepare_field/key={$field['key']}", $field );
|
|
|
|
|
|
// return
|
|
return $field;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_is_sub_field
|
|
*
|
|
* This function will return true if the field is a sub field
|
|
*
|
|
* @type function
|
|
* @date 17/05/2014
|
|
* @since 5.0.0
|
|
*
|
|
* @param $field (array)
|
|
* @return (boolean)
|
|
*/
|
|
|
|
function acf_is_sub_field( $field ) {
|
|
|
|
// local field uses a field instead of ID
|
|
if( acf_is_field_key($field['parent']) ) return true;
|
|
|
|
|
|
// attempt to load parent field
|
|
if( acf_get_field($field['parent']) ) return true;
|
|
|
|
|
|
// return
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_get_field_label
|
|
*
|
|
* This function will return the field label with appropriate required label
|
|
*
|
|
* @type function
|
|
* @date 4/11/2013
|
|
* @since 5.0.0
|
|
*
|
|
* @param $field (array)
|
|
* @return $label (string)
|
|
*/
|
|
|
|
function acf_get_field_label( $field ) {
|
|
|
|
// vars
|
|
$label = $field['label'];
|
|
|
|
|
|
if( $field['required'] ) {
|
|
|
|
$label .= ' <span class="acf-required">*</span>';
|
|
|
|
}
|
|
|
|
|
|
// filter for 3rd party customization
|
|
$label = apply_filters("acf/get_field_label", $label, $field);
|
|
|
|
|
|
// return
|
|
return $label;
|
|
|
|
}
|
|
|
|
function acf_the_field_label( $field ) {
|
|
|
|
echo acf_get_field_label( $field );
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_render_fields
|
|
*
|
|
* This function will render an array of fields for a given form.
|
|
* Becasue the $field's values have not been loaded yet, this function will also load values
|
|
*
|
|
* @type function
|
|
* @date 8/10/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $post_id (int) the post to load values from
|
|
* @param $fields (array) the fields to render
|
|
* @param $el (string) the wrapping element type
|
|
* @param $instruction (int) the instructions position
|
|
* @return n/a
|
|
*/
|
|
|
|
function acf_render_fields( $post_id = 0, $fields, $el = 'div', $instruction = 'label' ) {
|
|
|
|
// bail early if no fields
|
|
if( empty($fields) ) return false;
|
|
|
|
|
|
// remove corrupt fields
|
|
$fields = array_filter($fields);
|
|
|
|
|
|
// loop through fields
|
|
foreach( $fields as $field ) {
|
|
|
|
// load value
|
|
if( $field['value'] === null ) {
|
|
|
|
$field['value'] = acf_get_value( $post_id, $field );
|
|
|
|
}
|
|
|
|
|
|
// render
|
|
acf_render_field_wrap( $field, $el, $instruction );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_render_field
|
|
*
|
|
* This function will render a field input
|
|
*
|
|
* @type function
|
|
* @date 28/09/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $field (array)
|
|
* @return n/a
|
|
*/
|
|
|
|
function acf_render_field( $field = false ) {
|
|
|
|
// get valid field
|
|
$field = acf_get_valid_field( $field );
|
|
|
|
|
|
// prepare field for input
|
|
$field = acf_prepare_field( $field );
|
|
|
|
|
|
// update $field['name']
|
|
$field['name'] = $field['_input'];
|
|
|
|
|
|
// create field specific html
|
|
do_action( "acf/render_field", $field );
|
|
do_action( "acf/render_field/type={$field['type']}", $field );
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_render_field_wrap
|
|
*
|
|
* This function will render the complete HTML wrap with label & field
|
|
*
|
|
* @type function
|
|
* @date 28/09/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $field (array) must be a valid ACF field array
|
|
* @param $el (string) modifys the rendered wrapping elements. Default to 'div', but can be 'tr', 'ul', 'ol', 'dt' or custom
|
|
* @param $instruction (string) specifys the placement of the instructions. Default to 'label', but can be 'field'
|
|
* @param $atts (array) an array of custom attributes to render on the $el
|
|
* @return N/A
|
|
*/
|
|
|
|
function acf_render_field_wrap( $field, $el = 'div', $instruction = 'label' ) {
|
|
|
|
// get valid field
|
|
$field = acf_get_valid_field( $field );
|
|
|
|
|
|
// prepare field for input
|
|
$field = acf_prepare_field( $field );
|
|
|
|
|
|
// el
|
|
$elements = apply_filters('acf/render_field_wrap/elements', array(
|
|
'div' => 'div',
|
|
'tr' => 'td',
|
|
'ul' => 'li',
|
|
'ol' => 'li',
|
|
'dl' => 'dt',
|
|
'td' => 'div' // special case for sub field!
|
|
));
|
|
|
|
|
|
// validate $el
|
|
if( !array_key_exists($el, $elements) ) {
|
|
|
|
$el = 'div';
|
|
|
|
}
|
|
|
|
|
|
// wrapper
|
|
$wrapper = array(
|
|
'id' => '',
|
|
'class' => 'acf-field',
|
|
'width' => '',
|
|
'style' => '',
|
|
'data-name' => $field['name'],
|
|
'data-type' => $field['type'],
|
|
'data-key' => '',
|
|
);
|
|
|
|
|
|
// add required
|
|
if( $field['required'] ) {
|
|
|
|
$wrapper['data-required'] = 1;
|
|
|
|
}
|
|
|
|
|
|
// add type
|
|
$wrapper['class'] .= " acf-field-{$field['type']}";
|
|
|
|
|
|
// add key
|
|
if( $field['key'] ) {
|
|
|
|
$wrapper['class'] .= " acf-field-{$field['key']}";
|
|
$wrapper['data-key'] = $field['key'];
|
|
|
|
}
|
|
|
|
|
|
// replace
|
|
$wrapper['class'] = str_replace('_', '-', $wrapper['class']);
|
|
$wrapper['class'] = str_replace('field-field-', 'field-', $wrapper['class']);
|
|
|
|
|
|
// wrap classes have changed (5.2.7)
|
|
if( acf_get_compatibility('field_wrapper_class') ) {
|
|
|
|
$wrapper['class'] .= " field_type-{$field['type']}";
|
|
|
|
if( $field['key'] ) {
|
|
|
|
$wrapper['class'] .= " field_key-{$field['key']}";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// merge in atts
|
|
$wrapper = acf_merge_atts( $wrapper, $field['wrapper'] );
|
|
|
|
|
|
// add width
|
|
$width = (int) acf_extract_var( $wrapper, 'width' );
|
|
|
|
if( $el == 'tr' || $el == 'td' ) {
|
|
|
|
$width = 0;
|
|
|
|
} elseif( $width > 0 && $width < 100 ) {
|
|
|
|
$wrapper['data-width'] = $width;
|
|
$wrapper['style'] .= " width:{$width}%;";
|
|
|
|
}
|
|
|
|
|
|
// remove empty attributes
|
|
foreach( $wrapper as $k => $v ) {
|
|
|
|
if( $v == '' ) {
|
|
|
|
unset($wrapper[$k]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// vars
|
|
$show_label = ($el !== 'td') ? true : false;
|
|
|
|
|
|
?><<?php echo $el; ?> <?php echo acf_esc_attr($wrapper); ?>>
|
|
<?php if( $show_label ): ?>
|
|
<<?php echo $elements[ $el ]; ?> class="acf-label">
|
|
<label for="<?php echo $field['id']; ?>"><?php echo acf_get_field_label($field); ?></label>
|
|
<?php if( $instruction == 'label' && $field['instructions'] ): ?>
|
|
<p class="description"><?php echo $field['instructions']; ?></p>
|
|
<?php endif; ?>
|
|
</<?php echo $elements[ $el ]; ?>>
|
|
<?php endif; ?>
|
|
<<?php echo $elements[ $el ]; ?> class="acf-input">
|
|
<?php acf_render_field( $field ); ?>
|
|
<?php if( $instruction == 'field' && $field['instructions'] ): ?>
|
|
<p class="description"><?php echo $field['instructions']; ?></p>
|
|
<?php endif; ?>
|
|
</<?php echo $elements[ $el ]; ?>>
|
|
<?php if( !empty($field['conditional_logic'])): ?>
|
|
<script type="text/javascript">
|
|
if(typeof acf !== 'undefined'){ acf.conditional_logic.add( '<?php echo $field['key']; ?>', <?php echo json_encode($field['conditional_logic']); ?>); }
|
|
</script>
|
|
<?php endif; ?>
|
|
</<?php echo $el; ?>>
|
|
<?php
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_render_field_setting
|
|
*
|
|
* This function will render a tr element containing a label and field cell, but also setting the tr data attribute for AJAX
|
|
*
|
|
* @type function
|
|
* @date 28/09/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $field (array) the origional field being edited
|
|
* @param $setting (array) the settings field to create
|
|
* @return n/a
|
|
*/
|
|
|
|
function acf_render_field_setting( $field, $setting, $global = false ) {
|
|
|
|
// validate
|
|
$setting = acf_get_valid_field( $setting );
|
|
|
|
|
|
// if this setting is not global, add a data attribute
|
|
if( !$global ) {
|
|
|
|
$setting['wrapper']['data-setting'] = $field['type'];
|
|
|
|
}
|
|
|
|
|
|
// copy across prefix
|
|
$setting['prefix'] = $field['prefix'];
|
|
|
|
|
|
// copy across the $setting value
|
|
if( isset($field[ $setting['name'] ]) ) {
|
|
|
|
$setting['value'] = $field[ $setting['name'] ];
|
|
|
|
} elseif( isset($setting['default_value']) ) {
|
|
|
|
// use the default value
|
|
$setting['value'] = $setting['default_value'];
|
|
|
|
}
|
|
|
|
|
|
// vars
|
|
$instructions_placement = acf_extract_var( $setting, 'instructions_placement', 'label' );
|
|
|
|
|
|
// render
|
|
acf_render_field_wrap( $setting, 'tr', $instructions_placement );
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_get_fields
|
|
*
|
|
* This function will return an array of fields for the given $parent
|
|
*
|
|
* @type function
|
|
* @date 30/09/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $parent (array) a field or field group
|
|
* @return (array)
|
|
*/
|
|
|
|
function acf_get_fields( $parent = false ) {
|
|
|
|
// allow $parent to be a field group ID
|
|
if( !is_array($parent) ) {
|
|
|
|
$parent = acf_get_field_group( $parent );
|
|
|
|
}
|
|
|
|
|
|
// bail early if no parent
|
|
if( !$parent ) return false;
|
|
|
|
|
|
// vars
|
|
$fields = array();
|
|
|
|
|
|
// try JSON before DB to save query time
|
|
if( acf_have_local_fields( $parent['key'] ) ) {
|
|
|
|
$fields = acf_get_local_fields( $parent['key'] );
|
|
|
|
} else {
|
|
|
|
$fields = acf_get_fields_by_id( $parent['ID'] );
|
|
|
|
}
|
|
|
|
|
|
// filter
|
|
$fields = apply_filters('acf/get_fields', $fields, $parent);
|
|
|
|
|
|
// return
|
|
return $fields;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_get_fields_by_id
|
|
*
|
|
* This function will get all fields for the given parent
|
|
*
|
|
* @type function
|
|
* @date 27/02/2014
|
|
* @since 5.0.0
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $fields (array)
|
|
*/
|
|
|
|
function acf_get_fields_by_id( $parent_id = 0 ) {
|
|
|
|
// bail early if no ID
|
|
if( !$parent_id ) return false;
|
|
|
|
|
|
// vars
|
|
$fields = array();
|
|
$post_ids = array();
|
|
$cache_key = "get_fields/ID={$parent_id}";
|
|
|
|
|
|
// check cache for child ids
|
|
if( acf_isset_cache($cache_key) ) {
|
|
|
|
$post_ids = acf_get_cache($cache_key);
|
|
|
|
// query DB for child ids
|
|
} else {
|
|
|
|
// query
|
|
$posts = get_posts(array(
|
|
'posts_per_page' => -1,
|
|
'post_type' => 'acf-field',
|
|
'orderby' => 'menu_order',
|
|
'order' => 'ASC',
|
|
'suppress_filters' => true, // DO NOT allow WPML to modify the query
|
|
'post_parent' => $parent_id,
|
|
'post_status' => 'publish, trash', // 'any' won't get trashed fields
|
|
'update_post_meta_cache' => false
|
|
));
|
|
|
|
|
|
// loop
|
|
if( $posts ) {
|
|
|
|
foreach( $posts as $post ) {
|
|
|
|
$post_ids[] = $post->ID;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// update cache
|
|
acf_set_cache($cache_key, $post_ids);
|
|
|
|
}
|
|
|
|
|
|
// bail early if no children
|
|
if( empty($post_ids) ) return false;
|
|
|
|
|
|
// load fields
|
|
foreach( $post_ids as $post_id ) {
|
|
|
|
$fields[] = acf_get_field( $post_id );
|
|
|
|
}
|
|
|
|
|
|
// return
|
|
return $fields;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_get_field
|
|
*
|
|
* This function will return a field for the given selector.
|
|
*
|
|
* @type function
|
|
* @date 30/09/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $selector (mixed) identifyer of field. Can be an ID, key, name or post object
|
|
* @param $db_only (boolean) return $field in it's raw form without filters or cache
|
|
* @return $field (array)
|
|
*/
|
|
|
|
function acf_get_field( $selector = null, $db_only = false ) {
|
|
|
|
// vars
|
|
$field = false;
|
|
$type = 'ID';
|
|
|
|
|
|
// ID
|
|
if( is_numeric($selector) ) {
|
|
|
|
// do nothing
|
|
|
|
// object
|
|
} elseif( is_object($selector) ) {
|
|
|
|
$selector = $selector->ID;
|
|
|
|
// string
|
|
} elseif( is_string($selector) ) {
|
|
|
|
$type = acf_is_field_key($selector) ? 'key' : 'name';
|
|
|
|
// other
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
// return early if cache is found
|
|
$cache_key = "get_field/{$type}={$selector}";
|
|
|
|
if( !$db_only && acf_isset_cache($cache_key) ) {
|
|
|
|
return acf_get_cache($cache_key);
|
|
|
|
}
|
|
|
|
|
|
// ID
|
|
if( $type == 'ID' ) {
|
|
|
|
$field = _acf_get_field_by_id( $selector, $db_only );
|
|
|
|
// key
|
|
} elseif( $type == 'key' ) {
|
|
|
|
$field = _acf_get_field_by_key( $selector, $db_only );
|
|
|
|
// name (rare case)
|
|
} else {
|
|
|
|
$field = _acf_get_field_by_name( $selector, $db_only );
|
|
|
|
}
|
|
|
|
|
|
// bail early if no field
|
|
if( !$field ) return false;
|
|
|
|
|
|
// validate
|
|
$field = acf_get_valid_field( $field );
|
|
|
|
|
|
// set prefix (acf fields save with prefix 'acf')
|
|
$field['prefix'] = 'acf';
|
|
|
|
|
|
// bail early if db only value (no need to update cache)
|
|
if( $db_only ) return $field;
|
|
|
|
|
|
// filter for 3rd party customization
|
|
$field = apply_filters( "acf/load_field", $field);
|
|
$field = apply_filters( "acf/load_field/type={$field['type']}", $field );
|
|
$field = apply_filters( "acf/load_field/name={$field['name']}", $field );
|
|
$field = apply_filters( "acf/load_field/key={$field['key']}", $field );
|
|
|
|
|
|
// update cache
|
|
// - Use key instead of ID for best compatibility (not all fields exist in the DB)
|
|
$cache_key = acf_set_cache("get_field/key={$field['key']}", $field);
|
|
|
|
|
|
// update cache reference
|
|
// - allow cache to return if using an ID selector
|
|
acf_set_cache_reference("get_field/ID={$field['ID']}", $cache_key);
|
|
|
|
|
|
// return
|
|
return $field;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* _acf_get_field_by_id
|
|
*
|
|
* This function will get a field via its ID
|
|
*
|
|
* @type function
|
|
* @date 27/02/2014
|
|
* @since 5.0.0
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $field (array)
|
|
*/
|
|
|
|
function _acf_get_field_by_id( $post_id = 0, $db_only = false ) {
|
|
|
|
// get post
|
|
$post = get_post( $post_id );
|
|
|
|
|
|
// bail early if no post, or is not a field
|
|
if( empty($post) || $post->post_type != 'acf-field' ) return false;
|
|
|
|
|
|
// unserialize
|
|
$field = maybe_unserialize( $post->post_content );
|
|
|
|
|
|
// update attributes
|
|
$field['ID'] = $post->ID;
|
|
$field['key'] = $post->post_name;
|
|
$field['label'] = $post->post_title;
|
|
$field['name'] = $post->post_excerpt;
|
|
$field['menu_order'] = $post->menu_order;
|
|
$field['parent'] = $post->post_parent;
|
|
|
|
|
|
// override with JSON
|
|
if( !$db_only && acf_is_local_field($field['key']) ) {
|
|
|
|
// load JSON field
|
|
$local = acf_get_local_field( $field['key'] );
|
|
|
|
|
|
// override IDs
|
|
$local['ID'] = $field['ID'];
|
|
$local['parent'] = $field['parent'];
|
|
|
|
|
|
// return
|
|
return $local;
|
|
|
|
}
|
|
|
|
|
|
// return
|
|
return $field;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* _acf_get_field_by_key
|
|
*
|
|
* This function will get a field via its key
|
|
*
|
|
* @type function
|
|
* @date 27/02/2014
|
|
* @since 5.0.0
|
|
*
|
|
* @param $key (string)
|
|
* @return $field (array)
|
|
*/
|
|
|
|
function _acf_get_field_by_key( $key = '', $db_only = false ) {
|
|
|
|
// try JSON before DB to save query time
|
|
if( !$db_only && acf_is_local_field( $key ) ) {
|
|
|
|
return acf_get_local_field( $key );
|
|
|
|
}
|
|
|
|
|
|
// vars
|
|
$post_id = acf_get_field_id( $key );
|
|
|
|
|
|
// bail early if no post_id
|
|
if( !$post_id ) return false;
|
|
|
|
|
|
// return
|
|
return _acf_get_field_by_id( $post_id, $db_only );
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* _acf_get_field_by_name
|
|
*
|
|
* This function will get a field via its name
|
|
*
|
|
* @type function
|
|
* @date 27/02/2014
|
|
* @since 5.0.0
|
|
*
|
|
* @param $key (string)
|
|
* @return $field (array)
|
|
*/
|
|
|
|
function _acf_get_field_by_name( $name = '', $db_only = false ) {
|
|
|
|
// vars
|
|
$args = array(
|
|
'posts_per_page' => 1,
|
|
'post_type' => 'acf-field',
|
|
'orderby' => 'menu_order title',
|
|
'order' => 'ASC',
|
|
'suppress_filters' => false,
|
|
'acf_field_name' => $name
|
|
);
|
|
|
|
|
|
// load posts
|
|
$posts = get_posts( $args );
|
|
|
|
|
|
// bail early if no posts
|
|
if( empty($posts) ) return false;
|
|
|
|
|
|
// return
|
|
return _acf_get_field_by_id( $posts[0]->ID, $db_only );
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_maybe_get_field
|
|
*
|
|
* This function will return a field for the given selector.
|
|
* It will also review the field_reference to ensure the correct field is returned which makes it useful for the template API
|
|
*
|
|
* @type function
|
|
* @date 4/08/2015
|
|
* @since 5.2.3
|
|
*
|
|
* @param $selector (mixed) identifyer of field. Can be an ID, key, name or post object
|
|
* @param $post_id (mixed) the post_id of which the value is saved against
|
|
* @param $strict (boolean) if true, return a field only when a field key is found.
|
|
* @return $field (array)
|
|
*/
|
|
|
|
function acf_maybe_get_field( $selector, $post_id = false, $strict = true ) {
|
|
|
|
// complete init
|
|
// this function may be used in a theme file before the init action has been run
|
|
acf()->init();
|
|
|
|
|
|
// vars
|
|
$field_name = false;
|
|
|
|
|
|
// get valid post_id
|
|
$post_id = acf_get_valid_post_id( $post_id );
|
|
|
|
|
|
// load field reference if not a field_key
|
|
if( !acf_is_field_key($selector) ) {
|
|
|
|
// save selector as field_name (could be sub field name)
|
|
$field_name = $selector;
|
|
|
|
|
|
// get reference
|
|
$field_key = acf_get_field_reference( $selector, $post_id );
|
|
|
|
|
|
if( $field_key ) {
|
|
|
|
$selector = $field_key;
|
|
|
|
} elseif( $strict ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// get field key
|
|
$field = acf_get_field( $selector );
|
|
|
|
|
|
// bail early if no field
|
|
if( !$field ) return false;
|
|
|
|
|
|
// Override name - allows the $selector to be a sub field (images_0_image)
|
|
if( $field_name ) {
|
|
|
|
$field['name'] = $field_name;
|
|
|
|
}
|
|
|
|
|
|
// return
|
|
return $field;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_get_field_id
|
|
*
|
|
* This function will lookup a field's ID from the DB
|
|
* Useful for local fields to find DB sibling
|
|
*
|
|
* @type function
|
|
* @date 25/06/2015
|
|
* @since 5.2.3
|
|
*
|
|
* @param $key (string)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
function acf_get_field_id( $key = '' ) {
|
|
|
|
// vars
|
|
$args = array(
|
|
'posts_per_page' => 1,
|
|
'post_type' => 'acf-field',
|
|
'orderby' => 'menu_order title',
|
|
'order' => 'ASC',
|
|
'suppress_filters' => false,
|
|
'acf_field_key' => $key
|
|
);
|
|
|
|
|
|
// load posts
|
|
$posts = get_posts( $args );
|
|
|
|
|
|
// validate
|
|
if( empty($posts) ) return 0;
|
|
|
|
|
|
// return
|
|
return $posts[0]->ID;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_update_field
|
|
*
|
|
* This function will update a field into the DB.
|
|
* The returned field will always contain an ID
|
|
*
|
|
* @type function
|
|
* @date 1/10/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $field (array)
|
|
* @return $field (array)
|
|
*/
|
|
|
|
function acf_update_field( $field = false, $specific = false ) {
|
|
|
|
// $field must be an array
|
|
if( !is_array($field) ) return false;
|
|
|
|
|
|
// validate
|
|
$field = acf_get_valid_field( $field );
|
|
|
|
|
|
// may have been posted. Remove slashes
|
|
$field = wp_unslash( $field );
|
|
|
|
|
|
// parse types (converts string '0' to int 0)
|
|
$field = acf_parse_types( $field );
|
|
|
|
|
|
// clean up conditional logic keys
|
|
if( !empty($field['conditional_logic']) ) {
|
|
|
|
// extract groups
|
|
$groups = acf_extract_var( $field, 'conditional_logic' );
|
|
|
|
|
|
// clean array
|
|
$groups = array_filter($groups);
|
|
$groups = array_values($groups);
|
|
|
|
|
|
// clean rules
|
|
foreach( array_keys($groups) as $i ) {
|
|
|
|
$groups[ $i ] = array_filter($groups[ $i ]);
|
|
$groups[ $i ] = array_values($groups[ $i ]);
|
|
|
|
}
|
|
|
|
|
|
// reset conditional logic
|
|
$field['conditional_logic'] = $groups;
|
|
|
|
}
|
|
|
|
|
|
// parent may be a field key
|
|
// - lookup parent ID
|
|
if( acf_is_field_key($field['parent']) ) {
|
|
|
|
$field['parent'] = acf_get_field_id( $field['parent'] );
|
|
|
|
}
|
|
|
|
|
|
// filter for 3rd party customization
|
|
$field = apply_filters( "acf/update_field", $field);
|
|
$field = apply_filters( "acf/update_field/type={$field['type']}", $field );
|
|
$field = apply_filters( "acf/update_field/name={$field['name']}", $field );
|
|
$field = apply_filters( "acf/update_field/key={$field['key']}", $field );
|
|
|
|
|
|
// store origional field for return
|
|
$data = $field;
|
|
|
|
|
|
// extract some args
|
|
$extract = acf_extract_vars($data, array(
|
|
'ID',
|
|
'key',
|
|
'label',
|
|
'name',
|
|
'prefix',
|
|
'value',
|
|
'menu_order',
|
|
'id',
|
|
'class',
|
|
'parent',
|
|
'_name',
|
|
'_input',
|
|
'_valid',
|
|
));
|
|
|
|
|
|
// serialize for DB
|
|
$data = maybe_serialize( $data );
|
|
|
|
|
|
// save
|
|
$save = array(
|
|
'ID' => $extract['ID'],
|
|
'post_status' => 'publish',
|
|
'post_type' => 'acf-field',
|
|
'post_title' => $extract['label'],
|
|
'post_name' => $extract['key'],
|
|
'post_excerpt' => $extract['name'],
|
|
'post_content' => $data,
|
|
'post_parent' => $extract['parent'],
|
|
'menu_order' => $extract['menu_order'],
|
|
);
|
|
|
|
|
|
// $specific
|
|
if( !empty($specific) ) {
|
|
|
|
// prepend ID
|
|
array_unshift( $specific, 'ID' );
|
|
|
|
|
|
// vars
|
|
$_save = $save;
|
|
|
|
|
|
// reset
|
|
$save = array();
|
|
|
|
|
|
// appen data
|
|
foreach( $specific as $key ) {
|
|
|
|
$save[ $key ] = $_save[ $key ];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// allow fields to contain the same name
|
|
add_filter( 'wp_unique_post_slug', 'acf_update_field_wp_unique_post_slug', 100, 6 );
|
|
|
|
|
|
// update the field and update the ID
|
|
if( $field['ID'] ) {
|
|
|
|
wp_update_post( $save );
|
|
|
|
} else {
|
|
|
|
$field['ID'] = wp_insert_post( $save );
|
|
|
|
}
|
|
|
|
|
|
// clear cache
|
|
acf_delete_cache("get_field/key={$field['key']}");
|
|
|
|
|
|
// return
|
|
return $field;
|
|
|
|
}
|
|
|
|
function acf_update_field_wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug ) {
|
|
|
|
if( $post_type == 'acf-field' ) {
|
|
|
|
$slug = $original_slug;
|
|
|
|
}
|
|
|
|
// return
|
|
return $slug;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_duplicate_fields
|
|
*
|
|
* This function will duplicate an array of fields and update conditional logic references
|
|
*
|
|
* @type function
|
|
* @date 16/06/2014
|
|
* @since 5.0.0
|
|
*
|
|
* @param $fields (array)
|
|
* @param $new_parent (int)
|
|
* @return n/a
|
|
*/
|
|
|
|
function acf_duplicate_fields( $fields, $new_parent = 0 ) {
|
|
|
|
// bail early if no fields
|
|
if( empty($fields) ) return;
|
|
|
|
|
|
// create new field keys (for conditional logic fixes)
|
|
foreach( $fields as $field ) {
|
|
|
|
// ensure a delay for unique ID
|
|
usleep(1);
|
|
|
|
acf_update_setting( 'duplicate_key_' . $field['key'] , uniqid('field_') );
|
|
|
|
}
|
|
|
|
|
|
// duplicate fields
|
|
foreach( $fields as $field ) {
|
|
|
|
// duplicate
|
|
acf_duplicate_field( $field['ID'], $new_parent );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_duplicate_field
|
|
*
|
|
* This function will duplicate a field and attach it to the given field group ID
|
|
*
|
|
* @type function
|
|
* @date 17/10/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $selector (int)
|
|
* @param $new_parent (int)
|
|
* @return $field (array) the new field
|
|
*/
|
|
|
|
function acf_duplicate_field( $selector = 0, $new_parent = 0 ){
|
|
|
|
// disable filters to ensure ACF loads raw data from DB
|
|
acf_disable_filters();
|
|
|
|
|
|
// load the origional field
|
|
$field = acf_get_field( $selector );
|
|
|
|
|
|
// bail early if field did not load correctly
|
|
if( empty($field) ) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
// update ID
|
|
$field['ID'] = false;
|
|
|
|
|
|
// try duplicate keys
|
|
$field['key'] = acf_get_setting( 'duplicate_key_' . $field['key'] );
|
|
|
|
|
|
// default key
|
|
if( empty($field['key']) ) {
|
|
|
|
$field['key'] = uniqid('field_');
|
|
|
|
}
|
|
|
|
|
|
// update parent
|
|
if( $new_parent ) {
|
|
|
|
$field['parent'] = $new_parent;
|
|
|
|
}
|
|
|
|
|
|
// update conditional logic references (because field keys have changed)
|
|
if( !empty($field['conditional_logic']) ) {
|
|
|
|
// extract groups
|
|
$groups = acf_extract_var( $field, 'conditional_logic' );
|
|
|
|
|
|
// loop over groups
|
|
foreach( array_keys($groups) as $g ) {
|
|
|
|
// extract group
|
|
$group = acf_extract_var( $groups, $g );
|
|
|
|
|
|
// bail early if empty
|
|
if( empty($group) ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
// loop over rules
|
|
foreach( array_keys($group) as $r ) {
|
|
|
|
// extract rule
|
|
$rule = acf_extract_var( $group, $r );
|
|
|
|
|
|
// vars
|
|
$new_key = acf_get_setting( 'duplicate_key_' . $rule['field'] );
|
|
|
|
|
|
// update rule with new key
|
|
if( $new_key ) {
|
|
|
|
$rule['field'] = $new_key;
|
|
|
|
}
|
|
|
|
|
|
// append to group
|
|
$group[ $r ] = $rule;
|
|
|
|
}
|
|
|
|
|
|
// append to groups
|
|
$groups[ $g ] = $group;
|
|
|
|
}
|
|
|
|
|
|
// update conditional logic
|
|
$field['conditional_logic'] = $groups;
|
|
|
|
|
|
}
|
|
|
|
|
|
// filter for 3rd party customization
|
|
$field = apply_filters( "acf/duplicate_field", $field);
|
|
$field = apply_filters( "acf/duplicate_field/type={$field['type']}", $field );
|
|
|
|
|
|
// save
|
|
return acf_update_field( $field );
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_delete_field
|
|
*
|
|
* This function will delete a field from the databse
|
|
*
|
|
* @type function
|
|
* @date 2/10/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $id (int)
|
|
* @return (boolean)
|
|
*/
|
|
|
|
function acf_delete_field( $selector = 0 ) {
|
|
|
|
// disable filters to ensure ACF loads raw data from DB
|
|
acf_disable_filters();
|
|
|
|
|
|
// load the origional field gorup
|
|
$field = acf_get_field( $selector );
|
|
|
|
|
|
// bail early if field did not load correctly
|
|
if( empty($field) ) return false;
|
|
|
|
|
|
// delete field
|
|
wp_delete_post( $field['ID'], true );
|
|
|
|
|
|
// action for 3rd party customisation
|
|
do_action( "acf/delete_field", $field);
|
|
do_action( "acf/delete_field/type={$field['type']}", $field );
|
|
|
|
|
|
// clear cache
|
|
acf_delete_cache("get_field/key={$field['key']}");
|
|
|
|
|
|
// return
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_trash_field
|
|
*
|
|
* This function will trash a field from the databse
|
|
*
|
|
* @type function
|
|
* @date 2/10/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $id (int)
|
|
* @return (boolean)
|
|
*/
|
|
|
|
function acf_trash_field( $selector = 0 ) {
|
|
|
|
// disable filters to ensure ACF loads raw data from DB
|
|
acf_disable_filters();
|
|
|
|
|
|
// load the origional field gorup
|
|
$field = acf_get_field( $selector );
|
|
|
|
|
|
// bail early if field did not load correctly
|
|
if( empty($field) ) return false;
|
|
|
|
|
|
// delete field
|
|
wp_trash_post( $field['ID'] );
|
|
|
|
|
|
// action for 3rd party customisation
|
|
do_action( 'acf/trash_field', $field );
|
|
|
|
|
|
// return
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_untrash_field
|
|
*
|
|
* This function will restore a field from the trash
|
|
*
|
|
* @type function
|
|
* @date 2/10/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $id (int)
|
|
* @return (boolean)
|
|
*/
|
|
|
|
function acf_untrash_field( $selector = 0 ) {
|
|
|
|
// disable filters to ensure ACF loads raw data from DB
|
|
acf_disable_filters();
|
|
|
|
|
|
// load the origional field gorup
|
|
$field = acf_get_field( $selector );
|
|
|
|
|
|
// bail early if field did not load correctly
|
|
if( empty($field) ) return false;
|
|
|
|
|
|
// delete field
|
|
wp_untrash_post( $field['ID'] );
|
|
|
|
|
|
// action for 3rd party customisation
|
|
do_action( 'acf/untrash_field', $field );
|
|
|
|
|
|
// return
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_prepare_fields_for_export
|
|
*
|
|
* description
|
|
*
|
|
* @type function
|
|
* @date 11/03/2014
|
|
* @since 5.0.0
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
function acf_prepare_fields_for_export( $fields = false ) {
|
|
|
|
// validate
|
|
if( empty($fields) ) return $fields;
|
|
|
|
|
|
// format
|
|
foreach( array_keys($fields) as $i ) {
|
|
|
|
// prepare
|
|
$fields[ $i ] = acf_prepare_field_for_export( $fields[ $i ] );
|
|
|
|
}
|
|
|
|
|
|
// return
|
|
return $fields;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_prepare_field_for_export
|
|
*
|
|
* description
|
|
*
|
|
* @type function
|
|
* @date 11/03/2014
|
|
* @since 5.0.0
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
function acf_prepare_field_for_export( $field ) {
|
|
|
|
// extract some args
|
|
$extract = acf_extract_vars($field, array(
|
|
'ID',
|
|
'prefix',
|
|
'value',
|
|
'menu_order',
|
|
'id',
|
|
'class',
|
|
'parent',
|
|
'_name',
|
|
'_input',
|
|
'_valid',
|
|
));
|
|
|
|
|
|
// filter for 3rd party customization
|
|
$field = apply_filters( "acf/prepare_field_for_export", $field );
|
|
|
|
|
|
// return
|
|
return $field;
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_prepare_fields_for_import
|
|
*
|
|
* description
|
|
*
|
|
* @type function
|
|
* @date 11/03/2014
|
|
* @since 5.0.0
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
function acf_prepare_fields_for_import( $fields = false ) {
|
|
|
|
// validate
|
|
if( empty($fields) ) return array();
|
|
|
|
|
|
// re-index array
|
|
$fields = array_values($fields);
|
|
|
|
|
|
// vars
|
|
$i = 0;
|
|
|
|
|
|
// format
|
|
while( $i < count($fields) ) {
|
|
|
|
// prepare field
|
|
$field = acf_prepare_field_for_import( $fields[ $i ] );
|
|
|
|
|
|
// ensure $field is an array of fields
|
|
// this allows for multiepl sub fields to be returned
|
|
if( acf_is_associative_array($field) ) {
|
|
|
|
$field = array( $field );
|
|
|
|
}
|
|
|
|
|
|
// merge in $field (1 or more fields)
|
|
array_splice($fields, $i, 1, $field);
|
|
|
|
|
|
// $i
|
|
$i++;
|
|
|
|
}
|
|
|
|
|
|
// filter for 3rd party customization
|
|
$fields = apply_filters('acf/prepare_fields_for_import', $fields);
|
|
|
|
|
|
// return
|
|
return $fields;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_prepare_field_for_import
|
|
*
|
|
* description
|
|
*
|
|
* @type function
|
|
* @date 11/03/2014
|
|
* @since 5.0.0
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
function acf_prepare_field_for_import( $field ) {
|
|
|
|
// extract some args
|
|
$extract = acf_extract_vars($field, array(
|
|
'value',
|
|
'id',
|
|
'class',
|
|
'_name',
|
|
'_input',
|
|
'_valid',
|
|
));
|
|
|
|
|
|
// filter for 3rd party customization
|
|
$field = apply_filters( "acf/prepare_field_for_import", $field );
|
|
|
|
|
|
// return
|
|
return $field;
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_get_sub_field
|
|
*
|
|
* This function will return a field for the given selector, and $field (parent).
|
|
*
|
|
* @type function
|
|
* @date 30/09/13
|
|
* @since 5.0.0
|
|
*
|
|
* @param $selector (string)
|
|
* @param $field (mixed)
|
|
* @return $field (array)
|
|
*/
|
|
|
|
function acf_get_sub_field( $selector, $field ) {
|
|
|
|
// vars
|
|
$sub_field = false;
|
|
|
|
|
|
// filter for 3rd party customization
|
|
$sub_field = apply_filters( "acf/get_sub_field", $sub_field, $selector, $field );
|
|
$sub_field = apply_filters( "acf/get_sub_field/type={$field['type']}", $sub_field, $selector, $field );
|
|
|
|
|
|
// return
|
|
return $sub_field;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_get_field_ancestors
|
|
*
|
|
* This function will return an array of all ancestor fields
|
|
*
|
|
* @type function
|
|
* @date 22/06/2016
|
|
* @since 5.3.8
|
|
*
|
|
* @param $field (array)
|
|
* @return (array)
|
|
*/
|
|
|
|
function acf_get_field_ancestors( $field ) {
|
|
|
|
// get field
|
|
$ancestors = array();
|
|
|
|
|
|
// loop
|
|
while( $field && acf_is_field_key($field['parent']) ) {
|
|
|
|
$ancestors[] = $field['parent'];
|
|
$field = acf_get_field($field['parent']);
|
|
|
|
}
|
|
|
|
|
|
// return
|
|
return $ancestors;
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* acf_maybe_get_sub_field
|
|
*
|
|
* This function will attempt to find a sub field
|
|
*
|
|
* @type function
|
|
* @date 3/10/2016
|
|
* @since 5.4.0
|
|
*
|
|
* @param $post_id (int)
|
|
* @return $post_id (int)
|
|
*/
|
|
|
|
function acf_maybe_get_sub_field( $selectors, $post_id = false, $strict = true ) {
|
|
|
|
// bail ealry if not enough selectors
|
|
if( !is_array($selectors) || count($selectors) < 3 ) return false;
|
|
|
|
|
|
// vars
|
|
$selector = acf_extract_var( $selectors, 0 );
|
|
$selectors = array_values( $selectors ); // reset keys
|
|
|
|
|
|
// attempt get field
|
|
$field = acf_maybe_get_field( $selector, $post_id, $strict );
|
|
|
|
|
|
// bail early if no field
|
|
if( !$field ) return false;
|
|
|
|
|
|
// loop
|
|
for( $j = 0; $j < count($selectors); $j+=2 ) {
|
|
|
|
// vars
|
|
$sub_i = $selectors[ $j ];
|
|
$sub_s = $selectors[ $j+1 ];
|
|
$field_name = $field['name'];
|
|
|
|
|
|
// find sub field
|
|
$field = acf_get_sub_field( $sub_s, $field );
|
|
|
|
|
|
// bail early if no sub field
|
|
if( !$field ) return false;
|
|
|
|
|
|
// add to name
|
|
$field['name'] = $field_name . '_' . ($sub_i-1) . '_' . $field['name'];
|
|
|
|
}
|
|
|
|
|
|
// return
|
|
return $field;
|
|
|
|
|
|
}
|
|
|
|
|
|
?>
|