search_api_autocomplete.module in Search API Autocomplete 8
Same filename and directory in other branches
Adds autocomplete capabilities for Search API searches.
File
search_api_autocomplete.moduleView source
<?php
/**
* @file
* Adds autocomplete capabilities for Search API searches.
*/
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\search_api\Plugin\views\query\SearchApiQuery;
use Drupal\search_api_autocomplete\Search\SearchPluginDeriverBase;
use Drupal\search_api_page\SearchApiPageInterface;
use Drupal\views\ViewEntityInterface;
/**
* Implements hook_theme().
*/
function search_api_autocomplete_theme() {
$themes['search_api_autocomplete_suggestion'] = [
'variables' => [
'keys' => NULL,
'url' => NULL,
'label' => NULL,
'note' => NULL,
'results_count' => NULL,
'suggestion_prefix' => '',
'suggestion_suffix' => '',
'user_input' => '',
],
];
return $themes;
}
/**
* Implements hook_entity_operation().
*/
function search_api_autocomplete_entity_operation(EntityInterface $entity) {
if ($entity
->getEntityTypeId() != 'search_api_index') {
return [];
}
$operations = [];
$operations['autocomplete'] = [
'title' => t('Autocomplete'),
'weight' => 30,
'url' => Url::fromRoute('search_api_autocomplete.admin_overview', [
'search_api_index' => $entity
->id(),
]),
];
return $operations;
}
/**
* Implements hook_hook_info().
*
* Allows other modules to place all their hook implementations for this module
* into a "MODULE.search_api_autocomplete.inc" file.
*/
function search_api_autocomplete_hook_info() {
$hooks = [
'search_api_autocomplete_suggestions_alter',
'search_api_autocomplete_suggester_info_alter',
'search_api_autocomplete_search_info_alter',
'search_api_autocomplete_views_fulltext_fields_alter',
];
$info = [
'group' => 'search_api_autocomplete',
];
return array_fill_keys($hooks, $info);
}
/**
* Implements hook_form_FORM_ID_alter() for "views_exposed_form".
*
* Adds autocompletion to input fields for fulltext keywords on views with
* exposed filters.
*
* @see \Drupal\views\Form\ViewsExposedForm
* @see \Drupal\search_api_autocomplete\Plugin\search_api_autocomplete\search\Views
*/
function search_api_autocomplete_form_views_exposed_form_alter(array &$form, FormStateInterface $form_state) {
/** @var \Drupal\views\ViewExecutable $view */
$view = $form_state
->get('view');
if (substr($view->storage
->get('base_table'), 0, 17) != 'search_api_index_') {
return;
}
$plugin_id = 'views:' . $view
->id();
$cache_tag = "search_api_autocomplete_search_list:{$plugin_id}";
if (!isset($form['#cache']['tags']) || !in_array($cache_tag, $form['#cache']['tags'])) {
$form['#cache']['tags'][] = $cache_tag;
}
/** @var \Drupal\search_api_autocomplete\Entity\SearchStorage $search_storage */
$search_storage = \Drupal::entityTypeManager()
->getStorage('search_api_autocomplete_search');
$search = $search_storage
->loadBySearchPlugin($plugin_id);
if (!$search || !$search
->status()) {
return;
}
$config = $search
->getSearchPlugin()
->getConfiguration();
$selected = in_array($view->current_display, $config['displays']['selected']);
// @todo Replace with \Drupal\search_api\Utility\Utility::matches() once
// we can use it (Search API 1.8 dependency).
if ($selected == $config['displays']['default']) {
return;
}
$fields = $search
->getIndex()
->getFulltextFields();
if (!$fields) {
return;
}
// Add the "Search: Fulltext search" filter as another text field.
$fields[] = 'search_api_fulltext';
\Drupal::moduleHandler()
->alter('search_api_autocomplete_views_fulltext_fields', $fields, $search, $view);
$base_data = [
'display' => $view->current_display,
'arguments' => $view->args,
];
foreach ($view->filter as $filter_name => $filter) {
if (!in_array($filter->realField, $fields) || empty($filter->options['expose']['identifier'])) {
continue;
}
$key = $filter->options['expose']['identifier'];
if (isset($form[$key])) {
$element =& $form[$key];
}
elseif (isset($form[$key . '_wrapper'][$key])) {
$element =& $form[$key . '_wrapper'][$key];
}
else {
continue;
}
$data = $base_data;
// The Views filter for individual fulltext fields uses a nested "value"
// field for the real input, due to Views internals.
if (!empty($element['value'])) {
$element =& $element['value'];
// In this case, we also need to manually pass the fulltext fields, so
// they will be applied properly.
$data['field'] = $filter->realField;
}
if (isset($element['#type']) && $element['#type'] === 'textfield') {
$data['filter'] = $key;
\Drupal::getContainer()
->get('search_api_autocomplete.helper')
->alterElement($element, $search, $data);
}
unset($element);
}
}
/**
* Implements hook_form_BASE_FORM_ID_alter() for "search_api_page_block_form".
*
* Adds autocompletion to the keywords field on search pages, if enabled by the
* user.
*
* @see \Drupal\search_api_page\Form\SearchApiPageBlockForm
* @see \Drupal\search_api_autocomplete\Plugin\search_api_autocomplete\search\Page
*/
function search_api_autocomplete_form_search_api_page_block_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
$page_id = substr($form_id, strlen('search_api_page_block_form_'));
/** @var \Drupal\search_api_autocomplete\Entity\SearchStorage $search_storage */
$search_storage = \Drupal::entityTypeManager()
->getStorage('search_api_autocomplete_search');
$plugin_id = 'page:' . $page_id;
$search = $search_storage
->loadBySearchPlugin($plugin_id);
$cache_tag = "search_api_autocomplete_search_list:{$plugin_id}";
if (!isset($form['#cache']['tags']) || !in_array($cache_tag, $form['#cache']['tags'])) {
$form['#cache']['tags'][] = $cache_tag;
}
if ($search && $search
->status()) {
\Drupal::getContainer()
->get('search_api_autocomplete.helper')
->alterElement($form['keys'], $search);
}
}
/**
* Implements hook_ENTITY_TYPE_insert() for type "view".
*
* Clear the search plugin definitions cache when new search views are created.
* Could use better support from the Plugin API – see #2633878.
*/
function search_api_autocomplete_view_insert(ViewEntityInterface $view) {
if (SearchApiQuery::getIndexFromTable($view
->get('base_table'))) {
\Drupal::getContainer()
->get('plugin.manager.search_api_autocomplete.search')
->clearCachedDefinitions();
SearchPluginDeriverBase::resetStaticDerivativeCaches('views');
}
}
/**
* Implements hook_ENTITY_TYPE_delete() for type "view".
*
* Clear the search plugin definitions cache when search views are deleted.
* Could use better support from the Plugin API – see #2633878.
*/
function search_api_autocomplete_view_delete(ViewEntityInterface $view) {
if (SearchApiQuery::getIndexFromTable($view
->get('base_table'))) {
\Drupal::getContainer()
->get('plugin.manager.search_api_autocomplete.search')
->clearCachedDefinitions();
SearchPluginDeriverBase::resetStaticDerivativeCaches('views');
}
}
/**
* Implements hook_ENTITY_TYPE_insert() for type "search_api_page".
*
* Clear the search plugin definitions cache when search pages are created.
* Could use better support from the Plugin API – see #2633878.
*/
function search_api_autocomplete_search_api_page_insert(SearchApiPageInterface $page) {
\Drupal::getContainer()
->get('plugin.manager.search_api_autocomplete.search')
->clearCachedDefinitions();
SearchPluginDeriverBase::resetStaticDerivativeCaches('page');
}
/**
* Implements hook_ENTITY_TYPE_delete() for type "search_api_page".
*
* Clear the search plugin definitions cache when search pages are deleted.
* Could use better support from the Plugin API – see #2633878.
*/
function search_api_autocomplete_search_api_page_delete(SearchApiPageInterface $page) {
\Drupal::getContainer()
->get('plugin.manager.search_api_autocomplete.search')
->clearCachedDefinitions();
SearchPluginDeriverBase::resetStaticDerivativeCaches('page');
}
Functions
Name | Description |
---|---|
search_api_autocomplete_entity_operation | Implements hook_entity_operation(). |
search_api_autocomplete_form_search_api_page_block_form_alter | Implements hook_form_BASE_FORM_ID_alter() for "search_api_page_block_form". |
search_api_autocomplete_form_views_exposed_form_alter | Implements hook_form_FORM_ID_alter() for "views_exposed_form". |
search_api_autocomplete_hook_info | Implements hook_hook_info(). |
search_api_autocomplete_search_api_page_delete | Implements hook_ENTITY_TYPE_delete() for type "search_api_page". |
search_api_autocomplete_search_api_page_insert | Implements hook_ENTITY_TYPE_insert() for type "search_api_page". |
search_api_autocomplete_theme | Implements hook_theme(). |
search_api_autocomplete_view_delete | Implements hook_ENTITY_TYPE_delete() for type "view". |
search_api_autocomplete_view_insert | Implements hook_ENTITY_TYPE_insert() for type "view". |