Skip to content

Commit

Permalink
Merge pull request #91 from openeuropa/EWPP-837
Browse files Browse the repository at this point in the history
EWPP-837: Refactoring the default filter values and results processing.
  • Loading branch information
imanoleguskiza authored Apr 9, 2021
2 parents 55f6a61 + 4519a71 commit 62030c8
Show file tree
Hide file tree
Showing 34 changed files with 925 additions and 211 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,15 @@ public static function create(ContainerInterface $container, array $configuratio
* {@inheritdoc}
*/
public function build(FacetInterface $facet, array $results) {
// Loop over all results.
// Loop over all results and try to determine the country.
foreach ($results as $i => $result) {
$country = $this->countryRepository->get($result->getRawValue());
try {
$country = $this->countryRepository->get($result->getRawValue());
}
catch (\Exception $exception) {
continue;
}

$result->setDisplayValue($country->getName());
}
return $results;
Expand All @@ -77,9 +83,14 @@ public function build(FacetInterface $facet, array $results) {
*/
public function supportsFacet(FacetInterface $facet) {
$data_definition = $facet->getDataDefinition();
if ($data_definition->getDataType() === 'string') {
if (in_array($data_definition->getDataType(), [
'string',
'field_item:string',
'field_item:address_country',
])) {
return TRUE;
}

return FALSE;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

declare(strict_types = 1);

namespace Drupal\oe_list_pages_link_list_source;

use Drupal\Core\Entity\ContentEntityInterface;

/**
* Interface to indicate a search API processor is aware of contextual filters.
*
* This allows the processor plugins that index custom values into the index
* also provide corresponding values from an entity from context.
*/
interface ContextualAwareProcessorInterface {

/**
* Given an entity, return contextual filter values.
*
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
* The entity.
*
* @return array
* The filter values.
*/
public function getContextualValues(ContentEntityInterface $entity): array;

}
Original file line number Diff line number Diff line change
Expand Up @@ -305,14 +305,14 @@ public function deleteFilterValueSubmit(array &$form, FormStateInterface $form_s
*
* These are only the ones that use a Multiselect widget.
*
* @param \Drupal\oe_list_pages\ListSourceInterface $listSource
* @param \Drupal\oe_list_pages\ListSourceInterface $list_source
* The list source.
*
* @return array
* The options.
*/
protected function getAvailableFilters(ListSourceInterface $listSource): array {
$facets = $this->facetsManager->getFacetsByFacetSourceId($listSource->getSearchId());
protected function getAvailableFilters(ListSourceInterface $list_source): array {
$facets = $this->facetsManager->getFacetsByFacetSourceId($list_source->getSearchId());
$options = [];

foreach ($facets as $facet) {
Expand All @@ -321,6 +321,13 @@ protected function getAvailableFilters(ListSourceInterface $listSource): array {
continue;
}

// If the facet is based on a custom Search API field (processor), the
// latter should be contextual aware. Otherwise it won't be useful.
$processor = ContextualFiltersHelper::getSearchApiFieldProcessor($list_source, $facet);
if ($processor && !$processor instanceof ContextualAwareProcessorInterface) {
continue;
}

$options[$facet->id()] = $facet->label();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types = 1);

namespace Drupal\oe_list_pages_link_list_source;

use Drupal\facets\FacetInterface;
use Drupal\oe_list_pages\ListSourceInterface;
use Drupal\search_api\Processor\ProcessorInterface;

/**
* Helper class for the contextual filters logic.
*/
class ContextualFiltersHelper {

/**
* Returns the search API processor that is contextual filters aware.
*
* @param \Drupal\oe_list_pages\ListSourceInterface $list_source
* The list source.
* @param \Drupal\facets\FacetInterface $facet
* The facet for which to determine the plugin.
*
* @return \Drupal\oe_list_pages_link_list_source\ContextualAwareProcessorInterface|null
* The processor if found.
*/
public static function getContextualAwareSearchApiProcessor(ListSourceInterface $list_source, FacetInterface $facet): ?ContextualAwareProcessorInterface {
$processor = static::getSearchApiFieldProcessor($list_source, $facet);
if ($processor instanceof ContextualAwareProcessorInterface) {
return $processor;
}

return NULL;
}

/**
* Returns the custom Search API field processor this facet is based on.
*
* @param \Drupal\oe_list_pages\ListSourceInterface $list_source
* The list source.
* @param \Drupal\facets\FacetInterface $facet
* The facet.
*
* @return \Drupal\search_api\Processor\ProcessorInterface|null
* The processor if found, NULL otherwise.
*/
public static function getSearchApiFieldProcessor(ListSourceInterface $list_source, FacetInterface $facet): ?ProcessorInterface {
$property_path = $list_source->getIndex()->getField($facet->getFieldIdentifier())->getPropertyPath();
$processors = $list_source->getIndex()->getProcessorsByStage(ProcessorInterface::STAGE_ADD_PROPERTIES);
foreach ($processors as $processor) {
$properties = $processor->getPropertyDefinitions();
if (isset($properties[$property_path])) {
return $processor;
}
}

return NULL;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use Drupal\oe_list_pages\MultiselectFilterFieldPluginManager;
use Drupal\oe_list_pages_link_list_source\ContextualFilterFieldMapper;
use Drupal\oe_list_pages_link_list_source\ContextualFiltersConfigurationBuilder;
use Drupal\oe_list_pages_link_list_source\ContextualFiltersHelper;
use Drupal\oe_list_pages_link_list_source\Exception\InapplicableContextualFilter;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
Expand Down Expand Up @@ -321,24 +322,35 @@ protected function initializeConfiguration(CacheableMetadata $cache): ListPageCo
foreach ($contextual_filters as $contextual_filter) {
$facet = $this->contextualFiltersBuilder->getFacetById($list_source, $contextual_filter->getFacetId());
$definition = $this->getFacetFieldDefinition($facet, $list_source);
$field_name = $definition->getName();
// Map the field correctly.
$field_name = $this->contextualFieldMapper->getCorrespondingFieldName($field_name, $entity, $cache);
if (!$field_name) {
// If the field doesn't exist on the current entity, we need to not
// show any results.
throw new InapplicableContextualFilter();
if ($definition) {
$field_name = $definition->getName();
// Map the field correctly.
$field_name = $this->contextualFieldMapper->getCorrespondingFieldName($field_name, $entity, $cache);
if (!$field_name) {
// If the field doesn't exist on the current entity, we need to not
// show any results.
throw new InapplicableContextualFilter();
}

$field = $entity->get($field_name);
$values = $this->extractValuesFromField($field, $facet, $list_source);
if (empty($values)) {
// If the contextual filter does not have a value, we again cannot
// show any results.
throw new InapplicableContextualFilter();
}

$contextual_filter->setValues($values);
}
else {
$processor = ContextualFiltersHelper::getContextualAwareSearchApiProcessor($list_source, $facet);
if (!$processor) {
throw new InapplicableContextualFilter();
}

$field = $entity->get($field_name);
$values = $this->extractValuesFromField($field, $facet, $list_source);
if (empty($values)) {
// If the contextual filter does not have a value, we again cannot
// show any results.
throw new InapplicableContextualFilter();
$contextual_filter->setValues($processor->getContextualValues($entity));
}

$contextual_filter->setValues($values);
$default_filter_values[ContextualFiltersConfigurationBuilder::generateFilterId($contextual_filter->getFacetId(), array_keys($default_filter_values))] = $contextual_filter;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Drupal\Tests\oe_list_pages_link_list_source\FunctionalJavascript;

use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\node\Entity\Node;
use Drupal\oe_link_lists\Entity\LinkList;
use Drupal\oe_list_pages\DefaultFilterConfigurationBuilder;
Expand Down Expand Up @@ -32,6 +34,7 @@ class ListPageLinkSourcePluginTest extends ListPagePluginFormTestBase {
'oe_link_lists_test',
'oe_list_pages_event_subscriber_test',
'oe_list_pages_link_list_source_test',
'oe_list_pages_address',
'facets',
'entity_reference_revisions',
'oe_list_pages_filters_test',
Expand Down Expand Up @@ -642,6 +645,46 @@ public function testListPageContextualFilters(): void {
$this->assertSession()->elementsCount('css', '.block-oe-link-lists ul li', 2);
$this->assertSession()->linkExistsExact('visible reference');
$this->assertSession()->linkExistsExact('select one and reference');

// Test that we can also use custom search API fields as contextual filters.
$configuration['source']['plugin_configuration']['contextual_filters'] = [
ContextualFiltersConfigurationBuilder::generateFilterId('oe_list_pages_filters_test_test_field') => new ListPresetFilter('oe_list_pages_filters_test_test_field', [], 'or'),
];
$link_list->setConfiguration($configuration);
$link_list->save();
$this->drupalGet($node->toUrl());
// By default we don't have any results.
$this->assertSession()->elementsCount('css', '.block-oe-link-lists ul li', 0);
// Add the test contextual filter to the Page node type.
FieldStorageConfig::create([
'entity_type' => 'node',
'field_name' => 'field_test_contextual_filter',
'type' => 'string',
'translatable' => '0',
'cardinality' => 2,
])->save();
FieldConfig::create([
'label' => 'Test contextual filter',
'description' => '',
'field_name' => 'field_test_contextual_filter',
'entity_type' => 'node',
'bundle' => 'article',
'required' => 0,
])->save();
$list_nodes = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties(['title' => ['visible boolean', 'not visible boolean']]);
$ids = array_keys($list_nodes);
$node = Node::load($node->id());
$node->set('field_test_contextual_filter', reset($ids));
$node->save();
$this->drupalGet($node->toUrl());
$this->assertSession()->elementsCount('css', '.block-oe-link-lists ul li', 1);
$this->assertSession()->linkExistsExact('not visible boolean');
$node->set('field_test_contextual_filter', $ids);
$node->save();
$this->drupalGet($node->toUrl());
$this->assertSession()->elementsCount('css', '.block-oe-link-lists ul li', 2);
$this->assertSession()->linkExistsExact('not visible boolean');
$this->assertSession()->linkExistsExact('visible boolean');
}

/**
Expand Down
18 changes: 18 additions & 0 deletions oe_list_pages.post_update.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

declare(strict_types = 1);

use Drupal\facets\Entity\Facet;

/**
* Installs the new dependencies.
*/
Expand All @@ -25,3 +27,19 @@ function oe_list_pages_post_update_0002() {
'multivalue_form_element',
]);
}

/**
* Removes the date_processor_handler from existing facets.
*/
function oe_list_pages_post_update_0003() {
$facets = Facet::loadMultiple();
foreach ($facets as $facet) {
$processors = $facet->getProcessorConfigs();
if (!isset($processors['date_processor_handler'])) {
continue;
}

$facet->removeProcessor('date_processor_handler');
$facet->save();
}
}
24 changes: 22 additions & 2 deletions src/Annotation/MultiselectFilterField.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,31 @@ class MultiselectFilterField extends Plugin {
public $id;

/**
* The field types this plugin applies to.
* The Drupal field types this plugin applies to.
*
* @var array
*/
public $fieldTypes;
public $field_types;

/**
* The Search API data types this plugin applies to.
*
* This is optional in case a more specific Drupal field type could be
* determined on the facet.
*
* @var array
*/
public $data_types;

/**
* The Facet IDs this plugin applies to.
*
* This is when the plugin needs to be targeted towards a very specific
* facet.
*
* @var array
*/
public $facet_ids;

/**
* The human-readable name of the plugin.
Expand Down
Loading

0 comments on commit 62030c8

Please sign in to comment.