Skip to content

Commit

Permalink
perf: Incorporate inheritance mapping logic into `ObjectToObjectTrans…
Browse files Browse the repository at this point in the history
…former`.
  • Loading branch information
priyadi committed Feb 5, 2024
1 parent 7c6d08b commit 83a6812
Show file tree
Hide file tree
Showing 13 changed files with 63 additions and 213 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 @@

* fix: Add caching for `ObjectMapperTable`.
* perf: Use `ObjectMapperResolver` to resolve object mapper.
* perf: Incorporate inheritance mapping logic into `ObjectToObjectTransformer`.

## 0.6.0

Expand Down
17 changes: 6 additions & 11 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
use Rekalogika\Mapper\Transformer\ClassMethodTransformer;
use Rekalogika\Mapper\Transformer\CopyTransformer;
use Rekalogika\Mapper\Transformer\DateTimeTransformer;
use Rekalogika\Mapper\Transformer\InheritanceMapTransformer;
use Rekalogika\Mapper\Transformer\NullTransformer;
use Rekalogika\Mapper\Transformer\ObjectMapperTransformer;
use Rekalogika\Mapper\Transformer\ObjectToArrayTransformer;
Expand Down Expand Up @@ -104,7 +103,7 @@

$services
->set(ScalarToScalarTransformer::class)
->tag('rekalogika.mapper.transformer', ['priority' => -300]);
->tag('rekalogika.mapper.transformer', ['priority' => -350]);

$services
->set(ObjectMapperTransformer::class)
Expand All @@ -114,33 +113,29 @@
service('rekalogika.mapper.object_mapper.table_factory'),
service('rekalogika.mapper.object_mapper.resolver'),
])
->tag('rekalogika.mapper.transformer', ['priority' => -350]);
->tag('rekalogika.mapper.transformer', ['priority' => -400]);

$services
->set(DateTimeTransformer::class)
->tag('rekalogika.mapper.transformer', ['priority' => -400]);
->tag('rekalogika.mapper.transformer', ['priority' => -450]);

$services
->set(StringToBackedEnumTransformer::class)
->tag('rekalogika.mapper.transformer', ['priority' => -450]);
->tag('rekalogika.mapper.transformer', ['priority' => -500]);

$services
->set(ClassMethodTransformer::class)
->args([
service('rekalogika.mapper.sub_mapper.factory'),
])
->tag('rekalogika.mapper.transformer', ['priority' => -500]);

$services
->set(SymfonyUidTransformer::class)
->tag('rekalogika.mapper.transformer', ['priority' => -550]);

$services
->set(ObjectToStringTransformer::class)
->set(SymfonyUidTransformer::class)
->tag('rekalogika.mapper.transformer', ['priority' => -600]);

$services
->set(InheritanceMapTransformer::class)
->set(ObjectToStringTransformer::class)
->tag('rekalogika.mapper.transformer', ['priority' => -650]);

$services
Expand Down
2 changes: 1 addition & 1 deletion src/Attribute/InheritanceMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace Rekalogika\Mapper\Attribute;

#[\Attribute(\Attribute::TARGET_CLASS)]
final readonly class InheritanceMap implements MapperAttributeInterface
final readonly class InheritanceMap
{
/**
* @param array<class-string,class-string> $map
Expand Down
13 changes: 0 additions & 13 deletions src/MapperFactory/MapperFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
use Rekalogika\Mapper\Transformer\Contracts\TransformerInterface;
use Rekalogika\Mapper\Transformer\CopyTransformer;
use Rekalogika\Mapper\Transformer\DateTimeTransformer;
use Rekalogika\Mapper\Transformer\InheritanceMapTransformer;
use Rekalogika\Mapper\Transformer\NullTransformer;
use Rekalogika\Mapper\Transformer\ObjectMapperTransformer;
use Rekalogika\Mapper\Transformer\ObjectToArrayTransformer;
Expand Down Expand Up @@ -114,7 +113,6 @@ class MapperFactory
private ?TraversableToTraversableTransformer $traversableToTraversableTransformer = null;
private ?CopyTransformer $copyTransformer = null;
private ?ClassMethodTransformer $classMethodTransformer = null;
private ?InheritanceMapTransformer $inheritanceMapTransformer = null;
private ?SymfonyUidTransformer $symfonyUidTransformer = null;

private CacheItemPoolInterface $propertyInfoExtractorCache;
Expand Down Expand Up @@ -445,15 +443,6 @@ protected function getClassMethodTransformer(): ClassMethodTransformer
return $this->classMethodTransformer;
}

protected function getInheritanceMapTransformer(): InheritanceMapTransformer
{
if (null === $this->inheritanceMapTransformer) {
$this->inheritanceMapTransformer = new InheritanceMapTransformer();
}

return $this->inheritanceMapTransformer;
}

protected function getSymfonyUidTransformer(): SymfonyUidTransformer
{
if (null === $this->symfonyUidTransformer) {
Expand Down Expand Up @@ -525,8 +514,6 @@ protected function getTransformersIterator(): iterable

yield 'ObjectToStringTransformer'
=> $this->getObjectToStringTransformer();
yield 'InheritanceMapTransformer'
=> $this->getInheritanceMapTransformer();
yield 'TraversableToArrayAccessTransformer'
=> $this->getTraversableToArrayAccessTransformer();
yield 'TraversableToTraversableTransformer'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ClassNotInstantiableException extends NotMappableValueException
public function __construct(string $class, Context $context = null)
{
parent::__construct(
message: sprintf('Trying to instantiate class "%s", but this class is not instantiable.', $class),
message: sprintf('Trying to instantiate "%s", but it is not instantiable. You might solve this problem by adding an "InheritanceMap" to the class, so the mapper will know which concrete class to instantiate.', $class),
context: $context
);
}
Expand Down
40 changes: 7 additions & 33 deletions src/Transformer/Exception/NotAClassException.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

namespace Rekalogika\Mapper\Transformer\Exception;

use Rekalogika\Mapper\Attribute\InheritanceMap;
use Rekalogika\Mapper\Context\Context;

class NotAClassException extends NotMappableValueException
Expand All @@ -22,37 +21,12 @@ public function __construct(
string $class,
Context $context = null,
) {
/** @var class-string $class */

try {
$reflectionClass = new \ReflectionClass($class);

if ($reflectionClass->isInterface()) {
parent::__construct(
message: sprintf(
'Trying to map to "%s", but it is an interface, not a class. If you want to map to an interface, you need to add the attribute "%s" to the interface."',
$class,
InheritanceMap::class
),
context: $context,
);
} else {
parent::__construct(
message: sprintf(
'Trying to map to "%s", but it is not a class.',
$class,
),
context: $context,
);
}
} catch (\ReflectionException) {
parent::__construct(
message: sprintf(
'The name "%s" is not a valid class.',
$class
),
context: $context,
);
}
parent::__construct(
message: sprintf(
'Trying to map to "%s", but it is not a class.',
$class,
),
context: $context,
);
}
}
129 changes: 0 additions & 129 deletions src/Transformer/InheritanceMapTransformer.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ final class ObjectToObjectMetadata

/**
* @param class-string $sourceClass
* @param class-string $targetClass
* @param class-string $targetClass Effective target class after resolving inheritance map
* @param class-string $providedTargetClass
*/
public function __construct(
private string $sourceClass,
private string $targetClass,
private string $providedTargetClass,
) {
}

Expand All @@ -54,6 +56,14 @@ public function getTargetClass(): string
return $this->targetClass;
}

/**
* @return class-string
*/
public function getProvidedTargetClass(): string
{
return $this->providedTargetClass;
}

public function isInstantiable(): bool
{
return $this->instantiable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@

namespace Rekalogika\Mapper\Transformer\ObjectToObjectMetadata;

use Rekalogika\Mapper\Attribute\InheritanceMap;
use Rekalogika\Mapper\Context\Context;
use Rekalogika\Mapper\CustomMapper\PropertyMapperResolverInterface;
use Rekalogika\Mapper\Exception\InvalidArgumentException;
use Rekalogika\Mapper\Transformer\Exception\InternalClassUnsupportedException;
use Rekalogika\Mapper\Transformer\Exception\SourceClassNotInInheritanceMapException;
use Rekalogika\Mapper\Transformer\ObjectToObjectMetadata\Contracts\ObjectToObjectMetadata;
use Rekalogika\Mapper\Transformer\ObjectToObjectMetadata\Contracts\ObjectToObjectMetadataFactoryInterface;
use Rekalogika\Mapper\Transformer\ObjectToObjectMetadata\Contracts\PropertyMapping;
Expand Down Expand Up @@ -48,15 +50,44 @@ public function createObjectToObjectMetadata(
string $targetClass,
Context $context
): ObjectToObjectMetadata {
if ((new \ReflectionClass($sourceClass))->isInternal()) {
$providedTargetClass = $targetClass;

$sourceReflection = new \ReflectionClass($sourceClass);
$providedTargetReflection = new \ReflectionClass($providedTargetClass);

// check inheritance map

$attributes = $providedTargetReflection->getAttributes(InheritanceMap::class);

if (count($attributes) > 0) {
$inheritanceMap = $attributes[0]->newInstance();

$targetClass = $inheritanceMap->getTargetClassFromSourceClass($sourceClass);

if ($targetClass === null) {
throw new SourceClassNotInInheritanceMapException($sourceClass, $providedTargetClass, context: $context);
}
}

$targetReflection = new \ReflectionClass($targetClass);

// check if source and target classes are internal

if ($sourceReflection->isInternal()) {
throw new InternalClassUnsupportedException($sourceClass, context: $context);
}

if ((new \ReflectionClass($targetClass))->isInternal()) {
if ($targetReflection->isInternal()) {
throw new InternalClassUnsupportedException($targetClass, context: $context);
}

$objectToObjectMetadata = new ObjectToObjectMetadata($sourceClass, $targetClass);
// instantiate ObjectToObjectMetadata

$objectToObjectMetadata = new ObjectToObjectMetadata(
sourceClass: $sourceClass,
targetClass: $targetClass,
providedTargetClass: $providedTargetClass
);

// queries

Expand Down
Loading

0 comments on commit 83a6812

Please sign in to comment.