Drupal 8 Search API Processors. Exclude content by field value.
http://jmolivas.com/porting-symfony-2-acme-demo-bundle-as-drupal-8

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.

Like
Reply

Hey, this blog is very informative! Could you plz explain the use of below annotation => * stages = { * "alter_items" = 0, * },

Like
Reply

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.

Like
Reply

Thanks this made my day! :)

Like
Reply

Thanks, this was really useful

Like
Reply

To view or add a comment, sign in

More articles by Gene C.

Others also viewed

Explore content categories