8000 always call the parent class' constructor · symfony/symfony@34d463a · GitHub
[go: up one dir, main page]

Skip to content

Commit 34d463a

Browse files
committed
always call the parent class' constructor
1 parent 8d4e3c5 commit 34d463a

10 files changed

+324
-4
lines changed

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ public function dump(array $options = array())
128128

129129
if (0 !== strpos($baseClass = $options['base_class'], '\\') && 'Container' !== $baseClass) {
130130
$baseClass = sprintf('%s\%s', $options['namespace'] ? '\\'.$options['namespace'] : '', $baseClass);
131+
$baseClassWithNamespace = $baseClass;
132+
} elseif ('Container' === $baseClass) {
133+
$baseClassWithNamespace = 'Symfony\Component\DependencyInjection\Container';
134+
} else {
135+
$baseClassWithNamespace = $baseClass;
131136
}
132137

133138
$this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass);
@@ -169,7 +174,7 @@ public function dump(array $options = array())
169174
}
170175

171176
$code =
172-
$this->startClass($options['class'], $baseClass).
177+
$this->startClass($options['class'], $baseClass, $baseClassWithNamespace).
173178
$this->addServices().
174179
$this->addDefaultParametersMethod().
175180
$this->endClass()
@@ -917,12 +922,13 @@ private function addNewInstance(Definition $definition, $return, $instantiation,
917922
/**
918923
* Adds the class headers.
919924
*
920-
* @param string $class Class name
921-
* @param string $baseClass The name of the base class
925+
* @param string $class Class name
926+
* @param string $baseClass The name of the base class
927+
* @param string $baseClassWithNamespace Fully qualified base class name
922928
*
923929
* @return string
924930
*/
925-
private function startClass($class, $baseClass)
931+
private function startClass($class, $baseClass, $baseClassWithNamespace)
926932
{
927933
$bagClass = $this->container->isCompiled() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;';
928934
$namespaceLine = !$this->asFiles && $this->namespace ? "\nnamespace {$this->namespace};\n" : '';
@@ -970,9 +976,22 @@ public function __construct()
970976
}
971977

972978
if ($this->container->isCompiled()) {
979+
if (Container::class !== $baseClassWithNamespace) {
980+
try {
981+
$r = $this->container->getReflectionClass($baseClassWithNamespace);
982+
983+
if (null !== $r && (null !== $constructor = $r->getConstructor()) && 0 === $constructor->getNumberOfRequiredParameters()) {
984+
$code .= " parent::__construct();\n\n";
985+
}
986+
} catch (\ReflectionException $e) {
987+
// do not add parent constructor calls if the base class cannot be found
988+
}
989+
}
990+
973991
if ($this->container->getParameterBag()->all()) {
974992
$code .= " \$this->parameters = \$this->getDefaultParameters();\n\n";
975993
}
994+
976995
$code .= " \$this->services = array();\n";
977996
} else {
978997
$arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null;

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,46 @@ public function testDumpRelativeDir()
107107
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services12.php', $dumper->dump(array('file' => __FILE__)), '->dump() dumps __DIR__ relative strings');
108108
}
109109

110+
public function testDumpCustomContainerClassWithoutConstructor()
111+
{
112+
$container = new ContainerBuilder();
113+
$container->compile();
114+
115+
$dumper = new PhpDumper($container);
116+
117+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_without_constructor.php', $dumper->dump(array('base_class' => 'NoConstructorContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container')));
118+
}
119+
120+
public function testDumpCustomContainerClassConstructorWithoutArguments()
121+
{
122+
$container = new ContainerBuilder();
123+
$container->compile();
124+
125+
$dumper = new PhpDumper($container);
126+
127+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_constructor_without_arguments.php', $dumper->dump(array('base_class' => 'ConstructorWithoutArgumentsContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container')));
128+
}
129+
130+
public function testDumpCustomContainerClassWithOptionalArgumentLessConstructor()
131+
{
132+
$container = new ContainerBuilder();
133+
$container->compile();
134+
135+
$dumper = new PhpDumper($container);
136+
137+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_with_optional_constructor_arguments.php', $dumper->dump(array('base_class' => 'ConstructorWithOptionalArgumentsContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container')));
138+
}
139+
140+
public function testDumpCustomContainerClassWithMandatoryArgumentLessConstructor()
141+
{
142+
$container = new ContainerBuilder();
143+
$container->compile();
144+
145+
$dumper = new PhpDumper($container);
146+
147+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/custom_container_class_with_mandatory_constructor_arguments.php', $dumper->dump(array('base_class' => 'ConstructorWithMandatoryArgumentsContainer', 'namespace' => 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container')));
148+
}
149+
110150
/**
111151
* @dataProvider provideInvalidParameters
112152
* @expectedException \InvalidArgumentException
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Container;
4+
5+
class ConstructorWithMandatoryArgumentsContainer
6+
{
7+
public function __construct($mandatoryArgument)
8+
{
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Container;
4+
5+
class ConstructorWithOptionalArgumentsContainer
6+
{
7+
public function __construct($optionalArgument = 'foo')
8+
{
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Container;
4+
5+
class ConstructorWithoutArgumentsContainer
6+
{
7+
public function __construct()
8+
{
9+
}
10+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Container;
4+
5+
class NoConstructorContainer
6+
{
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Container;
4+
5+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
6+
use Symfony\Component\DependencyInjection\ContainerInterface;
7+
use Symfony\Component\DependencyInjection\Container;
8+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
9+
use Symfony\Component\DependencyInjection\Exception\LogicException;
10+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
11+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
12+
13+
/**
14+
* This class has been auto-generated
15+
* by the Symfony Dependency Injection Component.
16+
*
17+
* @final since Symfony 3.3
18+
*/
19+
class ProjectServiceContainer extends \Symfony\Component\DependencyInjection\Tests\Fixtures\Container\ConstructorWithoutArgumentsContainer
20+
{
21+
private $parameters;
22+
private $targetDirs = array();
23+
24+
public function __construct()
25+
{
26+
parent::__construct();
27+
28+
$this->services = array();
29+
30+
$this->aliases = array();
31+
}
32+
33+
public function getRemovedIds()
34+
{
35+
return array(
36+
'Psr\\Container\\ContainerInterface' => true,
37+
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
38+
);
39+
}
40+
41+
public function compile()
42+
{
43+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
44+
}
45+
46+
public function isCompiled()
47+
{
48+
return true;
49+
}
50+
51+
public function isFrozen()
52+
{
53+
@trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
54+
55+
return true;
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Container;
4+
5+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
6+
use Symfony\Component\DependencyInjection\ContainerInterface;
7+
use Symfony\Component\DependencyInjection\Container;
8+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
9+
use Symfony\Component\DependencyInjection\Exception\LogicException;
10+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
11+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
12+
13+
/**
14+
* This class has been auto-generated
15+
* by the Symfony Dependency Injection Component.
16+
*
17+
* @final since Symfony 3.3
18+
*/
19+
class ProjectServiceContainer extends \Symfony\Component\DependencyInjection\Tests\Fixtures\Container\ConstructorWithMandatoryArgumentsContainer
20+
{
21+
private $parameters;
22+
private $targetDirs = array();
23+
24+
public function __construct()
25+
{
26+
$this->services = array();
27+
28+
$this->aliases = array();
29+
}
30+
31+
public function getRemovedIds()
32+
{
33+
return array(
34+
'Psr\\Container\\ContainerInterface' => true,
35+
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
36+
);
37+
}
38+
39+
public function compile()
40+
{
41+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
42+
}
43+
44+
public function isCompiled()
45+
{
46+
return true;
47+
}
48+
49+
public function isFrozen()
50+
{
51+
@trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
52+
53+
return true;
54+
}
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Container;
4+
5+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
6+
use Symfony\Component\DependencyInjection\ContainerInterface;
7+
use Symfony\Component\DependencyInjection\Container;
8+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
9+
use Symfony\Component\DependencyInjection\Exception\LogicException;
10+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
11+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
12+
13+
/**
14+
* This class has been auto-generated
15+
* by the Symfony Dependency Injection Component.
16+
*
17+
* @final since Symfony 3.3
18+
*/
19+
class ProjectServiceContainer extends \Symfony\Component\DependencyInjection\Tests\Fixtures\Container\ConstructorWithOptionalArgumentsContainer
20+
{
21+
private $parameters;
22+
private $targetDirs = array();
23+
24+
public function __construct()
25+
{
26+
parent::__construct();
27+
28+
$this->services = array();
29+
30+
$this->aliases = array();
31+
}
32+
33+
public function getRemovedIds()
34+
{
35+
return array(
36+
'Psr\\Container\\ContainerInterface' => true,
37+
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
38+
);
39+
}
40+
41+
public function compile()
42+
{
43+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
44+
}
45+
46+
public function isCompiled()
47+
{
48+
return true;
49+
}
50+
51+
public function isFrozen()
52+
{
53+
@trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
54+
55+
return true;
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Container;
4+
5+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
6+
use Symfony\Component\DependencyInjection\ContainerInterface;
7+
use Symfony\Component\DependencyInjection\Container;
8+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
9+
use Symfony\Component\DependencyInjection\Exception\LogicException;
10+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
11+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
12+
13+
/**
14+
* This class has been auto-generated
15+
* by the Symfony Dependency Injection Component.
16+
*
17+
* @final since Symfony 3.3
18+
*/
19+
class ProjectServiceContainer extends \Symfony\Component\DependencyInjection\Tests\Fixtures\Container\NoConstructorContainer
20+
{
21+
private $parameters;
22+
private $targetDirs = array();
23+
24+
public function __construct()
25+
{
26+
$this->services = array();
27+
28+
$this->aliases = array();
29+
}
30+
31+
public function getRemovedIds()
32+
{
33+
return array(
34+
'Psr\\Container\\ContainerInterface' => true,
35+
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
36+
);
37+
}
38+
39+
public function compile()
40+
{
41+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
42+
}
43+
44+
public function isCompiled()
45+
{
46+
return true;
47+
}
48+
49+
public function isFrozen()
50+
{
51+
@trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
52+
53+
return true;
54+
}
55+
}

0 commit comments

Comments
 (0)
0