name = 'relationship';
$this->label = __("Relationship",'acf');
$this->category = __("Relational",'acf');
$this->defaults = array(
'post_type' => array('all'),
'max' => '',
'taxonomy' => array('all'),
'filters' => array('search'),
'result_elements' => array('post_title', 'post_type'),
'return_format' => 'object'
);
$this->l10n = array(
'max' => __("Maximum values reached ( {max} values )",'acf')
);
// do not delete!
parent::__construct();
// extra
add_action('wp_ajax_acf/fields/relationship/query_posts', array($this, 'query_posts'));
add_action('wp_ajax_nopriv_acf/fields/relationship/query_posts', array($this, 'query_posts'));
}
/*
* load_field()
*
* This filter is appied to the $field after it is loaded from the database
*
* @type filter
* @since 3.6
* @date 23/01/13
*
* @param $field - the field array holding all the field options
*
* @return $field - the field array holding all the field options
*/
function load_field( $field )
{
// validate post_type
if( !$field['post_type'] || !is_array($field['post_type']) || in_array('', $field['post_type']) )
{
$field['post_type'] = array( 'all' );
}
// validate taxonomy
if( !$field['taxonomy'] || !is_array($field['taxonomy']) || in_array('', $field['taxonomy']) )
{
$field['taxonomy'] = array( 'all' );
}
// validate result_elements
if( !is_array( $field['result_elements'] ) )
{
$field['result_elements'] = array();
}
if( !in_array('post_title', $field['result_elements']) )
{
$field['result_elements'][] = 'post_title';
}
// filters
if( !is_array( $field['filters'] ) )
{
$field['filters'] = array();
}
// return
return $field;
}
/*
* get_result
*
* description
*
* @type function
* @date 5/02/2015
* @since 5.1.5
*
* @param $post_id (int)
* @return $post_id (int)
*/
function get_result( $post, $field, $the_post, $options = array() ) {
// right aligned info
$title = '';
if( in_array('post_type', $field['result_elements']) ) {
$post_type_object = get_post_type_object( $post->post_type );
$title .= $post_type_object->labels->singular_name;
}
// WPML
if( !empty($options['lang']) ) {
$title .= ' (' . $options['lang'] . ')';
} elseif( defined('ICL_LANGUAGE_CODE') ) {
$title .= ' (' . ICL_LANGUAGE_CODE . ')';
}
$title .= ' ';
// featured_image
if( in_array('featured_image', $field['result_elements']) ) {
$image = '';
if( $post->post_type == 'attachment' ) {
$image = wp_get_attachment_image( $post->ID, array(21, 21) );
} else {
$image = get_the_post_thumbnail( $post->ID, array(21, 21) );
}
$title .= '
' . $image . '
';
}
// title
$post_title = get_the_title( $post->ID );
// empty
if( $post_title === '' ) {
$post_title = __('(no title)', 'acf');
}
$title .= $post_title;
// status
if( get_post_status( $post->ID ) != "publish" ) {
$title .= ' (' . get_post_status( $post->ID ) . ')';
}
// filters
$title = apply_filters('acf/fields/relationship/result', $title, $post, $field, $the_post);
$title = apply_filters('acf/fields/relationship/result/name=' . $field['_name'] , $title, $post, $field, $the_post);
$title = apply_filters('acf/fields/relationship/result/key=' . $field['key'], $title, $post, $field, $the_post);
// return
return $title;
}
/*
* query_posts
*
* @description:
* @since: 3.6
* @created: 27/01/13
*/
function query_posts()
{
// vars
$r = array(
'next_page_exists' => 1,
'html' => ''
);
// options
$options = array(
'post_type' => 'all',
'taxonomy' => 'all',
'posts_per_page' => 10,
'paged' => 1,
'orderby' => 'title',
'order' => 'ASC',
'post_status' => 'any',
'suppress_filters' => false,
's' => '',
'lang' => false,
'update_post_meta_cache' => false,
'field_key' => '',
'nonce' => '',
'ancestor' => false,
);
$options = array_merge( $options, $_POST );
// validate
if( ! wp_verify_nonce($options['nonce'], 'acf_nonce') )
{
die();
}
// WPML
if( $options['lang'] )
{
global $sitepress;
if( !empty($sitepress) )
{
$sitepress->switch_lang( $options['lang'] );
}
}
// convert types
$options['post_type'] = explode(',', $options['post_type']);
$options['taxonomy'] = explode(',', $options['taxonomy']);
// load all post types by default
if( in_array('all', $options['post_type']) )
{
$options['post_type'] = apply_filters('acf/get_post_types', array());
}
// attachment doesn't work if it is the only item in an array???
if( is_array($options['post_type']) && count($options['post_type']) == 1 )
{
$options['post_type'] = $options['post_type'][0];
}
// create tax queries
if( ! in_array('all', $options['taxonomy']) )
{
// vars
$taxonomies = array();
$options['tax_query'] = array();
foreach( $options['taxonomy'] as $v )
{
// find term (find taxonomy!)
// $term = array( 0 => $taxonomy, 1 => $term_id )
$term = explode(':', $v);
// validate
if( !is_array($term) || !isset($term[1]) )
{
continue;
}
// add to tax array
$taxonomies[ $term[0] ][] = $term[1];
}
// now create the tax queries
foreach( $taxonomies as $k => $v )
{
$options['tax_query'][] = array(
'taxonomy' => $k,
'field' => 'id',
'terms' => $v,
);
}
}
unset( $options['taxonomy'] );
// load field
$field = array();
if( $options['ancestor'] )
{
$ancestor = apply_filters('acf/load_field', array(), $options['ancestor'] );
$field = acf_get_child_field_from_parent_field( $options['field_key'], $ancestor );
}
else
{
$field = apply_filters('acf/load_field', array(), $options['field_key'] );
}
// get the post from which this field is rendered on
$the_post = get_post( $options['post_id'] );
// filters
$options = apply_filters('acf/fields/relationship/query', $options, $field, $the_post);
$options = apply_filters('acf/fields/relationship/query/name=' . $field['_name'], $options, $field, $the_post );
$options = apply_filters('acf/fields/relationship/query/key=' . $field['key'], $options, $field, $the_post );
// query
$wp_query = new WP_Query( $options );
// global
global $post;
// loop
while( $wp_query->have_posts() ) {
$wp_query->the_post();
// get title
$title = $this->get_result($post, $field, $the_post, $options);
// update html
$r['html'] .= '' . $title . ' ';
}
// next page
if( (int)$options['paged'] >= $wp_query->max_num_pages ) {
$r['next_page_exists'] = 0;
}
// reset
wp_reset_postdata();
// return JSON
echo json_encode( $r );
die();
}
/*
* create_field()
*
* Create the HTML interface for your field
*
* @param $field - an array holding all the field's data
*
* @type action
* @since 3.6
* @date 23/01/13
*/
function create_field( $field )
{
// global
global $post;
// no row limit?
if( !$field['max'] || $field['max'] < 1 )
{
$field['max'] = 9999;
}
// class
$class = '';
if( $field['filters'] )
{
foreach( $field['filters'] as $filter )
{
$class .= ' has-' . $filter;
}
}
$attributes = array(
'max' => $field['max'],
's' => '',
'paged' => 1,
'post_type' => implode(',', $field['post_type']),
'taxonomy' => implode(',', $field['taxonomy']),
'field_key' => $field['key']
);
// Lang
if( defined('ICL_LANGUAGE_CODE') )
{
$attributes['lang'] = ICL_LANGUAGE_CODE;
}
// parent
preg_match('/\[(field_.*?)\]/', $field['name'], $ancestor);
if( isset($ancestor[1]) && $ancestor[1] != $field['key'])
{
$attributes['ancestor'] = $ancestor[1];
}
?>
$v ): ?> data-="">
" type="text" id="relationship_" />
__("Filter by post type",'acf')
);
if( in_array('all', $field['post_type']) )
{
$post_types = apply_filters( 'acf/get_post_types', array() );
$choices = array_merge( $choices, $post_types);
}
else
{
foreach( $field['post_type'] as $post_type )
{
$choices[ $post_type ] = $post_type;
}
}
// create field
do_action('acf/create_field', array(
'type' => 'select',
'name' => '',
'class' => 'select-post_type',
'value' => '',
'choices' => $choices,
));
?>
'radio',
'name' => 'fields['.$key.'][return_format]',
'value' => $field['return_format'],
'layout' => 'horizontal',
'choices' => array(
'object' => __("Post Objects",'acf'),
'id' => __("Post IDs",'acf')
)
));
?>
__("All",'acf')
);
$choices = apply_filters('acf/get_post_types', $choices);
do_action('acf/create_field', array(
'type' => 'select',
'name' => 'fields['.$key.'][post_type]',
'value' => $field['post_type'],
'choices' => $choices,
'multiple' => 1,
));
?>
array(
'all' => __("All",'acf')
)
);
$simple_value = false;
$choices = apply_filters('acf/get_taxonomies_for_select', $choices, $simple_value);
do_action('acf/create_field', array(
'type' => 'select',
'name' => 'fields['.$key.'][taxonomy]',
'value' => $field['taxonomy'],
'choices' => $choices,
'multiple' => 1,
));
?>
'checkbox',
'name' => 'fields['.$key.'][filters]',
'value' => $field['filters'],
'choices' => array(
'search' => __("Search",'acf'),
'post_type' => __("Post Type Select",'acf'),
)
));
?>
'checkbox',
'name' => 'fields['.$key.'][result_elements]',
'value' => $field['result_elements'],
'choices' => array(
'featured_image' => __("Featured Image",'acf'),
'post_title' => __("Post Title",'acf'),
'post_type' => __("Post Type",'acf'),
),
'disabled' => array(
'post_title'
)
));
?>
'number',
'name' => 'fields['.$key.'][max]',
'value' => $field['max'],
));
?>
get_posts( $value );
}
}
// return value
return $value;
}
/*
* format_value_for_api()
*
* This filter is appied to the $value after it is loaded from the db and before it is passed back to the api functions such as the_field
*
* @type filter
* @since 3.6
* @date 23/01/13
*
* @param $value - the value which was loaded from the database
* @param $post_id - the $post_id from which the value was loaded
* @param $field - the field array holding all the field options
*
* @return $value - the modified value
*/
function format_value_for_api( $value, $post_id, $field )
{
// empty?
if( !$value )
{
return $value;
}
// Pre 3.3.3, the value is a string coma seperated
if( is_string($value) )
{
$value = explode(',', $value);
}
// empty?
if( !is_array($value) || empty($value) )
{
return $value;
}
// convert to integers
$value = array_map('intval', $value);
// return format
if( $field['return_format'] == 'object' )
{
$value = $this->get_posts( $value );
}
// return
return $value;
}
/*
* get_posts
*
* This function will take an array of post_id's ($value) and return an array of post_objects
*
* @type function
* @date 7/08/13
*
* @param $post_ids (array) the array of post ID's
* @return (array) an array of post objects
*/
function get_posts( $post_ids )
{
// validate
if( empty($post_ids) )
{
return $post_ids;
}
// vars
$r = array();
// find posts (DISTINCT POSTS)
$posts = get_posts(array(
'numberposts' => -1,
'post__in' => $post_ids,
'post_type' => apply_filters('acf/get_post_types', array()),
'post_status' => 'any',
));
$ordered_posts = array();
foreach( $posts as $p )
{
// create array to hold value data
$ordered_posts[ $p->ID ] = $p;
}
// override value array with attachments
foreach( $post_ids as $k => $v)
{
// check that post exists (my have been trashed)
if( isset($ordered_posts[ $v ]) )
{
$r[] = $ordered_posts[ $v ];
}
}
// return
return $r;
}
/*
* update_value()
*
* This filter is appied to the $value before it is updated in the db
*
* @type filter
* @since 3.6
* @date 23/01/13
*
* @param $value - the value which will be saved in the database
* @param $post_id - the $post_id of which the value will be saved
* @param $field - the field array holding all the field options
*
* @return $value - the modified value
*/
function update_value( $value, $post_id, $field )
{
// validate
if( empty($value) )
{
return $value;
}
if( is_string($value) )
{
// string
$value = explode(',', $value);
}
elseif( is_object($value) && isset($value->ID) )
{
// object
$value = array( $value->ID );
}
elseif( is_array($value) )
{
// array
foreach( $value as $k => $v ){
// object?
if( is_object($v) && isset($v->ID) )
{
$value[ $k ] = $v->ID;
}
}
}
// save value as strings, so we can clearly search for them in SQL LIKE statements
$value = array_map('strval', $value);
return $value;
}
}
new acf_field_relationship();
?>