В Drupal 8 у дефолтного поиска отсутствует возможность исключить из индексации тот или иной тип содержимого. Иссуй есть, а возможности — нет.
Можно сразу удариться в Search API, но для небольших сайтов может быть проще добавить ограничение по типам. Это не так уж трудно. Есть способ, подразумевающий вставку условий через хук query_alter по тегу search_node_search
, добавляемому в поисковые запросы. Правда, тогда материалы не будут выводиться, а индексироваться — будут.
Но можно и запретить индексацию. Посколько D8 весь оопнутый и прогрессивный, отбросим теплые ламповые хуки и сделаем свой нанотехнологичный плагин поиска, унаследовав его от дефолтного NodeSearch
.
Для этого создадим новый класс в нашем модуле в mymodule/src/Plugin/Search/NodeRestrictedSearch
и наследуем его от уже существующего плагина. Это удобно, не нужно копировать ничего лишнего, достаточно добавить новое свойство, перечисляющее типы, которые мы ограничиваем (в данном примере это ноды типа store
и secret_content
):
<?php namespace Drupal\mymodule\Plugin\Search; use Drupal\Core\Access\AccessibleInterface; use Drupal\node\Plugin\Search\NodeSearch; use Drupal\search\Plugin\SearchIndexingInterface; /** * @SearchPlugin( * id = "node_restricted_search", * title = @Translation("Content Restricted") * ) */ class NodeRestrictedSearch extends NodeSearch implements AccessibleInterface, SearchIndexingInterface { protected $restrictedTypes = ['store', 'secret_content'];
И переопределить пару методов. Во-первых, метод, отбирающий ноды для индексации — мы скопируем код метода из родителя и добавим проверку типа материала:
/** * {@inheritdoc} */ public function updateIndex() { // Interpret the cron limit setting as the maximum number of nodes to index // per cron run. $limit = (int) $this->searchSettings->get('index.cron_limit'); $query = $this->database->select('node', 'n', ['target' => 'replica']); $query->addField('n', 'nid'); $query->leftJoin('search_dataset', 'sd', 'sd.sid = n.nid AND sd.type = :type', [':type' => $this->getPluginId()]); $query->addExpression('CASE MAX(sd.reindex) WHEN NULL THEN 0 ELSE 1 END', 'ex'); $query->addExpression('MAX(sd.reindex)', 'ex2'); $query->condition( $query->orConditionGroup() ->where('sd.sid IS NULL') ->condition('sd.reindex', 0, '<>') ); // ПРОВЕРКА ТИПА: $query->condition('n.type', $this->restrictedTypes, 'NOT IN'); $query->orderBy('ex', 'DESC') ->orderBy('ex2') ->orderBy('n.nid') ->groupBy('n.nid') ->range(0, $limit); $nids = $query->execute()->fetchCol(); if (!$nids) { return; } $node_storage = $this->entityManager->getStorage('node'); foreach ($node_storage->loadMultiple($nids) as $node) { $this->indexNode($node); } }
Во-вторых (для порядку), переопределим метод, который показывает в админке, сколько материалов проиндексировано и сколько осталось:
/** * {@inheritdoc} */ public function indexStatus() { $total = $this->database->select('node', 'n') ->fields('n', ['nid']) // ПРОВЕРКА ТИПА: ->condition('n.type', $this->restrictedTypes, 'NOT IN') ->countQuery() ->execute() ->fetchField(); $query = $this->database->select('node', 'n'); $query->distinct() ->fields('n', ['nid']) ->leftJoin('search_dataset', 'sd', 'sd.sid = n.nid AND sd.type = :type', [':type' => $this->getPluginId()]); // ПРОВЕРКА ТИПА: $query->condition('n.type', $this->restrictedTypes, 'NOT IN'); $query->condition( $query->orConditionGroup() ->where('sd.sid IS NULL') ->condition('sd.reindex', 0, '<>') ); $remaining = $query->countQuery()->execute()->fetchField(); return ['remaining' => $remaining, 'total' => $total]; }
Останется только почистить кэш, пройти в админку, добавить поисковую страницу с новым плагином и отключить старый.