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 686af61

Browse filesBrowse files
[Config] Fix conditional class existence checks
1 parent ed6a2ed commit 686af61
Copy full SHA for 686af61

File tree

3 files changed

+58
-10
lines changed
Filter options

3 files changed

+58
-10
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Config/Resource/ClassExistenceResource.php
+41-10Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializ
2828
private $resource;
2929
private $existsStatus;
3030

31-
private static $checkingLevel = 0;
32-
private static $throwingAutoloader;
31+
private static $autoloadLevel = 0;
3332
private static $existsCache = array();
3433

3534
/**
@@ -68,21 +67,17 @@ public function isFresh($timestamp)
6867
if (null !== $exists = &self::$existsCache[$this->resource]) {
6968
$exists = $exists || class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false);
7069
} elseif (self::EXISTS_KO_WITH_THROWING_AUTOLOADER === $this->existsStatus) {
71-
if (null === self::$throwingAutoloader) {
72-
$signalingException = new \ReflectionException();
73-
self::$throwingAutoloader = function () use ($signalingException) { throw $signalingException; };
74-
}
75-
if (!self::$checkingLevel++) {
76-
spl_autoload_register(self::$throwingAutoloader);
70+
if (!self::$autoloadLevel++) {
71+
spl_autoload_register('Symfony\Component\Config\Resource\ClassExistenceResource::throwOnRequiredClass');
7772
}
7873

7974
try {
8075
$exists = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false);
8176
} catch (\ReflectionException $e) {
8277
$exists = false;
8378
} finally {
84-
if (!--self::$checkingLevel) {
85-
spl_autoload_unregister(self::$throwingAutoloader);
79+
if (!--self::$autoloadLevel) {
80+
spl_autoload_unregister('Symfony\Component\Config\Resource\ClassExistenceResource::throwOnRequiredClass');
8681
}
8782
}
8883
} else {
@@ -115,4 +110,40 @@ public function unserialize($serialized)
115110
{
116111
list($this->resource, $this->existsStatus) = unserialize($serialized);
117112
}
113+
114+
/**
115+
* @throws \ReflectionException When $class is not found and is required
116+
*/
117+
private static function throwOnRequiredClass($class)
118+
{
119+
$e = new \ReflectionException("Class $class does not exist");
120+
$trace = $e->getTrace();
121+
$autoloadFrame = array(
122+
'function' => 'spl_autoload_call',
123+
'args' => array($class),
124+
);
125+
$i = 1 + array_search($autoloadFrame, $trace, true);
126+
127+
if (isset($trace[$i]['function']) && !isset($trace[$i]['class'])) {
128+
switch ($trace[$i]['function']) {
129+
case 'get_class_methods':
130+
case 'get_class_vars':
131+
case 'get_parent_class':
132+
case 'is_a':
133+
case 'is_subclass_of':
134+
case 'class_exists':
135+
case 'class_implements':
136+
case 'class_parents':
137+
case 'trait_exists':
138+
case 'defined':
139+
case 'interface_exists':
140+
case 'method_exists':
141+
case 'property_exists':
142+
case 'is_callable':
143+
return;
144+
}
145+
}
146+
147+
throw $e;
148+
}
118149
}
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Symfony\Component\Config\Tests\Fixtures\Resource;
4+
5+
if (!class_exists(MissingClass::class)) {
6+
class ConditionalClass
7+
{
8+
}
9+
}

‎src/Symfony/Component/Config/Tests/Resource/ClassExistenceResourceTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Config/Tests/Resource/ClassExistenceResourceTest.php
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Config\Tests\Resource;
1313

1414
use Symfony\Component\Config\Resource\ClassExistenceResource;
15+
use Symfony\Component\Config\Tests\Fixtures\Resource\ConditionalClass;
1516

1617
class ClassExistenceResourceTest extends \PHPUnit_Framework_TestCase
1718
{
@@ -71,4 +72,11 @@ public function testExistsKo()
7172
spl_autoload_unregister($autoloader);
7273
}
7374
}
75+
76+
public function testConditionalClass()
77+
{
78+
$res = new ClassExistenceResource(ConditionalClass::class, ClassExistenceResource::EXISTS_KO_WITH_THROWING_AUTOLOADER);
79+
80+
$this->assertFalse($res->isFresh(0));
81+
}
7482
}

0 commit comments

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