Skip to content

Commit 2cbe011

Browse files
MartkCzdg
authored andcommitted
ContainerBuilder:resolveImplement supports polymorphism (#175)
1 parent 937a044 commit 2cbe011

File tree

3 files changed

+120
-1
lines changed

3 files changed

+120
-1
lines changed

src/DI/ContainerBuilder.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,8 @@ private function resolveImplement(ServiceDefinition $def, $name)
454454
$hint = Reflection::getParameterType($param);
455455
if (isset($ctorParams[$param->getName()])) {
456456
$arg = $ctorParams[$param->getName()];
457-
if ($hint !== Reflection::getParameterType($arg)) {
457+
$argHint = Reflection::getParameterType($arg);
458+
if ($hint !== $argHint && !is_a($hint, $argHint, true)) {
458459
throw new ServiceCreationException("Type hint for \${$param->getName()} in $methodName doesn't match type hint in $class constructor.");
459460
}
460461
$def->getFactory()->arguments[$arg->getPosition()] = self::literal('$' . $arg->getName());
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
/**
4+
* Test: Nette\DI\Compiler: generated services factories from interfaces with class type hints in parameters.
5+
*/
6+
7+
use Nette\DI;
8+
use Tester\Assert;
9+
10+
11+
require __DIR__ . '/../bootstrap.php';
12+
13+
interface IShape
14+
{
15+
public function getName();
16+
}
17+
18+
class Circle implements IShape
19+
{
20+
public function getName()
21+
{
22+
return 'circle';
23+
}
24+
}
25+
26+
class Triangle implements IShape
27+
{
28+
public function getName()
29+
{
30+
return 'triangle';
31+
}
32+
}
33+
34+
class Ellipse extends Circle
35+
{
36+
public function getName()
37+
{
38+
return 'ellipse';
39+
}
40+
}
41+
42+
interface ICircleFactory
43+
{
44+
/** @return Picture */
45+
public function create(Circle $shape);
46+
}
47+
48+
interface ITriangleFactory
49+
{
50+
/** @return Picture */
51+
public function create(Triangle $shape);
52+
}
53+
54+
interface IEllipseFactory
55+
{
56+
/** @return Picture */
57+
public function create(Ellipse $shape);
58+
}
59+
60+
class Picture
61+
{
62+
public $shape;
63+
64+
65+
public function __construct(IShape $shape)
66+
{
67+
$this->shape = $shape;
68+
}
69+
70+
71+
public function getName()
72+
{
73+
return $this->shape->getName();
74+
}
75+
}
76+
77+
$compiler = new DI\Compiler;
78+
$container = createContainer($compiler, 'files/compiler.generatedFactory.polymorphism.neon');
79+
80+
Assert::type(ICircleFactory::class, $container->getService('circle'));
81+
$picture = $container->getService('circle')->create(new Circle);
82+
Assert::type(Picture::class, $picture);
83+
Assert::same('circle', $picture->getName());
84+
85+
Assert::type(ITriangleFactory::class, $container->getService('triangle'));
86+
$picture = $container->getService('triangle')->create(new Triangle);
87+
Assert::type(Picture::class, $picture);
88+
Assert::same('triangle', $picture->getName());
89+
90+
Assert::type(IEllipseFactory::class, $container->getService('ellipse'));
91+
$picture = $container->getService('ellipse')->create(new Ellipse);
92+
Assert::type(Picture::class, $picture);
93+
Assert::same('ellipse', $picture->getName());
94+
95+
Assert::type(ICircleFactory::class, $container->getService('circle'));
96+
$picture = $container->getService('circle')->create(new Ellipse);
97+
Assert::type(Picture::class, $picture);
98+
Assert::same('ellipse', $picture->getName());
99+
100+
if (PHP_VERSION_ID < 70000) {
101+
Assert::error(function () use ($container) {
102+
$container->getService('ellipse')->create(new Circle);
103+
}, E_RECOVERABLE_ERROR);
104+
} else {
105+
Assert::throws(function () use ($container) {
106+
$container->getService('ellipse')->create(new Circle);
107+
}, TypeError::class);
108+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
services:
2+
3+
circle:
4+
implement: ICircleFactory
5+
6+
triangle:
7+
implement: ITriangleFactory
8+
9+
ellipse:
10+
implement: IEllipseFactory

0 commit comments

Comments
 (0)