Commit 499080f3 authored by alexpott's avatar alexpott
Browse files

Issue #1987858 by oenie, jibran, tim.plunkett: Convert taxonomy_autocomplete()...

Issue #1987858 by oenie, jibran, tim.plunkett: Convert taxonomy_autocomplete() to a new style controller.
parent e2e8b975
......@@ -306,7 +306,8 @@ protected function buildFilters(&$form, &$form_state) {
$form['displays']['show']['tagged_with'] = array(
'#type' => 'textfield',
'#title' => t('tagged with'),
'#autocomplete_path' => 'taxonomy/autocomplete/' . $tag_field_name,
'#autocomplete_route_name' => 'taxonomy_autocomplete',
'#autocomplete_route_parameters' => array('field_name' => $tag_field_name),
'#size' => 30,
'#maxlength' => 1024,
'#field_name' => $tag_field_name,
......
<?php
/**
* @file
* Contains \Drupal\taxonomy\Controller\TermAutocompleteController.
*/
namespace Drupal\taxonomy\Controller;
use Drupal\Component\Utility\Tags;
use Drupal\Component\Utility\Unicode;
use Drupal\Component\Utility\String;
use Drupal\Core\Controller\ControllerInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\field\FieldInfo;
use Drupal\taxonomy\TermStorageControllerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
/**
* Returns autocomplete responses for taxonomy terms.
*/
class TermAutocompleteController implements ControllerInterface {
/**
* Taxonomy term entity query interface.
*
* @var \Drupal\Core\Entity\Query\QueryInterface
*/
protected $termEntityQuery;
/**
* Field info service.
*
* @var \Drupal\field\FieldInfo
*/
protected $fieldInfo;
/**
* Term storage controller.
*
* @var \Drupal\taxonomy\TermStorageControllerInterface
*/
protected $termStorage;
/**
* Constructs a new \Drupal\taxonomy\Controller\TermAutocompleteController object.
*
* @param \Drupal\Core\Entity\Query\QueryInterface $term_entity_query
* The entity query service.
* @param \Drupal\field\FieldInfo $field_info
* The field info service.
* @param \Drupal\taxonomy\TermStorageControllerInterface $term_storage
* The term storage controller.
*/
public function __construct(QueryInterface $term_entity_query, FieldInfo $field_info, TermStorageControllerInterface $term_storage) {
$this->termEntityQuery = $term_entity_query;
$this->fieldInfo = $field_info;
$this->termStorage = $term_storage;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity.query')->get('taxonomy_term'),
$container->get('field.info'),
$container->get('plugin.manager.entity')->getStorageController('taxonomy_term')
);
}
/**
* Retrieves suggestions for taxonomy term autocompletion.
*
* This function outputs term name suggestions in response to Ajax requests
* made by the taxonomy autocomplete widget for taxonomy term reference
* fields. The output is a JSON object of plain-text term suggestions, keyed
* by the user-entered value with the completed term name appended.
* Term names containing commas are wrapped in quotes.
*
* For example, suppose the user has entered the string 'red fish, blue' in
* the field, and there are two taxonomy terms, 'blue fish' and 'blue moon'.
* The JSON output would have the following structure:
* @code
* {
* "red fish, blue fish": "blue fish",
* "red fish, blue moon": "blue moon",
* };
* @endcode
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request object.
* @param string $field_name
* The name of the term reference field.
*
* @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response
* When valid field name is specified, a JSON response containing the
* autocomplete suggestions for taxonomy terms. Otherwise a normal response
* containing an error message.
*/
public function autocomplete(Request $request, $field_name) {
// A comma-separated list of term names entered in the autocomplete form
// element. Only the last term is used for autocompletion.
$tags_typed = $request->query->get('q');
// Make sure the field exists and is a taxonomy field.
if (!($field = $this->fieldInfo->getField($field_name)) || $field['type'] !== 'taxonomy_term_reference') {
// Error string. The JavaScript handler will realize this is not JSON and
// will display it as debugging information.
return new Response(t('Taxonomy field @field_name not found.', array('@field_name' => $field_name)), 403);
}
// The user enters a comma-separated list of tags. We only autocomplete the
// last tag.
$tags_typed = Tags::explode($tags_typed);
$tag_last = Unicode::strtolower(array_pop($tags_typed));
$matches = array();
if ($tag_last != '') {
// Part of the criteria for the query come from the field's own settings.
$vids = array();
foreach ($field['settings']['allowed_values'] as $tree) {
$vids[] = $tree['vocabulary'];
}
$this->termEntityQuery->addTag('term_access');
// Do not select already entered terms.
if (!empty($tags_typed)) {
$this->termEntityQuery->condition('name', $tags_typed, 'NOT IN');
}
// Select rows that match by term name.
$tids = $this->termEntityQuery
->condition('vid', $vids, 'IN')
->condition('name', $tag_last, 'CONTAINS')
->range(0, 10)
->execute();
$prefix = count($tags_typed) ? Tags::implode($tags_typed) . ', ' : '';
if (!empty($tids)) {
$terms = $this->termStorage->loadMultiple(array_keys($tids));
foreach ($terms as $term) {
$name = $term->label();
// Term names containing commas or quotes must be wrapped in quotes.
if (strpos($name, ',') !== FALSE || strpos($name, '"') !== FALSE) {
$name = '"' . str_replace('"', '""', $name) . '"';
}
$matches[$prefix . $name] = String::checkPlain($term->label());
}
}
}
return new JsonResponse($matches);
}
}
......@@ -23,7 +23,7 @@
* },
* settings = {
* "size" = "60",
* "autocomplete_path" = "taxonomy/autocomplete",
* "autocomplete_route_name" = "taxonomy_autocomplete",
* "placeholder" = ""
* },
* multiple_values = TRUE
......@@ -73,7 +73,8 @@ public function formElement(FieldInterface $items, $delta, array $element, $lang
$element += array(
'#type' => 'textfield',
'#default_value' => taxonomy_implode_tags($tags),
'#autocomplete_path' => $this->getSetting('autocomplete_path') . '/' . $this->fieldDefinition->getFieldName(),
'#autocomplete_route_name' => $this->getSetting('autocomplete_route_name'),
'#autocomplete_route_parameters' => array('field_name' => $this->fieldDefinition->getFieldName()),
'#size' => $this->getSetting('size'),
'#placeholder' => $this->getSetting('placeholder'),
'#maxlength' => 1024,
......
......@@ -292,14 +292,6 @@ function taxonomy_menu() {
'type' => MENU_CALLBACK,
'file' => 'taxonomy.pages.inc',
);
$items['taxonomy/autocomplete/%'] = array(
'title' => 'Autocomplete taxonomy',
'page callback' => 'taxonomy_autocomplete',
'page arguments' => array(2),
'access arguments' => array('access content'),
'type' => MENU_CALLBACK,
'file' => 'taxonomy.pages.inc',
);
$items['admin/structure/taxonomy/manage/%taxonomy_vocabulary'] = array(
'title callback' => 'entity_page_label',
......
......@@ -6,8 +6,6 @@
*/
use Drupal\taxonomy\Entity\Term;
use Drupal\taxonomy\Entity\Vocabulary;
use Symfony\Component\HttpFoundation\JsonResponse;
/**
* Menu callback; displays all nodes associated with a term.
......@@ -78,86 +76,3 @@ function taxonomy_term_feed(Term $term) {
return node_feed($nids, $channel);
}
/**
* Page callback: Outputs JSON for taxonomy autocomplete suggestions.
*
* This callback outputs term name suggestions in response to Ajax requests
* made by the taxonomy autocomplete widget for taxonomy term reference
* fields. The output is a JSON object of plain-text term suggestions, keyed by
* the user-entered value with the completed term name appended. Term names
* containing commas are wrapped in quotes.
*
* For example, suppose the user has entered the string 'red fish, blue' in the
* field, and there are two taxonomy terms, 'blue fish' and 'blue moon'. The
* JSON output would have the following structure:
* @code
* {
* "red fish, blue fish": "blue fish",
* "red fish, blue moon": "blue moon",
* };
* @endcode
*
* @param $field_name
* The name of the term reference field.
*
* @see taxonomy_menu()
* @see taxonomy_field_widget_info()
*/
function taxonomy_autocomplete($field_name) {
// A comma-separated list of term names entered in the autocomplete form
// element. Only the last term is used for autocompletion.
$tags_typed = Drupal::request()->query->get('q');
// Make sure the field exists and is a taxonomy field.
if (!($field = field_info_field($field_name)) || $field['type'] !== 'taxonomy_term_reference') {
// Error string. The JavaScript handler will realize this is not JSON and
// will display it as debugging information.
print t('Taxonomy field @field_name not found.', array('@field_name' => $field_name));
exit;
}
// The user enters a comma-separated list of tags. We only autocomplete the last tag.
$tags_typed = drupal_explode_tags($tags_typed);
$tag_last = drupal_strtolower(array_pop($tags_typed));
$matches = array();
if ($tag_last != '') {
// Part of the criteria for the query come from the field's own settings.
$vids = array();
foreach ($field['settings']['allowed_values'] as $tree) {
$vids[] = $tree['vocabulary'];
}
$query = db_select('taxonomy_term_data', 't');
$query->addTag('term_access');
// Do not select already entered terms.
if (!empty($tags_typed)) {
$query->condition('t.name', $tags_typed, 'NOT IN');
}
// Select rows that match by term name.
$tags_return = $query
->fields('t', array('tid', 'name'))
->condition('t.vid', $vids)
->condition('t.name', '%' . db_like($tag_last) . '%', 'LIKE')
->range(0, 10)
->execute()
->fetchAllKeyed();
$prefix = count($tags_typed) ? drupal_implode_tags($tags_typed) . ', ' : '';
$term_matches = array();
foreach ($tags_return as $tid => $name) {
$n = $name;
// Term names containing commas or quotes must be wrapped in quotes.
if (strpos($name, ',') !== FALSE || strpos($name, '"') !== FALSE) {
$n = '"' . str_replace('"', '""', $name) . '"';
}
$term_matches[$prefix . $n] = check_plain($name);
}
}
return new JsonResponse($term_matches);
}
......@@ -32,3 +32,10 @@ taxonomy_vocabulary_reset:
_entity_form: 'taxonomy_vocabulary.reset'
requirements:
_permission: 'administer taxonomy'
taxonomy_autocomplete:
pattern: '/taxonomy/autocomplete/{field_name}'
defaults:
_controller: '\Drupal\taxonomy\Controller\TermAutocompleteController::autocomplete'
requirements:
_permission: 'access content'
......@@ -15,7 +15,7 @@ content:
weight: '-4'
settings:
size: '60'
autocomplete_path: taxonomy/autocomplete
autocomplete_route_name: taxonomy_autocomplete
placeholder: ''
field_image:
type: image_image
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment