Commit eb265cd9 authored by Eduard Reñé Claramunt's avatar Eduard Reñé Claramunt Committed by Thomas Seidl
Browse files

Issue #2855447 by edurenye, drunken monkey, alexdoma: Added option to...

Issue #2855447 by edurenye, drunken monkey, alexdoma: Added option to customize the separator used for aggregated fields of type "Fulltext".
parent 0273daf0
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
Search API 1.x, dev (xxxx-xx-xx):
---------------------------------
- #2855447 by edurenye, drunken monkey, alexdoma: Added option to customize the
  separator used for aggregated fields of type "Fulltext".
- #3304560 by recrit, Gertlor, drunken monkey: Fixed problems with "Multiple
  terms" parse mode and invalid UTF-8 strings.
- #3327383 by unstatu, drunken monkey: Fixed handling of the "view any
+3 −0
Original line number Diff line number Diff line
@@ -231,6 +231,9 @@ search_api.property_configuration.aggregated_field:
    type:
      type: string
      label: 'The type of the aggregation'
    separator:
      type: string
      label: 'The separator used if the "Concatenation" type is selected'
    fields:
      type: sequence
      label: 'The properties to be aggregated'
+2 −1
Original line number Diff line number Diff line
@@ -79,7 +79,8 @@ class AggregatedFields extends ProcessorPluginBase {

      switch ($configuration['type']) {
        case 'concat':
          $values = [implode("\n\n", $values)];
          $separator = $configuration['separator'] ?? "\n\n";
          $values = [implode($separator, $values)];
          break;

        case 'sum':
+17 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ class AggregatedFieldProperty extends ConfigurablePropertyBase {
  public function defaultConfiguration() {
    return [
      'type' => 'union',
      'separator' => "\n\n",
      'fields' => [],
    ];
  }
@@ -34,7 +35,7 @@ class AggregatedFieldProperty extends ConfigurablePropertyBase {
   */
  public function buildConfigurationForm(FieldInterface $field, array $form, FormStateInterface $form_state) {
    $index = $field->getIndex();
    $configuration = $field->getConfiguration();
    $configuration = $field->getConfiguration() + $this->defaultConfiguration();

    $form['#attached']['library'][] = 'search_api/drupal.search_api.admin_css';
    $form['#tree'] = TRUE;
@@ -52,6 +53,20 @@ class AggregatedFieldProperty extends ConfigurablePropertyBase {
      $form['type'][$type]['#description'] = $description;
    }

    $form['separator'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Value separator'),
      '#description' => $this->t('The text to insert between multiple values when aggregating them with the "@type" aggregation type. Can contain escape sequences like "\n" for a newline or "\t" for a horizontal tab.', ['@type' => $this->t('Concatenation')]),
      '#size' => 30,
      '#maxlength' => 64,
      '#default_value' => addcslashes($configuration['separator'], "\0..\37\\"),
      '#states' => [
        'visible' => [
          'input[name="type"]' => ['value' => 'concat'],
        ],
      ],
    ];

    $form['fields'] = [
      '#type' => 'checkboxes',
      '#title' => $this->t('Contained fields'),
@@ -114,6 +129,7 @@ class AggregatedFieldProperty extends ConfigurablePropertyBase {
  public function submitConfigurationForm(FieldInterface $field, array &$form, FormStateInterface $form_state) {
    $values = [
      'type' => $form_state->getValue('type'),
      'separator' => stripcslashes($form_state->getValue('separator')),
      'fields' => array_keys(array_filter($form_state->getValue('fields'))),
    ];
    $field->setConfiguration($values);
+36 −5
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@

namespace Drupal\Tests\search_api\Unit\Processor;

use Drupal\Core\Form\FormState;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\TypedData\ComplexDataInterface;
use Drupal\Core\TypedData\DataDefinition;
use Drupal\Core\TypedData\TypedDataInterface;
@@ -10,6 +12,7 @@ use Drupal\search_api\DataType\DataTypeInterface;
use Drupal\search_api\Entity\Index;
use Drupal\search_api\IndexInterface;
use Drupal\search_api\Item\Field;
use Drupal\search_api\Item\FieldInterface;
use Drupal\search_api\Item\ItemInterface;
use Drupal\search_api\Plugin\search_api\processor\AggregatedFields;
use Drupal\search_api\Plugin\search_api\processor\Property\AggregatedFieldProperty;
@@ -142,10 +145,12 @@ class AggregatedFieldsTest extends UnitTestCase {
   * @param bool $integer
   *   (optional) TRUE if the items' normal fields should contain integers,
   *   FALSE otherwise.
   * @param array $additional_config
   *   (optional) Additional configuration to set on the field.
   *
   * @dataProvider aggregationTestsDataProvider
   */
  public function testAggregation($type, array $expected, $integer = FALSE) {
  public function testAggregation(string $type, array $expected, bool $integer = FALSE, array $additional_config = []): void {
    // Add the field configuration.
    $configuration = [
      'type' => $type,
@@ -156,6 +161,7 @@ class AggregatedFieldsTest extends UnitTestCase {
        'entity:test3/always_empty',
      ],
    ];
    $configuration += $additional_config;
    $this->index->getField($this->fieldId)->setConfiguration($configuration);

    if ($integer) {
@@ -229,6 +235,18 @@ class AggregatedFieldsTest extends UnitTestCase {
          [''],
        ],
      ],
      '"Concatenation" aggregation with different separator' => [
        'concat',
        [
          ['foo bar baz'],
          ['foobar'],
          [''],
        ],
        FALSE,
        [
          'separator' => ' ',
        ],
      ],
      '"Sum" aggregation' => [
        'sum',
        [
@@ -306,13 +324,26 @@ class AggregatedFieldsTest extends UnitTestCase {
    $properties = $this->processor->getPropertyDefinitions(NULL);

    $this->assertArrayHasKey('aggregated_field', $properties, 'The "aggregated_field" property was added to the properties.');
    $this->assertInstanceOf(AggregatedFieldProperty::class, $properties['aggregated_field'], 'The "aggregated_field" property has the correct class.');
    $this->assertEquals('string', $properties['aggregated_field']->getDataType(), 'Correct data type set in the data definition.');
    $this->assertEquals($translation->translate('Aggregated field'), $properties['aggregated_field']->getLabel(), 'Correct label set in the data definition.');
    $property = $properties['aggregated_field'];
    $this->assertInstanceOf(AggregatedFieldProperty::class, $property, 'The "aggregated_field" property has the correct class.');
    $this->assertEquals('string', $property->getDataType(), 'Correct data type set in the data definition.');
    $this->assertEquals($translation->translate('Aggregated field'), $property->getLabel(), 'Correct label set in the data definition.');
    $expected_description = $translation->translate('An aggregation of multiple other fields.');
    $this->assertEquals($expected_description, $properties['aggregated_field']->getDescription(), 'Correct description set in the data definition.');
    $this->assertEquals($expected_description, $property->getDescription(), 'Correct description set in the data definition.');
    $this->assertTrue($properties['aggregated_field']->isList());

    // Verify that the property configuration form works correctly.
    $property->setStringTranslation($this->createMock(TranslationInterface::class));
    $field = $this->createMock(FieldInterface::class);
    $field->method('getIndex')->willReturn($this->processor->getIndex());
    $field->method('getConfiguration')->willReturn([
      'type' => 'concat',
      'separator' => "\n\t \\XX",
      'fields' => [],
    ]);
    $form = $property->buildConfigurationForm($field, [], new FormState());
    $this->assertEquals("\\n\\t \\\\XX", $form['separator']['#default_value']);

    // Verify that there are no properties if a datasource is given.
    $datasource = $this->createMock(DatasourceInterface::class);
    $properties = $this->processor->getPropertyDefinitions($datasource);