В 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];
}
Останется только почистить кэш, пройти в админку, добавить поисковую страницу с новым плагином и отключить старый.