Skip to content

Commit

Permalink
refactor: Move transformer query logic to TransformerRegistry.
Browse files Browse the repository at this point in the history
  • Loading branch information
priyadi committed Jan 13, 2024
1 parent 1ac9fe9 commit bdf1494
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 68 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
18 changes: 14 additions & 4 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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');
Expand Down
13 changes: 7 additions & 6 deletions src/Command/TryCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -29,7 +29,7 @@
class TryCommand extends Command
{
public function __construct(
private MainTransformer $mainTransformer,
private TransformerRegistryInterface $transformerRegistry,
private TypeResolverInterface $typeResolver
) {
parent::__construct();
Expand Down Expand Up @@ -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[] = [
Expand Down
65 changes: 11 additions & 54 deletions src/MainTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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,
Expand All @@ -142,38 +133,4 @@ public function transform(

throw new UnableToFindSuitableTransformerException($sourceType, $targetType);
}

/**
* @param Type|MixedType $sourceType
* @param Type|MixedType $targetType
* @return iterable<int,TransformerInterface>
*/
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<int,MappingEntry>
*/
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);
}
}
23 changes: 19 additions & 4 deletions src/MapperFactory/MapperFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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(),
);
}

Expand Down Expand Up @@ -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
//
Expand All @@ -497,7 +512,7 @@ protected function getTryCommand(): TryCommand
{
if (null === $this->tryCommand) {
$this->tryCommand = new TryCommand(
$this->getMainTransformer(),
$this->getTransformerRegistry(),
$this->getTypeResolver()
);
}
Expand Down
87 changes: 87 additions & 0 deletions src/TransformerRegistry/TransformerRegistry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/mapper package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* 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);
}
}
54 changes: 54 additions & 0 deletions src/TransformerRegistry/TransformerRegistryInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/mapper package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* 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<int,Type|MixedType> $sourceTypes
// * @param iterable<int,Type|MixedType> $targetTypes
// * @return iterable<int,TransformerInterface>
// */
// public function findBySourceAndTargetTypes(
// iterable $sourceTypes,
// iterable $targetTypes,
// ): iterable;

/**
* @param Type|MixedType $sourceType
* @param Type|MixedType $targetType
* @return iterable<int,TransformerInterface>
*/
public function findBySourceAndTargetType(
Type|MixedType $sourceType,
Type|MixedType $targetType,
): iterable;

/**
* @param Type|MixedType $sourceType
* @param Type|MixedType $targetType
* @return array<int,MappingEntry>
*/
public function getMappingBySourceAndTargetType(
Type|MixedType $sourceType,
Type|MixedType $targetType,
): array;
}

0 comments on commit bdf1494

Please sign in to comment.