From 20f10ced2448f18628d1d3254444edd015624894 Mon Sep 17 00:00:00 2001 From: Priyadi Iman Nurcahyo <1102197+priyadi@users.noreply.github.com> Date: Mon, 15 Jan 2024 00:25:50 +0700 Subject: [PATCH] feat: Transformers now have the option to have an invariant target type. --- CHANGELOG.md | 3 +- src/Command/MappingCommand.php | 12 +++--- src/Command/TryCommand.php | 27 +++++++------ src/Exception/ContextAwareExceptionTrait.php | 6 ++- .../CannotFindTransformerException.php | 2 +- src/MainTransformer/MainTransformer.php | 8 ++-- src/Mapping/Mapping.php | 26 ++++++------- src/Mapping/MappingEntry.php | 29 ++++++++++++-- src/Mapping/MappingFactory.php | 8 +++- src/MethodMapper/ClassMethodTransformer.php | 2 + src/Transformer/ArrayToObjectTransformer.php | 2 +- src/Transformer/Contracts/TypeMapping.php | 6 +++ src/Transformer/InheritanceMapTransformer.php | 3 +- src/Transformer/ObjectToObjectTransformer.php | 4 +- .../StringToBackedEnumTransformer.php | 1 + .../TraversableToArrayAccessTransformer.php | 2 + src/TransformerRegistry/SearchResultEntry.php | 12 ++++++ .../TransformerRegistry.php | 39 +++++++++++++++---- .../TransformerRegistryInterface.php | 11 ------ src/TypeResolver/CachingTypeResolver.php | 9 ++++- src/TypeResolver/TypeResolver.php | 8 +++- src/TypeResolver/TypeResolverInterface.php | 17 +++++++- src/Util/TypeCheck.php | 16 ++++---- .../ObjectWithEnumStringableProperty.php | 2 + .../ObjectWithEnumStringablePropertyDto.php | 5 +++ tests/IntegrationTest/AttributeTest.php | 2 +- .../ObjectEnumStringMappingTest.php | 4 ++ 27 files changed, 186 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f04f6eef..6299c41a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,11 +12,12 @@ * feat: If a transformer throws `RefuseToHandleException`, the `MainTransformer` will try the next suitable transformer. * style: Remove unused vars. +* feat: Transformers now have the option to have an invariant target type. ## 0.5.8 * fix: PropertyAccessor `UninitializedPropertyException` error now is regarded - as null. + as null.**** * fix: Transformer `SearchResult` was not properly ordered. * feat: `TryProperty` command, or `rekalogika:mapper:tryproperty` in console. diff --git a/src/Command/MappingCommand.php b/src/Command/MappingCommand.php index 891584ee..815572aa 100644 --- a/src/Command/MappingCommand.php +++ b/src/Command/MappingCommand.php @@ -57,13 +57,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int foreach ($mapping as $entry) { $order = $entry->getOrder(); - $sourceType = $entry->getSourceType(); - $targetType = $entry->getTargetType(); + $sourceType = $entry->getSourceTypeString(); + $targetType = $entry->getTargetTypeString(); $class = $entry->getClass(); $id = $entry->getId(); + $variantTargetType = $entry->isVariantTargetType(); if ($sourceOption) { - if (preg_match('/' . preg_quote($sourceOption) . '/i', $entry->getSourceType()) === 0) { + if (preg_match('/' . preg_quote($sourceOption) . '/i', $entry->getSourceTypeString()) === 0) { continue; } @@ -71,7 +72,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } if ($targetOption) { - if (preg_match('/' . preg_quote($targetOption) . '/i', $entry->getTargetType()) === 0) { + if (preg_match('/' . preg_quote($targetOption) . '/i', $entry->getTargetTypeString()) === 0) { continue; } @@ -94,6 +95,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $order, $sourceType, $targetType, + $variantTargetType ? 'variant' : 'invariant', $id, $class, ]; @@ -101,7 +103,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $io->section($title); $table = new Table($output); - $table->setHeaders(['Order', 'Source Type', 'Target Type', 'Service ID', 'Class']); + $table->setHeaders(['Ordering', 'Source Type', 'Target Type', 'Target Variance', 'Service ID', 'Class']); $table->setStyle('box'); $table->setRows($rows); $table->render(); diff --git a/src/Command/TryCommand.php b/src/Command/TryCommand.php index 8a152d5b..5be1b35e 100644 --- a/src/Command/TryCommand.php +++ b/src/Command/TryCommand.php @@ -56,7 +56,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $sourceTypeString = $input->getArgument('source'); $sourceType = TypeFactory::fromString($sourceTypeString); $sourceTypeStrings = $this->typeResolver - ->getApplicableTypeStrings($sourceType); + ->getAcceptedTransformerInputTypeStrings($sourceType); $rows[] = ['Source type', $sourceTypeString]; $rows[] = new TableSeparator(); @@ -73,7 +73,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $targetTypeString = $input->getArgument('target'); $targetType = TypeFactory::fromString($targetTypeString); $targetTypeStrings = $this->typeResolver - ->getApplicableTypeStrings($targetType); + ->getAcceptedTransformerOutputTypeStrings($targetType); $rows[] = new TableSeparator(); $rows[] = ['Target type', $targetTypeString]; @@ -100,19 +100,17 @@ protected function execute(InputInterface $input, OutputInterface $output): int $rows = []; - $transformers = $this->transformerRegistry - ->getMappingBySourceAndTargetType( - $sourceType, - $targetType - ); + $searchResult = $this->transformerRegistry + ->findBySourceAndTargetTypes([$sourceType], [$targetType]); - foreach ($transformers as $entry) { + foreach ($searchResult as $entry) { $rows[] = [ - $entry->getOrder(), - $entry->getId(), - $entry->getClass(), - $entry->getSourceType(), - $entry->getTargetType() + $entry->getMappingOrder(), + $entry->getTransformerServiceId(), + $entry->getTransformer()::class, + $this->typeResolver->getTypeString($entry->getSourceType()), + $this->typeResolver->getTypeString($entry->getTargetType()), + $entry->isVariantTargetType() ? 'variant' : 'invariant', ]; $rows[] = new TableSeparator(); } @@ -133,8 +131,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $table = new Table($output); - $table->setHeaders(['Order', 'Service ID', 'Class', 'Source Type', 'Target Type']); + $table->setHeaders(['Ordering', 'Service ID', 'Class', 'Source Type', 'Target Type', 'Variance']); $table->setStyle('box'); + $table->setVertical(); $table->setRows($rows); $table->render(); diff --git a/src/Exception/ContextAwareExceptionTrait.php b/src/Exception/ContextAwareExceptionTrait.php index 412fb218..0854e31e 100644 --- a/src/Exception/ContextAwareExceptionTrait.php +++ b/src/Exception/ContextAwareExceptionTrait.php @@ -32,7 +32,11 @@ public function __construct( } if ($path !== null) { - parent::__construct(sprintf('%s Mapping path: "%s"', $message, (string) $path), $code, $previous); + $path = (string) $path; + if ($path === '') { + $path = '(root)'; + } + parent::__construct(sprintf('%s Mapping path: "%s".', $message, $path), $code, $previous); } else { parent::__construct($message, $code, $previous); } diff --git a/src/MainTransformer/Exception/CannotFindTransformerException.php b/src/MainTransformer/Exception/CannotFindTransformerException.php index ca24b7bf..60acedc1 100644 --- a/src/MainTransformer/Exception/CannotFindTransformerException.php +++ b/src/MainTransformer/Exception/CannotFindTransformerException.php @@ -31,7 +31,7 @@ public function __construct(array $sourceTypes, array $targetTypes, Context $con $targetTypes = TypeUtil::getDebugType($targetTypes); parent::__construct( - sprintf('Cannot find a matching transformer for mapping the source types "%s" to the target types "%s".', $sourceTypes, $sourceTypes), + sprintf('Cannot find a matching transformer for mapping the source types "%s" to the target types "%s".', $sourceTypes, $targetTypes), context: $context ); } diff --git a/src/MainTransformer/MainTransformer.php b/src/MainTransformer/MainTransformer.php index 8edd153c..2e06229d 100644 --- a/src/MainTransformer/MainTransformer.php +++ b/src/MainTransformer/MainTransformer.php @@ -111,14 +111,14 @@ public function transform( $context = $context->with($pathContext->append($path)); } - // gets simple target types from the provided target type - - $targetTypes = $this->getSimpleTypes($targetTypes); - // guess the source type $sourceTypes = [$this->typeResolver->guessTypeFromVariable($source)]; + // gets simple target types from the provided target type + + $targetTypes = $this->getSimpleTypes($targetTypes); + // search for the matching transformers according to the source and // target types diff --git a/src/Mapping/Mapping.php b/src/Mapping/Mapping.php index b24593a9..fb20a23c 100644 --- a/src/Mapping/Mapping.php +++ b/src/Mapping/Mapping.php @@ -13,6 +13,9 @@ namespace Rekalogika\Mapper\Mapping; +use Rekalogika\Mapper\Transformer\Contracts\MixedType; +use Symfony\Component\PropertyInfo\Type; + /** * @implements \IteratorAggregate */ @@ -36,18 +39,24 @@ public function getIterator(): \Traversable public function addEntry( string $id, string $class, - string $sourceType, - string $targetType + Type|MixedType $sourceType, + Type|MixedType $targetType, + string $sourceTypeString, + string $targetTypeString, + bool $variantTargetType, ): void { $entry = new MappingEntry( id: $id, class: $class, sourceType: $sourceType, - targetType: $targetType + targetType: $targetType, + sourceTypeString: $sourceTypeString, + targetTypeString: $targetTypeString, + variantTargetType: $variantTargetType, ); $this->entries[$entry->getOrder()] = $entry; - $this->mappingBySourceAndTarget[$sourceType][$targetType][] = $entry; + $this->mappingBySourceAndTarget[$sourceTypeString][$targetTypeString][] = $entry; } /** @@ -71,15 +80,6 @@ public function getMappingBySourceAndTarget( } } - // sort by order - - usort( - $result, - fn (MappingEntry $a, MappingEntry $b) - => - $a->getOrder() <=> $b->getOrder() - ); - return $result; } } diff --git a/src/Mapping/MappingEntry.php b/src/Mapping/MappingEntry.php index 47f9254f..0b8636e5 100644 --- a/src/Mapping/MappingEntry.php +++ b/src/Mapping/MappingEntry.php @@ -13,6 +13,9 @@ namespace Rekalogika\Mapper\Mapping; +use Rekalogika\Mapper\Transformer\Contracts\MixedType; +use Symfony\Component\PropertyInfo\Type; + final class MappingEntry { private static int $counter = 0; @@ -21,8 +24,11 @@ final class MappingEntry public function __construct( private string $id, private string $class, - private string $sourceType, - private string $targetType, + private Type|MixedType $sourceType, + private Type|MixedType $targetType, + private string $sourceTypeString, + private string $targetTypeString, + private bool $variantTargetType, ) { $this->order = ++self::$counter; } @@ -42,13 +48,28 @@ public function getClass(): string return $this->class; } - public function getSourceType(): string + public function isVariantTargetType(): bool + { + return $this->variantTargetType; + } + + public function getSourceType(): Type|MixedType { return $this->sourceType; } - public function getTargetType(): string + public function getTargetType(): Type|MixedType { return $this->targetType; } + + public function getSourceTypeString(): string + { + return $this->sourceTypeString; + } + + public function getTargetTypeString(): string + { + return $this->targetTypeString; + } } diff --git a/src/Mapping/MappingFactory.php b/src/Mapping/MappingFactory.php index fa7243f3..e5d6f481 100644 --- a/src/Mapping/MappingFactory.php +++ b/src/Mapping/MappingFactory.php @@ -66,6 +66,7 @@ private function addMapping( foreach ($transformer->getSupportedTransformation() as $typeMapping) { $sourceTypes = $this->getSimpleTypes($typeMapping->getSourceType()); $targetTypes = $this->getSimpleTypes($typeMapping->getTargetType()); + $isVariantTargetType = $typeMapping->isVariantTargetType(); foreach ($sourceTypes as $sourceType) { foreach ($targetTypes as $targetType) { @@ -75,8 +76,11 @@ private function addMapping( $mapping->addEntry( id: $id, class: get_class($transformer), - sourceType: $sourceTypeString, - targetType: $targetTypeString + sourceType: $sourceType, + targetType: $targetType, + sourceTypeString: $sourceTypeString, + targetTypeString: $targetTypeString, + variantTargetType: $isVariantTargetType, ); } } diff --git a/src/MethodMapper/ClassMethodTransformer.php b/src/MethodMapper/ClassMethodTransformer.php index b1506972..c5beca91 100644 --- a/src/MethodMapper/ClassMethodTransformer.php +++ b/src/MethodMapper/ClassMethodTransformer.php @@ -93,11 +93,13 @@ public function getSupportedTransformation(): iterable yield new TypeMapping( TypeFactory::objectOfClass(MapToObjectInterface::class), TypeFactory::object(), + true, ); yield new TypeMapping( TypeFactory::object(), TypeFactory::objectOfClass(MapFromObjectInterface::class), + true, ); } } diff --git a/src/Transformer/ArrayToObjectTransformer.php b/src/Transformer/ArrayToObjectTransformer.php index 01f40740..0347226e 100644 --- a/src/Transformer/ArrayToObjectTransformer.php +++ b/src/Transformer/ArrayToObjectTransformer.php @@ -74,6 +74,6 @@ public function transform( public function getSupportedTransformation(): iterable { - yield new TypeMapping(TypeFactory::array(), TypeFactory::object()); + yield new TypeMapping(TypeFactory::array(), TypeFactory::object(), true); } } diff --git a/src/Transformer/Contracts/TypeMapping.php b/src/Transformer/Contracts/TypeMapping.php index 0be28b49..c1cc0df2 100644 --- a/src/Transformer/Contracts/TypeMapping.php +++ b/src/Transformer/Contracts/TypeMapping.php @@ -24,6 +24,7 @@ class TypeMapping public function __construct( private Type|MixedType $sourceType, private Type|MixedType $targetType, + private bool $variantTargetType = false, ) { } @@ -42,4 +43,9 @@ public function getTargetType(): Type|MixedType { return $this->targetType; } + + public function isVariantTargetType(): bool + { + return $this->variantTargetType; + } } diff --git a/src/Transformer/InheritanceMapTransformer.php b/src/Transformer/InheritanceMapTransformer.php index bdcd9d3f..89a4f4a1 100644 --- a/src/Transformer/InheritanceMapTransformer.php +++ b/src/Transformer/InheritanceMapTransformer.php @@ -121,7 +121,8 @@ public function getSupportedTransformation(): iterable { yield new TypeMapping( TypeFactory::object(), - TypeFactory::objectOfClass(InheritanceMap::class) + TypeFactory::objectOfClass(InheritanceMap::class), + true ); } } diff --git a/src/Transformer/ObjectToObjectTransformer.php b/src/Transformer/ObjectToObjectTransformer.php index 651d5523..cec30521 100644 --- a/src/Transformer/ObjectToObjectTransformer.php +++ b/src/Transformer/ObjectToObjectTransformer.php @@ -199,7 +199,7 @@ private function resolveTargetPropertyValue( public function getSupportedTransformation(): iterable { - yield new TypeMapping(TypeFactory::object(), TypeFactory::object()); + yield new TypeMapping(TypeFactory::object(), TypeFactory::object(), true); } protected function instantiateTarget( @@ -216,7 +216,7 @@ protected function instantiateTarget( $reflectionClass = new \ReflectionClass($targetClass); if (!$reflectionClass->isInstantiable()) { - throw new ClassNotInstantiableException($targetClass); + throw new ClassNotInstantiableException($targetClass, context: $context); } $initializableTargetProperties = $this diff --git a/src/Transformer/StringToBackedEnumTransformer.php b/src/Transformer/StringToBackedEnumTransformer.php index d4ee9054..10780d20 100644 --- a/src/Transformer/StringToBackedEnumTransformer.php +++ b/src/Transformer/StringToBackedEnumTransformer.php @@ -54,6 +54,7 @@ public function getSupportedTransformation(): iterable yield new TypeMapping( TypeFactory::string(), TypeFactory::objectOfClass(\BackedEnum::class), + true, ); } } diff --git a/src/Transformer/TraversableToArrayAccessTransformer.php b/src/Transformer/TraversableToArrayAccessTransformer.php index b159578b..17c70ba0 100644 --- a/src/Transformer/TraversableToArrayAccessTransformer.php +++ b/src/Transformer/TraversableToArrayAccessTransformer.php @@ -225,6 +225,8 @@ public function getSupportedTransformation(): iterable ]; $targetTypes = [ + TypeFactory::objectOfClass(Collection::class), + TypeFactory::objectOfClass(\ArrayObject::class), TypeFactory::objectOfClass(\ArrayAccess::class), TypeFactory::array(), ]; diff --git a/src/TransformerRegistry/SearchResultEntry.php b/src/TransformerRegistry/SearchResultEntry.php index e0b6eeb1..b0463971 100644 --- a/src/TransformerRegistry/SearchResultEntry.php +++ b/src/TransformerRegistry/SearchResultEntry.php @@ -24,6 +24,8 @@ public function __construct( private Type|MixedType $sourceType, private Type|MixedType $targetType, private TransformerInterface $transformer, + private string $transformerServiceId, + private bool $variantTargetType, ) { } @@ -46,4 +48,14 @@ public function getMappingOrder(): int { return $this->mappingOrder; } + + public function isVariantTargetType(): bool + { + return $this->variantTargetType; + } + + public function getTransformerServiceId(): string + { + return $this->transformerServiceId; + } } diff --git a/src/TransformerRegistry/TransformerRegistry.php b/src/TransformerRegistry/TransformerRegistry.php index 4d19978f..205cfebe 100644 --- a/src/TransformerRegistry/TransformerRegistry.php +++ b/src/TransformerRegistry/TransformerRegistry.php @@ -20,6 +20,7 @@ use Rekalogika\Mapper\Transformer\Contracts\MixedType; use Rekalogika\Mapper\Transformer\Contracts\TransformerInterface; use Rekalogika\Mapper\TypeResolver\TypeResolverInterface; +use Rekalogika\Mapper\Util\TypeCheck; use Symfony\Component\PropertyInfo\Type; class TransformerRegistry implements TransformerRegistryInterface @@ -61,11 +62,26 @@ public function findBySourceAndTargetTypes( ); foreach ($mapping as $mappingEntry) { - $mappingEntries[] = [ - $sourceType, - $targetType, - $mappingEntry, - ]; + if ($mappingEntry->isVariantTargetType()) { + $mappingEntries[] = [ + $sourceType, + $targetType, + $mappingEntry, + ]; + } else { + if ( + TypeCheck::isSomewhatIdentical( + $targetType, + $mappingEntry->getTargetType() + ) + ) { + $mappingEntries[] = [ + $sourceType, + $targetType, + $mappingEntry, + ]; + } + } } } } @@ -86,21 +102,28 @@ public function findBySourceAndTargetTypes( $mappingEntry[0], $mappingEntry[1], $this->get($mappingEntry[2]->getId()), + $mappingEntry[2]->getId(), + $mappingEntry[2]->isVariantTargetType() ); } return new SearchResult($result); } - public function getMappingBySourceAndTargetType( + /** + * @param Type|MixedType $sourceType + * @param Type|MixedType $targetType + * @return array + */ + private function getMappingBySourceAndTargetType( Type|MixedType $sourceType, Type|MixedType $targetType, ): array { $sourceTypeStrings = $this->typeResolver - ->getApplicableTypeStrings($sourceType); + ->getAcceptedTransformerInputTypeStrings($sourceType); $targetTypeStrings = $this->typeResolver - ->getApplicableTypeStrings($targetType); + ->getAcceptedTransformerOutputTypeStrings($targetType); return $this->mappingFactory->getMapping() ->getMappingBySourceAndTarget($sourceTypeStrings, $targetTypeStrings); diff --git a/src/TransformerRegistry/TransformerRegistryInterface.php b/src/TransformerRegistry/TransformerRegistryInterface.php index b1c76e68..8126c83f 100644 --- a/src/TransformerRegistry/TransformerRegistryInterface.php +++ b/src/TransformerRegistry/TransformerRegistryInterface.php @@ -13,7 +13,6 @@ namespace Rekalogika\Mapper\TransformerRegistry; -use Rekalogika\Mapper\Mapping\MappingEntry; use Rekalogika\Mapper\Transformer\Contracts\MixedType; use Rekalogika\Mapper\Transformer\Contracts\TransformerInterface; use Symfony\Component\PropertyInfo\Type; @@ -31,14 +30,4 @@ public function findBySourceAndTargetTypes( iterable $sourceTypes, iterable $targetTypes, ): SearchResult; - - /** - * @param Type|MixedType $sourceType - * @param Type|MixedType $targetType - * @return array - */ - public function getMappingBySourceAndTargetType( - Type|MixedType $sourceType, - Type|MixedType $targetType, - ): array; } diff --git a/src/TypeResolver/CachingTypeResolver.php b/src/TypeResolver/CachingTypeResolver.php index 0a9805b0..7a82bbb2 100644 --- a/src/TypeResolver/CachingTypeResolver.php +++ b/src/TypeResolver/CachingTypeResolver.php @@ -107,7 +107,7 @@ public function isSimpleType(Type $type): bool */ private array $applicableTypeStringsCache = []; - public function getApplicableTypeStrings(Type|MixedType $type): array + public function getAcceptedTransformerInputTypeStrings(Type|MixedType $type): array { $typeString = $this->getTypeString($type); @@ -115,9 +115,14 @@ public function getApplicableTypeStrings(Type|MixedType $type): array return $this->applicableTypeStringsCache[$typeString]; } - $applicableTypeStrings = $this->decorated->getApplicableTypeStrings($type); + $applicableTypeStrings = $this->decorated->getAcceptedTransformerInputTypeStrings($type); $this->applicableTypeStringsCache[$typeString] = $applicableTypeStrings; return $applicableTypeStrings; } + + public function getAcceptedTransformerOutputTypeStrings(Type|MixedType $type): array + { + return $this->decorated->getAcceptedTransformerOutputTypeStrings($type); + } } diff --git a/src/TypeResolver/TypeResolver.php b/src/TypeResolver/TypeResolver.php index ee4187ec..79ad154f 100644 --- a/src/TypeResolver/TypeResolver.php +++ b/src/TypeResolver/TypeResolver.php @@ -80,7 +80,7 @@ public function getSimpleTypes(Type|MixedType $type): array return TypeUtil::getSimpleTypes($type); } - public function getApplicableTypeStrings(Type|MixedType $type): array + public function getAcceptedTransformerInputTypeStrings(Type|MixedType $type): array { if ($type instanceof MixedType) { $type = ['mixed']; @@ -92,4 +92,10 @@ public function getApplicableTypeStrings(Type|MixedType $type): array TypeUtil::getAttributesTypeStrings($type) ); } + + + public function getAcceptedTransformerOutputTypeStrings(Type|MixedType $type): array + { + return $this->getAcceptedTransformerInputTypeStrings($type); + } } diff --git a/src/TypeResolver/TypeResolverInterface.php b/src/TypeResolver/TypeResolverInterface.php index 1df0e037..cea1ffe2 100644 --- a/src/TypeResolver/TypeResolverInterface.php +++ b/src/TypeResolver/TypeResolverInterface.php @@ -58,5 +58,20 @@ public function isSimpleType(Type $type): bool; * @param Type|MixedType $type * @return array */ - public function getApplicableTypeStrings(Type|MixedType $type): array; + public function getAcceptedTransformerInputTypeStrings(Type|MixedType $type): array; + + /** + * Example: If the variable type is + * 'IteratorAggregate>', then this method + * will return ['IteratorAggregate>', + * 'IteratorAggregate>', + * 'Traversable>', + * 'Traversable>'] + * + * Note: IteratorAggregate extends Traversable + * + * @param Type|MixedType $type + * @return array + */ + public function getAcceptedTransformerOutputTypeStrings(Type|MixedType $type): array; } diff --git a/src/Util/TypeCheck.php b/src/Util/TypeCheck.php index 49ef7def..001d146b 100644 --- a/src/Util/TypeCheck.php +++ b/src/Util/TypeCheck.php @@ -82,9 +82,9 @@ public static function isObject(?Type $type): bool /** * @param class-string $classes */ - public static function isObjectOfType(?Type $type, string ...$classes): bool + public static function isObjectOfType(null|Type|MixedType $type, string ...$classes): bool { - if ($type === null) { + if ($type === null || $type instanceof MixedType) { return false; } @@ -159,13 +159,15 @@ public static function isIterable(?Type $type): bool /** * Check for identity between Types, disregarding collection types - * - * @param Type $type1 - * @param Type $type2 - * @return boolean */ - public static function isSomewhatIdentical(Type $type1, Type $type2): bool + public static function isSomewhatIdentical(Type|MixedType $type1, Type|MixedType $type2): bool { + if ($type1 instanceof MixedType && $type2 instanceof MixedType) { + return true; + } elseif ($type1 instanceof MixedType || $type2 instanceof MixedType) { + return false; + } + return $type1->getBuiltinType() === $type2->getBuiltinType() && $type1->getClassName() === $type2->getClassName() && $type1->isNullable() === $type2->isNullable(); diff --git a/tests/Fixtures/EnumAndStringable/ObjectWithEnumStringableProperty.php b/tests/Fixtures/EnumAndStringable/ObjectWithEnumStringableProperty.php index 1fe713aa..14944ade 100644 --- a/tests/Fixtures/EnumAndStringable/ObjectWithEnumStringableProperty.php +++ b/tests/Fixtures/EnumAndStringable/ObjectWithEnumStringableProperty.php @@ -18,6 +18,8 @@ class ObjectWithEnumStringableProperty public ObjectImplementingStringable $stringable; public SomeBackedEnum $backedEnum = SomeBackedEnum::Foo; public SomeEnum $unitEnum = SomeEnum::Foo; + public string $stringBackedEnum = 'foo'; + // public string $stringUnitEnum = 'Foo'; public function __construct() { diff --git a/tests/Fixtures/EnumAndStringableDto/ObjectWithEnumStringablePropertyDto.php b/tests/Fixtures/EnumAndStringableDto/ObjectWithEnumStringablePropertyDto.php index 44c7d186..a3786f87 100644 --- a/tests/Fixtures/EnumAndStringableDto/ObjectWithEnumStringablePropertyDto.php +++ b/tests/Fixtures/EnumAndStringableDto/ObjectWithEnumStringablePropertyDto.php @@ -13,9 +13,14 @@ namespace Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto; +use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\SomeBackedEnum; +use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\SomeEnum; + class ObjectWithEnumStringablePropertyDto { public ?string $stringable = null; public ?string $backedEnum = null; public ?string $unitEnum = null; + public ?SomeBackedEnum $stringBackedEnum = null; + // public ?SomeEnum $stringUnitEnum = null; } diff --git a/tests/IntegrationTest/AttributeTest.php b/tests/IntegrationTest/AttributeTest.php index 2dea8353..d60d927d 100644 --- a/tests/IntegrationTest/AttributeTest.php +++ b/tests/IntegrationTest/AttributeTest.php @@ -25,7 +25,7 @@ public function testAttribute(): void $class = ObjectWithAttribute::class; $type = TypeFactory::objectOfClass($class); - $typeStrings = $this->typeResolver->getApplicableTypeStrings($type); + $typeStrings = $this->typeResolver->getAcceptedTransformerInputTypeStrings($type); $this->assertContainsEquals(SomeAttribute::class, $typeStrings); } diff --git a/tests/IntegrationTest/ObjectEnumStringMappingTest.php b/tests/IntegrationTest/ObjectEnumStringMappingTest.php index 233bf4db..8e75cab4 100644 --- a/tests/IntegrationTest/ObjectEnumStringMappingTest.php +++ b/tests/IntegrationTest/ObjectEnumStringMappingTest.php @@ -15,6 +15,8 @@ use Rekalogika\Mapper\Tests\Common\AbstractIntegrationTest; use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\ObjectWithEnumStringableProperty; +use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\SomeBackedEnum; +use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringable\SomeEnum; use Rekalogika\Mapper\Tests\Fixtures\EnumAndStringableDto\ObjectWithEnumStringablePropertyDto; class ObjectEnumStringMappingTest extends AbstractIntegrationTest @@ -27,5 +29,7 @@ public function testToString(): void $this->assertEquals('foo', $result->stringable); $this->assertEquals('foo', $result->backedEnum); $this->assertEquals('Foo', $result->unitEnum); + $this->assertEquals(SomeBackedEnum::Foo, $result->stringBackedEnum); + // $this->assertEquals(SomeEnum::Foo, $result->stringUnitEnum); } }