Drupal 8 Search API Processors. Exclude content by field value.
In Drupal 8 processors replaced altering search query and use hooks as in Drupal 7. Here is a short example of how nodes can be excluded from search index by field value.
First of all, create a processor in your module
module_name/src/Plugin/search_api/processor/ContentFilter.php
<?php
namespace Drupal\module_name\Plugin\search_api\processor;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\search_api\IndexInterface;
use Drupal\search_api\Plugin\PluginFormTrait;
use Drupal\search_api\Processor\ProcessorPluginBase;
use Drupal\node\NodeInterface;
/**
* Filters out users based on their role.
*
* @SearchApiProcessor(
* id = "content_filter",
* label = @Translation("Content filter"),
* description = @Translation("Filters out content by field value."),
* stages = {
* "alter_items" = 0,
* },
* )
*/
class ContentFilter extends ProcessorPluginBase implements PluginFormInterface {
use PluginFormTrait;
/**
* Can only be enabled for an index that indexes the user entity.
*
* {@inheritdoc}
*/public static function supportsIndex(IndexInterface $index) {
foreach ($index->getDatasources() as $datasource) {
if ($datasource->getEntityTypeId() == 'node') {
return TRUE;
}
}
return FALSE;
}
/**
* {@inheritdoc}
*/public function defaultConfiguration
() {
return [];
}
/**
* {@inheritdoc}
*/public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
return $form;
}
/**
* {@inheritdoc}
*/public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/public function alterIndexedItems(array &$items) {
/** @var \Drupal\search_api\Item\ItemInterface $item */foreach ($items as $item_id => $item) {
$node = $item->getOriginalObject()->getValue();
if (!($node instanceof NodeInterface)) {
continue;
}
if ($node->bundle() == 'out_content_type') {
if ($node->hasField('field_our_field')) {
$field_our_field = $node->get('field_our_field')->getValue();
if (isset($field_our_field[0]['value'])) {
if (strtolower($field_our_field[0]['value']) != 'our_value') {
unset($items[$item_id]);
}
}
}
}
}
}
}
Class annotation is very simple. The only thing that worth attention are stages. Browse Search API module to get more information of available stages.
You can find your declared processor on processors page for your search index.
admin/config/search/search-api/index/index_name/processors
Processors order and other settings can be set bellow this form on the page.
Let's check the code of this example. You can explore all methods in parent classes for more details and examples, there are a lot to see. I'll describe only those in the example.
public static function supportsIndex
Basically here it says to be available only for index based on nodes.
public function defaultConfiguration
public function buildConfigurationForm
public function submitConfigurationForm
These 3 functions just inherit configuration forms which are empty for this example. But can be extended, for instance, to select field name and value or any other settings. They are pretty basic and are not covered in this article.
public function alterIndexedItems
This is a method that runs during indexing before data sent to index. $items variable is an array of content that will be sent to search index. If for instance, we are indexing and batch size is 50 items per iteration, then $items array will have 50 content items that we can process during the loop. When next batch operation starts, we'll have next 50 items. In this function node object is received, than usual checks for fields are set and if our field does not match our value, remove it from items that will be sent to index. So they will never reach index and never appear in search results.
Exactly what I was looking for !! Thanks so much.
Hey, this blog is very informative! Could you plz explain the use of below annotation => * stages = { * "alter_items" = 0, * },
Hey this is awesome! Could you please help on how to deny items from indexing which are not published. With respect to Custom entity types.
Thanks this made my day! :)
Thanks, this was really useful