feature #20634 [DI] Deprecate dumping an uncompiled container (ro0NL)

This PR was squashed before being merged into the 3.3-dev branch (closes #20634).

Discussion
----------

[DI] Deprecate dumping an uncompiled container

| Q             | A
| ------------- | ---
| Branch?       | "master"
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | yes
| Tests pass?   | yes
| Fixed tickets | https://github.com/symfony/symfony/pull/19673#issuecomment-242001836
| License       | MIT
| Doc PR        | reference to the documentation PR, if any

It makes the PHP dumper less complex. Compiled container goes in, compiled container goes out.

Relates to #19673

Commits
-------

da50fdb [DI] Deprecate dumping an uncompiled container
This commit is contained in:
Fabien Potencier 2016-12-19 09:23:26 +01:00
commit ed5b1d8968
7 changed files with 201 additions and 18 deletions

View File

@ -72,6 +72,10 @@ class PhpDumper extends Dumper
*/
public function __construct(ContainerBuilder $container)
{
if (!$container->isFrozen()) {
@trigger_error('Dumping an uncompiled ContainerBuilder is deprecated since version 3.3 and will not be supported anymore in 4.0. Compile the container beforehand.', E_USER_DEPRECATED);
}
parent::__construct($container);
$this->inlinedDefinitions = new \SplObjectStorage();

View File

@ -35,12 +35,15 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
public function testDump()
{
$dumper = new PhpDumper($container = new ContainerBuilder());
$container = new ContainerBuilder();
$container->compile();
$dumper = new PhpDumper($container);
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services1.php', $dumper->dump(), '->dump() dumps an empty container as an empty PHP class');
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services1-1.php', $dumper->dump(array('class' => 'Container', 'base_class' => 'AbstractContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Dump')), '->dump() takes a class and a base_class options');
$container = new ContainerBuilder();
$container->compile();
new PhpDumper($container);
}
@ -97,7 +100,9 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
*/
public function testExportParameters($parameters)
{
$dumper = new PhpDumper(new ContainerBuilder(new ParameterBag($parameters)));
$container = new ContainerBuilder(new ParameterBag($parameters));
$container->compile();
$dumper = new PhpDumper($container);
$dumper->dump();
}
@ -114,25 +119,33 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
public function testAddParameters()
{
$container = include self::$fixturesPath.'/containers/container8.php';
$container->compile();
$dumper = new PhpDumper($container);
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services8.php', $dumper->dump(), '->dump() dumps parameters');
}
public function testAddService()
/**
* @group legacy
* @expectedDeprecation Dumping an uncompiled ContainerBuilder is deprecated since version 3.3 and will not be supported anymore in 4.0. Compile the container beforehand.
*/
public function testAddServiceWithoutCompilation()
{
// without compilation
$container = include self::$fixturesPath.'/containers/container9.php';
$dumper = new PhpDumper($container);
$this->assertEquals(str_replace('%path%', str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9.php')), $dumper->dump(), '->dump() dumps services');
}
// with compilation
public function testAddService()
{
$container = include self::$fixturesPath.'/containers/container9.php';
$container->compile();
$dumper = new PhpDumper($container);
$this->assertEquals(str_replace('%path%', str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9_compiled.php')), $dumper->dump(), '->dump() dumps services');
$dumper = new PhpDumper($container = new ContainerBuilder());
$container = new ContainerBuilder();
$container->register('foo', 'FooClass')->addArgument(new \stdClass());
$container->compile();
$dumper = new PhpDumper($container);
try {
$dumper->dump();
$this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources');
@ -145,6 +158,7 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
public function testServicesWithAnonymousFactories()
{
$container = include self::$fixturesPath.'/containers/container19.php';
$container->compile();
$dumper = new PhpDumper($container);
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services19.php', $dumper->dump(), '->dump() dumps services with anonymous factories');
@ -156,6 +170,7 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
$container = new ContainerBuilder();
$container->register('bar$', 'FooClass');
$container->register('bar$!', 'FooClass');
$container->compile();
$dumper = new PhpDumper($container);
eval('?>'.$dumper->dump(array('class' => $class)));
@ -169,6 +184,7 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
$container = new ContainerBuilder();
$container->register('foo_bar', 'FooClass');
$container->register('foobar', 'FooClass');
$container->compile();
$dumper = new PhpDumper($container);
eval('?>'.$dumper->dump(array('class' => $class)));
@ -182,6 +198,7 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
$container = new ContainerBuilder();
$container->register('bar', 'FooClass');
$container->register('foo_bar', 'FooClass');
$container->compile();
$dumper = new PhpDumper($container);
eval('?>'.$dumper->dump(array(
'class' => $class,
@ -203,6 +220,7 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
$def = new Definition('stdClass');
$def->setFactory($factory);
$container->setDefinition('bar', $def);
$container->compile();
$dumper = new PhpDumper($container);
$dumper->dump();
}
@ -285,6 +303,7 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase
public function testDumpAutowireData()
{
$container = include self::$fixturesPath.'/containers/container24.php';
$container->compile();
$dumper = new PhpDumper($container);
$this->assertEquals(file_get_contents(self::$fixturesPath.'/php/services24.php'), $dumper->dump());

View File

@ -6,7 +6,7 @@ use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
/**
* Container.
@ -24,6 +24,24 @@ class Container extends AbstractContainer
*/
public function __construct()
{
parent::__construct();
$this->services = array();
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped frozen container.');
}
/**
* {@inheritdoc}
*/
public function isFrozen()
{
return true;
}
}

View File

@ -5,7 +5,7 @@ use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
/**
* ProjectServiceContainer.
@ -23,6 +23,24 @@ class ProjectServiceContainer extends Container
*/
public function __construct()
{
parent::__construct();
$this->services = array();
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped frozen container.');
}
/**
* {@inheritdoc}
*/
public function isFrozen()
{
return true;
}
}

View File

@ -5,7 +5,7 @@ use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
/**
* ProjectServiceContainer.
@ -23,11 +23,29 @@ class ProjectServiceContainer extends Container
*/
public function __construct()
{
parent::__construct();
$this->services = array();
$this->methodMap = array(
'service_from_anonymous_factory' => 'getServiceFromAnonymousFactoryService',
'service_with_method_call_and_factory' => 'getServiceWithMethodCallAndFactoryService',
);
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped frozen container.');
}
/**
* {@inheritdoc}
*/
public function isFrozen()
{
return true;
}
/**

View File

@ -5,7 +5,7 @@ use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
/**
* ProjectServiceContainer.
@ -23,10 +23,28 @@ class ProjectServiceContainer extends Container
*/
public function __construct()
{
parent::__construct();
$this->services = array();
$this->methodMap = array(
'foo' => 'getFooService',
);
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped frozen container.');
}
/**
* {@inheritdoc}
*/
public function isFrozen()
{
return true;
}
/**

View File

@ -5,7 +5,7 @@ use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
/**
* ProjectServiceContainer.
@ -23,7 +23,95 @@ class ProjectServiceContainer extends Container
*/
public function __construct()
{
parent::__construct(new ParameterBag($this->getDefaultParameters()));
$this->parameters = $this->getDefaultParameters();
$this->services = array();
$this->aliases = array();
}
/**
* {@inheritdoc}
*/
public function compile()
{
throw new LogicException('You cannot compile a dumped frozen container.');
}
/**
* {@inheritdoc}
*/
public function isFrozen()
{
return true;
}
/**
* {@inheritdoc}
*/
public function getParameter($name)
{
$name = strtolower($name);
if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) {
throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name));
}
if (isset($this->loadedDynamicParameters[$name])) {
return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
}
return $this->parameters[$name];
}
/**
* {@inheritdoc}
*/
public function hasParameter($name)
{
$name = strtolower($name);
return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]);
}
/**
* {@inheritdoc}
*/
public function setParameter($name, $value)
{
throw new LogicException('Impossible to call set() on a frozen ParameterBag.');
}
/**
* {@inheritdoc}
*/
public function getParameterBag()
{
if (null === $this->parameterBag) {
$parameters = $this->parameters;
foreach ($this->loadedDynamicParameters as $name => $loaded) {
$parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name);
}
$this->parameterBag = new FrozenParameterBag($parameters);
}
return $this->parameterBag;
}
private $loadedDynamicParameters = array();
private $dynamicParameters = array();
/**
* Computes a dynamic parameter.
*
* @param string The name of the dynamic parameter to load
*
* @return mixed The value of the dynamic parameter
*
* @throws InvalidArgumentException When the dynamic parameter does not exist
*/
private function getDynamicParameter($name)
{
throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name));
}
/**
@ -34,9 +122,9 @@ class ProjectServiceContainer extends Container
protected function getDefaultParameters()
{
return array(
'foo' => '%baz%',
'foo' => 'bar',
'baz' => 'bar',
'bar' => 'foo is %%foo bar',
'bar' => 'foo is %foo bar',
'escape' => '@escapeme',
'values' => array(
0 => true,