Merge branch '3.4'
* 3.4: [Config] Always protect ClassExistenceResource against bad parents
This commit is contained in:
commit
9a8f779a5d
@ -21,25 +21,21 @@ namespace Symfony\Component\Config\Resource;
|
||||
*/
|
||||
class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializable
|
||||
{
|
||||
const EXISTS_OK = 1;
|
||||
const EXISTS_KO = 0;
|
||||
const EXISTS_KO_WITH_THROWING_AUTOLOADER = -1;
|
||||
|
||||
private $resource;
|
||||
private $existsStatus;
|
||||
private $exists;
|
||||
|
||||
private static $autoloadLevel = 0;
|
||||
private static $existsCache = array();
|
||||
|
||||
/**
|
||||
* @param string $resource The fully-qualified class name
|
||||
* @param int|null $existsStatus One of the self::EXISTS_* const if the existency check has already been done
|
||||
* @param string $resource The fully-qualified class name
|
||||
* @param bool|null $exists Boolean when the existency check has already been done
|
||||
*/
|
||||
public function __construct($resource, $existsStatus = null)
|
||||
public function __construct($resource, $exists = null)
|
||||
{
|
||||
$this->resource = $resource;
|
||||
if (null !== $existsStatus) {
|
||||
$this->existsStatus = (int) $existsStatus;
|
||||
if (null !== $exists) {
|
||||
$this->exists = (bool) $exists;
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,11 +60,13 @@ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializ
|
||||
*/
|
||||
public function isFresh($timestamp)
|
||||
{
|
||||
$loaded = class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false);
|
||||
|
||||
if (null !== $exists = &self::$existsCache[$this->resource]) {
|
||||
$exists = $exists || class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false);
|
||||
} elseif (self::EXISTS_KO_WITH_THROWING_AUTOLOADER === $this->existsStatus) {
|
||||
$exists = $exists || $loaded;
|
||||
} elseif (!$exists = $loaded) {
|
||||
if (!self::$autoloadLevel++) {
|
||||
spl_autoload_register('Symfony\Component\Config\Resource\ClassExistenceResource::throwOnRequiredClass');
|
||||
spl_autoload_register(__CLASS__.'::throwOnRequiredClass');
|
||||
}
|
||||
|
||||
try {
|
||||
@ -77,18 +75,16 @@ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializ
|
||||
$exists = false;
|
||||
} finally {
|
||||
if (!--self::$autoloadLevel) {
|
||||
spl_autoload_unregister('Symfony\Component\Config\Resource\ClassExistenceResource::throwOnRequiredClass');
|
||||
spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$exists = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false);
|
||||
}
|
||||
|
||||
if (null === $this->existsStatus) {
|
||||
$this->existsStatus = $exists ? self::EXISTS_OK : self::EXISTS_KO;
|
||||
if (null === $this->exists) {
|
||||
$this->exists = $exists;
|
||||
}
|
||||
|
||||
return self::EXISTS_OK === $this->existsStatus xor !$exists;
|
||||
return $this->exists xor !$exists;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,11 +92,11 @@ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializ
|
||||
*/
|
||||
public function serialize()
|
||||
{
|
||||
if (null === $this->existsStatus) {
|
||||
if (null === $this->exists) {
|
||||
$this->isFresh(0);
|
||||
}
|
||||
|
||||
return serialize(array($this->resource, $this->existsStatus));
|
||||
return serialize(array($this->resource, $this->exists));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,7 +104,7 @@ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializ
|
||||
*/
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
list($this->resource, $this->existsStatus) = unserialize($serialized);
|
||||
list($this->resource, $this->exists) = unserialize($serialized);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,7 +66,7 @@ EOF
|
||||
|
||||
$loadedClass = 123;
|
||||
|
||||
$res = new ClassExistenceResource('MissingFooClass', ClassExistenceResource::EXISTS_KO);
|
||||
$res = new ClassExistenceResource('MissingFooClass', false);
|
||||
|
||||
$this->assertSame(123, $loadedClass);
|
||||
} finally {
|
||||
@ -76,7 +76,7 @@ EOF
|
||||
|
||||
public function testConditionalClass()
|
||||
{
|
||||
$res = new ClassExistenceResource(ConditionalClass::class, ClassExistenceResource::EXISTS_KO_WITH_THROWING_AUTOLOADER);
|
||||
$res = new ClassExistenceResource(ConditionalClass::class, false);
|
||||
|
||||
$this->assertFalse($res->isFresh(0));
|
||||
}
|
||||
|
@ -376,7 +376,7 @@ class AutowirePass extends AbstractRecursivePass
|
||||
return;
|
||||
}
|
||||
|
||||
if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass(), true)) {
|
||||
if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -428,7 +428,7 @@ class AutowirePass extends AbstractRecursivePass
|
||||
*/
|
||||
private function createAutowiredDefinition($type)
|
||||
{
|
||||
if (!($typeHint = $this->container->getReflectionClass($type, true)) || !$typeHint->isInstantiable()) {
|
||||
if (!($typeHint = $this->container->getReflectionClass($type)) || !$typeHint->isInstantiable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -462,7 +462,7 @@ class AutowirePass extends AbstractRecursivePass
|
||||
|
||||
private function createTypeNotFoundMessage(TypedReference $reference, $label)
|
||||
{
|
||||
if (!$r = $this->container->getReflectionClass($type = $reference->getType(), true)) {
|
||||
if (!$r = $this->container->getReflectionClass($type = $reference->getType())) {
|
||||
$message = sprintf('has type "%s" but this class does not exist.', $type);
|
||||
} else {
|
||||
$message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists';
|
||||
|
@ -336,13 +336,12 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
* Retrieves the requested reflection class and registers it for resource tracking.
|
||||
*
|
||||
* @param string $class
|
||||
* @param bool $koWithThrowingAutoloader Whether autoload should be protected against bad parents or not
|
||||
*
|
||||
* @return \ReflectionClass|null
|
||||
*
|
||||
* @final
|
||||
*/
|
||||
public function getReflectionClass($class, $koWithThrowingAutoloader = false)
|
||||
public function getReflectionClass($class)
|
||||
{
|
||||
if (!$class = $this->getParameterBag()->resolveValue($class)) {
|
||||
return;
|
||||
@ -352,12 +351,9 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
try {
|
||||
if (isset($this->classReflectors[$class])) {
|
||||
$classReflector = $this->classReflectors[$class];
|
||||
} elseif ($koWithThrowingAutoloader) {
|
||||
$resource = new ClassExistenceResource($class, ClassExistenceResource::EXISTS_KO_WITH_THROWING_AUTOLOADER);
|
||||
|
||||
$classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class);
|
||||
} else {
|
||||
$classReflector = new \ReflectionClass($class);
|
||||
$resource = new ClassExistenceResource($class, false);
|
||||
$classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class);
|
||||
}
|
||||
} catch (\ReflectionException $e) {
|
||||
$classReflector = false;
|
||||
@ -365,7 +361,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
|
||||
if ($this->trackResources) {
|
||||
if (!$classReflector) {
|
||||
$this->addResource($resource ?: new ClassExistenceResource($class, ClassExistenceResource::EXISTS_KO));
|
||||
$this->addResource($resource ?: new ClassExistenceResource($class, false));
|
||||
} elseif (!$classReflector->isInternal()) {
|
||||
$path = $classReflector->getFileName();
|
||||
|
||||
|
Reference in New Issue
Block a user