[DependencyInjection] Use current class as default class for factory declarations
This commit is contained in:
parent
4e665548c2
commit
e6d85700d5
@ -4,6 +4,7 @@ CHANGELOG
|
||||
3.3.0
|
||||
-----
|
||||
|
||||
* added support for omitting the factory class name in a service definition if the definition class is set
|
||||
* deprecated case insensitivity of service identifiers
|
||||
* added "iterator" argument type for lazy iteration over a set of values and services
|
||||
* added "closure-proxy" argument type for turning services' methods into lazy callables
|
||||
|
@ -50,6 +50,7 @@ class PassConfig
|
||||
new ResolveDefinitionTemplatesPass(),
|
||||
new DecoratorServicePass(),
|
||||
new ResolveParameterPlaceHoldersPass(),
|
||||
new ResolveFactoryClassPass(),
|
||||
new FactoryReturnTypePass($resolveClassPass),
|
||||
new CheckDefinitionValidityPass(),
|
||||
new ResolveReferencesToAliasesPass(),
|
||||
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
|
||||
*/
|
||||
class ResolveFactoryClassPass extends AbstractRecursivePass
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if ($value instanceof Definition && is_array($factory = $value->getFactory()) && null === $factory[0]) {
|
||||
if (null === $class = $value->getClass()) {
|
||||
throw new RuntimeException(sprintf('The "%s" service is defined to be created by a factory, but is missing the factory class. Did you forget to define the factory or service class?', $this->currentId));
|
||||
}
|
||||
|
||||
$factory[0] = $class;
|
||||
$value->setFactory($factory);
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
}
|
@ -176,7 +176,9 @@ class XmlDumper extends Dumper
|
||||
$this->addService($callable[0], null, $factory);
|
||||
$factory->setAttribute('method', $callable[1]);
|
||||
} elseif (is_array($callable)) {
|
||||
$factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]);
|
||||
if (null !== $callable[0]) {
|
||||
$factory->setAttribute($callable[0] instanceof Reference ? 'service' : 'class', $callable[0]);
|
||||
}
|
||||
$factory->setAttribute('method', $callable[1]);
|
||||
} else {
|
||||
$factory->setAttribute('function', $callable);
|
||||
|
@ -257,7 +257,7 @@ class XmlFileLoader extends FileLoader
|
||||
} elseif ($childService = $factory->getAttribute('service')) {
|
||||
$class = new Reference($childService, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false);
|
||||
} else {
|
||||
$class = $factory->getAttribute('class');
|
||||
$class = $factory->hasAttribute('class') ? $factory->getAttribute('class') : null;
|
||||
}
|
||||
|
||||
$definition->setFactory(array($class, $factory->getAttribute('method')));
|
||||
|
@ -466,6 +466,10 @@ class YamlFileLoader extends FileLoader
|
||||
return array($this->resolveServices($callable[0]), $callable[1]);
|
||||
}
|
||||
|
||||
if ('factory' === $parameter && isset($callable[1]) && null === $callable[0]) {
|
||||
return $callable;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('Parameter "%s" must contain an array with two elements for service "%s" in %s. Check your YAML syntax.', $parameter, $id, $file));
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\ResolveFactoryClassPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
class ResolveFactoryClassPassTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testProcess()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
||||
$factory = $container->register('factory', 'Foo\Bar');
|
||||
$factory->setFactory(array(null, 'create'));
|
||||
|
||||
$pass = new ResolveFactoryClassPass();
|
||||
$pass->process($container);
|
||||
|
||||
$this->assertSame(array('Foo\Bar', 'create'), $factory->getFactory());
|
||||
}
|
||||
|
||||
public function testInlinedDefinitionFactoryIsProcessed()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
||||
$factory = $container->register('factory');
|
||||
$factory->setFactory(array((new Definition('Baz\Qux'))->setFactory(array(null, 'getInstance')), 'create'));
|
||||
|
||||
$pass = new ResolveFactoryClassPass();
|
||||
$pass->process($container);
|
||||
|
||||
$this->assertSame(array('Baz\Qux', 'getInstance'), $factory->getFactory()[0]->getFactory());
|
||||
}
|
||||
|
||||
public function provideFulfilledFactories()
|
||||
{
|
||||
return array(
|
||||
array(array('Foo\Bar', 'create')),
|
||||
array(array(new Reference('foo'), 'create')),
|
||||
array(array(new Definition('Baz'), 'create')),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideFulfilledFactories
|
||||
*/
|
||||
public function testIgnoresFulfilledFactories($factory)
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$definition = new Definition();
|
||||
$definition->setFactory($factory);
|
||||
|
||||
$container->setDefinition('factory', $definition);
|
||||
|
||||
$pass = new ResolveFactoryClassPass();
|
||||
$pass->process($container);
|
||||
|
||||
$this->assertSame($factory, $container->getDefinition('factory')->getFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||
* @expectedExceptionMessage The "factory" service is defined to be created by a factory, but is missing the factory class. Did you forget to define the factory or service class?
|
||||
*/
|
||||
public function testNotAnyClassThrowsException()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
||||
$factory = $container->register('factory');
|
||||
$factory->setFactory(array(null, 'create'));
|
||||
|
||||
$pass = new ResolveFactoryClassPass();
|
||||
$pass->process($container);
|
||||
}
|
||||
}
|
@ -58,5 +58,8 @@
|
||||
<service id="new_factory3" class="FooBarClass">
|
||||
<factory class="BazClass" method="getInstance" />
|
||||
</service>
|
||||
<service id="new_factory4" class="BazClass">
|
||||
<factory method="getInstance" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
@ -39,4 +39,5 @@ services:
|
||||
new_factory1: { class: FooBarClass, factory: factory}
|
||||
new_factory2: { class: FooBarClass, factory: ['@baz', getClass]}
|
||||
new_factory3: { class: FooBarClass, factory: [BazClass, getInstance]}
|
||||
new_factory4: { class: BazClass, factory: [~, getInstance]}
|
||||
with_shortcut_args: [foo, '@baz']
|
||||
|
@ -246,6 +246,7 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('factory', $services['new_factory1']->getFactory(), '->load() parses the factory tag');
|
||||
$this->assertEquals(array(new Reference('baz', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false), 'getClass'), $services['new_factory2']->getFactory(), '->load() parses the factory tag');
|
||||
$this->assertEquals(array('BazClass', 'getInstance'), $services['new_factory3']->getFactory(), '->load() parses the factory tag');
|
||||
$this->assertSame(array(null, 'getInstance'), $services['new_factory4']->getFactory(), '->load() accepts factory tag without class');
|
||||
|
||||
$aliases = $container->getAliases();
|
||||
$this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses <service> elements');
|
||||
|
@ -153,6 +153,7 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals('factory', $services['new_factory1']->getFactory(), '->load() parses the factory tag');
|
||||
$this->assertEquals(array(new Reference('baz'), 'getClass'), $services['new_factory2']->getFactory(), '->load() parses the factory tag');
|
||||
$this->assertEquals(array('BazClass', 'getInstance'), $services['new_factory3']->getFactory(), '->load() parses the factory tag');
|
||||
$this->assertSame(array(null, 'getInstance'), $services['new_factory4']->getFactory(), '->load() accepts factory tag without class');
|
||||
$this->assertEquals(array('foo', new Reference('baz')), $services['with_shortcut_args']->getArguments(), '->load() parses short service definition');
|
||||
|
||||
$aliases = $container->getAliases();
|
||||
|
Reference in New Issue
Block a user