-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #48 from jolicode/feat/transformer-factory-aware
fix(transformer): change the way transformer factory are injected to make it work as soon as automapper is created
- Loading branch information
Showing
17 changed files
with
239 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AutoMapper; | ||
|
||
/** | ||
* Allows to use a AutoMapperRegistry. | ||
* | ||
* @author Joel Wurtz <[email protected]> | ||
* | ||
* @internal | ||
*/ | ||
interface AutoMapperRegistryAwareInterface | ||
{ | ||
public function setAutoMapperRegistry(AutoMapperRegistryInterface $autoMapperRegistry): void; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AutoMapper; | ||
|
||
/** | ||
* Helper when using the AutoMapperRegistryAwareInterface. | ||
* | ||
* @internal | ||
*/ | ||
trait AutoMapperRegistryAwareTrait | ||
{ | ||
protected AutoMapperRegistryInterface $autoMapperRegistry; | ||
|
||
public function setAutoMapperRegistry(AutoMapperRegistryInterface $autoMapperRegistry): void | ||
{ | ||
$this->autoMapperRegistry = $autoMapperRegistry; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,12 +12,9 @@ | |
* | ||
* @author Joel Wurtz <[email protected]> | ||
*/ | ||
final class ArrayTransformerFactory extends AbstractUniqueTypeTransformerFactory implements PrioritizedTransformerFactoryInterface | ||
final class ArrayTransformerFactory extends AbstractUniqueTypeTransformerFactory implements PrioritizedTransformerFactoryInterface, ChainTransformerFactoryAwareInterface | ||
{ | ||
public function __construct( | ||
private readonly ChainTransformerFactory $chainTransformerFactory, | ||
) { | ||
} | ||
use ChainTransformerFactoryAwareTrait; | ||
|
||
protected function createTransformer(Type $sourceType, Type $targetType, MapperMetadataInterface $mapperMetadata): ?TransformerInterface | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,43 +4,107 @@ | |
|
||
namespace AutoMapper\Transformer; | ||
|
||
use AutoMapper\AutoMapperRegistryAwareInterface; | ||
use AutoMapper\AutoMapperRegistryInterface; | ||
use AutoMapper\MapperMetadataInterface; | ||
|
||
/** | ||
* @author Joel Wurtz <[email protected]> | ||
*/ | ||
final class ChainTransformerFactory implements TransformerPropertyFactoryInterface, TransformerFactoryInterface | ||
final class ChainTransformerFactory implements TransformerPropertyFactoryInterface, TransformerFactoryInterface, AutoMapperRegistryAwareInterface | ||
{ | ||
/** @var array<int, list<TransformerFactoryInterface|TransformerPropertyFactoryInterface>> */ | ||
private array $factories = []; | ||
protected ?AutoMapperRegistryInterface $autoMapperRegistry = null; | ||
|
||
/** @var list<TransformerFactoryInterface|TransformerPropertyFactoryInterface>|null */ | ||
private ?array $sorted = null; | ||
/** | ||
* @param array<TransformerFactoryInterface|TransformerPropertyFactoryInterface> $factories | ||
*/ | ||
public function __construct(private array $factories = []) | ||
{ | ||
foreach ($this->factories as $factory) { | ||
if ($factory instanceof ChainTransformerFactoryAwareInterface) { | ||
$factory->setChainTransformerFactory($this); | ||
} | ||
} | ||
|
||
$this->sortFactories(); | ||
} | ||
|
||
public function setAutoMapperRegistry(AutoMapperRegistryInterface $autoMapperRegistry): void | ||
{ | ||
$this->autoMapperRegistry = $autoMapperRegistry; | ||
|
||
foreach ($this->factories as $factory) { | ||
if ($factory instanceof AutoMapperRegistryAwareInterface) { | ||
$factory->setAutoMapperRegistry($autoMapperRegistry); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Biggest priority is MultipleTransformerFactory with 128, so default priority will be bigger in order to | ||
* be used before it, 256 should be enough. | ||
* | ||
* @deprecated since 8.2, will be removed in 9.0. Pass the factory into the constructor instead | ||
*/ | ||
public function addTransformerFactory(TransformerFactoryInterface|TransformerPropertyFactoryInterface $transformerFactory, int $priority = 256): void | ||
{ | ||
$this->sorted = null; | ||
trigger_deprecation('jolicode/automapper', '8.2', 'The "%s()" method will be removed in version 9.0, transformer must be injected in the constructor instead.', __METHOD__); | ||
|
||
if ($transformerFactory instanceof AutoMapperRegistryAwareInterface && null !== $this->autoMapperRegistry) { | ||
$transformerFactory->setAutoMapperRegistry($this->autoMapperRegistry); | ||
} | ||
|
||
if ($transformerFactory instanceof PrioritizedTransformerFactoryInterface) { | ||
$priority = $transformerFactory->getPriority(); | ||
if ($transformerFactory instanceof ChainTransformerFactoryAwareInterface) { | ||
$transformerFactory->setChainTransformerFactory($this); | ||
} | ||
|
||
if (!\array_key_exists($priority, $this->factories)) { | ||
$this->factories[$priority] = []; | ||
if (!$transformerFactory instanceof PrioritizedTransformerFactoryInterface) { | ||
/** @var TransformerFactoryInterface|TransformerPropertyFactoryInterface $transformerFactory */ | ||
$transformerFactory = new class($transformerFactory, $priority) implements TransformerFactoryInterface, TransformerPropertyFactoryInterface, PrioritizedTransformerFactoryInterface { | ||
public function __construct(private readonly TransformerFactoryInterface|TransformerPropertyFactoryInterface $transformerFactory, private readonly int $priority) | ||
{ | ||
} | ||
|
||
public function getTransformer(?array $sourceTypes, ?array $targetTypes, MapperMetadataInterface $mapperMetadata): ?TransformerInterface | ||
{ | ||
if ($this->transformerFactory instanceof TransformerFactoryInterface) { | ||
return $this->transformerFactory->getTransformer($sourceTypes, $targetTypes, $mapperMetadata); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
public function getPropertyTransformer(?array $sourceTypes, ?array $targetTypes, MapperMetadataInterface $mapperMetadata, string $property): ?TransformerInterface | ||
{ | ||
if ($this->transformerFactory instanceof TransformerPropertyFactoryInterface) { | ||
return $this->transformerFactory->getPropertyTransformer($sourceTypes, $targetTypes, $mapperMetadata, $property); | ||
} | ||
|
||
return $this->transformerFactory->getTransformer($sourceTypes, $targetTypes, $mapperMetadata); | ||
} | ||
|
||
public function getPriority(): int | ||
{ | ||
return $this->priority; | ||
} | ||
}; | ||
} | ||
$this->factories[$priority][] = $transformerFactory; | ||
|
||
$this->factories[] = $transformerFactory; | ||
$this->sortFactories(); | ||
} | ||
|
||
/** | ||
* @deprecated since 8.2, will be removed in 9.0. | ||
*/ | ||
public function hasTransformerFactory(TransformerFactoryInterface $transformerFactory): bool | ||
{ | ||
trigger_deprecation('jolicode/automapper', '8.2', 'The "%s()" method will be removed in version 9.0, transformer must be injected in the constructor instead.', __METHOD__); | ||
|
||
$this->sortFactories(); | ||
|
||
$transformerFactoryClass = $transformerFactory::class; | ||
foreach ($this->sorted ?? [] as $factory) { | ||
foreach ($this->factories as $factory) { | ||
if (is_a($factory, $transformerFactoryClass)) { | ||
return true; | ||
} | ||
|
@@ -51,9 +115,7 @@ public function hasTransformerFactory(TransformerFactoryInterface $transformerFa | |
|
||
public function getPropertyTransformer(?array $sourceTypes, ?array $targetTypes, MapperMetadataInterface $mapperMetadata, string $property): ?TransformerInterface | ||
{ | ||
$this->sortFactories(); | ||
|
||
foreach ($this->sorted ?? [] as $factory) { | ||
foreach ($this->factories as $factory) { | ||
if ($factory instanceof TransformerPropertyFactoryInterface) { | ||
$transformer = $factory->getPropertyTransformer($sourceTypes, $targetTypes, $mapperMetadata, $property); | ||
} else { | ||
|
@@ -70,17 +132,13 @@ public function getPropertyTransformer(?array $sourceTypes, ?array $targetTypes, | |
|
||
public function getTransformer(?array $sourceTypes, ?array $targetTypes, MapperMetadataInterface $mapperMetadata): ?TransformerInterface | ||
{ | ||
$this->sortFactories(); | ||
|
||
foreach ($this->sorted ?? [] as $factory) { | ||
$transformer = null; | ||
|
||
foreach ($this->factories as $factory) { | ||
if ($factory instanceof TransformerFactoryInterface) { | ||
$transformer = $factory->getTransformer($sourceTypes, $targetTypes, $mapperMetadata); | ||
} | ||
|
||
if (null !== $transformer) { | ||
return $transformer; | ||
if (null !== $transformer) { | ||
return $transformer; | ||
} | ||
} | ||
} | ||
|
||
|
@@ -89,15 +147,11 @@ public function getTransformer(?array $sourceTypes, ?array $targetTypes, MapperM | |
|
||
private function sortFactories(): void | ||
{ | ||
if (null === $this->sorted) { | ||
$this->sorted = []; | ||
krsort($this->factories); | ||
usort($this->factories, static function (TransformerPropertyFactoryInterface|TransformerFactoryInterface $a, TransformerPropertyFactoryInterface|TransformerFactoryInterface $b) { | ||
$aPriority = $a instanceof PrioritizedTransformerFactoryInterface ? $a->getPriority() : 256; | ||
$bPriority = $b instanceof PrioritizedTransformerFactoryInterface ? $b->getPriority() : 256; | ||
|
||
foreach ($this->factories as $prioritisedFactories) { | ||
foreach ($prioritisedFactories as $factory) { | ||
$this->sorted[] = $factory; | ||
} | ||
} | ||
} | ||
return $bPriority <=> $aPriority; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AutoMapper\Transformer; | ||
|
||
/** | ||
* Allows to use a chain transformer factory. | ||
* | ||
* @author Joel Wurtz <[email protected]> | ||
*/ | ||
interface ChainTransformerFactoryAwareInterface | ||
{ | ||
public function setChainTransformerFactory(ChainTransformerFactory $chainTransformerFactory): void; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AutoMapper\Transformer; | ||
|
||
trait ChainTransformerFactoryAwareTrait | ||
{ | ||
protected ChainTransformerFactory $chainTransformerFactory; | ||
|
||
public function setChainTransformerFactory(ChainTransformerFactory $chainTransformerFactory): void | ||
{ | ||
$this->chainTransformerFactory = $chainTransformerFactory; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,12 +9,9 @@ | |
/** | ||
* @author Joel Wurtz <[email protected]> | ||
*/ | ||
final readonly class MultipleTransformerFactory implements TransformerFactoryInterface, PrioritizedTransformerFactoryInterface | ||
final class MultipleTransformerFactory implements TransformerFactoryInterface, PrioritizedTransformerFactoryInterface, ChainTransformerFactoryAwareInterface | ||
{ | ||
public function __construct( | ||
private ChainTransformerFactory $chainTransformerFactory, | ||
) { | ||
} | ||
use ChainTransformerFactoryAwareTrait; | ||
|
||
public function getTransformer(?array $sourceTypes, ?array $targetTypes, MapperMetadataInterface $mapperMetadata): ?TransformerInterface | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,12 +10,9 @@ | |
/** | ||
* @author Joel Wurtz <[email protected]> | ||
*/ | ||
final readonly class NullableTransformerFactory implements TransformerFactoryInterface, PrioritizedTransformerFactoryInterface | ||
final class NullableTransformerFactory implements TransformerFactoryInterface, PrioritizedTransformerFactoryInterface, ChainTransformerFactoryAwareInterface | ||
{ | ||
public function __construct( | ||
private ChainTransformerFactory $chainTransformerFactory, | ||
) { | ||
} | ||
use ChainTransformerFactoryAwareTrait; | ||
|
||
public function getTransformer(?array $sourceTypes, ?array $targetTypes, MapperMetadataInterface $mapperMetadata): ?TransformerInterface | ||
{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,19 +4,17 @@ | |
|
||
namespace AutoMapper\Transformer; | ||
|
||
use AutoMapper\AutoMapperRegistryInterface; | ||
use AutoMapper\AutoMapperRegistryAwareInterface; | ||
use AutoMapper\AutoMapperRegistryAwareTrait; | ||
use AutoMapper\MapperMetadataInterface; | ||
use Symfony\Component\PropertyInfo\Type; | ||
|
||
/** | ||
* @author Joel Wurtz <[email protected]> | ||
*/ | ||
final class ObjectTransformerFactory extends AbstractUniqueTypeTransformerFactory implements PrioritizedTransformerFactoryInterface | ||
final class ObjectTransformerFactory extends AbstractUniqueTypeTransformerFactory implements PrioritizedTransformerFactoryInterface, AutoMapperRegistryAwareInterface | ||
{ | ||
public function __construct( | ||
private readonly AutoMapperRegistryInterface $autoMapper, | ||
) { | ||
} | ||
use AutoMapperRegistryAwareTrait; | ||
|
||
protected function createTransformer(Type $sourceType, Type $targetType, MapperMetadataInterface $mapperMetadata): ?TransformerInterface | ||
{ | ||
|
@@ -36,7 +34,7 @@ protected function createTransformer(Type $sourceType, Type $targetType, MapperM | |
$targetTypeName = $targetType->getClassName(); | ||
} | ||
|
||
if (null !== $sourceTypeName && null !== $targetTypeName && $this->autoMapper->hasMapper($sourceTypeName, $targetTypeName)) { | ||
if (null !== $sourceTypeName && null !== $targetTypeName && $this->autoMapperRegistry->hasMapper($sourceTypeName, $targetTypeName)) { | ||
return new ObjectTransformer($sourceType, $targetType); | ||
} | ||
|
||
|
Oops, something went wrong.