You are here

public function NewResultsCheck::getNewResults in Search API Saved Searches 8

Retrieves new results for the given search.

Parameters

\Drupal\search_api_saved_searches\SavedSearchInterface $search: The saved search to check for new results.

Return value

\Drupal\search_api\Query\ResultSetInterface|null The new results, if any could be found. NULL otherwise.

Throws

\Drupal\search_api_saved_searches\SavedSearchesException Thrown if an error was encountered (like an invalid type or query, or the search query failing).

1 call to NewResultsCheck::getNewResults()
NewResultsCheck::checkAll in src/Service/NewResultsCheck.php
Checks all saved searches that are "due" for new results.

File

src/Service/NewResultsCheck.php, line 216

Class

NewResultsCheck
Provides a service for checking saved searches for new results.

Namespace

Drupal\search_api_saved_searches\Service

Code

public function getNewResults(SavedSearchInterface $search) {
  $search_id = $search
    ->id();
  $type = $search
    ->getType();
  $query = $search
    ->getQuery();
  if (!$query) {
    throw new SavedSearchesException("Saved search #{$search_id} does not have a valid query set");
  }

  // Clone the query to make sure we don't make any modifications to its
  // stored version.
  $query = clone $query;
  $index_id = $query
    ->getIndex()
    ->id();
  $date_field = $type
    ->getOption("date_field.{$index_id}");
  if ($date_field) {
    $query
      ->addCondition($date_field, $search
      ->get('last_executed')->value, '>');
  }

  // Unify some general query options.
  $query
    ->setProcessingLevel(QueryInterface::PROCESSING_BASIC);
  $query
    ->setSearchId("search_api_saved_searches:{$search_id}");

  // If we're using the date field method, we can simply set the maximum
  // result count as the search query limit. Otherwise, we always need to
  // retrieve all results
  $max_results = $type
    ->getOption('max_results') ?: NULL;
  $limit = $type
    ->getOption('query_limit') ?: NULL;
  if ($date_field && $max_results) {
    $limit = $max_results;
  }
  $query
    ->range(NULL, $limit);
  try {

    // Pass the query to the server directly (since the query is already
    // marked as "executed", so calling $query->execute() wouldn't do
    // anything).
    $query
      ->getIndex()
      ->getServerInstance()
      ->search($query);
    $query
      ->postExecute();
    $results = $query
      ->getResults();
  } catch (SearchApiException $e) {
    $class = get_class($e);
    throw new SavedSearchesException("{$class} while executing the search query for saved search #{$search_id}: {$e->getMessage()}", 0, $e);
  }

  // If there were no results at all, we're done.
  if (!$results
    ->getResultCount()) {
    return NULL;
  }

  // Same when we used a date field, but in this case with results.
  if ($date_field) {
    return $results;
  }

  // Otherwise, we need to match the current results' IDs to the known ones.
  $old_result_ids = Database::getConnection()
    ->select('search_api_saved_searches_old_results', 't')
    ->fields('t', [
    'item_id',
  ])
    ->condition('search_id', $search_id)
    ->execute()
    ->fetchCol();
  $items = $results
    ->getResultItems();
  $items = array_diff_key($items, array_flip($old_result_ids));
  if ($items) {
    $results
      ->setResultCount(count($items));
    if (!$this
      ->saveKnownResults($search, $items)) {

      // To avoid reporting the same results again, better report no results
      // right now and hope the error gets resolved.
      return NULL;
    }
    if ($max_results && count($items) > $max_results) {
      $items = array_slice($items, 0, $max_results, TRUE);
    }
    $results
      ->setResultItems($items);
  }
  return $items ? $results : NULL;
}