web/wp-content/plugins/acf-extended/includes/fields/field-advanced-link.php (427 lines of code) (raw):
<?php
if(!defined('ABSPATH')){
exit;
}
if(!class_exists('acfe_field_advanced_link')):
class acfe_field_advanced_link extends acf_field{
/**
* initialize
*/
function initialize(){
$this->name = 'acfe_advanced_link';
$this->label = __('Advanced Link', 'acfe');
$this->category = 'relational';
$this->defaults = array(
'post_type' => array(),
'taxonomy' => array(),
);
$this->add_action('wp_ajax_acfe/fields/advanced_link/post_query', array($this, 'ajax_query'));
$this->add_action('wp_ajax_nopriv_acfe/fields/advanced_link/post_query', array($this, 'ajax_query'));
}
/**
* render_field_settings
*
* @param $field
*/
function render_field_settings($field){
// filter post types
acf_render_field_setting($field, array(
'label' => __('Filter by Post Type', 'acf'),
'instructions' => '',
'type' => 'select',
'name' => 'post_type',
'choices' => acf_get_pretty_post_types(),
'multiple' => 1,
'ui' => 1,
'allow_null' => 1,
'placeholder' => __('All post types', 'acf'),
));
// filter taxonomies
acf_render_field_setting($field, array(
'label' => __('Filter by Taxonomy', 'acf'),
'instructions' => '',
'type' => 'select',
'name' => 'taxonomy',
'choices' => acf_get_taxonomy_terms(),
'multiple' => 1,
'ui' => 1,
'allow_null' => 1,
'placeholder' => __('All taxonomies', 'acf'),
));
}
/**
* render_field
*
* @param $field
*/
function render_field($field){
// vars
$div = array(
'id' => $field['id'],
'class' => $field['class'] . ' acf-link',
);
// subfields
$sub_fields = $this->get_sub_fields($field);
// render value
$render = $this->render_value($field['value']);
// classes
if($render['url'] || $render['title']){
$div['class'] .= ' -value';
}
if($render['target']){
$div['class'] .= ' -external';
}
?>
<div <?php echo acf_esc_atts($div); ?>>
<?php acf_hidden_input(array('name' => $field['name'])); ?>
<div class="acfe-modal" data-title="<?php echo $field['label']; ?>" data-size="medium" data-footer="<?php _e('Close', 'acfe'); ?>">
<div class="acfe-modal-wrapper">
<div class="acfe-modal-content">
<div class="acf-fields -left">
<?php foreach($sub_fields as $sub_field): ?>
<?php acf_render_field_wrap($sub_field); ?>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
<a href="#" class="button" data-name="add" target=""><?php _e('Select Link', 'acf'); ?></a>
<div class="link-wrap">
<span class="link-title"><?php echo esc_html($render['title']); ?></span>
<a class="link-url" href="<?php echo esc_url($render['url']); ?>" target="_blank"><?php echo esc_html($render['name']); ?></a>
<i class="acf-icon -link-ext acf-js-tooltip" title="<?php _e('Opens in a new window/tab', 'acf'); ?>"></i><?php
?><a class="acf-icon -pencil -clear acf-js-tooltip" data-name="edit" href="#" title="<?php _e('Edit', 'acf'); ?>"></a><?php
?><a class="acf-icon -cancel -clear acf-js-tooltip" data-name="remove" href="#" title="<?php _e('Remove', 'acf'); ?>"></a>
</div>
</div>
<?php
}
/**
* get_sub_fields
*
* @param $field
*
* @return mixed|null
*/
function get_sub_fields($field){
// get value
$value = $field['value'];
// storage
$sub_fields = array();
// type
$sub_fields[] = array(
'name' => 'type',
'key' => 'type',
'label' => __('Type', 'acf'),
'type' => 'radio',
'required' => false,
'class' => 'input-type',
'choices' => array(
'url' => __('URL', 'acf'),
'post' => __('Post', 'acf'),
'term' => __('Term', 'acf'),
),
);
// url
$sub_fields[] = array(
'name' => 'url',
'key' => 'url',
'label' => __('URL', 'acf'),
'type' => 'text',
'required' => false,
'class' => 'input-url',
'value' => isset($value['type']) && $value['type'] === 'url' ? $value['value'] : '', // inject value based on type
'conditional_logic' => array(
array(
array(
'field' => 'type',
'operator' => '==',
'value' => 'url',
)
)
)
);
// post
$sub_fields[] = array(
'name' => 'post',
'key' => 'post',
'label' => __('Post', 'acf'),
'type' => 'select',
'required' => false,
'class' => 'input-post',
'allow_null' => 0,
'ui' => 1,
'ajax' => 1,
'ajax_action' => 'acfe/fields/advanced_link/post_query',
'choices' => $this->get_post_choices($field),
'value' => isset($value['type']) && $value['type'] === 'post' ? $value['value'] : '', // inject value based on type
'conditional_logic' => array(
array(
array(
'field' => 'type',
'operator' => '==',
'value' => 'post',
)
)
)
);
// term
$sub_fields[] = array(
'name' => 'term',
'key' => 'term',
'label' => __('Term', 'acf'),
'type' => 'acfe_taxonomy_terms',
'required' => false,
'class' => 'input-term',
'field_type' => 'select',
'return_format' => 'id',
'ui' => 1,
'allow_null' => 0,
'value' => isset($value['type']) && $value['type'] === 'term' ? $value['value'] : '', // inject value based on type
'conditional_logic' => array(
array(
array(
'field' => 'type',
'operator' => '==',
'value' => 'term',
)
)
)
);
// title
$sub_fields[] = array(
'name' => 'title',
'key' => 'title',
'label' => __('Link text', 'acf'),
'type' => 'text',
'required' => false,
'class' => 'input-title',
);
// target
$sub_fields[] = array(
'name' => 'target',
'key' => 'target',
'label' => __('Target', 'acf'),
'type' => 'true_false',
'message' => __('Open in a new window', 'acf'),
'required' => false,
'class' => 'input-target',
);
// deprecated
$sub_fields = apply_filters_deprecated('acfe/fields/advanced_link/fields', array($sub_fields, $field, $value), '0.8.1', 'acfe/fields/advanced_link/sub_fields');
$sub_fields = apply_filters_deprecated('acfe/fields/advanced_link/fields/name=' . $field['_name'], array($sub_fields, $field, $value), '0.8.1', 'acfe/fields/advanced_link/sub_fields/name=' . $field['_name']);
$sub_fields = apply_filters_deprecated('acfe/fields/advanced_link/fields/key=' . $field['key'], array($sub_fields, $field, $value), '0.8.1', 'acfe/fields/advanced_link/sub_fields/key=' . $field['key']);
// filters
$sub_fields = apply_filters('acfe/fields/advanced_link/sub_fields', $sub_fields, $field, $value);
$sub_fields = apply_filters('acfe/fields/advanced_link/sub_fields/name=' . $field['_name'], $sub_fields, $field, $value);
$sub_fields = apply_filters('acfe/fields/advanced_link/sub_fields/key=' . $field['key'], $sub_fields, $field, $value);
// map subfields
$sub_fields = acfe_map_fields($sub_fields, function($sub_field){
// handle missing key
if(!isset($sub_field['key'])){
$sub_field['key'] = $sub_field['name'];
}
return $sub_field;
});
foreach($sub_fields as &$sub_field){
// add value
if(isset($value[ $sub_field['key'] ])){
// this is a normal value
$sub_field['value'] = $value[ $sub_field['key'] ];
}elseif(isset($sub_field['default_value'])){
// no value, but this subfield has a default value
$sub_field['value'] = $sub_field['default_value'];
}
// update prefix to allow for nested values
$sub_field['prefix'] = $field['name'];
}
return $sub_fields;
}
/**
* load_value
*
* @param $value
* @param $post_id
* @param $field
*
* @return array
*/
function load_value($value, $post_id, $field){
// bail early
if(empty($value)){
return $value;
}
// if value is string then set as value
if(is_string($value)){
$value = array('value' => $value);
}
if(is_array($value)){
// defaults array
$value = wp_parse_args($value, array(
'type' => 'url',
'value' => '',
'title' => '',
'target' => false,
));
// handle old args
foreach(array('post', 'term') as $arg){
if(isset($value[ $arg ])){
$value['value'] = $value[ $arg ];
unset($value[ $arg ]);
}
}
}
// return value
return $value;
}
/**
* format_value
*
* @param $value
* @param $post_id
* @param $field
*
* @return array
*/
function format_value($value, $post_id, $field){
// bail early
if(empty($value)){
return $value;
}
// if value is string then set as value
if(is_string($value)){
$value = array('value' => $value);
}
// return
return $this->render_value($value);
}
/**
* validate_value
*
* @param $valid
* @param $value
* @param $field
* @param $input
*
* @return false
*/
function validate_value($valid, $value, $field, $input){
// bail early if not required
if(!$field['required']){
return $valid;
}
// loop over fields
foreach(array('url', 'post', 'term') as $type){
if($value['type'] === $type && empty($value[ $type ])){
return false;
}
}
// return
return $valid;
}
/**
* update_value
*
* @param $value
* @param $post_id
* @param $field
*
* @return array
*/
function update_value($value, $post_id, $field){
// bail early
if(empty($value)){
return $value;
}
// compatibility with string
if(is_string($value)){
$value = array('value' => $value);
}
if($value['type'] === 'url' && !empty($value['value'])){
$value['url'] = $value['value'];
}
// defaults
$value = wp_parse_args($value, array(
'type' => 'url',
'value' => '',
'url' => '',
'title' => '',
'target' => '',
));
// loop over fields
foreach(array('url', 'post', 'term') as $type){
if($value['type'] === $type && isset($value[ $type ])){
$value['value'] = $value[ $type ];
break;
}
}
// remove unecessary arguments
unset($value['url'], $value['post'], $value['term']);
// sanitize target
$value['target'] = (bool) $value['target'];
// empty value
// allow to save empty value to not pollute db
if(empty($value['value']) && empty($value['title'])){
// must be empty string so options page can save empty value
// fix a bug where option would not save value if value = false
$value = '';
}
return $value;
}
/**
* render_value
*
* @param $value
*
* @return array
*/
function render_value($value){
// defaults
$value = wp_parse_args($value, array(
'type' => 'url',
'value' => '',
'url' => '',
'name' => '',
'title' => '',
'target' => '',
));
if(!empty($value['value'])){
switch($value['type']){
case 'url': {
$value['url'] = $value['value'];
$value['name'] = $value['value'];
break;
}
case 'post': {
$value['url'] = is_numeric($value['value']) ? get_permalink($value['value']) : get_post_type_archive_link($value['value']);
$value['name'] = is_numeric($value['value']) ? get_the_title($value['value']) : acf_get_post_type_label($value['value']) . ' Archive';
break;
}
case 'term': {
$term = get_term($value['value']);
if(!empty($term) && !is_wp_error($term)){
$value['url'] = get_term_link($term);
$value['name'] = $term->name;
}
break;
}
}
}
// format target
$value['target'] = $value['target'] ? '_blank' : '';
return $value;
}
/**
* get_post_choices
*
* @param $field
*
* @return array
*/
function get_post_choices($field){
// vars
$value = $field['value'];
$choices = array();
if(empty($value)){
return $choices;
}
$post_object = acf_get_field_type('post_object');
// load posts
$posts = $post_object->get_posts($value['value'], $field);
if($posts){
foreach(array_keys($posts) as $i){
// append choice
$post = acf_extract_var($posts, $i);
$choices[ $post->ID ] = $post_object->get_post_title($post, $field);
}
}
// string value
// post type archive
if(!empty($value['value']) && is_string($value['value'])){
// get post type
$post_type = $value['value'];
// check post type exists
if(post_type_exists($post_type)){
$label = acf_get_post_type_label($post_type);
$choices[ $post_type ] = "{$label} Archive";
}
}
return $choices;
}
/**
* ajax_query
*/
function ajax_query(){
// validate
if(!acf_verify_ajax()){
die();
}
// get choices
$response = $this->get_ajax_query($_POST);
// return
acf_send_ajax_results($response);
}
/**
* get_ajax_query
*
* Based on the post_object get_ajax_query() function
*
* @param $options
*
* @return array|false
*/
function get_ajax_query($options = array()){
// defaults
$options = acf_parse_args($options, array(
'post_id' => 0,
's' => '',
'field_key' => '',
'paged' => 1,
));
// post object
$post_object = acf_get_field_type('post_object');
// load field
$field = acf_get_field($options['field_key']);
if(!$field){
return false;
}
// vars
$results = array();
$args = array();
$is_search = false;
// paged
$args['posts_per_page'] = 20;
$args['paged'] = $options['paged'];
// search
if($options['s'] !== ''){
// strip slashes (search may be integer)
$s = wp_unslash(strval($options['s']));
// update vars
$args['s'] = $s;
$is_search = true;
}
// post_type
$args['post_type'] = acf_get_post_types();
if(!empty($field['post_type'])){
$args['post_type'] = acf_get_array($field['post_type']);
}
// taxonomy
if(!empty($field['taxonomy'])){
// vars
$terms = acf_decode_taxonomy_terms($field['taxonomy']);
// append to $args
$args['tax_query'] = array();
// now create the tax queries
foreach($terms as $k => $v){
$args['tax_query'][] = array(
'taxonomy' => $k,
'field' => 'slug',
'terms' => $v,
);
}
}
// filters
$args = apply_filters('acf/fields/post_object/query', $args, $field, $options['post_id']);
$args = apply_filters('acf/fields/post_object/query/name=' . $field['name'], $args, $field, $options['post_id']);
$args = apply_filters('acf/fields/post_object/query/key=' . $field['key'], $args, $field, $options['post_id']);
// get posts grouped by post type
$groups = acf_get_grouped_posts($args);
$archives = array();
$post_types_archives = acfe_get_post_types(array(
'include' => $field['post_type'],
'has_archive' => true,
));
foreach($post_types_archives as $post_type){
$label = acf_get_post_type_label($post_type);
$label = "{$label} Archive";
if($is_search && stripos($label, $s) === false){
continue;
}
$archives[] = array(
'id' => $post_type,
'text' => $label,
);
}
if(!empty($archives)){
// data
$results[] = array(
'text' => __('Archives', 'acfe'),
'children' => $archives,
);
}
// loop
foreach(array_keys($groups) as $group_title){
// vars
$posts = acf_extract_var($groups, $group_title);
// data
$data = array(
'text' => $group_title,
'children' => array(),
);
// convert post objects to post titles
foreach(array_keys($posts) as $post_id){
$posts[ $post_id ] = $post_object->get_post_title($posts[ $post_id ], $field, $options['post_id'], $is_search);
}
// order posts by search
if($is_search && empty($args['orderby']) && isset($args['s'])){
$posts = acf_order_by_search($posts, $args['s']);
}
// append to $data
foreach(array_keys($posts) as $post_id){
$data['children'][] = $post_object->get_post_result($post_id, $posts[ $post_id ]);
}
// append to $results
$results[] = $data;
}
// optgroup or single
$post_type = acf_get_array($args['post_type']);
if(count($post_type) === 1 && empty($post_types_archives)){
$results = $results[0]['children'];
}
// vars
$response = array(
'results' => $results,
'limit' => $args['posts_per_page'],
);
// return
return $response;
}
}
// initialize
acf_register_field_type('acfe_field_advanced_link');
endif;