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
Loading
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
<?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 {

}
+55 −0
Original line number Diff line number Diff line
<?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);
          }
        }
      }
    }
  }

}
+4 −0
Original line number Diff line number Diff line
@@ -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'],
+13 −0
Original line number Diff line number Diff line
@@ -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']);
  }

}
+128 −0
Original line number Diff line number Diff line
<?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' => [],
          ],
        ],
        [],
      ],
    ];
  }

}