You are here

public function ContentEntityTrackingManager::indexUpdate in Search API 8

Implements hook_ENTITY_TYPE_update() for type "search_api_index".

Detects changes in the selected bundles or languages and adds/removes items to/from tracking accordingly.

Parameters

\Drupal\search_api\IndexInterface $index: The index that was updated.

Throws

\Drupal\Component\Plugin\Exception\PluginNotFoundException Thrown if a datasource referenced an unknown entity type.

\Drupal\search_api\SearchApiException Never thrown, but static analysis tools think it could be.

See also

search_api_search_api_index_update()

File

src/Plugin/search_api/datasource/ContentEntityTrackingManager.php, line 286

Class

ContentEntityTrackingManager
Provides hook implementations on behalf of the Content Entity datasource.

Namespace

Drupal\search_api\Plugin\search_api\datasource

Code

public function indexUpdate(IndexInterface $index) {
  if (!$index
    ->status()) {
    return;
  }

  /** @var \Drupal\search_api\IndexInterface $original */
  $original = $index->original ?? NULL;
  if (!$original || !$original
    ->status()) {
    return;
  }
  foreach ($index
    ->getDatasources() as $datasource_id => $datasource) {
    if ($datasource
      ->getBaseId() != 'entity' || !$original
      ->isValidDatasource($datasource_id)) {
      continue;
    }
    $old_datasource = $original
      ->getDatasource($datasource_id);
    $old_config = $old_datasource
      ->getConfiguration();
    $new_config = $datasource
      ->getConfiguration();
    if ($old_config != $new_config) {

      // Bundles and languages share the same structure, so changes can be
      // processed in a unified way.
      $tasks = [];
      $insert_task = ContentEntityTaskManager::INSERT_ITEMS_TASK_TYPE;
      $delete_task = ContentEntityTaskManager::DELETE_ITEMS_TASK_TYPE;
      $settings = [];
      $entity_type = $this->entityTypeManager
        ->getDefinition($datasource
        ->getEntityTypeId());
      if ($entity_type
        ->hasKey('bundle')) {
        $settings['bundles'] = $datasource
          ->getBundles();
      }
      if ($entity_type
        ->isTranslatable()) {
        $settings['languages'] = $this->languageManager
          ->getLanguages();
      }

      // Determine which bundles/languages have been newly selected or
      // deselected and then assign them to the appropriate actions depending
      // on the current "default" setting.
      foreach ($settings as $setting => $all) {
        $old_selected = array_flip($old_config[$setting]['selected']);
        $new_selected = array_flip($new_config[$setting]['selected']);

        // First, check if the "default" setting changed and invert the checked
        // items for the old config, so the following comparison makes sense.
        if ($old_config[$setting]['default'] != $new_config[$setting]['default']) {
          $old_selected = array_diff_key($all, $old_selected);
        }
        $newly_selected = array_keys(array_diff_key($new_selected, $old_selected));
        $newly_unselected = array_keys(array_diff_key($old_selected, $new_selected));
        if ($new_config[$setting]['default']) {
          $tasks[$insert_task][$setting] = $newly_unselected;
          $tasks[$delete_task][$setting] = $newly_selected;
        }
        else {
          $tasks[$insert_task][$setting] = $newly_selected;
          $tasks[$delete_task][$setting] = $newly_unselected;
        }
      }

      // This will keep only those tasks where at least one of "bundles" or
      // "languages" is non-empty.
      $tasks = array_filter($tasks, 'array_filter');
      foreach ($tasks as $task => $data) {
        $data += [
          'datasource' => $datasource_id,
          'page' => 0,
        ];
        $this->taskManager
          ->addTask($task, NULL, $index, $data);
      }

      // If we added any new tasks, set a batch for them. (If we aren't in a
      // form submission, this will just be ignored.)
      if ($tasks) {
        $this->taskManager
          ->setTasksBatch([
          'index_id' => $index
            ->id(),
          'type' => array_keys($tasks),
        ]);
      }
    }
  }
}