/**
  * {@inheritdoc}
  */
 public function execute()
 {
     /** @var \Drupal\core_search_facets\Plugin\CoreSearchFacetSourceInterface $facet_source */
     $facet_source = $this->facet->getFacetSource();
     $query_info = $facet_source->getQueryInfo($this->facet);
     /** @var \Drupal\core_search_facets\FacetsQuery $facet_query */
     $facet_query = $facet_source->getFacetQueryExtender();
     $tables_joined = [];
     // Add the filter to the query if there are active values.
     $active_items = $this->facet->getActiveItems();
     foreach ($active_items as $item) {
         foreach ($query_info['fields'] as $field_info) {
             // Adds join to the facet query.
             $facet_query->addFacetJoin($query_info, $field_info['table_alias']);
             // Adds join to search query, makes sure it is only added once.
             if (isset($query_info['joins'][$field_info['table_alias']])) {
                 if (!isset($tables_joined[$field_info['table_alias']])) {
                     $tables_joined[$field_info['table_alias']] = TRUE;
                     $join_info = $query_info['joins'][$field_info['table_alias']];
                     $this->query->join($join_info['table'], $join_info['alias'], $join_info['condition']);
                 }
             }
             // Adds facet conditions to the queries.
             $field = $field_info['table_alias'] . '.' . $field_info['field'];
             $this->query->condition($field, $item);
             $facet_query->condition($field, $item);
         }
     }
 }
 /**
  * {@inheritdoc}
  */
 public function execute()
 {
     /** @var \Drupal\facets\Utility\FacetsDateHandler $date_handler */
     $date_handler = \Drupal::getContainer()->get('facets.utility.date_handler');
     /** @var \Drupal\core_search_facets\Plugin\CoreSearchFacetSourceInterface $facet_source */
     $facet_source = $this->facet->getFacetSource();
     // Gets the last active date, bails if there isn't one.
     $active_items = $this->facet->getActiveItems();
     if (!($active_item = end($active_items))) {
         return;
     }
     // Gets facet query and this facet's query info.
     /** @var \Drupal\core_search_facets\FacetsQuery $facet_query */
     $facet_query = $facet_source->getFacetQueryExtender();
     $query_info = $facet_source->getQueryInfo($this->facet);
     $tables_joined = [];
     $active_item = $date_handler->extractActiveItems($active_item);
     foreach ($query_info['fields'] as $field_info) {
         // Adds join to the facet query.
         $facet_query->addFacetJoin($query_info, $field_info['table_alias']);
         // Adds join to search query, makes sure it is only added once.
         if (isset($query_info['joins'][$field_info['table_alias']])) {
             if (!isset($tables_joined[$field_info['table_alias']])) {
                 $tables_joined[$field_info['table_alias']] = TRUE;
                 $join_info = $query_info['joins'][$field_info['table_alias']];
                 $this->query->join($join_info['table'], $join_info['alias'], $join_info['condition']);
             }
         }
         // Adds field conditions to the facet and search query.
         $field = $field_info['table_alias'] . '.' . $field_info['field'];
         $this->query->condition($field, $active_item['start']['timestamp'], '>=');
         $this->query->condition($field, $active_item['end']['timestamp'], '<');
         $facet_query->condition($field, $active_item['start']['timestamp'], '>=');
         $facet_query->condition($field, $active_item['end']['timestamp'], '<');
     }
 }
Example #3
0
/**
 * Alter a search query before it gets executed.
 *
 * The hook is invoked after all enabled processors have preprocessed the query.
 *
 * @param \Drupal\search_api\Query\QueryInterface $query
 *   The query that will be executed.
 */
function hook_search_api_query_alter(\Drupal\search_api\Query\QueryInterface &$query) {
  // Exclude entities with ID 0. (Assume the ID field is always indexed.)
  $types = $query->getIndex()->getDatasourceIds();
  foreach ($types as $type) {
    if (strpos($type, ':')) {
      list(, $type) = explode(':', $type);
    }
    $definition = \Drupal::entityManager()->getDefinition($type, FALSE);
    if ($definition) {
      $keys = $definition->getKeys();
      $query->condition($keys['id'], 0, '<>');
    }
  }
}
 /**
  * Adds a node access filter to a search query, if applicable.
  *
  * @param \Drupal\search_api\Query\QueryInterface $query
  *   The query to which a node access filter should be added, if applicable.
  * @param \Drupal\Core\Session\AccountInterface $account
  *   The user for whom the search is executed.
  *
  * @throws \Drupal\search_api\SearchApiException
  *   Thrown if not all necessary fields are indexed on the index.
  */
 protected function addNodeAccess(QueryInterface $query, AccountInterface $account)
 {
     // Don't do anything if the user can access all content.
     if ($account->hasPermission('bypass node access')) {
         return;
     }
     // Gather the affected datasources, grouped by entity type, as well as the
     // unaffected ones.
     $affected_datasources = array();
     $unaffected_datasources = array();
     foreach ($this->index->getDatasources() as $datasource_id => $datasource) {
         $entity_type = $datasource->getEntityTypeId();
         if (in_array($entity_type, array('node', 'comment'))) {
             $affected_datasources[$entity_type][] = $datasource_id;
         } else {
             $unaffected_datasources[] = $datasource_id;
         }
     }
     // The filter structure we want looks like this:
     //   [belongs to other datasource]
     //   OR
     //   (
     //     [is enabled (or was created by the user, if applicable)]
     //     AND
     //     [grants view access to one of the user's gid/realm combinations]
     //   )
     // If there are no "other" datasources, we don't need the nested OR,
     // however, and can add the "ADD"
     // @todo Add a filter tag, once they are implemented.
     if ($unaffected_datasources) {
         $outer_filter = $query->createFilter('OR');
         $query->filter($outer_filter);
         foreach ($unaffected_datasources as $datasource_id) {
             $outer_filter->condition('search_api_datasource', $datasource_id);
         }
         $access_filter = $query->createFilter('AND');
         $outer_filter->filter($access_filter);
     } else {
         $access_filter = $query;
     }
     if (!$account->hasPermission('access content')) {
         unset($affected_datasources['node']);
     }
     if (!$account->hasPermission('access comments')) {
         unset($affected_datasources['comment']);
     }
     // If the user does not have the permission to see any content at all, deny
     // access to all items from affected datasources.
     if (!$affected_datasources) {
         // If there were "other" datasources, the existing filter will already
         // remove all results of node or comment datasources. Otherwise, we should
         // not return any results at all.
         if (!$unaffected_datasources) {
             // @todo More elegant way to return no results?
             $query->condition('search_api_language', '');
         }
         return;
     }
     // Collect all the required fields that need to be part of the index.
     $unpublished_own = $account->hasPermission('view own unpublished content');
     $enabled_filter = $query->createFilter('OR');
     foreach ($affected_datasources as $entity_type => $datasources) {
         $published = $entity_type == 'node' ? NODE_PUBLISHED : Comment::PUBLISHED;
         foreach ($datasources as $datasource_id) {
             // If this is a comment datasource, or users cannot view their own
             // unpublished nodes, a simple filter on "status" is enough. Otherwise,
             // it's a bit more complicated.
             $status_field = Utility::createCombinedId($datasource_id, 'status');
             $enabled_filter->condition($status_field, $published);
             if ($entity_type == 'node' && $unpublished_own) {
                 $author_field = Utility::createCombinedId($datasource_id, 'uid');
                 $enabled_filter->condition($author_field, $account->id());
             }
         }
     }
     $access_filter->filter($enabled_filter);
     // Filter by the user's node access grants.
     $grants_filter = $query->createFilter('OR');
     $grants = node_access_grants('view', $account);
     foreach ($grants as $realm => $gids) {
         foreach ($gids as $gid) {
             $grants_filter->condition('search_api_node_grants', "node_access_{$realm}:{$gid}");
         }
     }
     // Also add items that are accessible for everyone by checking the "access
     // all" pseudo grant.
     $grants_filter->condition('search_api_node_grants', 'node_access__all');
     $access_filter->filter($grants_filter);
 }