Skip to content

Commit

Permalink
autowiring via Service[] (#178)
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Oct 25, 2018
1 parent ac2ed7b commit 55f9894
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 2 deletions.
17 changes: 16 additions & 1 deletion src/DI/Autowiring.php
Expand Up @@ -153,7 +153,7 @@ public function rebuild(): void
* @param Resolver|Container $container
* @throws ServiceCreationException
*/
public static function completeArguments(\ReflectionFunctionAbstract $method, array $arguments, $container): array
public static function completeArguments(\ReflectionFunctionAbstract $method, array $arguments, $container, Definitions\Definition $current = null): array
{
$optCount = 0;
$num = -1;
Expand Down Expand Up @@ -192,6 +192,21 @@ public static function completeArguments(\ReflectionFunctionAbstract $method, ar
$optCount = 0;
}

} elseif (
$container instanceof Resolver
&& $method instanceof \ReflectionMethod
&& $parameter->isArray()
&& preg_match('#@param[ \t]+([\w\\\\]+)\[\][ \t]+\$' . $paramName . '#', (string) $method->getDocComment(), $m)
&& ($type = Reflection::expandClassName($m[1], $method->getDeclaringClass()))
&& (class_exists($type) || interface_exists($type))
) {
$res[$num] = [];
foreach ($container->getContainerBuilder()->findByType($type) as $def) {
if ($def !== $current) {
$res[$num][] = $def;
}
}

} elseif (($type && $parameter->allowsNull()) || $parameter->isOptional() || $parameter->isDefaultValueAvailable()) {
// !optional + defaultAvailable = func($a = null, $b) since 5.4.7
// optional + !defaultAvailable = i.e. Exception::__construct, mysqli::mysqli, ...
Expand Down
2 changes: 1 addition & 1 deletion src/DI/Resolver.php
Expand Up @@ -429,7 +429,7 @@ private function autowireArguments(\ReflectionFunctionAbstract $function, array
if (!$function->isClosure()) {
$this->addDependency($function);
}
return Autowiring::completeArguments($function, $arguments, $this);
return Autowiring::completeArguments($function, $arguments, $this, $this->currentService);
}


Expand Down
68 changes: 68 additions & 0 deletions tests/DI/ContainerBuilder.autowiring.type[].phpt
@@ -0,0 +1,68 @@
<?php

/**
* Test: Nette\DI\ContainerBuilder and typehint Service[].
*/

declare(strict_types=1);

use Nette\DI;
use Tester\Assert;


require __DIR__ . '/../bootstrap.php';


class Foo
{
public $bars;
public $foos;
public $strings;


/**
* @param Service[] $bars
* @param Foo[] $foos
* @param string[] $strings
*/
public function __construct(array $bars = [], array $foos = null, array $strings = ['default'])
{
$this->bars = $bars;
$this->foos = $foos;
$this->strings = $strings;
}
}

class Service
{
}

class ServiceChild extends Service
{
}


$builder = new DI\ContainerBuilder;

$builder->addDefinition('foo')
->setType('Foo');
$builder->addDefinition('s1')
->setType('Service');
$builder->addDefinition('s2')
->setType('Service');
$builder->addDefinition('s3')
->setType('ServiceChild');
$builder->addDefinition('s4')
->setType('stdClass');

$container = createContainer($builder);

$foo = $container->getService('foo');
Assert::type(Foo::class, $foo);
Assert::same([
$container->getService('s1'),
$container->getService('s2'),
$container->getService('s3'),
], $foo->bars);
Assert::same([], $foo->foos);
Assert::same(['default'], $foo->strings);

0 comments on commit 55f9894

Please sign in to comment.