diff --git a/src/Annotation/OverrideConstructor.php b/src/Annotation/OverrideConstructor.php new file mode 100644 index 0000000..1cef98b --- /dev/null +++ b/src/Annotation/OverrideConstructor.php @@ -0,0 +1,29 @@ +method); + + return array_map( + static fn ($parameter) => $container->get($parameter->getType()?->getName()), + $method->getParameters() + ); + } +} diff --git a/src/Hydrator.php b/src/Hydrator.php index 91687b9..5c78d4d 100644 --- a/src/Hydrator.php +++ b/src/Hydrator.php @@ -19,6 +19,7 @@ use SergiX44\Hydrator\Annotation\ArrayType; use SergiX44\Hydrator\Annotation\ConcreteResolver; use SergiX44\Hydrator\Annotation\Mutate; +use SergiX44\Hydrator\Annotation\OverrideConstructor; use SergiX44\Hydrator\Annotation\SkipConstructor; use SergiX44\Hydrator\Annotation\UnionResolver; use SergiX44\Hydrator\Exception\InvalidObjectException; @@ -266,6 +267,15 @@ private function initializeObject(string|object $object, array|object $data): ob } if ($this->container !== null) { + $overrideConstructor = $this->getAttributeInstance($reflectionClass, OverrideConstructor::class); + if ($overrideConstructor !== null) { + $obj = $reflectionClass->newInstanceWithoutConstructor(); + $args = $overrideConstructor->getArguments($obj, $this->container); + call_user_func([$obj, $overrideConstructor->method], ...$args); + + return $obj; + } + return $this->container->get($object); } diff --git a/tests/Fixtures/DI/Leaves.php b/tests/Fixtures/DI/Leaves.php index 704d5f1..45cc9c2 100644 --- a/tests/Fixtures/DI/Leaves.php +++ b/tests/Fixtures/DI/Leaves.php @@ -6,7 +6,7 @@ class Leaves { public int $n; - private Sun|null $sun = null; + private ?Sun $sun = null; public function __construct(?Sun $sun = null) { diff --git a/tests/Fixtures/DI/Tree.php b/tests/Fixtures/DI/Tree.php index 36f2a38..b17638a 100644 --- a/tests/Fixtures/DI/Tree.php +++ b/tests/Fixtures/DI/Tree.php @@ -10,7 +10,7 @@ class Tree public Leaves $leaves; - private Sun|null $sun = null; + private ?Sun $sun = null; public function __construct(?Sun $sun = null) { diff --git a/tests/Fixtures/DI/Wood.php b/tests/Fixtures/DI/Wood.php index 9079dd2..f6ac894 100644 --- a/tests/Fixtures/DI/Wood.php +++ b/tests/Fixtures/DI/Wood.php @@ -6,7 +6,7 @@ class Wood { public int $kg; - private Sun|null $sun = null; + private ?Sun $sun = null; public function __construct(?Sun $sun = null) { diff --git a/tests/Fixtures/Store/Audi.php b/tests/Fixtures/Store/Audi.php new file mode 100644 index 0000000..ea2ed4a --- /dev/null +++ b/tests/Fixtures/Store/Audi.php @@ -0,0 +1,13 @@ +key = $key; + + return $this; + } +} diff --git a/tests/Fixtures/Store/Key.php b/tests/Fixtures/Store/Key.php new file mode 100644 index 0000000..d0aba74 --- /dev/null +++ b/tests/Fixtures/Store/Key.php @@ -0,0 +1,8 @@ +hydrate(Fixtures\ObjectWithArrayOfStringableEnum::class, ['value' => [ - 'c1200a7e-136e-4a11-9bc3-cc937046e90f', - 'a2b29b37-1c5a-4b36-9981-097ddd25c740', - 'c1ea3762-9827-4c0c-808b-53be3febae6d', - ]]); + $object = (new Hydrator())->hydrate(Fixtures\ObjectWithArrayOfStringableEnum::class, [ + 'value' => [ + 'c1200a7e-136e-4a11-9bc3-cc937046e90f', + 'a2b29b37-1c5a-4b36-9981-097ddd25c740', + 'c1ea3762-9827-4c0c-808b-53be3febae6d', + ], + ]); $this->assertSame([ Fixtures\StringableEnum::foo, @@ -505,12 +509,14 @@ public function testHydrateArrayOfStringableEnumProperty(): void public function testHydrateArrayOfStringableEnumPropertyWithoutMatchingEnum(): void { - $object = (new Hydrator())->hydrate(Fixtures\ObjectWithArrayOfStringableEnum::class, ['value' => [ - 'c1200a7e-136e-4a11-9bc3-cc937046e90f', - 'a2b29b37-1c5a-4b36-9981-097ddd25c740', - 'c1ea3762-9827-4c0c-808b-53be3febae6d', - 'bbb', - ]]); + $object = (new Hydrator())->hydrate(Fixtures\ObjectWithArrayOfStringableEnum::class, [ + 'value' => [ + 'c1200a7e-136e-4a11-9bc3-cc937046e90f', + 'a2b29b37-1c5a-4b36-9981-097ddd25c740', + 'c1ea3762-9827-4c0c-808b-53be3febae6d', + 'bbb', + ], + ]); $this->assertSame([ Fixtures\StringableEnum::foo, @@ -828,11 +834,13 @@ public function testHydrateAbstractProperty(): void public function testHydrateArrayAbstractProperty(): void { $o = (new Hydrator())->hydrate(new ObjectWithArrayOfAbstracts(), [ - 'value' => [[ - 'type' => 'jack', - 'sweetness' => null, - 'category' => 'brandy', - ]], + 'value' => [ + [ + 'type' => 'jack', + 'sweetness' => null, + 'category' => 'brandy', + ], + ], ]); $this->assertInstanceOf(ObjectWithArrayOfAbstracts::class, $o); @@ -848,11 +856,13 @@ public function testHydrateArrayAbstractProperty(): void public function testHydrateArrayAbstractPropertyWithObject(): void { $o = (new Hydrator())->hydrate(new ObjectWithArrayOfAbstracts(), [ - 'value' => [(object) [ - 'type' => 'jack', - 'sweetness' => null, - 'category' => 'brandy', - ]], + 'value' => [ + (object) [ + 'type' => 'jack', + 'sweetness' => null, + 'category' => 'brandy', + ], + ], ]); $this->assertInstanceOf(ObjectWithArrayOfAbstracts::class, $o); @@ -1016,4 +1026,22 @@ public function testHydrateAdditionalWithMagicMethod() $this->assertFalse($object->type); $this->assertSame(42, $object->number); } + + public function testHydrateWithOverrideConstructor() + { + $container = new Container(); + $key = new Key(); + $container->bind(Key::class, function () use ($key) { + return $key; + }); + + $object = (new Hydrator($container))->hydrate(Audi::class, [ + 'model' => 'A4', + 'year' => 2021, + ]); + + $this->assertSame('A4', $object->model); + $this->assertSame(2021, $object->year); + $this->assertSame($key, $object->key); + } }