Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 547185f

Browse filesBrowse files
committed
bug #23573 [Config] Make ClassExistenceResource throw on invalid parents (nicolas-grekas)
This PR was merged into the 3.3 branch. Discussion ---------- [Config] Make ClassExistenceResource throw on invalid parents | Q | A | ------------- | --- | Branch? | 3.3 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #23564 | License | MIT | Doc PR | - Let's throw a more specific exception when a parent class/interface/trait is missing. Fine tunes #23041 Commits ------- 53b0190 [Config] Make ClassExistenceResource throw on invalid parents
2 parents cd25294 + 53b0190 commit 547185f
Copy full SHA for 547185f

File tree

6 files changed

+40
-15
lines changed
Filter options

6 files changed

+40
-15
lines changed

‎src/Symfony/Component/Config/Resource/ClassExistenceResource.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Config/Resource/ClassExistenceResource.php
+22-3Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializ
2525
private $exists;
2626

2727
private static $autoloadLevel = 0;
28+
private static $autoloadedClass;
2829
private static $existsCache = array();
2930

3031
/**
@@ -57,6 +58,8 @@ public function getResource()
5758

5859
/**
5960
* {@inheritdoc}
61+
*
62+
* @throws \ReflectionException when a parent class/interface/trait is not found
6063
*/
6164
public function isFresh($timestamp)
6265
{
@@ -68,12 +71,13 @@ public function isFresh($timestamp)
6871
if (!self::$autoloadLevel++) {
6972
spl_autoload_register(__CLASS__.'::throwOnRequiredClass');
7073
}
74+
$autoloadedClass = self::$autoloadedClass;
75+
self::$autoloadedClass = $this->resource;
7176

7277
try {
7378
$exists = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false);
74-
} catch (\ReflectionException $e) {
75-
$exists = false;
7679
} finally {
80+
self::$autoloadedClass = $autoloadedClass;
7781
if (!--self::$autoloadLevel) {
7882
spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass');
7983
}
@@ -112,7 +116,10 @@ public function unserialize($serialized)
112116
*/
113117
private static function throwOnRequiredClass($class)
114118
{
115-
$e = new \ReflectionException("Class $class does not exist");
119+
if (self::$autoloadedClass === $class) {
120+
return;
121+
}
122+
$e = new \ReflectionException("Class $class not found");
116123
$trace = $e->getTrace();
117124
$autoloadFrame = array(
118125
'function' => 'spl_autoload_call',
@@ -138,6 +145,18 @@ private static function throwOnRequiredClass($class)
138145
case 'is_callable':
139146
return;
140147
}
148+
149+
$props = array(
150+
'file' => $trace[$i]['file'],
151+
'line' => $trace[$i]['line'],
152+
'trace' => array_slice($trace, 0, 1 + $i),
153+
);
154+
155+
foreach ($props as $p => $v) {
156+
$r = new \ReflectionProperty('Exception', $p);
157+
$r->setAccessible(true);
158+
$r->setValue($e, $v);
159+
}
141160
}
142161

143162
throw $e;

‎src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
+6-6Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ private function doProcessValue($value, $isRoot = false)
124124
if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) {
125125
return $value;
126126
}
127-
if (!$reflectionClass = $this->container->getReflectionClass($value->getClass())) {
128-
$this->container->log($this, sprintf('Skipping service "%s": Class or interface "%s" does not exist.', $this->currentId, $value->getClass()));
127+
if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) {
128+
$this->container->log($this, sprintf('Skipping service "%s": Class or interface "%s" cannot be loaded.', $this->currentId, $value->getClass()));
129129

130130
return $value;
131131
}
@@ -388,7 +388,7 @@ private function populateAvailableType($id, Definition $definition)
388388
unset($this->ambiguousServiceTypes[$type]);
389389
}
390390

391-
if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass())) {
391+
if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass(), false)) {
392392
return;
393393
}
394394

@@ -444,7 +444,7 @@ private function set($type, $id)
444444
*/
445445
private function createAutowiredDefinition($type)
446446
{
447-
if (!($typeHint = $this->container->getReflectionClass($type)) || !$typeHint->isInstantiable()) {
447+
if (!($typeHint = $this->container->getReflectionClass($type, false)) || !$typeHint->isInstantiable()) {
448448
return;
449449
}
450450

@@ -478,8 +478,8 @@ private function createAutowiredDefinition($type)
478478

479479
private function createTypeNotFoundMessage(TypedReference $reference, $label)
480480
{
481-
if (!$r = $this->container->getReflectionClass($type = $reference->getType())) {
482-
$message = sprintf('has type "%s" but this class does not exist.', $type);
481+
if (!$r = $this->container->getReflectionClass($type = $reference->getType(), false)) {
482+
$message = sprintf('has type "%s" but this class cannot be loaded.', $type);
483483
} else {
484484
$message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists';
485485
$message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $this->createTypeAlternatives($reference));

‎src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ private function updateDefinition(ContainerBuilder $container, $id, Definition $
8181
$class = $factory[0];
8282
}
8383

84-
if (!$m = $container->getReflectionClass($class)) {
84+
if (!$m = $container->getReflectionClass($class, false)) {
8585
return;
8686
}
8787
try {

‎src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition
6666
$instanceofTags = array();
6767

6868
foreach ($conditionals as $interface => $instanceofDefs) {
69-
if ($interface !== $class && (!$container->getReflectionClass($class))) {
69+
if ($interface !== $class && (!$container->getReflectionClass($class, false))) {
7070
continue;
7171
}
7272

‎src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+7-1Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,12 +337,15 @@ public function addClassResource(\ReflectionClass $class)
337337
* Retrieves the requested reflection class and registers it for resource tracking.
338338
*
339339
* @param string $class
340+
* @param bool $throw
340341
*
341342
* @return \ReflectionClass|null
342343
*
344+
* @throws \ReflectionException when a parent class/interface/trait is not found and $throw is true
345+
*
343346
* @final
344347
*/
345-
public function getReflectionClass($class)
348+
public function getReflectionClass($class, $throw = true)
346349
{
347350
if (!$class = $this->getParameterBag()->resolveValue($class)) {
348351
return;
@@ -357,6 +360,9 @@ public function getReflectionClass($class)
357360
$classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class);
358361
}
359362
} catch (\ReflectionException $e) {
363+
if ($throw) {
364+
throw $e;
365+
}
360366
$classReflector = false;
361367
}
362368

‎src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ public function testDontTriggerAutowiring()
359359

360360
/**
361361
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
362-
* @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class does not exist.
362+
* @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class cannot be loaded.
363363
*/
364364
public function testClassNotFoundThrowsException()
365365
{
@@ -374,7 +374,7 @@ public function testClassNotFoundThrowsException()
374374

375375
/**
376376
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
377-
* @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadParentTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\OptionalServiceClass" but this class does not exist.
377+
* @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadParentTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\OptionalServiceClass" but this class cannot be loaded.
378378
*/
379379
public function testParentClassNotFoundThrowsException()
380380
{
@@ -744,7 +744,7 @@ public function testNotWireableCalls($method, $expectedMsg)
744744
public function provideNotWireableCalls()
745745
{
746746
return array(
747-
array('setNotAutowireable', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setNotAutowireable()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class does not exist.'),
747+
array('setNotAutowireable', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setNotAutowireable()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class cannot be loaded.'),
748748
array('setDifferentNamespace', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setDifferentNamespace()" references class "stdClass" but no such service exists. It cannot be auto-registered because it is from a different root namespace.'),
749749
array(null, 'Cannot autowire service "foo": method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setProtectedMethod()" must be public.'),
750750
);

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.