Skip to content

Commit 9a2cde2

Browse files
[Config] Make ClassExistenceResource throw on invalid parents
1 parent 4917b30 commit 9a2cde2

File tree

13 files changed

+45
-20
lines changed

13 files changed

+45
-20
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggingTranslatorPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function process(ContainerBuilder $container)
3434
$definition = $container->getDefinition((string) $translatorAlias);
3535
$class = $container->getParameterBag()->resolveValue($definition->getClass());
3636

37-
if (!$r = $container->getReflectionClass($class)) {
37+
if (!$r = $container->getReflectionClass($class, true)) {
3838
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias));
3939
}
4040
if ($r->isSubclassOf(TranslatorInterface::class) && $r->isSubclassOf(TranslatorBagInterface::class)) {

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

Lines 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/Console/DependencyInjection/AddConsoleCommandPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public function process(ContainerBuilder $container)
3232
$definition = $container->getDefinition($id);
3333
$class = $container->getParameterBag()->resolveValue($definition->getClass());
3434

35-
if (!$r = $container->getReflectionClass($class)) {
35+
if (!$r = $container->getReflectionClass($class, true)) {
3636
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
3737
}
3838
if (!$r->isSubclassOf(Command::class)) {

src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ protected function getConstructor(Definition $definition, $required)
115115

116116
$class = $definition->getClass();
117117

118-
if (!$r = $this->container->getReflectionClass($class)) {
118+
if (!$r = $this->container->getReflectionClass($class, true)) {
119119
throw new RuntimeException(sprintf('Unable to resolve service "%s": class "%s" does not exist.', $this->currentId, $class));
120120
}
121121
if (!$r = $r->getConstructor()) {
@@ -147,7 +147,7 @@ protected function getReflectionMethod(Definition $definition, $method)
147147
throw new RuntimeException(sprintf('Unable to resolve service "%s": the class is not set.', $this->currentId));
148148
}
149149

150-
if (!$r = $this->container->getReflectionClass($class)) {
150+
if (!$r = $this->container->getReflectionClass($class, true)) {
151151
throw new RuntimeException(sprintf('Unable to resolve service "%s": class "%s" does not exist.', $this->currentId, $class));
152152
}
153153

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ private function doProcessValue($value, $isRoot = false)
125125
return $value;
126126
}
127127
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()));
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
}
@@ -479,7 +479,7 @@ private function createAutowiredDefinition($type)
479479
private function createTypeNotFoundMessage(TypedReference $reference, $label)
480480
{
481481
if (!$r = $this->container->getReflectionClass($type = $reference->getType())) {
482-
$message = sprintf('has type "%s" but this class does not exist.', $type);
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/ResolveInstanceofConditionalsPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ private function mergeConditionals(array $autoconfiguredInstanceof, array $insta
133133

134134
foreach ($instanceofConditionals as $interface => $instanceofDef) {
135135
// make sure the interface/class exists (but don't validate automaticInstanceofConditionals)
136-
if (!$container->getReflectionClass($interface)) {
136+
if (!$container->getReflectionClass($interface, true)) {
137137
throw new RuntimeException(sprintf('"%s" is set as an "instanceof" conditional, but it does not exist.', $interface));
138138
}
139139

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 8 additions & 2 deletions
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 = false)
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

@@ -732,7 +738,7 @@ public function compile(/*$resolveEnvPlaceholders = false*/)
732738

733739
foreach ($this->definitions as $id => $definition) {
734740
if ($this->trackResources && $definition->isLazy()) {
735-
$this->getReflectionClass($definition->getClass());
741+
$this->getReflectionClass($definition->getClass(), true);
736742
}
737743
}
738744

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1627,7 +1627,7 @@ private function initializeMethodNamesMap($class)
16271627
$this->serviceIdToMethodNameMap = array();
16281628
$this->usedMethodNames = array();
16291629

1630-
if ($reflectionClass = $this->container->getReflectionClass($class)) {
1630+
if ($reflectionClass = $this->container->getReflectionClass($class, true)) {
16311631
foreach ($reflectionClass->getMethods() as $method) {
16321632
$this->usedMethodNames[strtolower($method->getName())] = true;
16331633
}

src/Symfony/Component/DependencyInjection/Extension/Extension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public function getConfiguration(array $config, ContainerBuilder $container)
7979
{
8080
$class = get_class($this);
8181
$class = substr_replace($class, '\Configuration', strrpos($class, '\\'));
82-
$class = $container->getReflectionClass($class);
82+
$class = $container->getReflectionClass($class, true);
8383
$constructor = $class ? $class->getConstructor() : null;
8484

8585
if ($class && (!$constructor || !$constructor->getNumberOfRequiredParameters())) {

src/Symfony/Component/DependencyInjection/Loader/FileLoader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ private function findClasses($namespace, $pattern, $excludePattern)
129129
continue;
130130
}
131131
// check to make sure the expected class exists
132-
if (!$r = $this->container->getReflectionClass($class)) {
132+
if (!$r = $this->container->getReflectionClass($class, true)) {
133133
throw new InvalidArgumentException(sprintf('Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.', $class, $path, $pattern));
134134
}
135135

0 commit comments

Comments
 (0)