Skip to content

Commit

Permalink
ContainerBuilder::resolveEntityClass() checking whether factory is ca…
Browse files Browse the repository at this point in the history
…llable counts with interfaces and traits [Closes #32]
  • Loading branch information
dg committed Jan 15, 2015
1 parent 9ad7c71 commit 3f5484f
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 5 deletions.
11 changes: 8 additions & 3 deletions src/DI/ContainerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -376,15 +376,20 @@ private function resolveEntityClass($entity, $recursive = array())

try {
$reflection = Nette\Utils\Callback::toReflection($entity);
$refClass = $reflection instanceof \ReflectionMethod ? $reflection->getDeclaringClass() : NULL;
} catch (\ReflectionException $e) {
}
if (isset($e) || !is_callable($entity)) {

if (isset($e) || ($refClass && (!$reflection->isPublic()
|| (PHP_VERSION_ID >= 50400 && $refClass->isTrait() && !$reflection->isStatic())
))) {

This comment has been minimized.

Copy link
@enumag

enumag Jan 26, 2015

Contributor

$refClass->isTrait() will never be true because $reflection->getDeclaringClass() does not return traits. Use the new method from nette/reflection instead. That should fix problems with use statements and return annotations as well.

This comment has been minimized.

Copy link
@dg

dg Jan 26, 2015

Author Member

Can you send PR?

$name = array_slice(array_keys($recursive), -1);
throw new ServiceCreationException(sprintf("Factory '%s' used in service '%s' is not callable.", Nette\Utils\Callback::toString($entity), $name[0]));
}

$class = preg_replace('#[|\s].*#', '', $reflection->getAnnotation('return'));
if ($class && $reflection instanceof \ReflectionMethod) {
$class = Reflection\AnnotationsParser::expandClassName($class, $reflection->getDeclaringClass());
if ($class && $refClass) {
$class = Reflection\AnnotationsParser::expandClassName($class, $refClass);
}
return $class;

Expand Down
40 changes: 38 additions & 2 deletions tests/DI/ContainerBuilder.byClass.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,16 @@ use Nette\DI,
require __DIR__ . '/../bootstrap.php';


class Factory
interface IFactory
{
static function create();
}

class Factory implements IFactory
{
public static $methods;

static function create($arg)
static function create()
{
self::$methods[] = array(__FUNCTION__, func_get_args());
return new stdClass;
Expand All @@ -37,6 +42,22 @@ class AnnotatedFactory
}


class UninstantiableFactory
{
public static function getInstance()
{
return new self;
}

private function __construct()
{}

/** @return stdClass */
function create()
{}
}


$builder = new DI\ContainerBuilder;
$builder->addDefinition('factory')
->setClass('Factory');
Expand All @@ -59,6 +80,19 @@ $builder->addDefinition('four')
->setAutowired(FALSE)
->setFactory('@\AnnotatedFactory::create');

$builder->addDefinition('five')
->setAutowired(FALSE)
->setFactory('@\IFactory::create');

$builder->addDefinition('uninstantiableFactory')
->setClass('UninstantiableFactory')
->setFactory('UninstantiableFactory::getInstance');

$builder->addDefinition('six')
->setAutowired(FALSE)
->setFactory('@\UninstantiableFactory::create');



$container = createContainer($builder);

Expand All @@ -85,3 +119,5 @@ Assert::type( 'stdClass', $container->getService('four') );
Assert::same(array(
array('create', array()),
), $annotatedFactory->methods);

Assert::type( 'stdClass', $container->getService('five') );
24 changes: 24 additions & 0 deletions tests/DI/ContainerBuilder.factory.error2.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/**
* Test: Nette\DI\ContainerBuilder and generated factories errors.
* @phpversion 5.4
*/

use Nette\DI,
Tester\Assert;


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


trait Bad1
{
function method() {}
}

Assert::exception(function() {
$builder = new DI\ContainerBuilder;
$builder->addDefinition('one')->setFactory('Bad1::method');
$builder->generateClasses();
}, 'Nette\InvalidStateException', "Factory 'Bad1::method' used in service 'one' is not callable.");

0 comments on commit 3f5484f

Please sign in to comment.