/** * {@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'], '<'); } }
/** * 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); }