class SearchApiQueryPreExecute in JSON:API Search API 8
Adds Facets support to a Search API Query.
Hierarchy
- class \Drupal\jsonapi_search_api_facets\EventSubscriber\SearchApiQueryPreExecute implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
Expanded class hierarchy of SearchApiQueryPreExecute
1 string reference to 'SearchApiQueryPreExecute'
- jsonapi_search_api_facets.services.yml in modules/
jsonapi_search_api_facets/ jsonapi_search_api_facets.services.yml - modules/jsonapi_search_api_facets/jsonapi_search_api_facets.services.yml
1 service uses SearchApiQueryPreExecute
- jsonapi_search_api_facets.query_pre_execute in modules/
jsonapi_search_api_facets/ jsonapi_search_api_facets.services.yml - Drupal\jsonapi_search_api_facets\EventSubscriber\SearchApiQueryPreExecute
File
- modules/
jsonapi_search_api_facets/ src/ EventSubscriber/ SearchApiQueryPreExecute.php, line 14
Namespace
Drupal\jsonapi_search_api_facets\EventSubscriberView source
class SearchApiQueryPreExecute implements EventSubscriberInterface {
/**
* The facet manager.
*
* @var \Drupal\facets\FacetManager\DefaultFacetManager
*/
protected $facetManager;
/**
* Constructs a new event subscriber.
*
* @param \Drupal\facets\FacetManager\DefaultFacetManager $facet_manager
* The facet manager.
*/
public function __construct(DefaultFacetManager $facet_manager) {
$this->facetManager = $facet_manager;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
$events[SearchApiEvents::QUERY_PRE_EXECUTE][] = [
'includeFacetsInQuery',
];
return $events;
}
/**
* Alter the Search API query to include Facets if enabled.
*
* @param \Drupal\search_api\Event\QueryPreExecuteEvent $event
* The event being emitted by Search API.
*/
public function includeFacetsInQuery(QueryPreExecuteEvent $event) {
$query = $event
->getQuery();
$search_id = $query
->getSearchId();
if (strpos($search_id, 'jsonapi_search_api:') === 0 && $query
->getIndex()
->getServerInstance()
->supportsFeature('search_api_facets')) {
$facet_source_id = strtr('jsonapi_search_api_facets:!index', [
'!index' => $query
->getIndex()
->id(),
]);
$this->facetManager
->alterQuery($query, $facet_source_id);
$facets = $this->facetManager
->getFacetsByFacetSourceId($facet_source_id);
$facet_tags = [];
$aliased_facets = [];
foreach ($facets as $facet) {
if ($facet
->getUrlAlias() !== $facet
->getFieldIdentifier()) {
$aliased_facets[] = $facet
->getUrlAlias();
}
if ($facet
->getQueryOperator() === 'or') {
$facet_field = $facet
->getFieldIdentifier();
$facet_tag = strtr('facet:!field', [
'!field' => $facet_field,
]);
$facet_tags[$facet_field] = $facet_tag;
}
}
// When using the OR operator for facets a filter is created to
// support tagging and excluding filters. The base JSON:API search will
// add the initial filter from the URL parameters which will stomp over
// the one that is added via facets.
// Only way to alter these conditions is modifying by reference.
// @see: https://www.drupal.org/project/search_api/issues/2910522#comment-12270738.
$conditions = $query
->getConditionGroup();
$this
->removeAliasConditions($conditions, $aliased_facets);
$this
->tagConditionsWithFacetTags($conditions, $facet_tags);
}
}
/**
* Removes alias conditions from the query.
*
* The index resource adds all filter conditions to the Search API query,
* which includes the facet URL alias. Remove them to prevent errors for
* non-existant fields.
*
* @param \Drupal\search_api\Query\ConditionGroupInterface $condition_group
* The condition group.
* @param array $aliases
* The facet aliases.
*/
protected function removeAliasConditions(ConditionGroupInterface $condition_group, array $aliases) {
$conditions =& $condition_group
->getConditions();
foreach ($conditions as $key => $condition) {
if ($condition instanceof ConditionGroupInterface) {
$this
->removeAliasConditions($condition, $aliases);
}
else {
if (in_array($condition
->getField(), $aliases, TRUE)) {
unset($conditions[$key]);
}
}
}
}
/**
* Handles tagging conditionGroups with appropriate facet tags as needed.
*
* @param \Drupal\search_api\Query\ConditionInterface|\Drupal\search_api\Query\ConditionGroupInterface $condition_or_group
* The ConditionGroup or Condition being evaluated.
* @param array $facet_tags
* The facet tags that may need to be applied to the condition.
*
* @return void|string
* Void if the Condition is being modified, the tag to be added otherwise.
*/
protected function tagConditionsWithFacetTags($condition_or_group, array $facet_tags) {
if ($condition_or_group instanceof ConditionGroupInterface) {
foreach ($condition_or_group
->getConditions() as $condition) {
$tags_to_add = $this
->tagConditionsWithFacetTags($condition, $facet_tags);
if ($tags_to_add) {
$tags =& $condition_or_group
->getTags();
$tags[$tags_to_add] = $tags_to_add;
}
}
}
else {
$field = $condition_or_group
->getField();
if (isset($facet_tags[$field])) {
return $facet_tags[$field];
}
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
SearchApiQueryPreExecute:: |
protected | property | The facet manager. | |
SearchApiQueryPreExecute:: |
public static | function | ||
SearchApiQueryPreExecute:: |
public | function | Alter the Search API query to include Facets if enabled. | |
SearchApiQueryPreExecute:: |
protected | function | Removes alias conditions from the query. | |
SearchApiQueryPreExecute:: |
protected | function | Handles tagging conditionGroups with appropriate facet tags as needed. | |
SearchApiQueryPreExecute:: |
public | function | Constructs a new event subscriber. |