Skip to content

Commit

Permalink
Merge pull request #6 from openeuropa/OPENEUROPA-3373
Browse files Browse the repository at this point in the history
OPENEUROPA-3373: Add query functionality
  • Loading branch information
hernani authored Jul 23, 2020
2 parents a7d0216 + 60104c5 commit 8cf2465
Show file tree
Hide file tree
Showing 13 changed files with 621 additions and 139 deletions.
5 changes: 5 additions & 0 deletions oe_list_pages.services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
*
Expand All @@ -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;
}
Expand Down Expand Up @@ -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
Expand Up @@ -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
Expand Up @@ -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.
Expand All @@ -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.
*
Expand All @@ -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

0 comments on commit 8cf2465

Please sign in to comment.