Skip to content

Commit

Permalink
feat(transformer): use directly the custom transformer instead of ext…
Browse files Browse the repository at this point in the history
…racting it as a callback
  • Loading branch information
joelwurtz committed Mar 11, 2024
1 parent 166385c commit d89263d
Show file tree
Hide file tree
Showing 50 changed files with 448 additions and 226 deletions.
27 changes: 14 additions & 13 deletions src/AutoMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
namespace AutoMapper;

use AutoMapper\Exception\NoMappingFoundException;
use AutoMapper\Extractor\ClassMethodToCallbackExtractor;
use AutoMapper\Extractor\CustomTransformerExtractor;
use AutoMapper\Extractor\FromSourceMappingExtractor;
use AutoMapper\Extractor\FromTargetMappingExtractor;
use AutoMapper\Extractor\MapToContextPropertyInfoExtractorDecorator;
Expand All @@ -18,6 +16,7 @@
use AutoMapper\Transformer\ArrayTransformerFactory;
use AutoMapper\Transformer\BuiltinTransformerFactory;
use AutoMapper\Transformer\ChainTransformerFactory;
use AutoMapper\Transformer\CustomTransformer\CustomTransformerFactory;
use AutoMapper\Transformer\CustomTransformer\CustomTransformerInterface;
use AutoMapper\Transformer\CustomTransformer\CustomTransformersRegistry;
use AutoMapper\Transformer\DateTimeTransformerFactory;
Expand Down Expand Up @@ -63,7 +62,7 @@ public function __construct(
private readonly ClassLoaderInterface $classLoader,
private readonly ChainTransformerFactory $chainTransformerFactory,
public readonly CustomTransformersRegistry $customTransformersRegistry,
private readonly ?MapperGeneratorMetadataFactoryInterface $mapperConfigurationFactory = null
private readonly ?MapperGeneratorMetadataFactoryInterface $mapperConfigurationFactory = null,
) {
}

Expand All @@ -90,13 +89,18 @@ public function getMapper(string $source, string $target): MapperInterface
$this->classLoader->loadClass($metadata);
}

$this->mapperRegistry[$className] = new $className();
$this->mapperRegistry[$className]->injectMappers($this);
/** @var GeneratedMapper $mapper */
$mapper = new $className();
$this->mapperRegistry[$className] = $mapper;

$mapper->injectMappers($this);

foreach ($metadata->getCallbacks() as $property => $callback) {
$this->mapperRegistry[$className]->addCallback($property, $callback);
$mapper->addCallback($property, $callback);
}

$mapper->setCustomTransformers($this->customTransformersRegistry->getCustomTransformers());

return $this->mapperRegistry[$className];
}

Expand Down Expand Up @@ -152,9 +156,9 @@ public function bindTransformerFactory(TransformerFactoryInterface $transformerF
}
}

public function bindCustomTransformer(CustomTransformerInterface $customTransformer): void
public function bindCustomTransformer(CustomTransformerInterface $customTransformer, ?string $id = null): void
{
$this->customTransformersRegistry->addCustomTransformer($customTransformer);
$this->customTransformersRegistry->addCustomTransformer($customTransformer, $id);
}

public static function create(
Expand All @@ -165,7 +169,7 @@ public static function create(
bool $attributeChecking = true,
bool $autoRegister = true,
string $dateTimeFormat = \DateTimeInterface::RFC3339,
bool $allowReadOnlyTargetToPopulate = false
bool $allowReadOnlyTargetToPopulate = false,
): self {
if (class_exists(AttributeLoader::class)) {
$loaderClass = new AttributeLoader();
Expand All @@ -179,7 +183,6 @@ public static function create(
if (null === $loader) {
$loader = new EvalLoader(
new MapperGenerator(
new CustomTransformerExtractor(new ClassMethodToCallbackExtractor()),
new ClassDiscriminatorResolver(new ClassDiscriminatorFromClassMetadata($classMetadataFactory)),
$allowReadOnlyTargetToPopulate
));
Expand All @@ -205,7 +208,6 @@ public static function create(
new MapToContextPropertyInfoExtractorDecorator($reflectionExtractor),
$reflectionExtractor,
$transformerFactory,
$customTransformerRegistry,
$classMetadataFactory
);

Expand All @@ -214,7 +216,6 @@ public static function create(
$reflectionExtractor,
$reflectionExtractor,
$transformerFactory,
$customTransformerRegistry,
$classMetadataFactory,
$nameConverter
);
Expand All @@ -224,7 +225,6 @@ public static function create(
new MapToContextPropertyInfoExtractorDecorator($reflectionExtractor),
$reflectionExtractor,
$transformerFactory,
$customTransformerRegistry,
$classMetadataFactory,
$nameConverter
);
Expand Down Expand Up @@ -252,6 +252,7 @@ public static function create(
$transformerFactory->addTransformerFactory(new ArrayTransformerFactory($transformerFactory));
$transformerFactory->addTransformerFactory(new ObjectTransformerFactory($autoMapper));
$transformerFactory->addTransformerFactory(new EnumTransformerFactory());
$transformerFactory->addTransformerFactory(new CustomTransformerFactory($customTransformerRegistry));

if (class_exists(AbstractUid::class)) {
$transformerFactory->addTransformerFactory(new SymfonyUidTransformerFactory());
Expand Down
42 changes: 0 additions & 42 deletions src/Extractor/CustomTransformerExtractor.php

This file was deleted.

14 changes: 8 additions & 6 deletions src/Extractor/FromSourceMappingExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

use AutoMapper\Exception\InvalidMappingException;
use AutoMapper\MapperGeneratorMetadataInterface;
use AutoMapper\Transformer\CustomTransformer\CustomTransformersRegistry;
use AutoMapper\Transformer\TransformerFactoryInterface;
use AutoMapper\Transformer\TransformerPropertyFactoryInterface;
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyReadInfo;
use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
Expand All @@ -33,12 +33,11 @@ public function __construct(
PropertyInfoExtractorInterface $propertyInfoExtractor,
PropertyReadInfoExtractorInterface $readInfoExtractor,
PropertyWriteInfoExtractorInterface $writeInfoExtractor,
TransformerFactoryInterface $transformerFactory,
CustomTransformersRegistry $customTransformerRegistry,
TransformerFactoryInterface|TransformerPropertyFactoryInterface $transformerFactory,
ClassMetadataFactoryInterface $classMetadataFactory = null,
private readonly ?AdvancedNameConverterInterface $nameConverter = null,
) {
parent::__construct($propertyInfoExtractor, $readInfoExtractor, $writeInfoExtractor, $transformerFactory, $customTransformerRegistry, $classMetadataFactory);
parent::__construct($propertyInfoExtractor, $readInfoExtractor, $writeInfoExtractor, $transformerFactory, $classMetadataFactory);
}

public function getPropertiesMapping(MapperGeneratorMetadataInterface $mapperMetadata): array
Expand Down Expand Up @@ -77,8 +76,11 @@ public function getPropertiesMapping(MapperGeneratorMetadataInterface $mapperMet
}
}

$transformer = $this->customTransformerRegistry->getCustomTransformerClass($mapperMetadata, $sourceTypes, $targetTypes, $property)
?? $this->transformerFactory->getTransformer($sourceTypes, $targetTypes, $mapperMetadata);
if ($this->transformerFactory instanceof TransformerPropertyFactoryInterface) {
$transformer = $this->transformerFactory->getPropertyTransformer($sourceTypes, $targetTypes, $mapperMetadata, $property);
} else {
$transformer = $this->transformerFactory->getTransformer($sourceTypes, $targetTypes, $mapperMetadata);
}

if (null === $transformer) {
continue;
Expand Down
14 changes: 8 additions & 6 deletions src/Extractor/FromTargetMappingExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

use AutoMapper\Exception\InvalidMappingException;
use AutoMapper\MapperGeneratorMetadataInterface;
use AutoMapper\Transformer\CustomTransformer\CustomTransformersRegistry;
use AutoMapper\Transformer\TransformerFactoryInterface;
use AutoMapper\Transformer\TransformerPropertyFactoryInterface;
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyReadInfo;
use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
Expand All @@ -34,12 +34,11 @@ public function __construct(
PropertyInfoExtractorInterface $propertyInfoExtractor,
PropertyReadInfoExtractorInterface $readInfoExtractor,
PropertyWriteInfoExtractorInterface $writeInfoExtractor,
TransformerFactoryInterface $transformerFactory,
CustomTransformersRegistry $customTransformerRegistry,
TransformerFactoryInterface|TransformerPropertyFactoryInterface $transformerFactory,
ClassMetadataFactoryInterface $classMetadataFactory = null,
private readonly ?AdvancedNameConverterInterface $nameConverter = null,
) {
parent::__construct($propertyInfoExtractor, $readInfoExtractor, $writeInfoExtractor, $transformerFactory, $customTransformerRegistry, $classMetadataFactory);
parent::__construct($propertyInfoExtractor, $readInfoExtractor, $writeInfoExtractor, $transformerFactory, $classMetadataFactory);
}

public function getPropertiesMapping(MapperGeneratorMetadataInterface $mapperMetadata): array
Expand Down Expand Up @@ -72,8 +71,11 @@ public function getPropertiesMapping(MapperGeneratorMetadataInterface $mapperMet
}
}

$transformer = $this->customTransformerRegistry->getCustomTransformerClass($mapperMetadata, $sourceTypes, $targetTypes, $property)
?? $this->transformerFactory->getTransformer($sourceTypes, $targetTypes, $mapperMetadata);
if ($this->transformerFactory instanceof TransformerPropertyFactoryInterface) {
$transformer = $this->transformerFactory->getPropertyTransformer($sourceTypes, $targetTypes, $mapperMetadata, $property);
} else {
$transformer = $this->transformerFactory->getTransformer($sourceTypes, $targetTypes, $mapperMetadata);
}

if (null === $transformer) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
final readonly class MapToContextPropertyInfoExtractorDecorator implements PropertyListExtractorInterface, PropertyTypeExtractorInterface, PropertyAccessExtractorInterface, PropertyInitializableExtractorInterface, PropertyReadInfoExtractorInterface, PropertyWriteInfoExtractorInterface, ConstructorArgumentTypeExtractorInterface
{
public function __construct(
private ReflectionExtractor $decorated
private ReflectionExtractor $decorated,
) {
}

Expand Down
5 changes: 2 additions & 3 deletions src/Extractor/MappingExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

namespace AutoMapper\Extractor;

use AutoMapper\Transformer\CustomTransformer\CustomTransformersRegistry;
use AutoMapper\Transformer\TransformerFactoryInterface;
use AutoMapper\Transformer\TransformerPropertyFactoryInterface;
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
use Symfony\Component\PropertyInfo\PropertyReadInfo;
use Symfony\Component\PropertyInfo\PropertyReadInfoExtractorInterface;
Expand All @@ -25,8 +25,7 @@ public function __construct(
protected readonly PropertyInfoExtractorInterface $propertyInfoExtractor,
protected readonly PropertyReadInfoExtractorInterface $readInfoExtractor,
protected readonly PropertyWriteInfoExtractorInterface $writeInfoExtractor,
protected readonly TransformerFactoryInterface $transformerFactory,
protected readonly CustomTransformersRegistry $customTransformerRegistry,
protected readonly TransformerFactoryInterface|TransformerPropertyFactoryInterface $transformerFactory,
private readonly ?ClassMetadataFactoryInterface $classMetadataFactory = null,
) {
}
Expand Down
14 changes: 1 addition & 13 deletions src/Extractor/PropertyMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace AutoMapper\Extractor;

use AutoMapper\MapperGeneratorMetadataInterface;
use AutoMapper\Transformer\CustomTransformer\CustomTransformerInterface;
use AutoMapper\Transformer\TransformerInterface;

/**
Expand All @@ -22,8 +21,7 @@ public function __construct(
public ?ReadAccessor $readAccessor,
public ?WriteMutator $writeMutator,
public ?WriteMutator $writeMutatorConstructor,
/** @var TransformerInterface|class-string<CustomTransformerInterface> */
public TransformerInterface|string $transformer,
public TransformerInterface $transformer,
public string $property,
public bool $checkExists = false,
public ?array $sourceGroups = null,
Expand All @@ -42,14 +40,4 @@ public function shouldIgnoreProperty(bool $shouldMapPrivateProperties = true): b
|| $this->targetIgnored
|| !($shouldMapPrivateProperties || $this->isPublic);
}

/**
* @phpstan-assert-if-false TransformerInterface $this->transformer
*
* @phpstan-assert-if-true string $this->transformer
*/
public function hasCustomTransformer(): bool
{
return \is_string($this->transformer);
}
}
13 changes: 7 additions & 6 deletions src/Extractor/SourceTargetMappingExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use AutoMapper\MapperGeneratorMetadataInterface;
use AutoMapper\MapperMetadataInterface;
use AutoMapper\Transformer\TransformerPropertyFactoryInterface;
use Symfony\Component\PropertyInfo\PropertyReadInfo;

/**
Expand Down Expand Up @@ -56,15 +57,15 @@ public function getPropertiesMapping(MapperGeneratorMetadataInterface $mapperMet
continue;
}

if ($propertyMapping = $this->toPropertyMapping($mapperMetadata, $property, onlyCustomTransformer: true)) {
if ($propertyMapping = $this->toPropertyMapping($mapperMetadata, $property)) {
$mapping[] = $propertyMapping;
}
}

return $mapping;
}

private function toPropertyMapping(MapperGeneratorMetadataInterface $mapperMetadata, string $property, bool $onlyCustomTransformer = false): ?PropertyMapping
private function toPropertyMapping(MapperGeneratorMetadataInterface $mapperMetadata, string $property): ?PropertyMapping
{
$targetMutatorConstruct = $this->getWriteMutator($mapperMetadata->getSource(), $mapperMetadata->getTarget(), $property, [
'enable_constructor_extraction' => true,
Expand All @@ -77,9 +78,9 @@ private function toPropertyMapping(MapperGeneratorMetadataInterface $mapperMetad
$sourceTypes = $this->propertyInfoExtractor->getTypes($mapperMetadata->getSource(), $property) ?? [];
$targetTypes = $this->propertyInfoExtractor->getTypes($mapperMetadata->getTarget(), $property) ?? [];

$transformer = $this->customTransformerRegistry->getCustomTransformerClass($mapperMetadata, $sourceTypes, $targetTypes, $property);

if (null === $transformer && !$onlyCustomTransformer) {
if ($this->transformerFactory instanceof TransformerPropertyFactoryInterface) {
$transformer = $this->transformerFactory->getPropertyTransformer($sourceTypes, $targetTypes, $mapperMetadata, $property);
} else {
$transformer = $this->transformerFactory->getTransformer($sourceTypes, $targetTypes, $mapperMetadata);
}

Expand Down Expand Up @@ -115,7 +116,7 @@ private function guessMaxDepth(MapperMetadataInterface $mapperMetadata, string $
null !== $maxDepthSource && null !== $maxDepthTarget => min($maxDepthSource, $maxDepthTarget),
null !== $maxDepthSource => $maxDepthSource,
null !== $maxDepthTarget => $maxDepthTarget,
default => null
default => null,
};
}
}
13 changes: 13 additions & 0 deletions src/GeneratedMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace AutoMapper;

use AutoMapper\Transformer\CustomTransformer\CustomTransformerInterface;

/**
* Class derived for each generated mapper.
*
Expand All @@ -28,6 +30,9 @@ abstract class GeneratedMapper implements MapperInterface

protected $circularReferenceLimit;

/** @var array<string, CustomTransformerInterface> */
protected array $transformers = [];

/**
* Add a callable for a specific property.
*/
Expand All @@ -52,4 +57,12 @@ public function setCircularReferenceLimit(?int $circularReferenceLimit): void
{
$this->circularReferenceLimit = $circularReferenceLimit;
}

/**
* @param array<string, CustomTransformerInterface> $transformers
*/
public function setCustomTransformers(array $transformers): void
{
$this->transformers = $transformers;
}
}
Loading

0 comments on commit d89263d

Please sign in to comment.