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 a736458

Browse filesBrowse files
bug #21527 [Config] Fix conditional class existence checks (nicolas-grekas)
This PR was merged into the 3.3-dev branch. Discussion ---------- [Config] Fix conditional class existence checks | Q | A | ------------- | --- | Branch? | master | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - Commits ------- 686af61 [Config] Fix conditional class existence checks
2 parents ed6a2ed + 686af61 commit a736458
Copy full SHA for a736458

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.