<?php
class acf_field_relationship extends acf_field
{
function __construct()
{
$this->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')
);
parent::__construct();
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'));
}
function load_field( $field )
{
if( !$field['post_type'] || !is_array($field['post_type']) || in_array('', $field['post_type']) )
{
$field['post_type'] = array( 'all' );
}
if( !$field['taxonomy'] || !is_array($field['taxonomy']) || in_array('', $field['taxonomy']) )
{
$field['taxonomy'] = array( 'all' );
}
if( !is_array( $field['result_elements'] ) )
{
$field['result_elements'] = array();
}
if( !in_array('post_title', $field['result_elements']) )
{
$field['result_elements'][] = 'post_title';
}
if( !is_array( $field['filters'] ) )
{
$field['filters'] = array();
}
return $field;
}
function get_result( $post, $field, $the_post, $options = array() ) {
$title = '<span class="relationship-item-info">';
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;
}
if( !empty($options['lang']) ) {
$title .= ' (' . $options['lang'] . ')';
} elseif( defined('ICL_LANGUAGE_CODE') ) {
$title .= ' (' . ICL_LANGUAGE_CODE . ')';
}
$title .= '</span>';
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 .= '<div class="result-thumbnail">' . $image . '</div>';
}
$post_title = get_the_title( $post->ID );
if( $post_title === '' ) {
$post_title = __('(no title)', 'acf');
}
$title .= $post_title;
if( get_post_status( $post->ID ) != "publish" ) {
$title .= ' (' . get_post_status( $post->ID ) . ')';
}
$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 $title;
}
function query_posts()
{
$r = array(
'next_page_exists' => 1,
'html' => ''
);
$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 );
if( ! wp_verify_nonce($options['nonce'], 'acf_nonce') )
{
die();
}
if( $options['lang'] )
{
global $sitepress;
if( !empty($sitepress) )
{
$sitepress->switch_lang( $options['lang'] );
}
}
$options['post_type'] = explode(', ', $options['post_type']);
$options['taxonomy'] = explode(', ', $options['taxonomy']);
if( in_array('all', $options['post_type']) )
{
$options['post_type'] = apply_filters('acf/get_post_types', array());
}
if( is_array($options['post_type']) && count($options['post_type']) == 1 )
{
$options['post_type'] = $options['post_type'][0];
}
if( ! in_array('all', $options['taxonomy']) )
{
$taxonomies = array();
$options['tax_query'] = array();
foreach( $options['taxonomy'] as $v )
{
$term = explode(':', $v);
if( !is_array($term) || !isset($term[1]) )
{
continue;
}
$taxonomies[ $term[0] ][] = $term[1];
}
foreach( $taxonomies as $k => $v )
{
$options['tax_query'][] = array(
'taxonomy' => $k,
'field' => 'id',
'terms' => $v,
);
}
}
unset( $options['taxonomy'] );
$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'] );
}
$the_post = get_post( $options['post_id'] );
$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 );
$wp_query = new WP_Query( $options );
global $post;
while( $wp_query->have_posts() ) {
$wp_query->the_post();
$title = $this->get_result($post, $field, $the_post, $options);
$r['html'] .= '<li><a href="' . get_permalink($post->ID) . '" data-post_id="' . $post->ID . '">' . $title . '<span class="acf-button-add"></span></a></li>';
}
if( (int)$options['paged'] >= $wp_query->max_num_pages ) {
$r['next_page_exists'] = 0;
}
wp_reset_postdata();
JSON
echo json_encode( $r );
die();
}
function create_field( $field )
{
global $post;
if( !$field['max'] || $field['max'] < 1 )
{
$field['max'] = 9999;
}
$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']
);
if( defined('ICL_LANGUAGE_CODE') )
{
$attributes['lang'] = ICL_LANGUAGE_CODE;
}
preg_match('/\[(field_.*?)\]/', $field['name'], $ancestor);
if( isset($ancestor[1]) && $ancestor[1] != $field['key'])
{
$attributes['ancestor'] = $ancestor[1];
}
?>
<div class="acf_relationship<?php echo $class; ?>"<?php foreach( $attributes as $k => $v ): ?> data-<?php echo $k; ?>="<?php echo $v; ?>"<?php endforeach; ?>>
<!-- Hidden Blank default value -->
<input type="hidden" name="<?php echo $field['name']; ?>" value="" />
<!-- Left List -->
<div class="relationship_left">
<table class="widefat">
<thead>
<?php if(in_array( 'search', $field['filters']) ): ?>
<tr>
<th>
<input class="relationship_search" placeholder="<?php _e("Search...", 'acf'); ?>" type="text" id="relationship_<?php echo $field['name']; ?>" />
</th>
</tr>
<?php endif; ?>
<?php if(in_array( 'post_type', $field['filters']) ): ?>
<tr>
<th>
<?php
$choices = array(
'all' => __("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;
}
}
do_action('acf/create_field', array(
'type' => 'select',
'name' => '',
'class' => 'select-post_type',
'value' => '',
'choices' => $choices,
));
?>
</th>
</tr>
<?php endif; ?>
</thead>
</table>
<ul class="bl relationship_list">
<li class="load-more">
<div class="acf-loading"></div>
</li>
</ul>
</div>
<!-- /Left List -->
<!-- Right List -->
<div class="relationship_right">
<ul class="bl relationship_list">
<?php
if( $field['value'] )
{
foreach( $field['value'] as $p )
{
$title = $this->get_result($p, $field, $post);
echo '<li>
<a href="' . get_permalink($p->ID) . '" class="" data-post_id="' . $p->ID . '">' . $title . '<span class="acf-button-remove"></span></a>
<input type="hidden" name="' . $field['name'] . '[]" value="' . $p->ID . '" />
</li>';
}
}
?>
</ul>
</div>
<!-- / Right List -->
</div>
<?php
}
function create_options( $field )
{
$key = $field['name'];
?>
<tr class="field_option field_option_<?php echo $this->name; ?>">
<td class="label">
<label><?php _e("Return Format", 'acf'); ?></label>
<p><?php _e("Specify the returned value on front end", 'acf') ?></p>
</td>
<td>
<?php
do_action('acf/create_field', array(
'type' => 'radio',
'name' => 'fields['.$key.'][return_format]',
'value' => $field['return_format'],
'layout' => 'horizontal',
'choices' => array(
'object' => __("Post Objects", 'acf'),
'id' => __("Post IDs", 'acf')
)
));
?>
</td>
</tr>
<tr class="field_option field_option_<?php echo $this->name; ?>">
<td class="label">
<label for=""><?php _e("Post Type", 'acf'); ?></label>
</td>
<td>
<?php
$choices = array(
'all' => __("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,
));
?>
</td>
</tr>
<tr class="field_option field_option_<?php echo $this->name; ?>">
<td class="label">
<label><?php _e("Filter from Taxonomy", 'acf'); ?></label>
</td>
<td>
<?php
$choices = array(
'' => 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,
));
?>
</td>
</tr>
<tr class="field_option field_option_<?php echo $this->name; ?>">
<td class="label">
<label><?php _e("Filters", 'acf'); ?></label>
</td>
<td>
<?php
do_action('acf/create_field', array(
'type' => 'checkbox',
'name' => 'fields['.$key.'][filters]',
'value' => $field['filters'],
'choices' => array(
'search' => __("Search", 'acf'),
'post_type' => __("Post Type Select", 'acf'),
)
));
?>
</td>
</tr>
<tr class="field_option field_option_<?php echo $this->name; ?>">
<td class="label">
<label><?php _e("Elements", 'acf'); ?></label>
<p><?php _e("Selected elements will be displayed in each result", 'acf') ?></p>
</td>
<td>
<?php
do_action('acf/create_field', array(
'type' => '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'
)
));
?>
</td>
</tr>
<tr class="field_option field_option_<?php echo $this->name; ?>">
<td class="label">
<label><?php _e("Maximum posts", 'acf'); ?></label>
</td>
<td>
<?php
do_action('acf/create_field', array(
'type' => 'number',
'name' => 'fields['.$key.'][max]',
'value' => $field['max'],
));
?>
</td>
</tr>
<?php
}
function format_value( $value, $post_id, $field )
{
?
if( !empty($value) )
{
if( is_string($value) )
{
$value = explode(', ', $value);
}
if( is_array($value) )
{
$value = array_map('intval', $value);
$value = $this->get_posts( $value );
}
}
value
return $value;
}
function format_value_for_api( $value, $post_id, $field )
{
?
if( !$value )
{
return $value;
}
if( is_string($value) )
{
$value = explode(', ', $value);
}
?
if( !is_array($value) || empty($value) )
{
return $value;
}
$value = array_map('intval', $value);
format
if( $field['return_format'] == 'object' )
{
$value = $this->get_posts( $value );
}
return $value;
}
function get_posts( $post_ids )
{
if( empty($post_ids) )
{
return $post_ids;
}
$r = array();
$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 )
{
$ordered_posts[ $p->ID ] = $p;
}
foreach( $post_ids as $k => $v)
{
if( isset($ordered_posts[ $v ]) )
{
$r[] = $ordered_posts[ $v ];
}
}
return $r;
}
function update_value( $value, $post_id, $field )
{
if( empty($value) )
{
return $value;
}
if( is_string($value) )
{
$value = explode(', ', $value);
}
elseif( is_object($value) && isset($value->ID) )
{
$value = array( $value->ID );
}
elseif( is_array($value) )
{
foreach( $value as $k => $v ) {
?
if( is_object($v) && isset($v->ID) )
{
$value[ $k ] = $v->ID;
}
}
}
$value = array_map('strval', $value);
return $value;
}
}
new acf_field_relationship();
?>