You are here

class SearchApiQuery in Search API 8

Defines a Views query class for searching on Search API indexes.

Plugin annotation


@ViewsQuery(
  id = "search_api_query",
  title = @Translation("Search API Query"),
  help = @Translation("The query will be generated and run using the Search API.")
)

Hierarchy

Expanded class hierarchy of SearchApiQuery

13 files declare their use of SearchApiQuery
AllTermsArgumentTest.php in tests/src/Unit/Views/AllTermsArgumentTest.php
SearchApiCachePluginTrait.php in src/Plugin/views/cache/SearchApiCachePluginTrait.php
SearchApiDataRow.php in src/Plugin/views/row/SearchApiDataRow.php
SearchApiFulltext.php in src/Plugin/views/argument/SearchApiFulltext.php
SearchApiHandlerTrait.php in src/Plugin/views/SearchApiHandlerTrait.php

... See full list

File

src/Plugin/views/query/SearchApiQuery.php, line 43

Namespace

Drupal\search_api\Plugin\views\query
View source
class SearchApiQuery extends QueryPluginBase {
  use LoggerTrait;

  /**
   * Number of results to display.
   *
   * @var int
   */
  protected $limit;

  /**
   * Offset of first displayed result.
   *
   * @var int
   */
  protected $offset;

  /**
   * The index this view accesses.
   *
   * @var \Drupal\search_api\IndexInterface
   */
  protected $index;

  /**
   * The query that will be executed.
   *
   * @var \Drupal\search_api\Query\QueryInterface
   */
  protected $query;

  /**
   * Array of all encountered errors.
   *
   * Each of these is fatal, meaning that a non-empty $errors property will
   * result in an empty result being returned.
   *
   * @var array
   */
  protected $errors = [];

  /**
   * Whether to abort the search instead of executing it.
   *
   * @var bool
   */
  protected $abort = FALSE;

  /**
   * The IDs of fields whose values should be retrieved by the backend.
   *
   * @var string[]
   */
  protected $retrievedFieldValues = [];

  /**
   * The query's conditions representing the different Views filter groups.
   *
   * @var array
   */
  protected $where = [];

  /**
   * The conjunction with which multiple filter groups are combined.
   *
   * @var string
   */
  protected $groupOperator = 'AND';

  /**
   * The module handler.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface|null
   */
  protected $moduleHandler;

  /**
   * The messenger.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface|null
   */
  protected $messenger;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {

    /** @var static $plugin */
    $plugin = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $plugin
      ->setModuleHandler($container
      ->get('module_handler'));
    $plugin
      ->setMessenger($container
      ->get('messenger'));
    $plugin
      ->setLogger($container
      ->get('logger.channel.search_api'));
    return $plugin;
  }

  /**
   * Loads the search index belonging to the given Views base table.
   *
   * @param string $table
   *   The Views base table ID.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   (optional) The entity type manager to use.
   *
   * @return \Drupal\search_api\IndexInterface|null
   *   The requested search index, or NULL if it could not be found and loaded.
   */
  public static function getIndexFromTable($table, EntityTypeManagerInterface $entity_type_manager = NULL) {

    // @todo Instead use Views::viewsData() – injected, too – to load the base
    //   table definition and use the "index" (or maybe rename to
    //   "search_api_index") field from there.
    if (substr($table, 0, 17) == 'search_api_index_') {
      $index_id = substr($table, 17);
      if ($entity_type_manager) {
        return $entity_type_manager
          ->getStorage('search_api_index')
          ->load($index_id);
      }
      return Index::load($index_id);
    }
    return NULL;
  }

  /**
   * Retrieves the contained entity from a Views result row.
   *
   * @param \Drupal\search_api\Plugin\views\ResultRow $row
   *   The Views result row.
   * @param string $relationship_id
   *   The ID of the view relationship to use.
   * @param \Drupal\views\ViewExecutable $view
   *   The current view object.
   *
   * @return \Drupal\Core\Entity\EntityInterface|null
   *   The entity contained in the result row, if any.
   */
  public static function getEntityFromRow(ResultRow $row, $relationship_id, ViewExecutable $view) {
    if ($relationship_id === 'none') {
      try {
        $object = $row->_object ?: $row->_item
          ->getOriginalObject();
      } catch (SearchApiException $e) {
        return NULL;
      }
      $entity = $object
        ->getValue();
      if ($entity instanceof EntityInterface) {
        return $entity;
      }
      return NULL;
    }

    // To avoid code duplication, just create a dummy field handler and use it
    // to retrieve the entity.
    $handler = new SearchApiStandard([], '', [
      'title' => '',
    ]);
    $options = [
      'relationship' => $relationship_id,
    ];
    $handler
      ->init($view, $view->display_handler, $options);
    return $handler
      ->getEntity($row);
  }

  /**
   * Retrieves the module handler.
   *
   * @return \Drupal\Core\Extension\ModuleHandlerInterface
   *   The module handler.
   */
  public function getModuleHandler() {
    return $this->moduleHandler ?: \Drupal::moduleHandler();
  }

  /**
   * Sets the module handler.
   *
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The new module handler.
   *
   * @return $this
   */
  public function setModuleHandler(ModuleHandlerInterface $module_handler) {
    $this->moduleHandler = $module_handler;
    return $this;
  }

  /**
   * Retrieves the messenger.
   *
   * @return \Drupal\Core\Messenger\MessengerInterface
   *   The messenger.
   */
  public function getMessenger() {
    return $this->messenger ?: \Drupal::service('messenger');
  }

  /**
   * Sets the messenger.
   *
   * @param \Drupal\Core\Messenger\MessengerInterface $messenger
   *   The new messenger.
   *
   * @return $this
   */
  public function setMessenger(MessengerInterface $messenger) {
    $this->messenger = $messenger;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
    try {
      parent::init($view, $display, $options);
      $this->index = static::getIndexFromTable($view->storage
        ->get('base_table'));
      if (!$this->index) {
        $this
          ->abort(new FormattableMarkup('View %view is not based on Search API but tries to use its query plugin.', [
          '%view' => $view->storage
            ->label(),
        ]));
      }
      $this->query = $this->index
        ->query();
      $this->query
        ->addTag('views');
      $this->query
        ->addTag('views_' . $view
        ->id());
      $display_type = $display
        ->getPluginId();
      if ($display_type === 'rest_export') {
        $display_type = 'rest';
      }
      $this->query
        ->setSearchId("views_{$display_type}:" . $view
        ->id() . '__' . $display->display['id']);
      $this->query
        ->setOption('search_api_view', $view);
    } catch (\Exception $e) {
      $this
        ->abort($e
        ->getMessage());
    }
  }

  /**
   * Adds a property to be retrieved.
   *
   * Currently doesn't serve any purpose, but might be added to the search query
   * in the future to help backends that support returning fields determine
   * which of the fields should actually be returned.
   *
   * @param string $combined_property_path
   *   The combined property path of the property that should be retrieved.
   *
   * @return $this
   *
   * @deprecated in search_api:8.x-1.11 and is removed from search_api:2.0.0. Use
   *   addRetrievedFieldValue() instead.
   *
   * @see https://www.drupal.org/node/3011060
   */
  public function addRetrievedProperty($combined_property_path) {
    @trigger_error('\\Drupal\\search_api\\Plugin\\views\\query\\SearchApiQuery::addRetrievedProperty() is deprecated in search_api:8.x-1.11 and is removed from search_api:2.0.0. Use addRetrievedFieldValue() instead. See https://www.drupal.org/node/3011060', E_USER_DEPRECATED);
    $this
      ->addField(NULL, $combined_property_path);
    return $this;
  }

  /**
   * Adds a field value to be retrieved.
   *
   * Helps backends that support returning fields to determine which of the
   * fields should actually be returned.
   *
   * @param string $field_id
   *   The ID of the field whose value should be retrieved.
   *
   * @return $this
   */
  public function addRetrievedFieldValue($field_id) {
    $this->retrievedFieldValues[$field_id] = $field_id;
    return $this;
  }

  /**
   * Adds a field to the table.
   *
   * This replicates the interface of Views' default SQL backend to simplify
   * the Views integration of the Search API. If you are writing Search
   * API-specific Views code, you should better use the addRetrievedFieldValue()
   * method.
   *
   * @param string|null $table
   *   Ignored.
   * @param string $field
   *   The combined property path of the property that should be retrieved.
   * @param string $alias
   *   (optional) Ignored.
   * @param array $params
   *   (optional) Ignored.
   *
   * @return string
   *   The name that this field can be referred to as (always $field).
   *
   * @see \Drupal\views\Plugin\views\query\Sql::addField()
   * @see \Drupal\search_api\Plugin\views\query\SearchApiQuery::addRetrievedFieldValue()
   */
  public function addField($table, $field, $alias = '', array $params = []) {

    // Ignore calls for built-in fields which don't need to be retrieved.
    $built_in = [
      'search_api_id' => TRUE,
      'search_api_datasource' => TRUE,
      'search_api_language' => TRUE,
      'search_api_relevance' => TRUE,
      'search_api_excerpt' => TRUE,
    ];
    if (isset($built_in[$field])) {
      return $field;
    }
    foreach ($this
      ->getIndex()
      ->getFields(TRUE) as $field_id => $field_object) {
      if ($field_object
        ->getCombinedPropertyPath() === $field) {
        $this
          ->addRetrievedFieldValue($field_id);
        break;
      }
    }
    return $field;
  }

  /**
   * {@inheritdoc}
   */
  public function defineOptions() {
    return parent::defineOptions() + [
      'bypass_access' => [
        'default' => FALSE,
      ],
      'skip_access' => [
        'default' => FALSE,
      ],
      'preserve_facet_query_args' => [
        'default' => FALSE,
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);
    $form['skip_access'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Skip item access checks'),
      '#description' => $this
        ->t("By default, an additional access check will be executed for each item returned by the search query. However, since removing results this way will break paging and result counts, it is preferable to configure the view in a way that it will only return accessible results. If you are sure that only accessible results will be returned in the search, or if you want to show results to which the user normally wouldn't have access, you can enable this option to skip those additional access checks. This should be used with care."),
      '#default_value' => $this->options['skip_access'],
      '#weight' => -1,
    ];
    $form['bypass_access'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Bypass access checks'),
      '#description' => $this
        ->t('If the underlying search index has access checks enabled (for example, through the "Content access" processor), this option allows you to disable them for this view. This will never disable any filters placed on this view.'),
      '#default_value' => $this->options['bypass_access'],
    ];
    $form['bypass_access']['#states']['visible'][':input[name="query[options][skip_access]"]']['checked'] = TRUE;
    if ($this
      ->getModuleHandler()
      ->moduleExists('facets')) {
      $form['preserve_facet_query_args'] = [
        '#type' => 'checkbox',
        '#title' => $this
          ->t('Preserve facets while using filters'),
        '#description' => $this
          ->t("By default, changing an exposed filter would reset all selected facets. This option allows you to prevent this behavior."),
        '#default_value' => $this->options['preserve_facet_query_args'],
      ];
    }
    else {
      $form['preserve_facet_query_args'] = [
        '#type' => 'value',
        '#value' => FALSE,
      ];
    }
  }

  /**
   * Checks for entity types contained in the current view's index.
   *
   * @param bool $return_bool
   *   (optional) If TRUE, returns a boolean instead of a list of datasources.
   *
   * @return string[]|bool
   *   If $return_bool is FALSE, an associative array mapping all datasources
   *   containing entities to their entity types. Otherwise, TRUE if there is at
   *   least one such datasource.
   *
   * @deprecated in search_api:8.x-1.5 and is removed from search_api:2.0.0. Use
   *   \Drupal\search_api\IndexInterface::getEntityTypes() instead.
   *
   * @see https://www.drupal.org/node/2899682
   */
  public function getEntityTypes($return_bool = FALSE) {
    @trigger_error('\\Drupal\\search_api\\Plugin\\views\\query\\SearchApiQuery::getEntityTypes() is deprecated in Search API 8.x-1.5. Use \\Drupal\\search_api\\IndexInterface::getEntityTypes() instead. See https://www.drupal.org/node/2899682', E_USER_DEPRECATED);
    $types = $this->index
      ->getEntityTypes();
    return $return_bool ? (bool) $types : $types;
  }

  /**
   * {@inheritdoc}
   */
  public function query($get_count = FALSE) {

    // Try to determine whether build() has been called yet.
    if (empty($this->view->build_info['query'])) {

      // If not, call it in case we at least have a view set. If we don't, we
      // can't really do anything.
      if (!$this->view) {
        return NULL;
      }
      $this
        ->build($this->view);
    }
    $query = clone $this->query;

    // A count query doesn't need to return any results.
    if ($get_count) {
      $query
        ->range(0, 0);
    }
    return $query;
  }

  /**
   * {@inheritdoc}
   */
  public function build(ViewExecutable $view) {
    $this->view = $view;

    // Initialize the pager and let it modify the query to add limits. This has
    // to be done even for aborted queries since it might otherwise lead to a
    // fatal error when Views tries to access $view->pager.
    $view
      ->initPager();
    $view->pager
      ->query();

    // If the query was aborted by some plugin (or, possibly, hook), we don't
    // need to do anything else here. Adding conditions or other options to an
    // aborted query doesn't make sense.
    if ($this
      ->shouldAbort()) {
      return;
    }

    // Setup the nested filter structure for this query.
    if (!empty($this->where)) {

      // If the different groups are combined with the OR operator, we have to
      // add a new OR filter to the query to which the filters for the groups
      // will be added.
      if ($this->groupOperator === 'OR') {
        $base = $this->query
          ->createConditionGroup('OR');
        $this->query
          ->addConditionGroup($base);
      }
      else {
        $base = $this->query;
      }

      // Add a nested filter for each filter group, with its set conjunction.
      foreach ($this->where as $group_id => $group) {
        if (!empty($group['conditions']) || !empty($group['condition_groups'])) {
          $group += [
            'type' => 'AND',
          ];

          // For filters without a group, we want to always add them directly to
          // the query.
          $conditions = $group_id === '' ? $this->query : $this->query
            ->createConditionGroup($group['type']);
          if (!empty($group['conditions'])) {
            foreach ($group['conditions'] as $condition) {
              list($field, $value, $operator) = $condition;
              $conditions
                ->addCondition($field, $value, $operator);
            }
          }
          if (!empty($group['condition_groups'])) {
            foreach ($group['condition_groups'] as $nested_conditions) {
              $conditions
                ->addConditionGroup($nested_conditions);
            }
          }

          // If no group was given, the filters were already set on the query.
          if ($group_id !== '') {
            $base
              ->addConditionGroup($conditions);
          }
        }
      }
    }

    // Add the "search_api_bypass_access" option to the query, if desired.
    if (!empty($this->options['bypass_access'])) {
      $this->query
        ->setOption('search_api_bypass_access', TRUE);
    }

    // If the View and the Panel conspire to provide an overridden path then
    // pass that through as the base path.
    if (($path = $this->view
      ->getPath()) && strpos(Url::fromRoute('<current>')
      ->toString(), $path) !== 0) {
      $this->query
        ->setOption('search_api_base_path', $path);
    }

    // Save query information for Views UI.
    $view->build_info['query'] = (string) $this->query;

    // Add the fields to be retrieved to the query, as information for the
    // backend.
    $this->query
      ->setOption('search_api_retrieved_field_values', array_values($this->retrievedFieldValues));
  }

  /**
   * {@inheritdoc}
   */
  public function alter(ViewExecutable $view) {
    $this
      ->getModuleHandler()
      ->invokeAll('views_query_alter', [
      $view,
      $this,
    ]);
  }

  /**
   * {@inheritdoc}
   */
  public function execute(ViewExecutable $view) {
    if ($this
      ->shouldAbort()) {
      if (error_displayable()) {
        foreach ($this->errors as $msg) {
          $this
            ->getMessenger()
            ->addError($msg);
        }
      }
      $view->result = [];
      $view->total_rows = 0;
      $view->execute_time = 0;
      return;
    }

    // Calculate the "skip result count" option, if it wasn't already set to
    // FALSE.
    $skip_result_count = $this->query
      ->getOption('skip result count', TRUE);
    if ($skip_result_count) {
      $skip_result_count = !$view->pager
        ->useCountQuery() && empty($view->get_total_rows);
      $this->query
        ->setOption('skip result count', $skip_result_count);
    }
    try {

      // Trigger pager preExecute().
      $view->pager
        ->preExecute($this->query);

      // Views passes sometimes NULL and sometimes the integer 0 for "All" in a
      // pager. If set to 0 items, a string "0" is passed. Therefore, we unset
      // the limit if an empty value OTHER than a string "0" was passed.
      if (!$this->limit && $this->limit !== '0') {
        $this->limit = NULL;
      }

      // Set the range. We always set this, as there might be an offset even if
      // all items are shown.
      $this->query
        ->range($this->offset, $this->limit);
      $start = microtime(TRUE);

      // Execute the search.
      $results = $this->query
        ->execute();

      // Store the results.
      if (!$skip_result_count) {
        $view->pager->total_items = $results
          ->getResultCount();
        if (!empty($view->pager->options['offset'])) {
          $view->pager->total_items -= $view->pager->options['offset'];
        }
        $view->total_rows = $view->pager->total_items;
      }
      $view->result = [];
      if ($results
        ->getResultItems()) {
        $this
          ->addResults($results, $view);
      }
      $view->execute_time = microtime(TRUE) - $start;

      // Trigger pager postExecute().
      $view->pager
        ->postExecute($view->result);
      $view->pager
        ->updatePageInfo();
    } catch (\Exception $e) {
      $this
        ->abort($e
        ->getMessage());

      // Recursion to get the same error behaviour as above.
      $this
        ->execute($view);
    }
  }

  /**
   * Aborts this search query.
   *
   * Used by handlers to flag a fatal error which shouldn't be displayed but
   * still lead to the view returning empty and the search not being executed.
   *
   * @param \Drupal\Component\Render\MarkupInterface|string|null $msg
   *   Optionally, a translated, unescaped error message to display.
   */
  public function abort($msg = NULL) {
    if ($msg) {
      $this->errors[] = $msg;
    }
    $this->abort = TRUE;
    if (isset($this->query)) {
      $this->query
        ->abort($msg);
    }
  }

  /**
   * Checks whether this query should be aborted.
   *
   * @return bool
   *   TRUE if the query should/will be aborted, FALSE otherwise.
   *
   * @see SearchApiQuery::abort()
   */
  public function shouldAbort() {
    return $this->abort || !$this->query || $this->query
      ->wasAborted();
  }

  /**
   * Adds Search API result items to a view's result set.
   *
   * @param \Drupal\search_api\Query\ResultSetInterface $result_set
   *   The search results.
   * @param \Drupal\views\ViewExecutable $view
   *   The executed view.
   */
  protected function addResults(ResultSetInterface $result_set, ViewExecutable $view) {
    $results = $result_set
      ->getResultItems();

    // Views \Drupal\views\Plugin\views\style\StylePluginBase::renderFields()
    // uses a numeric results index to key the rendered results.
    // The ResultRow::index property is the key then used to retrieve these.
    $count = 0;

    // First, unless disabled, check access for all entities in the results.
    if (!$this->options['skip_access']) {
      $account = $this
        ->getAccessAccount();

      // If search items are not loaded already, pre-load them now in bulk to
      // avoid them being individually loaded inside checkAccess().
      $result_set
        ->preLoadResultItems();
      foreach ($results as $item_id => $result) {
        if (!$result
          ->getAccessResult($account)
          ->isAllowed()) {
          unset($results[$item_id]);
        }
      }
    }
    foreach ($results as $item_id => $result) {
      $values = [];
      $values['_item'] = $result;
      try {
        $object = $result
          ->getOriginalObject(FALSE);
        if ($object) {
          $values['_object'] = $object;
          $values['_relationship_objects'][NULL] = [
            $object,
          ];
          if ($object instanceof EntityAdapter) {
            $values['_entity'] = $object
              ->getEntity();
          }
        }
      } catch (SearchApiException $e) {

        // Can't actually be thrown here, but catch for the static analyzer's
        // sake.
      }

      // Gather any properties from the search results.
      foreach ($result
        ->getFields(FALSE) as $field_id => $field) {
        if ($field
          ->getValues()) {
          $path = $field
            ->getCombinedPropertyPath();
          try {
            $property = $field
              ->getDataDefinition();

            // For configurable processor-defined properties, our Views field
            // handlers use a special property path to distinguish multiple
            // fields with the same property path. Therefore, we here also set
            // the values using that special property path so this will work
            // correctly.
            if ($property instanceof ConfigurablePropertyInterface) {
              $path .= '|' . $field_id;
            }
          } catch (SearchApiException $e) {

            // If we're not able to retrieve the data definition at this point,
            // it doesn't really matter.
          }
          $values[$path] = $field
            ->getValues();
        }
      }
      $values['index'] = $count++;
      $view->result[] = new ResultRow($values);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheContexts() {
    $query = $this
      ->getSearchApiQuery();
    if ($query instanceof CacheableDependencyInterface) {
      return $query
        ->getCacheContexts();
    }

    // We are not returning the cache contexts from the parent class since these
    // are based on the default SQL storage from Views, while our results are
    // coming from the search engine.
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheTags() {
    $tags = parent::getCacheTags();
    $query = $this
      ->getSearchApiQuery();
    if ($query instanceof CacheableDependencyInterface) {
      $tags = Cache::mergeTags($query
        ->getCacheTags(), $tags);
    }
    return $tags;
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheMaxAge() {
    $max_age = parent::getCacheMaxAge();
    $query = $this
      ->getSearchApiQuery();
    if ($query instanceof CacheableDependencyInterface) {
      $max_age = Cache::mergeMaxAges($query
        ->getCacheMaxAge(), $max_age);
    }
    return $max_age;
  }

  /**
   * Retrieves the conditions placed on this query.
   *
   * @return array
   *   The conditions placed on this query, separated by groups, as an
   *   associative array with a structure like this:
   *   - GROUP_ID:
   *     - type: "AND"/"OR"
   *     - conditions:
   *       - [FILTER, VALUE, OPERATOR]
   *       - [FILTER, VALUE, OPERATOR]
   *       …
   *     - condition_groups:
   *       - ConditionGroupInterface object
   *       - ConditionGroupInterface object
   *       …
   *   - GROUP_ID:
   *     …
   *   Returned by reference.
   */
  public function &getWhere() {
    return $this->where;
  }

  /**
   * Retrieves the account object to use for access checks for this query.
   *
   * @return \Drupal\Core\Session\AccountInterface|null
   *   The account for which to check access to returned or displayed entities.
   *   Or NULL to use the currently logged-in user.
   */
  public function getAccessAccount() {
    $account = $this
      ->getOption('search_api_access_account');
    if ($account && is_scalar($account)) {
      $account = User::load($account);
    }
    return $account;
  }

  /**
   * Returns the Search API query object used by this Views query.
   *
   * @return \Drupal\search_api\Query\QueryInterface|null
   *   The search query object used internally by this plugin, if any has been
   *   successfully created. NULL otherwise.
   */
  public function getSearchApiQuery() {
    return $this->query;
  }

  /**
   * Sets the Search API query object.
   *
   * Usually this is done by the query plugin class itself, but in rare cases
   * (such as for caching purposes) it might be necessary to set it from
   * outside.
   *
   * @param \Drupal\search_api\Query\QueryInterface $query
   *   The new query.
   *
   * @return $this
   */
  public function setSearchApiQuery(QueryInterface $query) {
    $this->query = $query;
    return $this;
  }

  /**
   * Retrieves the Search API result set returned for this query.
   *
   * @return \Drupal\search_api\Query\ResultSetInterface
   *   The result set of this query. Might not contain the actual results yet if
   *   the query hasn't been executed yet.
   */
  public function getSearchApiResults() {
    return $this->query
      ->getResults();
  }

  /**
   * {@inheritdoc}
   */
  public function calculateDependencies() {
    $dependencies = parent::calculateDependencies();
    $dependencies[$this->index
      ->getConfigDependencyKey()][] = $this->index
      ->getConfigDependencyName();
    return $dependencies;
  }

  //
  // Query interface methods (proxy to $this->query)
  //

  /**
   * Retrieves the parse mode.
   *
   * @return \Drupal\search_api\ParseMode\ParseModeInterface
   *   The parse mode.
   *
   * @see \Drupal\search_api\Query\QueryInterface::getParseMode()
   */
  public function getParseMode() {
    if (!$this
      ->shouldAbort()) {
      return $this->query
        ->getParseMode();
    }
    return new Terms([], 'terms', []);
  }

  /**
   * Sets the parse mode.
   *
   * @param \Drupal\search_api\ParseMode\ParseModeInterface $parse_mode
   *   The parse mode.
   *
   * @return $this
   *
   * @see \Drupal\search_api\Query\QueryInterface::setParseMode()
   */
  public function setParseMode(ParseModeInterface $parse_mode) {
    if (!$this
      ->shouldAbort()) {
      $this->query
        ->setParseMode($parse_mode);
    }
    return $this;
  }

  /**
   * Retrieves the languages that will be searched by this query.
   *
   * @return string[]|null
   *   The language codes of languages that will be searched by this query, or
   *   NULL if there shouldn't be any restriction on the language.
   *
   * @see \Drupal\search_api\Query\QueryInterface::getLanguages()
   */
  public function getLanguages() {
    if (!$this
      ->shouldAbort()) {
      return $this->query
        ->getLanguages();
    }
    return NULL;
  }

  /**
   * Sets the languages that should be searched by this query.
   *
   * @param string[]|null $languages
   *   The language codes to search for, or NULL to not restrict the query to
   *   specific languages.
   *
   * @return $this
   *
   * @see \Drupal\search_api\Query\QueryInterface::setLanguages()
   */
  public function setLanguages(array $languages = NULL) {
    if (!$this
      ->shouldAbort()) {
      $this->query
        ->setLanguages($languages);
    }
    return $this;
  }

  /**
   * Creates a new condition group to use with this query object.
   *
   * @param string $conjunction
   *   The conjunction to use for the condition group – either 'AND' or 'OR'.
   * @param string[] $tags
   *   (optional) Tags to set on the condition group.
   *
   * @return \Drupal\search_api\Query\ConditionGroupInterface
   *   A condition group object that is set to use the specified conjunction.
   *
   * @see \Drupal\search_api\Query\QueryInterface::createConditionGroup()
   */
  public function createConditionGroup($conjunction = 'AND', array $tags = []) {
    if (!$this
      ->shouldAbort()) {
      return $this->query
        ->createConditionGroup($conjunction, $tags);
    }
    return new ConditionGroup($conjunction, $tags);
  }

  /**
   * Sets the keys to search for.
   *
   * If this method is not called on the query before execution, this will be a
   * filter-only query.
   *
   * @param string|array|null $keys
   *   A string with the search keys, in one of the formats specified by
   *   getKeys(). A passed string will be parsed according to the set parse
   *   mode. Use NULL to not use any search keys.
   *
   * @return $this
   *
   * @see \Drupal\search_api\Query\QueryInterface::keys()
   */
  public function keys($keys = NULL) {
    if (!$this
      ->shouldAbort()) {
      $this->query
        ->keys($keys);
    }
    return $this;
  }

  /**
   * Sets the fields that will be searched for the search keys.
   *
   * If this is not called, all fulltext fields will be searched.
   *
   * @param array $fields
   *   An array containing fulltext fields that should be searched.
   *
   * @return $this
   *
   * @see \Drupal\search_api\Query\QueryInterface::setFulltextFields()
   */
  public function setFulltextFields(array $fields = NULL) {
    if (!$this
      ->shouldAbort()) {
      $this->query
        ->setFulltextFields($fields);
    }
    return $this;
  }

  /**
   * Adds a nested condition group.
   *
   * If $group is given, the filter is added to the relevant filter group
   * instead.
   *
   * @param \Drupal\search_api\Query\ConditionGroupInterface $condition_group
   *   A condition group that should be added.
   * @param string|null $group
   *   (optional) The Views query filter group to add this filter to.
   *
   * @return $this
   *
   * @see \Drupal\search_api\Query\QueryInterface::addConditionGroup()
   */
  public function addConditionGroup(ConditionGroupInterface $condition_group, $group = NULL) {
    if (!$this
      ->shouldAbort()) {

      // Ensure all variants of 0 are actually 0. Thus '', 0 and NULL are all
      // the default group.
      if (empty($group)) {
        $group = 0;
      }
      $this->where[$group]['condition_groups'][] = $condition_group;
    }
    return $this;
  }

  /**
   * Adds a new ($field $operator $value) condition filter.
   *
   * @param string $field
   *   The ID of the field to filter on, for example "status". The special
   *   fields "search_api_datasource" (filter on datasource ID),
   *   "search_api_language" (filter on language code) and "search_api_id"
   *   (filter on item ID) can be used in addition to all indexed fields on the
   *   index.
   *   However, for filtering on language code, using
   *   \Drupal\search_api\Plugin\views\query\SearchApiQuery::setLanguages is the
   *   preferred method, unless a complex condition containing the language code
   *   is required.
   * @param mixed $value
   *   The value the field should have (or be related to by the operator). If
   *   $operator is "IN" or "NOT IN", $value has to be an array of values. If
   *   $operator is "BETWEEN" or "NOT BETWEEN", it has to be an array with
   *   exactly two values: the lower bound in key 0 and the upper bound in key 1
   *   (both inclusive). Otherwise, $value must be a scalar.
   * @param string $operator
   *   The operator to use for checking the constraint. The following operators
   *   are always supported for primitive types: "=", "<>", "<", "<=", ">=",
   *   ">", "IN", "NOT IN", "BETWEEN", "NOT BETWEEN". They have the same
   *   semantics as the corresponding SQL operators. Other operators might be
   *   added by backend features.
   *   If $field is a fulltext field, $operator can only be "=" or "<>", which
   *   are in this case interpreted as "contains" or "doesn't contain",
   *   respectively.
   *   If $value is NULL, $operator also can only be "=" or "<>", meaning the
   *   field must have no or some value, respectively.
   * @param string|null $group
   *   (optional) The Views query filter group to add this filter to.
   *
   * @return $this
   *
   * @see \Drupal\search_api\Query\QueryInterface::addCondition()
   */
  public function addCondition($field, $value, $operator = '=', $group = NULL) {
    if (!$this
      ->shouldAbort()) {

      // Ensure all variants of 0 are actually 0. Thus '', 0 and NULL are all
      // the default group.
      if (empty($group)) {
        $group = 0;
      }
      $condition = [
        $field,
        $value,
        $operator,
      ];
      $this->where[$group]['conditions'][] = $condition;
    }
    return $this;
  }

  /**
   * Adds a simple condition to the query.
   *
   * This replicates the interface of Views' default SQL backend to simplify
   * the Views integration of the Search API. If you are writing Search
   * API-specific Views code, you should better use the addConditionGroup() or
   * addCondition() methods.
   *
   * @param int $group
   *   The condition group to add these to; groups are used to create AND/OR
   *   sections. Groups cannot be nested. Use 0 as the default group.
   *   If the group does not yet exist it will be created as an AND group.
   * @param string|\Drupal\Core\Database\Query\ConditionInterface|\Drupal\search_api\Query\ConditionGroupInterface $field
   *   The ID of the field to check; or a filter object to add to the query; or,
   *   for compatibility purposes, a database condition object to transform into
   *   a search filter object and add to the query. If a field ID is passed and
   *   starts with a period (.), it will be stripped.
   * @param mixed $value
   *   (optional) The value the field should have (or be related to by the
   *   operator). Or NULL if an object is passed as $field.
   * @param string|null $operator
   *   (optional) The operator to use for checking the constraint. The following
   *   operators are supported for primitive types: "=", "<>", "<", "<=", ">=",
   *   ">". They have the same semantics as the corresponding SQL operators.
   *   If $field is a fulltext field, $operator can only be "=" or "<>", which
   *   are in this case interpreted as "contains" or "doesn't contain",
   *   respectively.
   *   If $value is NULL, $operator also can only be "=" or "<>", meaning the
   *   field must have no or some value, respectively.
   *   To stay compatible with Views, "!=" is supported as an alias for "<>".
   *   If an object is passed as $field, $operator should be NULL.
   *
   * @return $this
   *
   * @see \Drupal\views\Plugin\views\query\Sql::addWhere()
   * @see \Drupal\search_api\Plugin\views\query\SearchApiQuery::filter()
   * @see \Drupal\search_api\Plugin\views\query\SearchApiQuery::condition()
   */
  public function addWhere($group, $field, $value = NULL, $operator = NULL) {
    if ($this
      ->shouldAbort()) {
      return $this;
    }

    // Ensure all variants of 0 are actually 0. Thus '', 0 and NULL are all the
    // default group.
    if (empty($group)) {
      $group = 0;
    }
    if (is_object($field)) {
      if ($field instanceof ConditionInterface) {
        $field = $this
          ->transformDbCondition($field);
      }
      if ($field instanceof ConditionGroupInterface) {
        $this->where[$group]['condition_groups'][] = $field;
      }
      elseif (!$this
        ->shouldAbort()) {

        // We only need to abort  if that wasn't done by transformDbCondition()
        // already.
        $this
          ->abort('Unexpected condition passed to addWhere().');
      }
    }
    else {
      $condition = [
        $this
          ->sanitizeFieldId($field),
        $value,
        $this
          ->sanitizeOperator($operator),
      ];
      $this->where[$group]['conditions'][] = $condition;
    }
    return $this;
  }

  /**
   * Retrieves the conjunction with which multiple filter groups are combined.
   *
   * @return string
   *   Either "AND" or "OR".
   */
  public function getGroupOperator() {
    return $this->groupOperator;
  }

  /**
   * Returns the group type of the given group.
   *
   * @param int $group
   *   The group whose type should be retrieved.
   *
   * @return string
   *   The group type – "AND" or "OR".
   */
  public function getGroupType($group) {
    return !empty($this->where[$group]) ? $this->where[$group] : 'AND';
  }

  /**
   * Transforms a database condition to an equivalent search filter.
   *
   * @param \Drupal\Core\Database\Query\ConditionInterface $db_condition
   *   The condition to transform.
   *
   * @return \Drupal\search_api\Query\ConditionGroupInterface|null
   *   A search filter equivalent to $condition, or NULL if the transformation
   *   failed.
   */
  protected function transformDbCondition(ConditionInterface $db_condition) {
    $conditions = $db_condition
      ->conditions();
    $filter = $this->query
      ->createConditionGroup($conditions['#conjunction']);
    unset($conditions['#conjunction']);
    foreach ($conditions as $condition) {
      if ($condition['operator'] === NULL) {
        $this
          ->abort('Trying to include a raw SQL condition in a Search API query.');
        return NULL;
      }
      if ($condition['field'] instanceof ConditionInterface) {
        $nested_filter = $this
          ->transformDbCondition($condition['field']);
        if ($nested_filter) {
          $filter
            ->addConditionGroup($nested_filter);
        }
        else {
          return NULL;
        }
      }
      else {
        $filter
          ->addCondition($this
          ->sanitizeFieldId($condition['field']), $condition['value'], $this
          ->sanitizeOperator($condition['operator']));
      }
    }
    return $filter;
  }

  /**
   * Adapts a field ID for use in a Search API query.
   *
   * This method will remove a leading period (.), if present. This is done
   * because in the SQL Views query plugin field IDs are always prefixed with a
   * table alias (in our case always empty) followed by a period.
   *
   * @param string $field_id
   *   The field ID to adapt for use in the Search API.
   *
   * @return string
   *   The sanitized field ID.
   */
  protected function sanitizeFieldId($field_id) {
    if ($field_id && $field_id[0] === '.') {
      $field_id = substr($field_id, 1);
    }
    return $field_id;
  }

  /**
   * Adapts an operator for use in a Search API query.
   *
   * This method maps Views' "!=" to the "<>" Search API uses.
   *
   * @param string $operator
   *   The operator to adapt for use in the Search API.
   *
   * @return string
   *   The sanitized operator.
   */
  protected function sanitizeOperator($operator) {
    if ($operator === '!=') {
      $operator = '<>';
    }
    elseif (in_array($operator, [
      'in',
      'not in',
      'between',
      'not between',
    ])) {
      $operator = strtoupper($operator);
    }
    elseif (in_array($operator, [
      'IS NULL',
      'IS NOT NULL',
    ])) {
      $operator = $operator == 'IS NULL' ? '=' : '<>';
    }
    return $operator;
  }

  /**
   * Adds a sort directive to this search query.
   *
   * If no sort is manually set, the results will be sorted descending by
   * relevance.
   *
   * @param string $field
   *   The field to sort by. The special fields 'search_api_relevance' (sort by
   *   relevance) and 'search_api_id' (sort by item id) may be used.
   * @param string $order
   *   The order to sort items in - either 'ASC' or 'DESC'.
   *
   * @return $this
   *
   * @see \Drupal\search_api\Query\QueryInterface::sort()
   */
  public function sort($field, $order = 'ASC') {
    if (!$this
      ->shouldAbort()) {
      $this->query
        ->sort($field, $order);
    }
    return $this;
  }

  /**
   * Adds an ORDER BY clause to the query.
   *
   * This replicates the interface of Views' default SQL backend to simplify
   * the Views integration of the Search API. If you are writing Search
   * API-specific Views code, you should better use the sort() method directly.
   *
   * Currently, only random sorting (by passing "rand" as the table) is
   * supported (for backends that support it), all other calls are silently
   * ignored.
   *
   * @param string|null $table
   *   The table this field is part of. If you want to order the results
   *   randomly, use "rand" as table and nothing else. Otherwise, use NULL.
   * @param string|null $field
   *   (optional) Ignored.
   * @param string $order
   *   (optional) Either ASC or DESC. (Lowercase variants will be uppercased.)
   * @param string $alias
   *   (optional) The field to sort on. Unless sorting randomly, "search_api_id"
   *   and "search_api_datasource" are supported.
   * @param array $params
   *   (optional) For sorting randomly, additional random sort parameters can be
   *   passed through here. Otherwise, the parameter is ignored.
   *
   * @throws \Drupal\search_api\SearchApiException
   *   Thrown if the searched index's server couldn't be loaded.
   *
   * @see \Drupal\views\Plugin\views\query\Sql::addOrderBy()
   */
  public function addOrderBy($table, $field = NULL, $order = 'ASC', $alias = '', array $params = []) {
    $server = $this
      ->getIndex()
      ->getServerInstance();
    if ($table == 'rand') {
      if ($server
        ->supportsFeature('search_api_random_sort')) {
        $this
          ->sort('search_api_random', $order);
        if ($params) {
          $this
            ->setOption('search_api_random_sort', $params);
        }
      }
      else {
        $variables['%server'] = $server
          ->label();
        $this
          ->getLogger()
          ->warning('Tried to sort results randomly on server %server which does not support random sorting.', $variables);
      }
    }
    elseif (in_array($alias, [
      'search_api_id',
      'search_api_datasource',
    ])) {
      $order = strtoupper($order) === 'DESC' ? 'DESC' : 'ASC';
      $this
        ->sort($alias, $order);
    }
  }

  /**
   * Adds a range of results to return.
   *
   * This will be saved in the query's options. If called without parameters,
   * this will remove all range restrictions previously set.
   *
   * @param int|null $offset
   *   The zero-based offset of the first result returned.
   * @param int|null $limit
   *   The number of results to return.
   *
   * @return $this
   *
   * @see \Drupal\search_api\Query\QueryInterface::range()
   */
  public function range($offset = NULL, $limit = NULL) {
    if (!$this
      ->shouldAbort()) {
      $this->query
        ->range($offset, $limit);
    }
    return $this;
  }

  /**
   * Retrieves the index associated with this search.
   *
   * @return \Drupal\search_api\IndexInterface
   *   The search index this query should be executed on.
   *
   * @see \Drupal\search_api\Query\QueryInterface::getIndex()
   */
  public function getIndex() {
    return $this->index;
  }

  /**
   * Retrieves the search keys for this query.
   *
   * @return array|string|null
   *   This object's search keys, in the format described by
   *   \Drupal\search_api\ParseMode\ParseModeInterface::parseInput(). Or NULL if
   *   the query doesn't have any search keys set.
   *
   * @see \Drupal\search_api\Plugin\views\query\SearchApiQuery::keys()
   *
   * @see \Drupal\search_api\Query\QueryInterface::getKeys()
   */
  public function &getKeys() {
    if (!$this
      ->shouldAbort()) {
      return $this->query
        ->getKeys();
    }
    $ret = NULL;
    return $ret;
  }

  /**
   * Retrieves the unparsed search keys for this query as originally entered.
   *
   * @return array|string|null
   *   The unprocessed search keys, exactly as passed to this object. Has the
   *   same format as the return value of getKeys().
   *
   * @see keys()
   *
   * @see \Drupal\search_api\Query\QueryInterface::getOriginalKeys()
   */
  public function getOriginalKeys() {
    if (!$this
      ->shouldAbort()) {
      return $this->query
        ->getOriginalKeys();
    }
    return NULL;
  }

  /**
   * Retrieves the fulltext fields that will be searched for the search keys.
   *
   * @return string[]|null
   *   An array containing the fields that should be searched for the search
   *   keys.
   *
   * @see setFulltextFields()
   * @see \Drupal\search_api\Query\QueryInterface::getFulltextFields()
   */
  public function &getFulltextFields() {
    if (!$this
      ->shouldAbort()) {
      return $this->query
        ->getFulltextFields();
    }
    $ret = NULL;
    return $ret;
  }

  /**
   * Retrieves the filter object associated with this search query.
   *
   * @return \Drupal\search_api\Query\ConditionGroupInterface
   *   This object's associated filter object.
   *
   * @see \Drupal\search_api\Query\QueryInterface::getConditionGroup()
   */
  public function getFilter() {
    if (!$this
      ->shouldAbort()) {
      return $this->query
        ->getConditionGroup();
    }
    return NULL;
  }

  /**
   * Retrieves the sorts set for this query.
   *
   * @return array
   *   An array specifying the sort order for this query. Array keys are the
   *   field names in order of importance, the values are the respective order
   *   in which to sort the results according to the field.
   *
   * @see sort()
   *
   * @see \Drupal\search_api\Query\QueryInterface::getSorts()
   */
  public function &getSort() {
    if (!$this
      ->shouldAbort()) {
      return $this->query
        ->getSorts();
    }
    $ret = NULL;
    return $ret;
  }

  /**
   * Retrieves an option set on this search query.
   *
   * @param string $name
   *   The name of an option.
   * @param mixed $default
   *   The value to return if the specified option is not set.
   *
   * @return mixed
   *   The value of the option with the specified name, if set. NULL otherwise.
   *
   * @see \Drupal\search_api\Query\QueryInterface::getOption()
   */
  public function getOption($name, $default = NULL) {
    if (!$this
      ->shouldAbort()) {
      return $this->query
        ->getOption($name, $default);
    }
    return $default;
  }

  /**
   * Sets an option for this search query.
   *
   * @param string $name
   *   The name of an option. The following options are recognized by default:
   *   - offset: The position of the first returned search results relative to
   *     the whole result in the index.
   *   - limit: The maximum number of search results to return. -1 means no
   *     limit.
   *   - 'search id': A string that will be used as the identifier when storing
   *     this search in the Search API's static cache.
   *   - 'skip result count': If present and set to TRUE, the search's result
   *     count will not be needed. Service classes can check for this option to
   *     possibly avoid executing expensive operations to compute the result
   *     count in cases where it is not needed.
   *   - search_api_access_account: The account which will be used for entity
   *     access checks, if available and enabled for the index.
   *   - search_api_bypass_access: If set to TRUE, entity access checks will be
   *     skipped, even if enabled for the index.
   *   However, contrib modules might introduce arbitrary other keys with their
   *   own, special meaning. (Usually they should be prefixed with the module
   *   name, though, to avoid conflicts.)
   * @param mixed $value
   *   The new value of the option.
   *
   * @return mixed
   *   The option's previous value, or NULL if none was set.
   *
   * @see \Drupal\search_api\Query\QueryInterface::setOption()
   */
  public function setOption($name, $value) {
    if (!$this
      ->shouldAbort()) {
      return $this->query
        ->setOption($name, $value);
    }
    return NULL;
  }

  /**
   * Retrieves all options set for this search query.
   *
   * The return value is a reference to the options so they can also be altered
   * this way.
   *
   * @return array
   *   An associative array of query options.
   *
   * @see \Drupal\search_api\Query\QueryInterface::getOptions()
   */
  public function &getOptions() {
    if (!$this
      ->shouldAbort()) {
      return $this->query
        ->getOptions();
    }
    $ret = NULL;
    return $ret;
  }

  //
  // Methods from Views' SQL query plugin, to simplify integration.
  //

  /**
   * Ensures a table exists in the query.
   *
   * This replicates the interface of Views' default SQL backend to simplify
   * the Views integration of the Search API. Since the Search API has no
   * concept of "tables", this method implementation does nothing. If you are
   * writing Search API-specific Views code, there is therefore no reason at all
   * to call this method.
   * See https://www.drupal.org/node/2484565 for more information.
   *
   * @return string
   *   An empty string.
   */
  public function ensureTable() {
    return '';
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
LoggerTrait::$logger protected property The logging channel to use.
LoggerTrait::getLogger public function Retrieves the logger.
LoggerTrait::logException protected function Logs an exception.
LoggerTrait::setLogger public function Sets the logger.
MessengerTrait::messenger public function Gets the messenger. 29
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$definition public property Plugins's definition
PluginBase::$displayHandler public property The display object this plugin is for.
PluginBase::$options public property Options for this plugin will be held here.
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::$renderer protected property Stores the render API renderer. 3
PluginBase::$usesOptions protected property Denotes whether the plugin has an additional options form. 8
PluginBase::$view public property The top object of a view. 1
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::destroy public function Clears a plugin. Overrides ViewsPluginInterface::destroy 2
PluginBase::doFilterByDefinedOptions protected function Do the work to filter out stored options depending on the defined options.
PluginBase::filterByDefinedOptions public function Filter out stored options depending on the defined options. Overrides ViewsPluginInterface::filterByDefinedOptions
PluginBase::getAvailableGlobalTokens public function Returns an array of available token replacements. Overrides ViewsPluginInterface::getAvailableGlobalTokens
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::getProvider public function Returns the plugin provider. Overrides ViewsPluginInterface::getProvider
PluginBase::getRenderer protected function Returns the render API renderer. 1
PluginBase::globalTokenForm public function Adds elements for available core tokens to a form. Overrides ViewsPluginInterface::globalTokenForm
PluginBase::globalTokenReplace public function Returns a string with any core tokens replaced. Overrides ViewsPluginInterface::globalTokenReplace
PluginBase::INCLUDE_ENTITY constant Include entity row languages when listing languages.
PluginBase::INCLUDE_NEGOTIATED constant Include negotiated languages when listing languages.
PluginBase::isConfigurable public function Determines if the plugin is configurable.
PluginBase::listLanguages protected function Makes an array of languages, optionally including special languages.
PluginBase::pluginTitle public function Return the human readable name of the display. Overrides ViewsPluginInterface::pluginTitle
PluginBase::preRenderAddFieldsetMarkup public static function Moves form elements into fieldsets for presentation purposes. Overrides ViewsPluginInterface::preRenderAddFieldsetMarkup
PluginBase::preRenderFlattenData public static function Flattens the structure of form elements. Overrides ViewsPluginInterface::preRenderFlattenData
PluginBase::queryLanguageSubstitutions public static function Returns substitutions for Views queries for languages.
PluginBase::setOptionDefaults protected function Fills up the options of the plugin with defaults.
PluginBase::themeFunctions public function Provide a full list of possible theme templates used by this style. Overrides ViewsPluginInterface::themeFunctions 1
PluginBase::trustedCallbacks public static function Lists the trusted callbacks provided by the implementing class. Overrides TrustedCallbackInterface::trustedCallbacks 6
PluginBase::unpackOptions public function Unpack options over our existing defaults, drilling down into arrays so that defaults don't get totally blown away. Overrides ViewsPluginInterface::unpackOptions
PluginBase::usesOptions public function Returns the usesOptions property. Overrides ViewsPluginInterface::usesOptions 8
PluginBase::validate public function Validate that the plugin is correct and can be saved. Overrides ViewsPluginInterface::validate 6
PluginBase::viewsTokenReplace protected function Replaces Views' tokens in a given string. The resulting string will be sanitized with Xss::filterAdmin. 1
PluginBase::VIEWS_QUERY_LANGUAGE_SITE_DEFAULT constant Query string to indicate the site default language.
PluginBase::__construct public function Constructs a PluginBase object. Overrides PluginBase::__construct
QueryPluginBase::$pager public property A pager plugin that should be provided by the display.
QueryPluginBase::addSignature public function Add a signature to the query, if such a thing is feasible. 1
QueryPluginBase::getAggregationInfo public function Get aggregation info for group by queries. 1
QueryPluginBase::getDateField public function Returns a Unix timestamp to database native timestamp expression. 1
QueryPluginBase::getDateFormat public function Creates cross-database date formatting. 1
QueryPluginBase::getEntityTableInfo public function Returns an array of all tables from the query that map to an entity type.
QueryPluginBase::getLimit public function Returns the limit of the query.
QueryPluginBase::getTimezoneOffset public function Get the timezone offset in seconds.
QueryPluginBase::loadEntities public function Loads all entities contained in the passed-in $results. . If the entity belongs to the base table, then it gets stored in $result->_entity. Otherwise, it gets stored in $result->_relationship_entities[$relationship_id]; 1
QueryPluginBase::setFieldTimezoneOffset public function Applies a timezone offset to the given field. 2
QueryPluginBase::setGroupOperator public function Control how all WHERE and HAVING groups are put together.
QueryPluginBase::setLimit public function Set a LIMIT on the query, specifying a maximum number of results.
QueryPluginBase::setOffset public function Set an OFFSET on the query, specifying a number of results to skip
QueryPluginBase::setupTimezone public function Set the database to the current user timezone. 1
QueryPluginBase::setWhereGroup public function Create a new grouping for the WHERE or HAVING clause.
QueryPluginBase::submitOptionsForm public function Handle any special handling on the validate form. Overrides PluginBase::submitOptionsForm 1
QueryPluginBase::summaryTitle public function Returns the summary of the settings in the display. Overrides PluginBase::summaryTitle
QueryPluginBase::validateOptionsForm public function Validate the options form. Overrides PluginBase::validateOptionsForm
SearchApiQuery::$abort protected property Whether to abort the search instead of executing it.
SearchApiQuery::$errors protected property Array of all encountered errors.
SearchApiQuery::$groupOperator protected property The conjunction with which multiple filter groups are combined.
SearchApiQuery::$index protected property The index this view accesses.
SearchApiQuery::$limit protected property Number of results to display. Overrides QueryPluginBase::$limit
SearchApiQuery::$messenger protected property The messenger. Overrides MessengerTrait::$messenger
SearchApiQuery::$moduleHandler protected property The module handler.
SearchApiQuery::$offset protected property Offset of first displayed result.
SearchApiQuery::$query protected property The query that will be executed.
SearchApiQuery::$retrievedFieldValues protected property The IDs of fields whose values should be retrieved by the backend.
SearchApiQuery::$where protected property The query's conditions representing the different Views filter groups.
SearchApiQuery::abort public function Aborts this search query.
SearchApiQuery::addCondition public function Adds a new ($field $operator $value) condition filter.
SearchApiQuery::addConditionGroup public function Adds a nested condition group.
SearchApiQuery::addField public function Adds a field to the table.
SearchApiQuery::addOrderBy public function Adds an ORDER BY clause to the query.
SearchApiQuery::addResults protected function Adds Search API result items to a view's result set.
SearchApiQuery::addRetrievedFieldValue public function Adds a field value to be retrieved.
SearchApiQuery::addRetrievedProperty Deprecated public function Adds a property to be retrieved.
SearchApiQuery::addWhere public function Adds a simple condition to the query.
SearchApiQuery::alter public function Let modules modify the query just prior to finalizing it. Overrides QueryPluginBase::alter
SearchApiQuery::build public function Builds the necessary info to execute the query. Overrides QueryPluginBase::build
SearchApiQuery::buildOptionsForm public function Provide a form to edit options for this plugin. Overrides PluginBase::buildOptionsForm
SearchApiQuery::calculateDependencies public function Calculates dependencies for the configured plugin. Overrides QueryPluginBase::calculateDependencies
SearchApiQuery::create public static function Creates an instance of the plugin. Overrides PluginBase::create
SearchApiQuery::createConditionGroup public function Creates a new condition group to use with this query object.
SearchApiQuery::defineOptions public function Information about options for all kinds of purposes will be held here. @code 'option_name' => array( Overrides PluginBase::defineOptions
SearchApiQuery::ensureTable public function Ensures a table exists in the query.
SearchApiQuery::execute public function Executes the query and fills the associated view object with according values. Overrides QueryPluginBase::execute
SearchApiQuery::getAccessAccount public function Retrieves the account object to use for access checks for this query.
SearchApiQuery::getCacheContexts public function The cache contexts associated with this object. Overrides QueryPluginBase::getCacheContexts
SearchApiQuery::getCacheMaxAge public function The maximum age for which this object may be cached. Overrides QueryPluginBase::getCacheMaxAge
SearchApiQuery::getCacheTags public function The cache tags associated with this object. Overrides QueryPluginBase::getCacheTags
SearchApiQuery::getEntityFromRow public static function Retrieves the contained entity from a Views result row.
SearchApiQuery::getEntityTypes Deprecated public function Checks for entity types contained in the current view's index.
SearchApiQuery::getFilter public function Retrieves the filter object associated with this search query.
SearchApiQuery::getFulltextFields public function Retrieves the fulltext fields that will be searched for the search keys.
SearchApiQuery::getGroupOperator public function Retrieves the conjunction with which multiple filter groups are combined.
SearchApiQuery::getGroupType public function Returns the group type of the given group.
SearchApiQuery::getIndex public function Retrieves the index associated with this search.
SearchApiQuery::getIndexFromTable public static function Loads the search index belonging to the given Views base table.
SearchApiQuery::getKeys public function Retrieves the search keys for this query.
SearchApiQuery::getLanguages public function Retrieves the languages that will be searched by this query.
SearchApiQuery::getMessenger public function Retrieves the messenger.
SearchApiQuery::getModuleHandler public function Retrieves the module handler.
SearchApiQuery::getOption public function Retrieves an option set on this search query.
SearchApiQuery::getOptions public function Retrieves all options set for this search query.
SearchApiQuery::getOriginalKeys public function Retrieves the unparsed search keys for this query as originally entered.
SearchApiQuery::getParseMode public function Retrieves the parse mode.
SearchApiQuery::getSearchApiQuery public function Returns the Search API query object used by this Views query.
SearchApiQuery::getSearchApiResults public function Retrieves the Search API result set returned for this query.
SearchApiQuery::getSort public function Retrieves the sorts set for this query.
SearchApiQuery::getWhere public function Retrieves the conditions placed on this query.
SearchApiQuery::init public function Constructor; Create the basic query object and fill with default values. Overrides PluginBase::init
SearchApiQuery::keys public function Sets the keys to search for.
SearchApiQuery::query public function Generate a query and a countquery from all of the information supplied to the object. Overrides QueryPluginBase::query
SearchApiQuery::range public function Adds a range of results to return.
SearchApiQuery::sanitizeFieldId protected function Adapts a field ID for use in a Search API query.
SearchApiQuery::sanitizeOperator protected function Adapts an operator for use in a Search API query.
SearchApiQuery::setFulltextFields public function Sets the fields that will be searched for the search keys.
SearchApiQuery::setLanguages public function Sets the languages that should be searched by this query.
SearchApiQuery::setMessenger public function Sets the messenger. Overrides MessengerTrait::setMessenger
SearchApiQuery::setModuleHandler public function Sets the module handler.
SearchApiQuery::setOption public function Sets an option for this search query.
SearchApiQuery::setParseMode public function Sets the parse mode.
SearchApiQuery::setSearchApiQuery public function Sets the Search API query object.
SearchApiQuery::shouldAbort public function Checks whether this query should be aborted.
SearchApiQuery::sort public function Adds a sort directive to this search query.
SearchApiQuery::transformDbCondition protected function Transforms a database condition to an equivalent search filter.
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.
TrustedCallbackInterface::THROW_EXCEPTION constant Untrusted callbacks throw exceptions.
TrustedCallbackInterface::TRIGGER_SILENCED_DEPRECATION constant Untrusted callbacks trigger silenced E_USER_DEPRECATION errors.
TrustedCallbackInterface::TRIGGER_WARNING constant Untrusted callbacks trigger E_USER_WARNING errors.