View source
<?php
function term_reference_filter_by_views_menu() {
$items['term_reference_filter_by_views/autocomplete/%/%/%'] = array(
'title' => 'Autocomplete taxonomy',
'page callback' => 'term_reference_filter_by_views_taxonomy_autocomplete',
'page arguments' => array(
2,
3,
4,
),
'access arguments' => array(
'access content',
),
'type' => MENU_CALLBACK,
);
return $items;
}
function term_reference_filter_by_views_field_widget_form_alter(&$element, &$form_state, $context) {
if ($context['field']['type'] == 'taxonomy_term_reference') {
if (!empty($context['instance']['view']['view_name'])) {
if (isset($element['#type']) && ($element['#type'] == 'select' || $element['#type'] == 'radios' || $element['#type'] == 'checkboxes')) {
$allowed = _get_referencable_terms_from_view($context['field'], $context['instance'], NULL, 0, NULL, FALSE);
if (!empty($allowed)) {
$options = array();
if (isset($element['#options']['_none'])) {
$options = array(
'_none' => $element['#options']['_none'],
);
}
else {
$options = array(
'_none' => theme('options_none', array(
'instance' => $context['instance'],
'option' => $element['#properties']['empty_option'],
)),
);
}
$options += array_intersect_key($allowed, $element['#options']);
$element['#options'] = $options;
}
}
elseif (isset($element['#autocomplete_path']) || isset($element['tid']['#autocomplete_path'])) {
if (isset($element['#field_name'])) {
$element['#instance'] = $context['instance'];
$element['#autocomplete_path'] = 'term_reference_filter_by_views/autocomplete/' . $element['#field_name'] . '/' . $context['instance']['entity_type'] . '/' . $context['instance']['bundle'] . '/';
if (!empty($context['instance']['view']['size'])) {
$element['#size'] = $context['instance']['view']['size'];
}
}
elseif (isset($element['tid']['#field_name'])) {
$element['tid']['#instance'] = $context['instance'];
if (!empty($element['tid']['#default_value'])) {
$view_term = _get_referencable_terms_from_view($context['field'], $context['instance'], NULL, 0, array(
$element['tid']['#default_value'],
));
$element['tid']['#default_value'] = current($view_term);
}
if (!empty($context['instance']['view']['size'])) {
$element['tid']['#size'] = $context['instance']['view']['size'];
}
$element['tid']['#element_validate'] = array(
'_term_reference_autocomplete_validate',
);
$element['tid']['#autocomplete_path'] = 'term_reference_filter_by_views/autocomplete/' . $element['tid']['#field_name'] . '/' . $context['instance']['entity_type'] . '/' . $context['instance']['bundle'] . '/';
}
}
elseif (isset($element['#autocomplete_deluxe_path']) && module_exists('autocomplete_deluxe')) {
if (!empty($element['#default_value'])) {
foreach ($context['items'] as $item) {
$tids[$item['tid']] = $item['tid'];
}
$referencable_terms = _get_referencable_terms_from_view($context['field'], $context['instance'], NULL, 0, $tids);
$element['#default_value'] = implode(',', $referencable_terms);
}
if (!empty($context['instance']['view']['size'])) {
$element['#size'] = $context['instance']['view']['size'];
}
$element['#instance'] = $context['instance'];
$element['#element_validate'] = array(
'_term_reference_autocomplete_validate',
);
$element['#autocomplete_deluxe_path'] = url('term_reference_filter_by_views/autocomplete/' . $element['#field_name'] . '/' . $context['instance']['entity_type'] . '/' . $context['instance']['bundle'] . '/', array(
'absolute' => TRUE,
));
}
}
}
}
function _term_reference_autocomplete_validate($element, &$form_state, $form) {
$value = '';
if (!empty($element['#value'])) {
if (isset($element['#multiple']) && $element['value_field']['#type'] == 'textfield') {
$terms_data = drupal_explode_tags($element['#value']);
}
else {
$terms_data = array(
$element['#value'],
);
}
foreach ($terms_data as $term_data) {
if (preg_match("/.+\\(\\s*id\\s*:(\\d+)\\)/", $term_data, $matches)) {
if ($element['#instance']['widget']['type'] == 'references_dialog_term_reference') {
$value = $matches[1];
}
else {
$value[] = (array) taxonomy_term_load($matches[1]);
}
}
else {
$value[] = NULL;
}
}
}
form_set_value($element, $value, $form_state);
}
function term_reference_filter_by_views_form_field_ui_field_edit_form_alter(&$form) {
if ($form['#field']['type'] == 'taxonomy_term_reference') {
$field = $form['#field'];
$view_settings = empty($form['#instance']['view']) ? '' : $form['#instance']['view'];
$displays = views_get_applicable_views('term_reference display');
$entity_info = entity_get_info('taxonomy_term');
$options = array();
foreach ($displays as $data) {
list($view, $display_id) = $data;
if ($view->base_table == $entity_info['base table']) {
$options[$view->name . ':' . $display_id] = $view->name . ' - ' . $view->display[$display_id]->display_title;
}
}
if ($options) {
$options = array(
'' => '<' . t('none') . '>',
) + $options;
$default = !empty($view_settings['view_name']) ? $view_settings['view_name'] . ':' . $view_settings['display_name'] : '';
$form['instance']['view'] = array(
'#type' => 'fieldset',
'#title' => t('Filter by Views settings'),
'#element_validate' => array(
'term_reference_view_settings_validate',
),
);
$form['instance']['view']['view_and_display'] = array(
'#type' => 'select',
'#title' => t('View used to select the entities'),
'#options' => $options,
'#default_value' => $default,
'#description' => '<p>' . t('Choose the view and display that select the entities that can be referenced.<br />Only views with a display of type "Term Reference" are eligible.') . '</p>',
);
$default = !empty($view_settings['args']) ? implode(', ', $view_settings['args']) : '';
$form['instance']['view']['args'] = array(
'#type' => 'textfield',
'#title' => t('View arguments'),
'#default_value' => $default,
'#required' => FALSE,
'#description' => t('Provide a comma separated list of arguments to pass to the view.'),
);
$form['instance']['view']['match_operator'] = array(
'#type' => 'select',
'#title' => t('Autocomplete matching'),
'#default_value' => isset($view_settings['match_operator']) ? $view_settings['match_operator'] : 'CONTAINS',
'#options' => array(
'STARTS_WITH' => t('Starts with'),
'CONTAINS' => t('Contains'),
),
'#description' => t('Select the method used to collect autocomplete suggestions. Note that <em>Contains</em> can cause performance issues on sites with thousands of terms.'),
);
$form['instance']['view']['size'] = array(
'#type' => 'textfield',
'#title' => t('Size of textfield'),
'#default_value' => isset($view_settings['size']) ? $view_settings['size'] : NULL,
'#element_validate' => array(
'_element_validate_integer_positive',
),
);
if (!empty($view_settings['view_name']) && isset($form['instance']['widget']['settings']['autocomplete_match'])) {
$form['instance']['widget']['settings']['autocomplete_match']['#access'] = FALSE;
}
}
else {
$form['instance']['view']['no_view_help'] = array(
'#markup' => '<p>' . t('No eligible views were found. <a href="@create">Create a view</a> with an <em>Term Reference</em> display, or add such a display to an <a href="@existing">existing view</a>.', array(
'@create' => url('admin/structure/views/add'),
'@existing' => url('admin/structure/views'),
)) . '</p>',
);
}
}
}
function term_reference_view_settings_validate($element, &$form_state, $form) {
if (!empty($element['view_and_display']['#value'])) {
list($view, $display) = explode(':', $element['view_and_display']['#value']);
}
else {
$view = '';
$display = '';
}
$args_string = trim($element['args']['#value']);
if ($args_string === '') {
$args = array();
}
else {
$args = array_map('trim', explode(',', $args_string));
}
$value = array(
'view_name' => $view,
'display_name' => $display,
'args' => $args,
'match_operator' => $element['match_operator']['#value'],
'size' => $element['size']['#value'],
);
form_set_value($element, $value, $form_state);
}
function term_reference_filter_by_views_taxonomy_autocomplete($field_name, $entity_type, $bundle_name, $tid = '', $string = '') {
$field = field_info_field($field_name);
$instance = field_info_instance($entity_type, $field_name, $bundle_name);
$matches = array();
$type = 'tags';
if (!$field || !$instance || $field['type'] != 'taxonomy_term_reference' || !field_access('edit', $field, $entity_type)) {
return MENU_ACCESS_DENIED;
}
$term = NULL;
if ($tid !== 'NULL' && is_numeric($tid)) {
$term = entity_load_single('taxonomy_term', $tid);
if (!$term || !entity_access('view', 'taxonomy_term', $term)) {
return MENU_ACCESS_DENIED;
}
}
if ($type == 'tags') {
$tags_typed = drupal_explode_tags($string);
$tag_last = drupal_strtolower(array_pop($tags_typed));
if (!empty($tag_last)) {
$prefix = count($tags_typed) ? drupal_implode_tags($tags_typed) . ', ' : '';
}
}
else {
$prefix = '';
$tag_last = $string;
}
if (!empty($tag_last)) {
$term_labels = _get_referencable_terms_from_view($field, $instance, $tag_last, 15, NULL, FALSE);
foreach ($term_labels as $tid => $label) {
$key = "{$label} (id:{$tid})";
if (strpos($key, ',') !== FALSE || strpos($key, '"') !== FALSE) {
$key = '"' . str_replace('"', '""', $key) . '"';
}
$matches[$prefix . $key] = $key;
}
}
drupal_json_output($matches);
}
function _get_referencable_terms_from_view($field, $instance, $match = NULL, $limit = 0, $ids = NULL, $width_tid = TRUE) {
$terms = array();
$view_terms = _get_view_results_for_term_reference_field($field, $instance, $match, $limit, $ids);
foreach ($view_terms as $tid => $row) {
$terms[$tid] = preg_replace('/\\s\\s+/', ' ', str_replace("\n", '', trim(decode_entities(strip_tags($row)))));
if ($width_tid) {
$terms[$tid] .= " (id:{$tid})";
}
}
return $terms;
}
function _get_view_results_for_term_reference_field($field, $instance, $match = NULL, $limit = 0, $ids = NULL) {
$display_name = $instance['view']['display_name'];
$args = $instance['view']['args'];
$result = array();
$view_name = $instance['view']['view_name'];
$display_name = $instance['view']['display_name'];
$args = $instance['view']['args'];
$entity_type = 'taxonomy_term';
$view = views_get_view($view_name);
if (!$view || !isset($view->display[$display_name]) || !$view
->access($display_name)) {
watchdog('term_reference_filter_by_views', 'The view %view_name is no longer eligible for the %field_name field.', array(
'%view_name' => $view_name,
'%field_name' => $instance['label'],
), WATCHDOG_WARNING);
return $result;
}
$view
->set_display($display_name);
$view->is_cacheable = FALSE;
$term_reference_options = array(
'match' => $match,
'match_operator' => isset($instance['view']['match_operator']) ? $instance['view']['match_operator'] : 'CONTAINS',
'limit' => $limit,
'ids' => $ids,
);
$view->display_handler
->set_option('term_reference_options', $term_reference_options);
$result = $view
->execute_display($display_name, $args);
return $result;
}
function term_reference_filter_by_views_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'term_reference_filter_by_views') . '/views',
);
}
function term_reference_filter_by_views_views_plugins_alter(&$plugins) {
if (isset($plugins['display']['references_dialog'])) {
$plugins['display']['references_dialog']['handler'] = 'term_reference_references_dialog_plugin_display';
}
}