entity_autocomplete.module in Entity Autocomplete 7
Provides functionalities for entity fields autocompletion.
File
entity_autocomplete.moduleView source
<?php
/**
* @file
* Provides functionalities for entity fields autocompletion.
*/
/**
* Implements hook_permission().
*
*/
function entity_autocomplete_permission() {
return array(
'use entity autocomplete' => array(
'title' => t('Use Entity Autocomplete'),
'description' => t('Access any entity autocomplete path. Warning: gives visibility to all entities.'),
),
);
}
/**
* Implements hook_menu().
*/
function entity_autocomplete_menu() {
$items = array();
$items['entity-autocomplete/%'] = array(
'title' => 'Entity Autocomplete',
'page callback' => 'entity_autocomplete',
'page arguments' => array(
2,
1,
NULL,
),
'access arguments' => array(
'use entity autocomplete',
),
'type' => MENU_CALLBACK,
);
$items['entity-autocomplete/bundle/%/%entity_autocomplete_bundles'] = array(
'title' => 'Entity Autocomplete',
'page callback' => 'entity_autocomplete',
'page arguments' => array(
4,
2,
3,
),
'access arguments' => array(
'use entity autocomplete',
),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Returns a bundles list from bundles path part.
*/
function entity_autocomplete_bundles_load($bundles) {
return empty($bundles) ? NULL : explode('+', $bundles);
}
/**
* Autocomplete callback for all entity types.
*/
function entity_autocomplete($string, $entity_type, $bundles = NULL) {
$info = entity_get_info($entity_type);
$table = $info['base table'];
$matches = array();
if (drupal_strlen($string)) {
$query = db_select($table);
$query
->addField($table, $info['entity keys']['id'], 'id');
$query
->addField($table, $info['entity keys']['label'], 'label');
$query
->condition($info['entity keys']['label'], '%' . db_like($string) . '%', 'LIKE');
if ($bundles) {
$bundle_field = $info['entity keys']['bundle'];
if ($entity_type == 'taxonomy_term') {
$vids = array_map(create_function('$v', 'return $v->vid;'), taxonomy_vocabulary_get_names());
$bundles = array_intersect_key($vids, array_flip($bundles));
$bundle_field = 'vid';
}
$query
->condition($bundle_field, $bundles);
}
$result = $query
->execute();
while ($entity = $result
->fetch()) {
$label = entity_autocomplete_get_label($entity->label, $entity->id);
$matches[$label] = $label;
}
}
drupal_json_output($matches);
}
/**
* Build a label smaller than 128 chars.
*/
function entity_autocomplete_get_label($label, $id) {
$label = check_plain($label);
$ref_id = ' [id:' . $id . ']';
$ref_id_length = strlen($ref_id);
if (drupal_strlen($label) >= 128 - $ref_id_length) {
$label = drupal_substr($label, 124 - $ref_id_length) . ' ...';
}
return strip_tags(decode_entities($label)) . $ref_id;
}
/**
* Extract an ID from a string returned by one of the autocomplete callbacks.
*
* @param $value
* A string of the form "title [id:ID]" or an integer.
* @return
* The extracted ID.
*/
function entity_autocomplete_get_id($value) {
return is_numeric($value) ? $value : preg_replace('/.*\\[id:(.*)\\].*/', '${1}', $value);
}
/**
* Implements hook_element_info().
*/
function entity_autocomplete_element_info() {
return array(
'entity_autocomplete' => array(
'#input' => TRUE,
'#size' => 60,
'#maxlength' => 128,
'#autocomplete_path' => FALSE,
'#entity_type' => 'node',
'#bundles' => array(),
'#process' => array(
'entity_autocomplete_element_process',
'ajax_process_form',
),
'#element_validate' => array(
'entity_autocomplete_element_validate',
),
'#value_callback' => 'entity_autocomplete_element_value',
'#theme' => 'textfield',
'#theme_wrappers' => array(
'form_element',
),
),
);
}
/**
* Determines the value for an entity autocomplete form element.
*
* @param $form
* The form element whose value is being populated.
* @param $input
* The incoming input to populate the form element. If this is FALSE,
* the element's default value should be returned.
*
* @return
* The data that will appear in the $element_state['values'] collection
* for this element. Return nothing to use the default.
*/
function entity_autocomplete_element_value($element, $input = FALSE) {
if (FALSE === $input) {
return isset($element['#default_value']) ? $element['#default_value'] : '';
}
else {
return isset($input) && strlen($input) ? entity_autocomplete_get_id($input) : '';
}
}
/**
* Form element processing handler for the #autocomplete_path property.
*/
function entity_autocomplete_element_process($element, $form_state) {
if (user_access('use entity autocomplete')) {
$parts = array(
'entity-autocomplete',
$element['#entity_type'],
);
if ($element['#bundles']) {
array_splice($parts, 1, 0, 'bundle');
$parts[] = implode('+', (array) $element['#bundles']);
}
$element['#autocomplete_path'] = implode('/', $parts);
// Try to display the full entity label.
if (!empty($element['#value']) && is_numeric($element['#value'])) {
$element['#value'] = entity_autocomplete_element_label($element['#value'], $element['#entity_type']);
}
}
// Function form_process_autocomplete() was added to core in v7.39.
if (function_exists('form_process_autocomplete')) {
$element = form_process_autocomplete($element);
}
// Keep compatible with AJAX.
if (isset($element['#ajax']) && !isset($element['#ajax']['event'])) {
// The ajax_pre_render_element() function does not recognize the
// 'entity_autocomplete' element, so is does not add the expected event
// that triggers the AJAX callback.
$element['#ajax']['event'] = 'blur';
}
return $element;
}
/**
* Retrieve entity label from its ID.
*/
function entity_autocomplete_element_label($entity_id, $entity_type) {
$labels =& drupal_static(__FUNCTION__, array());
if (!isset($labels[$entity_type][$entity_id])) {
$labels[$entity_type][$entity_id] = $entity_id;
if ($info = entity_get_info($entity_type)) {
$table = $info['base table'];
$query = db_select($table);
$query
->addField($table, $info['entity keys']['label'], 'label');
$query
->condition($info['entity keys']['id'], $entity_id);
if ($row = $query
->execute()
->fetch()) {
$labels[$entity_type][$entity_id] = entity_autocomplete_get_label($row->label, $entity_id);
}
}
}
return $labels[$entity_type][$entity_id];
}
/**
* Validate an entity autocomplete element.
*/
function entity_autocomplete_element_validate($element, &$form_state, $form) {
if (!empty($element['#value'])) {
$info = entity_get_info($element['#entity_type']);
$table = $info['base table'];
$id_field = $info['entity keys']['id'];
$query = db_select($table);
$query
->addField($table, $id_field);
$query
->condition($id_field, entity_autocomplete_get_id($element['#value']));
if ($element['#bundles']) {
$bundle_field = $info['entity keys']['bundle'];
$bundles = (array) $element['#bundles'];
// Handle taxonomy seperately as its bundles work differently.
if ($element['#entity_type'] === 'taxonomy_term') {
$vids = array();
foreach (taxonomy_get_vocabularies() as $vid => $vocab) {
$vids[$vocab->machine_name] = $vid;
}
$bundles = array_intersect_key($vids, array_flip($bundles));
$bundle_field = 'vid';
}
$query
->condition($bundle_field, $bundles);
}
if (!$query
->execute()
->fetch()) {
form_error($element, t('The specified entity %value does not match requirements.', array(
'%value' => $element['#value'],
)));
}
}
}
Functions
Name | Description |
---|---|
entity_autocomplete | Autocomplete callback for all entity types. |
entity_autocomplete_bundles_load | Returns a bundles list from bundles path part. |
entity_autocomplete_element_info | Implements hook_element_info(). |
entity_autocomplete_element_label | Retrieve entity label from its ID. |
entity_autocomplete_element_process | Form element processing handler for the #autocomplete_path property. |
entity_autocomplete_element_validate | Validate an entity autocomplete element. |
entity_autocomplete_element_value | Determines the value for an entity autocomplete form element. |
entity_autocomplete_get_id | Extract an ID from a string returned by one of the autocomplete callbacks. |
entity_autocomplete_get_label | Build a label smaller than 128 chars. |
entity_autocomplete_menu | Implements hook_menu(). |
entity_autocomplete_permission | Implements hook_permission(). |