search icon indicating copy to clipboard operation
search copied to clipboard

Add an interface for each condition factory to allow decorating

Open dkarlovi opened this issue 7 years ago • 3 comments

Description
Adding an interface to the factory allows to more easily decorate it for use cases such as https://github.com/rollerworks/search/issues/249#issuecomment-445166278

dkarlovi avatar Dec 07 '18 09:12 dkarlovi

The alternative would be to expand each factory to support that use case out of the box, maybe also something to think about.

dkarlovi avatar Dec 07 '18 09:12 dkarlovi

@dkarlovi is this Elasticsearch specific? And if so, is it still relevant?

sstok avatar Apr 12 '20 18:04 sstok

It's definitely relevant, since now I have to extend the existing factory instead of implementing the interface.

Currently I have:

<?php

declare(strict_types=1);

namespace App\Infrastructure\RollerworksSearch\Elasticsearch;

use Rollerworks\Component\Search\Elasticsearch\ConditionGenerator;
use Rollerworks\Component\Search\Elasticsearch\ElasticsearchFactory;
use Rollerworks\Component\Search\SearchCondition;

class DynamicElasticsearchFactory extends ElasticsearchFactory
{
    /**
     * @var ElasticsearchFactory
     */
    private $factory;

    /**
     * @var array
     */
    private $mappings = [];

    public function __construct(ElasticsearchFactory $factory)
    {
        $this->factory = $factory;
    }

    public function setMapping(string $name, array $mapping): void
    {
        $this->mappings[$name] = $mapping;
    }

    public function createConditionGenerator(SearchCondition $searchCondition): ConditionGenerator
    {
        $condition = $this->factory->createConditionGenerator($searchCondition);

        $this->applyMappings($condition);

        return $condition;
    }

    public function createCachedConditionGenerator(ConditionGenerator $conditionGenerator, $ttl = 0): ConditionGenerator
    {
        $condition = $this->factory->createCachedConditionGenerator($conditionGenerator, $ttl);

        $this->applyMappings($condition);

        return $condition;
    }

    private function applyMappings(ConditionGenerator $condition): void
    {
        foreach ($this->mappings as $name => $mapping) {
            $condition->registerField($name, $mapping['mapping'], $mapping['conditions']);
        }
    }
}

This allows me to decorate the condition factory with one which allows me to attach mappings before the condition is created (via setMapping).

The ElasticsearchFactory should implement an interface which could then be implemented against. This is probably true for all condition factories.

dkarlovi avatar Apr 13 '20 08:04 dkarlovi