Commit 3323ecff authored by borisson_'s avatar borisson_ Committed by borisson_

Issue #2913329 by borisson_, ekes, d.novikov: Move numeric granularity to a processor

parent 33826d87
......@@ -123,3 +123,11 @@ plugin.plugin_configuration.facets_processor.date_item:
date_format:
type: string
label: 'Date format'
plugin.plugin_configuration.facets_processor.granularity_item:
type: mapping
label: 'Granular item processor'
mapping:
granularity:
type: integer
label: 'Granularity'
......@@ -126,3 +126,26 @@ function facets_update_8004() {
}
}
}
/**
* Migrate facets with granular widget to use date processors + links widget.
*/
function facets_update_8005() {
foreach (Facet::loadMultiple() as $facet) {
$widget = $facet->getWidget();
if ($widget['type'] === 'numericgranular') {
// Set widget to use links instead.
$facet->setWidget('links', ['show_numbers' => $widget['config']['show_numbers']]);
// Migrate widget to processor settings and enable date_item processor.
$settings = [
'granularity' => $widget['config']['granularity'],
];
$facet->addProcessor([
'processor_id' => 'granularity_item',
'weights' => ['build' => 35],
'settings' => $settings,
]);
$facet->save();
}
}
}
<?php
namespace Drupal\facets\Plugin\facets\widget;
namespace Drupal\facets\Plugin\facets\processor;
use Drupal\Core\Form\FormStateInterface;
use Drupal\facets\FacetInterface;
use Drupal\facets\Processor\BuildProcessorInterface;
use Drupal\facets\Processor\ProcessorPluginBase;
/**
* Basic granular widget.
* Provides a processor for granularity.
*
* @FacetsWidget(
* id = "numericgranular",
* label = @Translation("Granular numeric list"),
* @FacetsProcessor(
* id = "granularity_item",
* label = @Translation("Granularity item processor"),
* description = @Translation("List of numbers grouped in steps."),
* stages = {
* "build" = 35
* }
* )
*/
class NumericGranularWidget extends LinksWidget {
class GranularItemProcessor extends ProcessorPluginBase implements BuildProcessorInterface {
/**
* {@inheritdoc}
*/
public function build(FacetInterface $facet, array $results) {
return $results;
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return [
'granularity' => 0,
'granularity' => 1,
] + parent::defaultConfiguration();
}
......@@ -31,16 +43,15 @@ class NumericGranularWidget extends LinksWidget {
public function buildConfigurationForm(array $form, FormStateInterface $form_state, FacetInterface $facet) {
$configuration = $this->getConfiguration();
$form += parent::buildConfigurationForm($form, $form_state, $facet);
$form['granularity'] = [
$build['granularity'] = [
'#type' => 'number',
'#attributes' => ['min' => 1, 'step' => 1],
'#title' => $this->t('Granularity'),
'#default_value' => $configuration['granularity'],
'#description' => $this->t('The numeric size of the steps to group the result facets in.'),
];
return $form;
return $build;
}
/**
......
......@@ -23,7 +23,7 @@ class SearchApiGranular extends QueryTypeRangeBase {
public function calculateRange($value) {
return [
'start' => $value,
'stop' => $value + $this->getGranularity(),
'stop' => (int) $value + $this->getGranularity(),
];
}
......@@ -31,6 +31,7 @@ class SearchApiGranular extends QueryTypeRangeBase {
* {@inheritdoc}
*/
public function calculateResultFilter($value) {
assert($this->getGranularity() > 0);
return [
'display' => $value - ($value % $this->getGranularity()),
'raw' => $value - ($value % $this->getGranularity()) ,
......@@ -42,11 +43,11 @@ class SearchApiGranular extends QueryTypeRangeBase {
*
* Default behaviour an integer for the steps that the facet works in.
*
* @return mixed
* @return int
* If not an integer the inheriting class needs to deal with calculations.
*/
protected function getGranularity() {
return $this->facet->getWidgetInstance()->getConfiguration()['granularity'];
return $this->facet->getProcessors()['granularity_item']->getConfiguration()['granularity'];
}
}
<?php
namespace Drupal\facets_custom_widget\Plugin\facets\widget;
use Drupal\facets\Widget\WidgetPluginBase;
/**
* Test widget.
*
* @FacetsWidget(
* id = "widget_date_qt",
* label = @Translation("Widget with date query type"),
* description = @Translation("Widget with date query type"),
* )
*/
class WidgetDateQT extends WidgetPluginBase {
/**
* {@inheritdoc}
*/
public function getQueryType() {
return 'date';
}
}
......@@ -203,6 +203,96 @@ class ProcessorIntegrationTest extends FacetsTestBase {
$this->assertFacetLabel('Øn');
}
/**
* Tests the for configuration of granularity processor.
*/
public function testNumericGranularity() {
$field_name = 'field_integer';
$field_storage = FieldStorageConfig::create([
'field_name' => $field_name,
'entity_type' => 'entity_test_mulrev_changed',
'type' => 'integer',
]);
$field_storage->save();
$field = FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => 'item',
]);
$field->save();
$field = FieldConfig::create([
'field_storage' => $field_storage,
'bundle' => 'article',
]);
$field->save();
$index = $this->getIndex();
// Index the taxonomy and entity reference fields.
$integerField = new Field($index, $field_name);
$integerField->setType('integer');
$integerField->setPropertyPath($field_name);
$integerField->setDatasourceId('entity:entity_test_mulrev_changed');
$integerField->setLabel('IntegerField');
$index->addField($integerField);
$index->save();
$this->indexItems($this->indexId);
$entity_test_storage = \Drupal::entityTypeManager()
->getStorage('entity_test_mulrev_changed');
foreach ([30, 35, 40, 100] as $val) {
$entity_test_storage->create([
'name' => 'foo bar baz',
'body' => 'test test int',
'type' => 'item',
'keywords' => ['orange'],
'category' => 'item_category',
$field_name => $val,
])->save();
}
$this->indexItems($this->indexId);
$facet_id = "integer";
// Create facet.
$this->editForm = 'admin/config/search/facets/' . $facet_id . '/edit';
$this->createFacet("Integer", $facet_id, $field_name);
// Check values.
$this->drupalGet('search-api-test-fulltext');
$this->assertFacetLabel('100');
$this->assertFacetLabel('30');
$this->assertFacetLabel('35');
$this->assertFacetLabel('40');
$form = [
'facet_settings[granularity_item][status]' => TRUE,
];
$this->drupalPostForm($this->editForm, $form, 'Save');
// Check values.
$this->drupalGet('search-api-test-fulltext');
$this->assertFacetLabel('30 (1)');
$this->assertFacetLabel('35');
$this->assertFacetLabel('40');
$this->assertFacetLabel('100');
$form = [
'facet_settings[granularity_item][status]' => TRUE,
'facet_settings[granularity_item][settings][granularity]' => 10,
];
$this->drupalPostForm($this->editForm, $form, 'Save');
// Check values.
$this->drupalGet('search-api-test-fulltext');
$this->assertFacetLabel('30 (2)');
$this->assertEmpty($this->findFacetLink('35'));
$this->assertFacetLabel('40');
$this->assertFacetLabel('100');
}
/**
* Tests the for sorting processors in the frontend with a 'keywords' facet.
*/
......
......@@ -178,7 +178,7 @@ class FacetFacetSourceTest extends EntityKernelTestBase {
*/
public function testQueryTypeJugglingInvalidCombo() {
$entity = new Facet([], 'facets_facet');
$entity->setWidget('numericgranular');
$entity->setWidget('widget_date_qt');
$entity->setFacetSourceId('search_api:views_page__search_api_test_view__page_1');
$entity->setFieldIdentifier('name');
$processor = [
......
......@@ -2,16 +2,19 @@
namespace Drupal\Tests\facets\Unit\Plugin\query_type;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\facets\Entity\Facet;
use Drupal\facets\FacetInterface;
use Drupal\facets\Plugin\facets\processor\GranularItemProcessor;
use Drupal\facets\Plugin\facets\query_type\SearchApiGranular;
use Drupal\facets\Processor\ProcessorPluginManager;
use Drupal\search_api\Backend\BackendInterface;
use Drupal\search_api\IndexInterface;
use Drupal\facets\Result\ResultInterface;
use Drupal\facets\Widget\WidgetPluginInterface;
use Drupal\search_api\Plugin\views\query\SearchApiQuery;
use Drupal\search_api\ServerInterface;
use Drupal\Tests\UnitTestCase;
use Prophecy\Argument;
/**
* Unit test for granular query type.
......@@ -20,6 +23,32 @@ use Drupal\Tests\UnitTestCase;
*/
class SearchApiGranularTest extends UnitTestCase {
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
$processor_id = 'granularity_item';
$processor_definitions = [
$processor_id => [
'id' => $processor_id,
'class' => GranularItemProcessor::class,
],
];
$granularityProcessor = new GranularItemProcessor(['granularity' => 10], 'granularity_item', []);
$processor_manager = $this->prophesize(ProcessorPluginManager::class);
$processor_manager->getDefinitions()->willReturn($processor_definitions);
$processor_manager->createInstance('granularity_item', Argument::any())
->willReturn($granularityProcessor);
$container = new ContainerBuilder();
$container->set('plugin.manager.facets.processor', $processor_manager->reveal());
\Drupal::setContainer($container);
}
/**
* Tests string query type without executing the query with an "AND" operator.
*/
......@@ -37,14 +66,11 @@ class SearchApiGranularTest extends UnitTestCase {
['query_operator' => 'AND', 'widget' => 'links'],
'facets_facet'
);
$facetReflection = new \ReflectionClass(Facet::class);
$widget = $this->getMockBuilder(WidgetPluginInterface::class)
->disableOriginalConstructor()
->getMock();
$widget->method('getConfiguration')->will($this->returnValue(['granularity' => 10]));
$widget_instance = $facetReflection->getProperty('widgetInstance');
$widget_instance->setAccessible(TRUE);
$widget_instance->setValue($facet, $widget);
$facet->addProcessor([
'processor_id' => 'granularity_item',
'weights' => [],
'settings' => ['granularity' => 10],
]);
// Results for the widget.
$original_results = [
......
<?php
namespace Drupal\Tests\facets\Unit\Plugin\widget;
use Drupal\facets\Plugin\facets\widget\NumericGranularWidget;
/**
* Unit test for widget.
*
* @group facets
*/
class NumericGranularWidgetTest extends WidgetTestBase {
/**
* {@inheritdoc}
*/
public function setUp() {
parent::setUp();
$this->widget = new NumericGranularWidget();
}
/**
* {@inheritdoc}
*/
public function testGetQueryType() {
$result = $this->widget->getQueryType($this->queryTypes);
$this->assertEquals('numeric', $result);
}
/**
* {@inheritdoc}
*/
public function testDefaultConfiguration() {
$default_config = $this->widget->defaultConfiguration();
$expected = [
'show_numbers' => FALSE,
'soft_limit' => 0,
'granularity' => 0,
'soft_limit_settings' => [
'show_less_label' => 'Show less',
'show_more_label' => 'Show more',
],
];
$this->assertEquals($expected, $default_config);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment