Skip to content
Snippets Groups Projects
Commit 860df955 authored by Andrew Chappell's avatar Andrew Chappell Committed by Kim Pepper
Browse files

Issue #3316753 by achap: Add date range data type

parent 76d5ed5a
Branches
Tags
1 merge request!41Issue #3285438: Prevent index clear when field mapping hasn't changed.
Pipeline #7703 failed
<?php
namespace Drupal\search_api_opensearch\Plugin\search_api\data_type;
use Drupal\search_api\Plugin\search_api\data_type\DateDataType;
/**
* Provides a date range data type.
*
* @SearchApiDataType(
* id = "search_api_opensearch_date_range",
* label = @Translation("Date range"),
* description = @Translation("Date field that contains date ranges."),
* fallback = "date",
* prefix = "dr"
* )
*/
class DateRangeDataType extends DateDataType {
}
<?php
namespace Drupal\search_api_opensearch\Plugin\search_api\processor;
use Drupal\search_api\Processor\ProcessorPluginBase;
/**
* Add date ranges to the index.
*
* @SearchApiProcessor(
* id = "search_api_opensearch_date_range",
* label = @Translation("Date ranges"),
* description = @Translation("Date ranges."),
* stages = {
* "preprocess_index" = 0,
* },
* locked = true,
* hidden = true,
* )
*/
class DateRange extends ProcessorPluginBase {
/**
* {@inheritdoc}
*/
public function preprocessIndexItems(array $items) {
foreach ($items as $item) {
foreach ($item->getFields() as $field) {
if ('search_api_opensearch_date_range' == $field->getType()) {
$required_properties = [
$item->getDatasourceId() => [
$field->getPropertyPath() . ':value' => 'start',
$field->getPropertyPath() . ':end_value' => 'end',
],
];
$item_values = $this->getFieldsHelper()->extractItemValues([$item], $required_properties);
foreach ($item_values as $dates) {
$start_dates = $dates['start'];
$end_dates = $dates['end'];
for ($i = 0, $n = count($start_dates); $i < $n; $i++) {
$values[$i] = [
'gte' => $start_dates[$i],
'lte' => $end_dates[$i],
];
}
}
if (!empty($values)) {
$field->setValues($values);
}
}
}
}
}
}
......@@ -145,6 +145,10 @@ class FieldMapper {
'type' => 'date',
'format' => 'strict_date_optional_time||epoch_second',
],
'search_api_opensearch_date_range' => [
'type' => 'date_range',
'format' => 'strict_date_optional_time||epoch_second',
],
'attachment' => ['type' => 'attachment'],
'object' => ['type' => 'nested'],
'location' => ['type' => 'geo_point'],
......
......@@ -29,4 +29,17 @@ class DataTypeTest extends KernelTestBase {
$this->assertEquals('search_api_opensearch', $definition['provider']);
}
/**
* Tests the date range type is found.
*/
public function testHasDateRangeDataType() {
/** @var \Drupal\search_api\DataType\DataTypePluginManager $manager */
$manager = $this->container->get('plugin.manager.search_api.data_type');
$definitions = $manager->getDefinitions();
$this->assertArrayHasKey('search_api_opensearch_date_range', $definitions);
$definition = $definitions['search_api_opensearch_date_range'];
$this->assertEquals('search_api_opensearch_date_range', $definition['id']);
$this->assertEquals('search_api_opensearch', $definition['provider']);
}
}
<?php
namespace Drupal\Tests\search_api_opensearch\Unit\Plugin\processor;
use Drupal\search_api\Datasource\DatasourceInterface;
use Drupal\search_api\IndexInterface;
use Drupal\search_api\Item\Field;
use Drupal\search_api\Item\Item;
use Drupal\search_api\Utility\FieldsHelper;
use Drupal\search_api_opensearch\Plugin\search_api\processor\DateRange;
use Drupal\Tests\UnitTestCase;
/**
* Tests the date range processor.
*
* @coversDefaultClass \Drupal\search_api_opensearch\Plugin\search_api\processor\DateRange
* @group search_api_opensearch
*/
class DateRangeTest extends UnitTestCase {
/**
* Test making date range field types compatible with OS.
*
* @covers ::preprocessIndexItems
* @dataProvider dateValueDataProvider
*/
public function testPreProcessingDateRangeItems(
array $extractItemResult,
array $expectedResult
): void {
$dataSource = $this->prophesize(DatasourceInterface::class);
$dataSource->getPluginId()->willReturn('entity:node');
$index = $this->prophesize(IndexInterface::class);
$indexId = "index_" . $this->randomMachineName();
$index->id()->willReturn($indexId);
$itemId = "item1_" . $this->randomMachineName();
$item = (new Item($index->reveal(), $itemId, $dataSource->reveal()))
->setFieldsExtracted(TRUE)
->setField(
'event_date_range',
(new Field($index->reveal(), 'event_date_range'))
->setType("search_api_opensearch_date_range")
->setPropertyPath('field_event_instance')
);
$fieldsHelper = $this->prophesize(FieldsHelper::class);
$fieldsHelper->extractItemValues([$item], [
'entity:node' => [
'field_event_instance:value' => 'start',
'field_event_instance:end_value' => 'end',
],
])->willReturn($extractItemResult);
$dateRange = new DateRange([], 'search_api_opensearch_date_range', []);
$dateRange->setFieldsHelper($fieldsHelper->reveal());
$dateRange->preprocessIndexItems([$item]);
$fieldValues = $item->getField('event_date_range')->getValues();
$this->assertEquals($expectedResult, $fieldValues);
}
/**
* Provides dummy date range data.
*/
public function dateValueDataProvider(): array {
return [
'Single date range' => [
[
[
'start' => [
'2022-07-01T09:30:00',
],
'end' => [
'2022-07-01T13:00:00',
],
],
],
[
[
'gte' => '2022-07-01T09:30:00',
'lte' => '2022-07-01T13:00:00',
],
],
],
'Multiple date ranges' => [
[
[
'start' => [
'2022-07-01T09:30:00',
'2022-08-05T09:30:00',
],
'end' => [
'2022-07-01T13:00:00',
'2022-08-05T13:00:00',
],
],
],
[
[
'gte' => '2022-07-01T09:30:00',
'lte' => '2022-07-01T13:00:00',
],
[
'gte' => '2022-08-05T09:30:00',
'lte' => '2022-08-05T13:00:00',
],
],
],
'No date ranges' => [
[
[
'start' => [],
'end' => [],
],
],
[],
],
];
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment