Skip to content

Commit 481646e

Browse files
committed
ContainerBuilder::resolveEntityClass() checking whether factory is callable counts with interfaces and traits [Closes #32]
1 parent 9ad7c71 commit 481646e

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

src/DI/ContainerBuilder.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,15 +376,16 @@ private function resolveEntityClass($entity, $recursive = array())
376376

377377
try {
378378
$reflection = Nette\Utils\Callback::toReflection($entity);
379+
$refClass = $reflection instanceof \ReflectionMethod ? $reflection->getDeclaringClass() : NULL;
379380
} catch (\ReflectionException $e) {
380381
}
381-
if (isset($e) || !is_callable($entity)) {
382+
if (isset($e) || ($refClass && !$reflection->isPublic() || !($reflection->isStatic() || $refClass->isInstantiable() || $refClass->isInterface()))) {
382383
$name = array_slice(array_keys($recursive), -1);
383384
throw new ServiceCreationException(sprintf("Factory '%s' used in service '%s' is not callable.", Nette\Utils\Callback::toString($entity), $name[0]));
384385
}
385386
$class = preg_replace('#[|\s].*#', '', $reflection->getAnnotation('return'));
386-
if ($class && $reflection instanceof \ReflectionMethod) {
387-
$class = Reflection\AnnotationsParser::expandClassName($class, $reflection->getDeclaringClass());
387+
if ($class && $refClass) {
388+
$class = Reflection\AnnotationsParser::expandClassName($class, $refClass);
388389
}
389390
return $class;
390391

tests/DI/ContainerBuilder.byClass.phpt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,16 @@ use Nette\DI,
1111
require __DIR__ . '/../bootstrap.php';
1212

1313

14-
class Factory
14+
interface IFactory
15+
{
16+
static function create();
17+
}
18+
19+
class Factory implements IFactory
1520
{
1621
public static $methods;
1722

18-
static function create($arg)
23+
static function create()
1924
{
2025
self::$methods[] = array(__FUNCTION__, func_get_args());
2126
return new stdClass;
@@ -59,6 +64,11 @@ $builder->addDefinition('four')
5964
->setAutowired(FALSE)
6065
->setFactory('@\AnnotatedFactory::create');
6166

67+
$builder->addDefinition('five')
68+
->setAutowired(FALSE)
69+
->setFactory('@\IFactory::create');
70+
71+
6272

6373
$container = createContainer($builder);
6474

@@ -85,3 +95,5 @@ Assert::type( 'stdClass', $container->getService('four') );
8595
Assert::same(array(
8696
array('create', array()),
8797
), $annotatedFactory->methods);
98+
99+
Assert::type( 'stdClass', $container->getService('five') );
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/**
4+
* Test: Nette\DI\ContainerBuilder and generated factories errors.
5+
* @phpversion 5.4
6+
*/
7+
8+
use Nette\DI,
9+
Tester\Assert;
10+
11+
12+
require __DIR__ . '/../bootstrap.php';
13+
14+
15+
trait Bad1
16+
{
17+
function method() {}
18+
}
19+
20+
Assert::exception(function() {
21+
$builder = new DI\ContainerBuilder;
22+
$builder->addDefinition('one')->setFactory('Bad1::method');
23+
$builder->generateClasses();
24+
}, 'Nette\InvalidStateException', "Factory 'Bad1::method' used in service 'one' is not callable.");

0 commit comments

Comments
 (0)