From 69eb0e97b226b53cc9991085504d50be20c9deeb Mon Sep 17 00:00:00 2001
From: Samuel <samuel@bodeboca.com>
Date: Fri, 17 May 2019 08:58:40 +0200
Subject: [PATCH] Issue #3055325: Exclude entity based on a field value

---
 config/schema/search_api_exclude_entity.schema.yml |  13 +++
 .../processor/SearchApiExcludeEntityByField.php    | 120 +++++++++++++++++++++
 2 files changed, 133 insertions(+)
 create mode 100644 src/Plugin/search_api/processor/SearchApiExcludeEntityByField.php

diff --git a/config/schema/search_api_exclude_entity.schema.yml b/config/schema/search_api_exclude_entity.schema.yml
index b780dde..bc8559d 100644
--- a/config/schema/search_api_exclude_entity.schema.yml
+++ b/config/schema/search_api_exclude_entity.schema.yml
@@ -12,3 +12,16 @@ field.widget.settings.search_api_exclude_entity_widget:
     field_label:
       type: label
       label: 'Yes, exclude this entity from the search indexes.'
+search_api_exclude_entity.configuration:
+  type: config_object
+  label: 'Search Api Exclude Entity settings'
+  mapping:
+    search_api_index:
+      type: string
+      label: 'Search api index'
+    field:
+      type: string
+      label: 'Field id'
+    value:
+      type: string
+      label: 'Value of the field'
\ No newline at end of file
diff --git a/src/Plugin/search_api/processor/SearchApiExcludeEntityByField.php b/src/Plugin/search_api/processor/SearchApiExcludeEntityByField.php
new file mode 100644
index 0000000..89476fb
--- /dev/null
+++ b/src/Plugin/search_api/processor/SearchApiExcludeEntityByField.php
@@ -0,0 +1,120 @@
+<?php
+
+namespace Drupal\search_api_exclude_entity\Plugin\search_api\processor;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Plugin\PluginFormInterface;
+use Drupal\search_api\Item\Field;
+use Drupal\search_api\Plugin\PluginFormTrait;
+use Drupal\search_api\Processor\ProcessorPluginBase;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Excludes entities marked as 'excluded' from being indexes.
+ *
+ * @SearchApiProcessor(
+ *   id = "search_api_exclude_entity_by_field_processor",
+ *   label = @Translation("Search API Exclude entity By Field"),
+ *   description = @Translation("Exclude some items from being indexed depends of the field values."),
+ *   stages = {
+ *     "alter_items" = -50
+ *   }
+ * )
+ */
+class SearchApiExcludeEntityByField extends ProcessorPluginBase implements PluginFormInterface {
+
+  use PluginFormTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
+    /** @var static $processor */
+    $processor = parent::create($container, $configuration, $plugin_id, $plugin_definition);
+    return $processor;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    $config = $this->getConfiguration();
+
+    $fields = $this->index->getFields();
+    $indexName = $this->index->getOriginalId();
+    foreach ($fields as $field) {
+      $fieldName = $field->getFieldIdentifier();
+      $form[$indexName]['fields'][$fieldName] = array(
+        '#type' => 'textfield',
+        '#title' => $field->getLabel(),
+        '#description' => $this->t("The item won't be in the index if the field has this value"),
+        '#default_value' => isset($config[$indexName]['fields'][$fieldName]) ? $config[$indexName]['fields'][$fieldName] : '',
+        '#multiple' => TRUE,
+      );
+    }
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
+    $values = $form_state->getValues();
+    $indexName = $this->index->getOriginalId();
+
+    // Remove empty values.
+    if (isset($values[$indexName]['fields']) && is_array($values[$indexName]['fields'])) {
+      $values[$indexName]['fields'] = array_filter($values[$indexName]['fields']);
+    }
+
+    $this->setConfiguration($values);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function alterIndexedItems(array &$items) {
+    $config = $this->getConfiguration();
+    $indexName = $this->index->getOriginalId();
+    $configuredField = $config[$indexName]['fields'];
+
+    /** @var \Drupal\search_api\Item\ItemInterface $item */
+    foreach ($items as $item_id => $item) {
+      $object = $item->getOriginalObject()->getValue();
+      $fieldList = $object->getFields();
+
+      foreach ($configuredField as $fieldName => $fieldValue) {
+        if (isset($fieldList[$fieldName])) {
+          $value = $fieldList[$fieldName]->getValue();
+          $value = $value[0]['value'];
+          if ($value == $this->sanitizeFilterString($fieldValue)) {
+            unset($items[$item_id]);
+            continue;
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Sanitize the values of the field depends of the comparision type.
+   *
+   * @param mixed $value
+   *   The value to be sanitized.
+   *
+   * @return mixed
+   *   The sanitized value.
+   */
+  protected function sanitizeFilterString($value) {
+    if ($value == 'false') {
+      return FALSE;
+    }
+    if ($value == 'true') {
+      return TRUE;
+    }
+
+    return $value;
+  }
+
+}
-- 
2.7.4

