From bdf1494ad6abd7a28ae1d7005ff732d6fa56bce2 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Sat, 13 Jan 2024 10:35:46 +0700 Subject: [PATCH] refactor: Move transformer query logic to `TransformerRegistry`. --- CHANGELOG.md | 1 + config/services.php | 18 +++- src/Command/TryCommand.php | 13 +-- src/MainTransformer.php | 65 +++----------- src/MapperFactory/MapperFactory.php | 23 ++++- .../TransformerRegistry.php | 87 +++++++++++++++++++ .../TransformerRegistryInterface.php | 54 ++++++++++++ 7 files changed, 193 insertions(+), 68 deletions(-) create mode 100644 src/TransformerRegistry/TransformerRegistry.php create mode 100644 src/TransformerRegistry/TransformerRegistryInterface.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 6324a8c..f906ee7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * docs: Add link to documentation website. * refactor: Consolidate boilerplate code for getting the `ObjectCache`. +* refactor: Move transformer query logic to `TransformerRegistry`. ## 0.5.4 diff --git a/config/services.php b/config/services.php index e5d4c60..892ec84 100644 --- a/config/services.php +++ b/config/services.php @@ -33,6 +33,7 @@ use Rekalogika\Mapper\Transformer\StringToBackedEnumTransformer; use Rekalogika\Mapper\Transformer\TraversableToArrayAccessTransformer; use Rekalogika\Mapper\Transformer\TraversableToTraversableTransformer; +use Rekalogika\Mapper\TransformerRegistry\TransformerRegistry; use Rekalogika\Mapper\TypeResolver\CachingTypeResolver; use Rekalogika\Mapper\TypeResolver\TypeResolver; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; @@ -186,6 +187,16 @@ service('rekalogika.mapper.type_resolver.caching.inner'), ]); + # transformer registry + + $services + ->set('rekalogika.mapper.transformer_registry', TransformerRegistry::class) + ->args([ + '$transformersLocator' => tagged_locator('rekalogika.mapper.transformer'), + '$typeResolver' => service('rekalogika.mapper.type_resolver'), + '$mappingFactory' => service('rekalogika.mapper.mapping_factory'), + ]); + # method mapper $services @@ -203,10 +214,9 @@ $services ->set('rekalogika.mapper.main_transformer', MainTransformer::class) ->args([ - '$transformersLocator' => tagged_locator('rekalogika.mapper.transformer'), - '$typeResolver' => service('rekalogika.mapper.type_resolver'), - '$mappingFactory' => service('rekalogika.mapper.mapping_factory'), '$objectCacheFactory' => service('rekalogika.mapper.object_cache_factory'), + '$typeResolver' => service('rekalogika.mapper.type_resolver'), + '$transformerRegistry' => service('rekalogika.mapper.transformer_registry'), ]); $services @@ -226,7 +236,7 @@ $services ->set('rekalogika.mapper.command.try', TryCommand::class) ->args([ - service('rekalogika.mapper.main_transformer'), + service('rekalogika.mapper.transformer_registry'), service('rekalogika.mapper.type_resolver'), ]) ->tag('console.command'); diff --git a/src/Command/TryCommand.php b/src/Command/TryCommand.php index 3872b3e..8a152d5 100644 --- a/src/Command/TryCommand.php +++ b/src/Command/TryCommand.php @@ -13,7 +13,7 @@ namespace Rekalogika\Mapper\Command; -use Rekalogika\Mapper\MainTransformer; +use Rekalogika\Mapper\TransformerRegistry\TransformerRegistryInterface; use Rekalogika\Mapper\TypeResolver\TypeResolverInterface; use Rekalogika\Mapper\Util\TypeFactory; use Symfony\Component\Console\Attribute\AsCommand; @@ -29,7 +29,7 @@ class TryCommand extends Command { public function __construct( - private MainTransformer $mainTransformer, + private TransformerRegistryInterface $transformerRegistry, private TypeResolverInterface $typeResolver ) { parent::__construct(); @@ -100,10 +100,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int $rows = []; - $transformers = $this->mainTransformer->getTransformerMapping( - $sourceType, - $targetType - ); + $transformers = $this->transformerRegistry + ->getMappingBySourceAndTargetType( + $sourceType, + $targetType + ); foreach ($transformers as $entry) { $rows[] = [ diff --git a/src/MainTransformer.php b/src/MainTransformer.php index 56c41fe..b0ec284 100644 --- a/src/MainTransformer.php +++ b/src/MainTransformer.php @@ -13,47 +13,35 @@ namespace Rekalogika\Mapper; -use Psr\Container\ContainerInterface; use Rekalogika\Mapper\Contracts\MainTransformerAwareInterface; use Rekalogika\Mapper\Contracts\MainTransformerInterface; use Rekalogika\Mapper\Contracts\MixedType; use Rekalogika\Mapper\Contracts\TransformerInterface; use Rekalogika\Mapper\Exception\LogicException; use Rekalogika\Mapper\Exception\UnableToFindSuitableTransformerException; -use Rekalogika\Mapper\Mapping\MappingEntry; -use Rekalogika\Mapper\Mapping\MappingFactoryInterface; use Rekalogika\Mapper\ObjectCache\ObjectCache; use Rekalogika\Mapper\ObjectCache\ObjectCacheFactoryInterface; +use Rekalogika\Mapper\TransformerRegistry\TransformerRegistryInterface; use Rekalogika\Mapper\TypeResolver\TypeResolverInterface; -use Symfony\Component\PropertyInfo\Type; class MainTransformer implements MainTransformerInterface { public const OBJECT_CACHE = 'object_cache'; public function __construct( - private ContainerInterface $transformersLocator, - private TypeResolverInterface $typeResolver, - private MappingFactoryInterface $mappingFactory, private ObjectCacheFactoryInterface $objectCacheFactory, + private TransformerRegistryInterface $transformerRegistry, + private TypeResolverInterface $typeResolver, ) { } - private function getTransformer(string $id): TransformerInterface - { - $transformer = $this->transformersLocator->get($id); - - if (!$transformer instanceof TransformerInterface) { - throw new LogicException(sprintf( - 'Transformer with id "%s" must implement %s', - $id, - TransformerInterface::class - )); - } - + private function processTransformer( + TransformerInterface $transformer + ): TransformerInterface { if ($transformer instanceof MainTransformerAwareInterface) { return $transformer->withMainTransformer($this); } + return $transformer; } @@ -124,9 +112,12 @@ public function transform( // iterate simple target types and find the suitable transformer foreach ($simpleTargetTypes as $singleTargetType) { - $transformers = $this->getTransformers($sourceType, $singleTargetType); + $transformers = $this->transformerRegistry + ->findBySourceAndTargetType($sourceType, $singleTargetType); foreach ($transformers as $transformer) { + $transformer = $this->processTransformer($transformer); + /** @var mixed */ $result = $transformer->transform( source: $source, @@ -142,38 +133,4 @@ public function transform( throw new UnableToFindSuitableTransformerException($sourceType, $targetType); } - - /** - * @param Type|MixedType $sourceType - * @param Type|MixedType $targetType - * @return iterable - */ - private function getTransformers( - Type|MixedType $sourceType, - Type|MixedType $targetType, - ): iterable { - foreach ($this->getTransformerMapping($sourceType, $targetType) as $item) { - $id = $item->getId(); - yield $this->getTransformer($id); - } - } - - /** - * @param Type|MixedType $sourceType - * @param Type|MixedType $targetType - * @return array - */ - public function getTransformerMapping( - Type|MixedType $sourceType, - Type|MixedType $targetType, - ): array { - $sourceTypeStrings = $this->typeResolver - ->getApplicableTypeStrings($sourceType); - - $targetTypeStrings = $this->typeResolver - ->getApplicableTypeStrings($targetType); - - return $this->mappingFactory->getMapping() - ->getMappingBySourceAndTarget($sourceTypeStrings, $targetTypeStrings); - } } diff --git a/src/MapperFactory/MapperFactory.php b/src/MapperFactory/MapperFactory.php index af94aa3..926d799 100644 --- a/src/MapperFactory/MapperFactory.php +++ b/src/MapperFactory/MapperFactory.php @@ -38,6 +38,8 @@ use Rekalogika\Mapper\Transformer\StringToBackedEnumTransformer; use Rekalogika\Mapper\Transformer\TraversableToArrayAccessTransformer; use Rekalogika\Mapper\Transformer\TraversableToTraversableTransformer; +use Rekalogika\Mapper\TransformerRegistry\TransformerRegistry; +use Rekalogika\Mapper\TransformerRegistry\TransformerRegistryInterface; use Rekalogika\Mapper\TypeResolver\CachingTypeResolver; use Rekalogika\Mapper\TypeResolver\TypeResolver; use Rekalogika\Mapper\TypeResolver\TypeResolverInterface; @@ -94,6 +96,7 @@ class MapperFactory private ?MappingFactoryInterface $mappingFactory = null; private ?ObjectCacheFactoryInterface $objectCacheFactory = null; private ?SubMapper $subMapper = null; + private ?TransformerRegistryInterface $transformerRegistry = null; private ?MappingCommand $mappingCommand = null; private ?TryCommand $tryCommand = null; @@ -436,10 +439,9 @@ protected function getMainTransformer(): MainTransformer { if (null === $this->mainTransformer) { $this->mainTransformer = new MainTransformer( - $this->getTransformersLocator(), - $this->getTypeResolver(), - $this->getMappingFactory(), $this->getObjectCacheFactory(), + $this->getTransformerRegistry(), + $this->getTypeResolver(), ); } @@ -478,6 +480,19 @@ protected function getSubMapper(): SubMapper return $this->subMapper; } + protected function getTransformerRegistry(): TransformerRegistryInterface + { + if (null === $this->transformerRegistry) { + $this->transformerRegistry = new TransformerRegistry( + $this->getTransformersLocator(), + $this->getTypeResolver(), + $this->getMappingFactory(), + ); + } + + return $this->transformerRegistry; + } + // // command // @@ -497,7 +512,7 @@ protected function getTryCommand(): TryCommand { if (null === $this->tryCommand) { $this->tryCommand = new TryCommand( - $this->getMainTransformer(), + $this->getTransformerRegistry(), $this->getTypeResolver() ); } diff --git a/src/TransformerRegistry/TransformerRegistry.php b/src/TransformerRegistry/TransformerRegistry.php new file mode 100644 index 0000000..a038694 --- /dev/null +++ b/src/TransformerRegistry/TransformerRegistry.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper\TransformerRegistry; + +use Psr\Container\ContainerInterface; +use Rekalogika\Mapper\Contracts\MixedType; +use Rekalogika\Mapper\Contracts\TransformerInterface; +use Rekalogika\Mapper\Exception\LogicException; +use Rekalogika\Mapper\Mapping\MappingFactoryInterface; +use Rekalogika\Mapper\TypeResolver\TypeResolverInterface; +use Symfony\Component\PropertyInfo\Type; + +class TransformerRegistry implements TransformerRegistryInterface +{ + public function __construct( + private ContainerInterface $transformersLocator, + private TypeResolverInterface $typeResolver, + private MappingFactoryInterface $mappingFactory, + ) { + } + + public function get(string $id): TransformerInterface + { + $transformer = $this->transformersLocator->get($id); + + if (!$transformer instanceof TransformerInterface) { + throw new LogicException(sprintf( + 'Transformer with id "%s" must implement %s', + $id, + TransformerInterface::class + )); + } + + return $transformer; + } + + // public function findBySourceAndTargetTypes( + // iterable $sourceTypes, + // iterable $targetTypes, + // ): iterable { + // foreach ($sourceTypes as $sourceType) { + // foreach ($targetTypes as $targetType) { + // yield from $this->findBySourceAndTargetType( + // $sourceType, + // $targetType + // ); + // } + // } + // } + + public function findBySourceAndTargetType( + Type|MixedType $sourceType, + Type|MixedType $targetType, + ): iterable { + $mapping = $this->getMappingBySourceAndTargetType($sourceType, $targetType); + + foreach ($mapping as $item) { + $id = $item->getId(); + yield $this->get($id); + } + } + + public function getMappingBySourceAndTargetType( + Type|MixedType $sourceType, + Type|MixedType $targetType, + ): array { + $sourceTypeStrings = $this->typeResolver + ->getApplicableTypeStrings($sourceType); + + $targetTypeStrings = $this->typeResolver + ->getApplicableTypeStrings($targetType); + + return $this->mappingFactory->getMapping() + ->getMappingBySourceAndTarget($sourceTypeStrings, $targetTypeStrings); + } +} diff --git a/src/TransformerRegistry/TransformerRegistryInterface.php b/src/TransformerRegistry/TransformerRegistryInterface.php new file mode 100644 index 0000000..dc76798 --- /dev/null +++ b/src/TransformerRegistry/TransformerRegistryInterface.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE file + * that was distributed with this source code. + */ + +namespace Rekalogika\Mapper\TransformerRegistry; + +use Rekalogika\Mapper\Contracts\MixedType; +use Rekalogika\Mapper\Contracts\TransformerInterface; +use Rekalogika\Mapper\Mapping\MappingEntry; +use Symfony\Component\PropertyInfo\Type; + +interface TransformerRegistryInterface +{ + public function get(string $id): TransformerInterface; + + // /** + // * @param iterable $sourceTypes + // * @param iterable $targetTypes + // * @return iterable + // */ + // public function findBySourceAndTargetTypes( + // iterable $sourceTypes, + // iterable $targetTypes, + // ): iterable; + + /** + * @param Type|MixedType $sourceType + * @param Type|MixedType $targetType + * @return iterable + */ + public function findBySourceAndTargetType( + Type|MixedType $sourceType, + Type|MixedType $targetType, + ): iterable; + + /** + * @param Type|MixedType $sourceType + * @param Type|MixedType $targetType + * @return array + */ + public function getMappingBySourceAndTargetType( + Type|MixedType $sourceType, + Type|MixedType $targetType, + ): array; +}