View source
<?php
namespace Drupal\search_api_autocomplete\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\search_api_autocomplete\SearchApiAutocompleteException;
use Drupal\search_api_autocomplete\SearchInterface;
use Drupal\search_api_autocomplete\Utility\AutocompleteHelperInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Component\Transliteration\TransliterationInterface;
class AutocompleteController extends ControllerBase implements ContainerInjectionInterface {
protected $autocompleteHelper;
protected $renderer;
protected $transliterator;
public function __construct(AutocompleteHelperInterface $autocomplete_helper, RendererInterface $renderer, TransliterationInterface $transliterator) {
$this->autocompleteHelper = $autocomplete_helper;
$this->renderer = $renderer;
$this->transliterator = $transliterator;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('search_api_autocomplete.helper'), $container
->get('renderer'), $container
->get('transliteration'));
}
public function autocomplete(SearchInterface $search_api_autocomplete_search, Request $request) {
$matches = [];
$search = $search_api_autocomplete_search;
if (!$search
->status() || !$search
->hasValidIndex()) {
return new JsonResponse($matches);
}
try {
$keys = $request->query
->get('q');
$split_keys = $this->autocompleteHelper
->splitKeys($keys);
list($complete, $incomplete) = $split_keys;
$data = $request->query
->all();
unset($data['q']);
$query = $search
->createQuery($complete, $data);
if (!$query) {
return new JsonResponse($matches);
}
$query
->setSearchId('search_api_autocomplete:' . $search
->id());
$query
->addTag('search_api_autocomplete');
$limit = $search
->getOption('limit');
$suggester_limits = $search
->getSuggesterLimits();
$suggesters = $search
->getSuggesters();
$suggester_weights = $search
->getSuggesterWeights();
$suggester_weights = array_intersect_key($suggester_weights, $suggesters);
$suggester_weights += array_fill_keys(array_keys($suggesters), 0);
asort($suggester_weights);
$suggestions = [];
foreach (array_keys($suggester_weights) as $suggester_id) {
$tmp_query = clone $query;
if (isset($suggester_limits[$suggester_id])) {
$suggester_limit = min($limit, $suggester_limits[$suggester_id]);
}
else {
$suggester_limit = $limit;
}
$tmp_query
->range(0, $suggester_limit);
$new_suggestions = $suggesters[$suggester_id]
->getAutocompleteSuggestions($tmp_query, $incomplete, $keys);
foreach ($new_suggestions as $suggestion) {
$suggestions[] = $suggestion;
if (--$limit == 0) {
break 2;
}
}
}
$alter_params = [
'query' => $query,
'search' => $search,
'incomplete_key' => $incomplete,
'user_input' => $keys,
];
$this
->moduleHandler()
->alter('search_api_autocomplete_suggestions', $suggestions, $alter_params);
$show_count = $search
->getOption('show_count');
foreach ($suggestions as $suggestion) {
if (!$show_count) {
$suggestion
->setResultsCount(NULL);
}
$build = $suggestion
->toRenderable();
if ($build) {
try {
$label = $this->renderer
->render($build);
} catch (\Exception $e) {
watchdog_exception('search_api_autocomplete', $e, '%type while rendering an autocomplete suggestion: @message in %function (line %line of %file).');
continue;
}
if ($suggestion
->getUrl()) {
$url = $suggestion
->getUrl()
->toString();
$trimmed_label = trim(strip_tags((string) $label)) ?: $url;
$matches[] = [
'value' => $trimmed_label,
'url' => $url,
'label' => $label,
];
}
else {
$matches[] = [
'value' => trim($suggestion
->getSuggestedKeys()),
'label' => $label,
];
}
}
}
} catch (SearchApiAutocompleteException $e) {
watchdog_exception('search_api_autocomplete', $e, '%type while retrieving autocomplete suggestions: @message in %function (line %line of %file).');
}
return new JsonResponse($matches);
}
}