diff --git a/src/FlatMapper.php b/src/FlatMapper.php index 9bd3043..e8a3c61 100644 --- a/src/FlatMapper.php +++ b/src/FlatMapper.php @@ -25,7 +25,7 @@ class FlatMapper // TODO for now those are unused private ?CacheInterface $cacheService = null; // @phpstan-ignore-line - private bool $validateMapping = true; // @phpstan-ignore-line + private bool $validateMapping = true; public function setCacheService(CacheInterface $cacheService): void { @@ -57,7 +57,8 @@ private function createMappingRecursive(string $dtoClassName, string $rootDtoCla $reflectionClass = new ReflectionClass($dtoClassName); - foreach ($reflectionClass->getProperties() as $reflectionProperty) { + $identifiersCount = 0; + foreach ($reflectionClass->getConstructor()->getParameters() as $reflectionProperty) { $propertyName = $reflectionProperty->getName(); $isIdentifier = false; foreach ($reflectionProperty->getAttributes() as $attribute) { @@ -65,18 +66,13 @@ private function createMappingRecursive(string $dtoClassName, string $rootDtoCla $this->objectsMapping[$rootDtoClassName][$dtoClassName][$propertyName] = (string)$attribute->getArguments()[0]; $this->createMappingRecursive($attribute->getArguments()[0], $rootDtoClassName); continue 2; - } - - if ($attribute->getName() === ColumnArray::class) { + } else if ($attribute->getName() === ColumnArray::class) { $this->objectsMapping[$rootDtoClassName][$dtoClassName][$propertyName] = (string)$attribute->getArguments()[0]; continue 2; - } - - if ($attribute->getName() === Identifier::class) { + } else if ($attribute->getName() === Identifier::class) { + $identifiersCount++; $isIdentifier = true; - } - - if ($attribute->getName() === InboundPropertyName::class) { + } else if ($attribute->getName() === InboundPropertyName::class) { $propertyName = $attribute->getArguments()[0]; } } @@ -88,8 +84,14 @@ private function createMappingRecursive(string $dtoClassName, string $rootDtoCla $this->objectsMapping[$rootDtoClassName][$dtoClassName][$propertyName] = null; } - if (count($this->objectIdentifiers[$rootDtoClassName]) !== count(array_unique($this->objectIdentifiers[$rootDtoClassName]))) { - throw new RuntimeException('Several data identifiers are identical: ' . print_r($this->objectIdentifiers[$rootDtoClassName], true)); + if($this->validateMapping) { + if($identifiersCount !== 1) { + throw new RuntimeException($dtoClassName.' contains more than one #[Identifier] attribute.'); + } + + if (count($this->objectIdentifiers[$rootDtoClassName]) !== count(array_unique($this->objectIdentifiers[$rootDtoClassName]))) { + throw new RuntimeException('Several data identifiers are identical: ' . print_r($this->objectIdentifiers[$rootDtoClassName], true)); + } } } diff --git a/tests/Examples/Invalid/RootDTOWithTooManyIdentifiers.php b/tests/Examples/Invalid/RootDTOWithTooManyIdentifiers.php new file mode 100644 index 0000000..3ca3adf --- /dev/null +++ b/tests/Examples/Invalid/RootDTOWithTooManyIdentifiers.php @@ -0,0 +1,26 @@ + $leafs + */ + public function __construct( + #[Identifier] + #[InboundPropertyName('object1_id')] + public int $id, + #[Identifier] + #[InboundPropertyName('object1_name')] + public string $name, + #[ReferencesArray(LeafDTO::class)] + public array $leafs, + ) {} +} diff --git a/tests/FlatMapperTest.php b/tests/FlatMapperTest.php index c375012..123984d 100644 --- a/tests/FlatMapperTest.php +++ b/tests/FlatMapperTest.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\Attributes\CoversMethod; use PHPUnit\Framework\TestCase; use Pixelshaped\FlatMapperBundle\FlatMapper; +use Pixelshaped\FlatMapperBundle\Tests\Examples\Invalid\RootDTOWithTooManyIdentifiers; use Pixelshaped\FlatMapperBundle\Tests\Examples\Valid\ColumnArrayDTO; use Pixelshaped\FlatMapperBundle\Tests\Examples\Valid\LeafDTO; use Pixelshaped\FlatMapperBundle\Tests\Examples\Valid\RootDTO as ValidRootDTO; @@ -24,7 +25,7 @@ public function testCreateMappingWithValidDTOsDoesNotAssert(): void $mapper->createMapping(ValidRootDTO::class); } - public function testCreateMappingWithInvalidDTOsAsserts(): void + public function testCreateMappingWithSeveralIdenticalIdentifiersAsserts(): void { $this->expectException(RuntimeException::class); $this->expectExceptionMessageMatches("/Several data identifiers are identical/"); @@ -32,6 +33,14 @@ public function testCreateMappingWithInvalidDTOsAsserts(): void $mapper->createMapping(InvalidRootDTO::class); } + public function testCreateMappingWithTooManyIdentifiersAsserts(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessageMatches("/contains more than one #\[Identifier\] attribute/"); + $mapper = new FlatMapper(); + $mapper->createMapping(RootDTOWithTooManyIdentifiers::class); + } + public function testMapValidNestedDTOs(): void { $results = [