You are here

class IndexTaskManager in Search API 8

Provides a service for managing pending index tasks.

Hierarchy

Expanded class hierarchy of IndexTaskManager

1 file declares its use of IndexTaskManager
search_api.module in ./search_api.module
Provides a rich framework for creating searches.
1 string reference to 'IndexTaskManager'
search_api.services.yml in ./search_api.services.yml
search_api.services.yml
1 service uses IndexTaskManager
search_api.index_task_manager in ./search_api.services.yml
Drupal\search_api\Task\IndexTaskManager

File

src/Task/IndexTaskManager.php, line 17

Namespace

Drupal\search_api\Task
View source
class IndexTaskManager implements IndexTaskManagerInterface, EventSubscriberInterface {
  use StringTranslationTrait;

  /**
   * The Search API task type used by this service for "track items" tasks.
   */
  const TRACK_ITEMS_TASK_TYPE = 'trackItems';

  /**
   * The Search API task manager.
   *
   * @var \Drupal\search_api\Task\TaskManagerInterface
   */
  protected $taskManager;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * Constructs an IndexTaskManager object.
   *
   * @param \Drupal\search_api\Task\TaskManagerInterface $task_manager
   *   The Search API task manager.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   */
  public function __construct(TaskManagerInterface $task_manager, EntityTypeManagerInterface $entity_type_manager) {
    $this->taskManager = $task_manager;
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events['search_api.task.' . self::TRACK_ITEMS_TASK_TYPE][] = [
      'trackItems',
    ];
    return $events;
  }

  /**
   * Processes all pending index tasks inside a batch run.
   *
   * @param array|\ArrayAccess $context
   *   The current batch context.
   * @param \Drupal\Core\Config\ConfigImporter $config_importer
   *   The config importer.
   */
  public static function processIndexTasks(&$context, ConfigImporter $config_importer) {
    $index_task_manager = \Drupal::getContainer()
      ->get('search_api.index_task_manager');
    if (!isset($context['sandbox']['indexes'])) {
      $context['sandbox']['indexes'] = [];
      $indexes = \Drupal::entityTypeManager()
        ->getStorage('search_api_index')
        ->loadByProperties([
        'status' => TRUE,
      ]);
      $deleted = $config_importer
        ->getUnprocessedConfiguration('delete');

      /** @var \Drupal\search_api\IndexInterface $index */
      foreach ($indexes as $index_id => $index) {
        if (!$index_task_manager
          ->isTrackingComplete($index) && !in_array($index
          ->getConfigDependencyName(), $deleted)) {
          $context['sandbox']['indexes'][] = $index_id;
        }
      }
      $context['sandbox']['total'] = count($context['sandbox']['indexes']);
      if (!$context['sandbox']['total']) {
        $context['finished'] = 1;
        return;
      }
    }
    $index_id = array_shift($context['sandbox']['indexes']);
    $index = Index::load($index_id);
    try {
      if (!$index_task_manager
        ->addItemsOnce($index)) {
        array_unshift($context['sandbox']['indexes'], $index_id);
      }
    } catch (SearchApiException $e) {
      watchdog_exception('search_api', $e);
    }
    if (empty($context['sandbox']['indexes'])) {
      $context['finished'] = 1;
    }
    else {
      $finished = $context['sandbox']['total'] - count($context['sandbox']['indexes']);
      $context['finished'] = $finished / $context['sandbox']['total'];
      $args = [
        '%index' => $index
          ->label(),
        '@num' => $finished + 1,
        '@total' => $context['sandbox']['total'],
      ];
      $context['message'] = \Drupal::translation()
        ->translate('Tracking items for search index %index (@num of @total)', $args);
    }
  }

  /**
   * Tracks items according to the given event.
   *
   * @param \Drupal\search_api\Task\TaskEvent $event
   *   The task event.
   */
  public function trackItems(TaskEvent $event) {
    $event
      ->stopPropagation();
    $task = $event
      ->getTask();
    $index = $task
      ->getIndex();
    if (!$index
      ->hasValidTracker()) {
      $args['%index'] = $index
        ->label();
      $message = new FormattableMarkup('Index %index does not have a valid tracker set.', $args);
      $event
        ->setException(new SearchApiException($message));
      return;
    }
    $data = $task
      ->getData();
    $datasource_id = $data['datasource'];
    $reschedule = FALSE;
    if ($index
      ->isValidDatasource($datasource_id)) {
      $raw_ids = $index
        ->getDatasource($datasource_id)
        ->getItemIds($data['page']);
      if ($raw_ids !== NULL) {
        $reschedule = TRUE;
        if ($raw_ids) {
          $index
            ->startBatchTracking();
          $index
            ->trackItemsInserted($datasource_id, $raw_ids);
          $index
            ->stopBatchTracking();
        }
      }
    }
    if ($reschedule) {
      ++$data['page'];
      $this->taskManager
        ->addTask(self::TRACK_ITEMS_TASK_TYPE, NULL, $index, $data);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function startTracking(IndexInterface $index, array $datasource_ids = NULL) {
    foreach ($datasource_ids ?? $index
      ->getDatasourceIds() as $datasource_id) {
      $data = [
        'datasource' => $datasource_id,
        'page' => 0,
      ];
      $this->taskManager
        ->addTask(self::TRACK_ITEMS_TASK_TYPE, NULL, $index, $data);
    }
  }

  /**
   * Gets a set of conditions for finding the tracking tasks of the given index.
   *
   * @param \Drupal\search_api\IndexInterface $index
   *   The index for which to retrieve tasks.
   *
   * @return array
   *   An array of conditions to pass to the Search API task manager.
   */
  protected function getTaskConditions(IndexInterface $index) {
    return [
      'type' => self::TRACK_ITEMS_TASK_TYPE,
      'index_id' => $index
        ->id(),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function addItemsOnce(IndexInterface $index) {
    return !$this->taskManager
      ->executeSingleTask($this
      ->getTaskConditions($index));
  }

  /**
   * {@inheritdoc}
   */
  public function addItemsBatch(IndexInterface $index) {
    $this->taskManager
      ->setTasksBatch($this
      ->getTaskConditions($index));
  }

  /**
   * {@inheritdoc}
   */
  public function addItemsAll(IndexInterface $index) {
    $this->taskManager
      ->executeAllTasks($this
      ->getTaskConditions($index));
  }

  /**
   * {@inheritdoc}
   */
  public function stopTracking(IndexInterface $index, array $datasource_ids = NULL) {
    $valid_tracker = $index
      ->hasValidTracker();
    if (!isset($datasource_ids)) {
      $this->taskManager
        ->deleteTasks($this
        ->getTaskConditions($index));
      if ($valid_tracker) {
        $index
          ->getTrackerInstance()
          ->trackAllItemsDeleted();
      }
      return;
    }

    // Catch the case of being called with an empty array of datasources.
    if (!$datasource_ids) {
      return;
    }
    $tasks = $this->taskManager
      ->loadTasks($this
      ->getTaskConditions($index));
    foreach ($tasks as $task_id => $task) {
      $data = $task
        ->getData();
      if (in_array($data['datasource'], $datasource_ids)) {
        $this->taskManager
          ->deleteTask($task_id);
      }
    }
    foreach ($datasource_ids as $datasource_id) {
      $index
        ->getTrackerInstance()
        ->trackAllItemsDeleted($datasource_id);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function isTrackingComplete(IndexInterface $index) {
    return !$this->taskManager
      ->getTasksCount($this
      ->getTaskConditions($index));
  }

}

Members

Namesort descending Modifiers Type Description Overrides
IndexTaskManager::$entityTypeManager protected property The entity type manager.
IndexTaskManager::$taskManager protected property The Search API task manager.
IndexTaskManager::addItemsAll public function Tracks all remaining items for the given index. Overrides IndexTaskManagerInterface::addItemsAll
IndexTaskManager::addItemsBatch public function Sets a batch to track all remaining items for the given index. Overrides IndexTaskManagerInterface::addItemsBatch
IndexTaskManager::addItemsOnce public function Adds a single page of items to the tracker. Overrides IndexTaskManagerInterface::addItemsOnce
IndexTaskManager::getSubscribedEvents public static function Returns an array of event names this subscriber wants to listen to.
IndexTaskManager::getTaskConditions protected function Gets a set of conditions for finding the tracking tasks of the given index.
IndexTaskManager::isTrackingComplete public function Checks whether tracking has already been completed for the given index. Overrides IndexTaskManagerInterface::isTrackingComplete
IndexTaskManager::processIndexTasks public static function Processes all pending index tasks inside a batch run.
IndexTaskManager::startTracking public function Creates a task to start tracking for the given index, or some datasources. Overrides IndexTaskManagerInterface::startTracking
IndexTaskManager::stopTracking public function Stops tracking for the given index. Overrides IndexTaskManagerInterface::stopTracking
IndexTaskManager::trackItems public function Tracks items according to the given event.
IndexTaskManager::TRACK_ITEMS_TASK_TYPE constant The Search API task type used by this service for "track items" tasks.
IndexTaskManager::__construct public function Constructs an IndexTaskManager object.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.