Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OPENEUROPA-3373: Add query functionality #6

Merged
merged 10 commits into from
Jul 23, 2020
5 changes: 5 additions & 0 deletions oe_list_pages.services.yml
Original file line number Diff line number Diff line change
@@ -2,3 +2,8 @@ services:
oe_list_pages.list_source.factory:
class: Drupal\oe_list_pages\ListSourceFactory
arguments: ['@facets.manager', '@entity_type.manager']
oe_list_pages.query_event_subscriber:
class: Drupal\oe_list_pages\EventSubscriber\QuerySubscriber
arguments: ['@facets.manager', '@plugin.manager.facets.query_type']
tags:
- { name: event_subscriber }
97 changes: 97 additions & 0 deletions src/EventSubscriber/QuerySubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

namespace Drupal\oe_list_pages\EventSubscriber;

use Drupal\facets\FacetManager\DefaultFacetManager;
use Drupal\facets\QueryType\QueryTypePluginManager;
use Drupal\search_api\Event\QueryPreExecuteEvent;
use Drupal\search_api\Event\SearchApiEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* Provides an event subscriber that allows to alter list source queries.
*/
class QuerySubscriber implements EventSubscriberInterface {

/**
* The facets manager.
*
* @var \Drupal\facets\FacetManager\DefaultFacetManager
*/
protected $facetManager;

/**
* The query type plugin manager.
*
* @var \Drupal\facets\QueryType\QueryTypePluginManager
*/
protected $queryTypePluginManager;

/**
* QuerySubscriber Constructor.
*
* @param \Drupal\facets\FacetManager\DefaultFacetManager $facetManager
* The facets manager.
* @param \Drupal\facets\QueryType\QueryTypePluginManager $queryTypePluginManager
* The query type plugin manager.
*/
public function __construct(DefaultFacetManager $facetManager, QueryTypePluginManager $queryTypePluginManager) {
$this->facetManager = $facetManager;
$this->queryTypePluginManager = $queryTypePluginManager;
}

/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
SearchApiEvents::QUERY_PRE_EXECUTE => 'queryAlter',
];
}

/**
* Reacts to the query alter event.
*
* @param \Drupal\search_api\Event\QueryPreExecuteEvent $event
* The query alter event.
*/
public function queryAlter(QueryPreExecuteEvent $event) {
$query = $event->getQuery();

$ignored_filters = $preset_filters = [];

if (!$query->getIndex()->getServerInstance()->supportsFeature('search_api_facets')) {
return;
}

$facetsource_id = $query->getSearchId();
/** @var \Drupal\oe_list_pages\ListQueryOptionsInterface $query_options */
$query_options = $query->getOption('oe_list_page_query_options');

if (!empty($query_options)) {
$ignored_filters = $query_options->getIgnoredFilters();
$preset_filters = $query_options->getPresetFiltersValues();
}

// Add the active filters.
foreach ($this->facetManager->getFacetsByFacetSourceId($facetsource_id) as $facet) {
// Handle preset filters. If filter is preset, set as active items.
if (in_array($facet->id(), array_keys($preset_filters))) {
$facet->setActiveItems([$preset_filters[$facet->id()]]);
}

// Handle ignored filters. If filter is ignored unset its active items.
if (in_array($facet->id(), $ignored_filters)) {
$facet->setActiveItems([]);
}

/** @var \Drupal\facets\QueryType\QueryTypeInterface $query_type_plugin */
$query_type_plugin = $this->queryTypePluginManager->createInstance($facet->getQueryType(), [
'query' => $query,
'facet' => $facet,
]);
$query_type_plugin->execute();
}
}

}
69 changes: 69 additions & 0 deletions src/ListQueryOptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

declare(strict_types = 1);

namespace Drupal\oe_list_pages;

/**
* List source query options value object.
*
* Used to store list options that are applied to search api query.
*/
class ListQueryOptions implements ListQueryOptionsInterface {

/**
* The ignored filters.
*
* @var array
*/
protected $ignoredFilters = [];

/**
* The preset filters.
*
* @var array
*/
protected $presetFiltersValues = [];

/**
* ListQueryOptions constructor.
*
* @param array $ignored_filters
* The ignored filters.
* @param array $preset_filters
* The preset filters.
*/
public function __construct(array $ignored_filters, array $preset_filters) {
$this->ignoredFilters = $ignored_filters;
$this->presetFiltersValues = $preset_filters;
}

/**
* {@inheritdoc}
*/
public function getIgnoredFilters(): array {
return $this->ignoredFilters;
}

/**
* {@inheritdoc}
*/
public function setIgnoredFilters(array $ignoredFilters): void {
$this->ignoredFilters = $ignoredFilters;
}

/**
* {@inheritdoc}
*/
public function getPresetFiltersValues(): array {
return $this->presetFiltersValues;
}

/**
* {@inheritdoc}
*/
public function setPresetFiltersValues(array $presetFiltersValues): void {
$this->presetFiltersValues = $presetFiltersValues;
}

}
46 changes: 46 additions & 0 deletions src/ListQueryOptionsInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types = 1);

namespace Drupal\oe_list_pages;

/**
* Interface for List source query options value object.
*
* Used to store list page options that are applied to search api query.
*/
interface ListQueryOptionsInterface {

/**
* Gets the ignored filters.
*
* @return array
* The ignored filters.
*/
public function getIgnoredFilters(): array;

/**
* Sets the ignored filters.
*
* @param array $ignoredFilters
* The ignored filters.
*/
public function setIgnoredFilters(array $ignoredFilters): void;

/**
* Gets the preset filters.
*
* @return array
* The preset filters.
*/
public function getPresetFiltersValues(): array;

/**
* Sets the preset filters.
*
* @param array $presetFiltersValues
* The preset filters.
*/
public function setPresetFiltersValues(array $presetFiltersValues): void;

}
37 changes: 36 additions & 1 deletion src/ListSource.php
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
namespace Drupal\oe_list_pages;

use Drupal\search_api\IndexInterface;
use Drupal\search_api\Query\QueryInterface;

/**
* List sources are associated with a facet source.
@@ -49,6 +50,13 @@ class ListSource implements ListSourceInterface {
*/
protected $filters;

/**
* The bundle entity key used to reference the entity bundle.
*
* @var string
*/
protected $bundleKey;

/**
* ListSource constructor.
*
@@ -58,15 +66,18 @@ class ListSource implements ListSourceInterface {
* The entity type.
* @param string $bundle
* The bundle.
* @param string $bundle_key
* The bundle key.
* @param \Drupal\search_api\IndexInterface $index
* The search api index.
* @param array $filters
* The filters.
*/
public function __construct(string $search_id, string $entity_type, string $bundle, IndexInterface $index, array $filters) {
public function __construct(string $search_id, string $entity_type, string $bundle, string $bundle_key, IndexInterface $index, array $filters) {
$this->searchId = $search_id;
$this->entityType = $entity_type;
$this->bundle = $bundle;
$this->bundleKey = $bundle_key;
$this->index = $index;
$this->filters = $filters;
}
@@ -99,11 +110,35 @@ public function getSearchId(): string {
return $this->searchId;
}

/**
* {@inheritdoc}
*/
public function getBundleKey(): string {
return $this->bundleKey;
}

/**
* {@inheritdoc}
*/
public function getIndex(): IndexInterface {
return $this->index;
}

/**
* {@inheritdoc}
*/
public function getQuery(int $limit = 10, int $page = 0, array $ignored_filters = [], array $preset_filters = []): QueryInterface {

$query = $this->index->query([
'limit' => $limit,
'offset' => ($limit * $page),
]);
$query_options = new ListQueryOptions($ignored_filters, $preset_filters);
$query->setOption('oe_list_page_query_options', $query_options);
$query->setSearchId($this->getSearchId());
$query->addCondition($this->getBundleKey(), $this->getBundle());
$query->addCondition('search_api_datasource', 'entity:' . $this->getEntityType());
return $query;
}

}
3 changes: 2 additions & 1 deletion src/ListSourceFactory.php
Original file line number Diff line number Diff line change
@@ -128,7 +128,8 @@ protected function create(string $entity_type, string $bundle, IndexInterface $i
$filters[$field_id] = $facet->getFacetSource()->getIndex()->getField($field_id)->getLabel();
}

return new ListSource($id, $entity_type, $bundle, $index, $filters);
$bundle_field_id = $this->entityTypeManager->getDefinition($entity_type)->getKey('bundle');
return new ListSource($id, $entity_type, $bundle, $bundle_field_id, $index, $filters);
}

}
28 changes: 27 additions & 1 deletion src/ListSourceInterface.php
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
namespace Drupal\oe_list_pages;

use Drupal\search_api\IndexInterface;
use Drupal\search_api\Query\QueryInterface;

/**
* Defines the interface for list source implementations.
@@ -23,10 +24,18 @@ public function getAvailableFilters(): array;
* Gets the bundle.
*
* @return string
* The bundle
* The bundle.
*/
public function getBundle(): string;

/**
* Gets the bundle key.
*
* @return string
* The bundle key.
*/
public function getBundleKey(): string;

/**
* Gets the entity type.
*
@@ -51,4 +60,21 @@ public function getSearchId();
*/
public function getIndex(): IndexInterface;

/**
* Gets the query.
*
* @param int $limit
* The query limit.
* @param int $page
* The query offset.
* @param array $ignored_filters
* Ignored filter keys.
* @param array $preset_filters
* Preset filter values.
*
* @return \Drupal\search_api\Query\QueryInterface
* The search api query.
*/
public function getQuery(int $limit = 10, int $page = 0, array $ignored_filters = [], array $preset_filters = []): QueryInterface;

}
Loading