From 8224b32770f824f5565fe8d965048a547321797d Mon Sep 17 00:00:00 2001 From: MartkCz Date: Sun, 16 Sep 2018 22:07:19 +0200 Subject: [PATCH] ContainerBuilder:resolveImplement supports polymorphism (#175) --- src/DI/ContainerBuilder.php | 7 +- ...ompiler.generatedFactory.polymorphism.phpt | 101 ++++++++++++++++++ ...ompiler.generatedFactory.polymorphism.neon | 10 ++ 3 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 tests/DI/Compiler.generatedFactory.polymorphism.phpt create mode 100644 tests/DI/files/compiler.generatedFactory.polymorphism.neon diff --git a/src/DI/ContainerBuilder.php b/src/DI/ContainerBuilder.php index 1d6e5bcdf..c84574a3d 100644 --- a/src/DI/ContainerBuilder.php +++ b/src/DI/ContainerBuilder.php @@ -417,8 +417,11 @@ private function resolveImplement(ServiceDefinition $def, $name): void $hint = Reflection::getParameterType($param); if (isset($ctorParams[$param->getName()])) { $arg = $ctorParams[$param->getName()]; - if ($hint !== Reflection::getParameterType($arg)) { - throw new ServiceCreationException("Type hint for \${$param->getName()} in $methodName doesn't match type hint in $class constructor."); + if ($hint) { + $hints = [$hint => $hint] + (class_exists($hint) ? class_parents($hint) + class_implements($hint) : []); + if (!isset($hints[Reflection::getParameterType($arg)])) { + throw new ServiceCreationException("Type hint for \${$param->getName()} in $methodName doesn't match type hint in $class constructor."); + } } $def->getFactory()->arguments[$arg->getPosition()] = self::literal('$' . $arg->getName()); } elseif (!$def->getSetup()) { diff --git a/tests/DI/Compiler.generatedFactory.polymorphism.phpt b/tests/DI/Compiler.generatedFactory.polymorphism.phpt new file mode 100644 index 000000000..c30206999 --- /dev/null +++ b/tests/DI/Compiler.generatedFactory.polymorphism.phpt @@ -0,0 +1,101 @@ +shape = $shape; + } + + + public function getName(): string + { + return $this->shape->getName(); + } +} + +$compiler = new DI\Compiler; +$container = createContainer($compiler, 'files/compiler.generatedFactory.polymorphism.neon'); + +Assert::type(ICircleFactory::class, $container->getService('circle')); +$picture = $container->getService('circle')->create(new Circle); +Assert::type(Picture::class, $picture); +Assert::same('circle', $picture->getName()); + +Assert::type(ITriangleFactory::class, $container->getService('triangle')); +$picture = $container->getService('triangle')->create(new Triangle); +Assert::type(Picture::class, $picture); +Assert::same('triangle', $picture->getName()); + +Assert::type(IEllipseFactory::class, $container->getService('ellipse')); +$picture = $container->getService('ellipse')->create(new Ellipse); +Assert::type(Picture::class, $picture); +Assert::same('ellipse', $picture->getName()); + +Assert::type(ICircleFactory::class, $container->getService('circle')); +$picture = $container->getService('circle')->create(new Ellipse); +Assert::type(Picture::class, $picture); +Assert::same('ellipse', $picture->getName()); + +Assert::throws(function () use ($container) { + $container->getService('ellipse')->create(new Circle); +}, TypeError::class); diff --git a/tests/DI/files/compiler.generatedFactory.polymorphism.neon b/tests/DI/files/compiler.generatedFactory.polymorphism.neon new file mode 100644 index 000000000..7e0acc83f --- /dev/null +++ b/tests/DI/files/compiler.generatedFactory.polymorphism.neon @@ -0,0 +1,10 @@ +services: + + circle: + implement: ICircleFactory + + triangle: + implement: ITriangleFactory + + ellipse: + implement: IEllipseFactory