From e00f74cca70a544d31be85b2bb8c946be1975152 Mon Sep 17 00:00:00 2001 From: Vincent Quatrevieux Date: Sun, 19 Jul 2026 18:15:51 +0200 Subject: [PATCH] feat: Handle enum with constructor data mapper --- src/DataMapper/ConstructorDataMapper.php | 8 +++- .../ConstructorParameterMetadata.php | 7 ++- .../DataMapper/ConstructorDataMapperTest.php | 44 ++++++++++++++++++- tests/Fixtures/ConstructorWithSimpleEnum.php | 16 +++++++ 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 tests/Fixtures/ConstructorWithSimpleEnum.php diff --git a/src/DataMapper/ConstructorDataMapper.php b/src/DataMapper/ConstructorDataMapper.php index 5e7527b..c775be4 100644 --- a/src/DataMapper/ConstructorDataMapper.php +++ b/src/DataMapper/ConstructorDataMapper.php @@ -194,7 +194,13 @@ private function resolveFallbackValueFromType(?ReflectionType $type): mixed if (!$type->isBuiltin()) { // @phpstan-ignore-next-line - return (new ReflectionClass($type->getName()))->newInstanceWithoutConstructor(); + $class = new ReflectionClass($type->getName()); + + if ($class->isEnum()) { + return $type->getName()::cases()[0]; + } + + return $class->newInstanceWithoutConstructor(); } return match ($type->getName()) { diff --git a/src/DataMapper/ConstructorParameterMetadata.php b/src/DataMapper/ConstructorParameterMetadata.php index 6d09f07..e152a89 100644 --- a/src/DataMapper/ConstructorParameterMetadata.php +++ b/src/DataMapper/ConstructorParameterMetadata.php @@ -6,6 +6,7 @@ use Quatrevieux\Form\Util\Expr; use ReflectionClass; use stdClass; +use UnitEnum; use function is_object; @@ -20,7 +21,11 @@ public function __construct( public function compiledFallback(): string { - if (is_object($this->fallback) && $this->fallback::class !== stdClass::class) { + if ( + is_object($this->fallback) + && $this->fallback::class !== stdClass::class + && !$this->fallback instanceof UnitEnum + ) { return (string) Expr::new(ReflectionClass::class, [$this->fallback::class])->newInstanceWithoutConstructor(); } diff --git a/tests/DataMapper/ConstructorDataMapperTest.php b/tests/DataMapper/ConstructorDataMapperTest.php index a9392e2..9cf8cd7 100644 --- a/tests/DataMapper/ConstructorDataMapperTest.php +++ b/tests/DataMapper/ConstructorDataMapperTest.php @@ -5,7 +5,9 @@ use PHPUnit\Framework\TestCase; use Quatrevieux\Form\DataMapper\Generator\DataMapperGenerator; use Quatrevieux\Form\DefaultRegistry; +use Quatrevieux\Form\Fixtures\ConstructorWithSimpleEnum; use Quatrevieux\Form\Fixtures\EmbeddedFormConstructor; +use Quatrevieux\Form\Fixtures\MySimpleEnum; use Quatrevieux\Form\Fixtures\RequestWithDefaultValueConstructor; use Quatrevieux\Form\Fixtures\RequiredParametersRequestConstructor; use Quatrevieux\Form\Fixtures\SimpleRequestConstructor; @@ -148,7 +150,6 @@ public function test_with_embedded() $this->assertEquals('This value is required', (string) $dto->errors['bar']); $this->assertEquals('This value is required', (string) $dto->errors['embedded']); - $dto = $mapper->toDataObject([ 'foo' => 'azerty', 'bar' => 'uiop', @@ -185,4 +186,45 @@ public function test_with_embedded() $mapper->generateToDataObject($mapper) ); } + + public function test_with_enum() + { + $mapper = new ConstructorDataMapper(ConstructorWithSimpleEnum::class, new DefaultRegistry()); + + $dto = $mapper->toDataObject([]); + + $this->assertSame(ConstructorWithSimpleEnum::class, $mapper->className()); + $this->assertInstanceOf(ConstructorWithSimpleEnum::class, $dto->dto); + + $this->assertSame(MySimpleEnum::Foo, $dto->dto->enum); + + $this->assertCount(1, $dto->errors); + $this->assertEquals('This value is required', (string) $dto->errors['enum']); + + $dto = $mapper->toDataObject([ + 'enum' => MySimpleEnum::Bar, + ]); + + $this->assertEquals(new ConstructorWithSimpleEnum( + enum: MySimpleEnum::Bar + ), $dto->dto); + + $this->assertEmpty($dto->errors); + + $this->assertSame( + <<<'PHP' + $errors = []; + $dto = new \Quatrevieux\Form\Fixtures\ConstructorWithSimpleEnum(enum: $fields['enum'] ?? \Quatrevieux\Form\Fixtures\MySimpleEnum::Foo); + + foreach (['enum' => 'This value is required'] as $field => $message) { + if (!isset($fields[$field])) { + $errors[$field] = new \Quatrevieux\Form\Validator\FieldError($message, [], 'b1ac3a70-06db-5cd6-8f0e-8e6b98b3fcb5', $this->registry->getTranslator()); + } + } + + return new \Quatrevieux\Form\DataMapper\DataMapperResult($dto, $errors); + PHP, + $mapper->generateToDataObject($mapper) + ); + } } diff --git a/tests/Fixtures/ConstructorWithSimpleEnum.php b/tests/Fixtures/ConstructorWithSimpleEnum.php new file mode 100644 index 0000000..4c651fd --- /dev/null +++ b/tests/Fixtures/ConstructorWithSimpleEnum.php @@ -0,0 +1,16 @@ +