8000 [Config][DI] Add ComposerResource to track runtime + vendors · symfony/symfony@b7adaad · GitHub
[go: up one dir, main page]

Skip to content

Commit b7adaad

Browse files
[Config][DI] Add ComposerResource to track runtime + vendors
1 parent a46e691 commit b7adaad

File tree

7 files changed

+202
-26
lines changed

7 files changed

+202
-26
lines changed

src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -268,30 +268,30 @@ protected function assertValidMappingConfiguration(array $mappingConfig, $object
268268
*/
269269
protected function detectMetadataDriver($dir, ContainerBuilder $container)
270270
{
271-
// add the closest existing directory as a resource
272271
$configPath = $this->getMappingResourceConfigDirectory();
273-
$resource = $dir.'/'.$configPath;
274-
while (!is_dir($resource)) {
275-
$resource = dirname($resource);
276-
}
272+
$extension = $this->getMappingResourceExtension();
277273

278-
$container->addResource(new FileResource($resource));
274+
if (glob($dir.'/'.$configPath.'/*.'.$extension.'.xml')) {
275+
$driver = 'xml';
276+
} elseif (glob($dir.'/'.$configPath.'/*.'.$extension.'.yml')) {
277+
$driver = 'yml';
278+
} elseif (glob($dir.'/'.$configPath.'/*.'.$extension.'.php')) {
279+
$driver = 'php';
280+
} else {
281+
// add the directory itself as a resource
282+
$container->fileExists($dir);
279283

280-
$extension = $this->getMappingResourceExtension();
281-
if (($files = glob($dir.'/'.$configPath.'/*.'.$extension.'.xml')) && count($files)) {
282-
return 'xml';
283-
} elseif (($files = glob($dir.'/'.$configPath.'/*.'.$extension.'.yml')) && count($files)) {
284-
return 'yml';
285-
} elseif (($files = glob($dir.'/'.$configPath.'/*.'.$extension.'.php')) && count($files)) {
286-
return 'php';
284+
return is_dir($dir.'/'.$this->getMappingObjectDefaultName()) ? 'annotation' : null;
287285
}
288286

289-
// add the directory itself as a resource
290-
$container->addResource(new FileResource($dir));
291-
292-
if (is_dir($dir.'/'.$this->getMappingObjectDefaultName())) {
293-
return 'annotation';
287+
// add the closest existing directory as a resource
288+
$resource = $dir.'/'.$configPath;
289+
while (!is_dir($resource)) {
290+
$resource = dirname($resource);
294291
}
292+
$container->fileExists($resource);
293+
294+
return $driver;
295295
}
296296

297297
/**

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 1 addition & 2 deletions
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
Original file line numberDiff line numberDiff line change
@@ -994,8 +994,7 @@ private function getValidatorMappingFiles(ContainerBuilder $container, array &$f
994994
{
995995
if (interface_exists('Symfony\Component\Form\FormInterface')) {
996996
$reflClass = new \ReflectionClass('Symfony\Component\Form\FormInterface');
997-
$files['xml'][] = $file = dirname($reflClass->getFileName()).'/Resources/config/validation.xml';
998-
$container->addResource(new FileResource($file));
997+
$files['xml'][] = dirname($reflClass->getFileName()).'/Resources/config/validation.xml';
999998
}
1000999

10011000
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Config\Resource;
13+
14+
/**
15+
* ComposerResource tracks the PHP version and Composer dependencies.
16+
*
17+
* @author Nicolas Grekas <p@tchwork.com>
18+
*/
19+
class ComposerResource implements SelfCheckingResourceInterface, \Serializable
20+
{
21+
private $versions;
22+
private $vendors;
23+
24+
private static $runtimeVersion;
25+
private static $runtimeVendors;
26+
27+
public function __construct()
28+
{
29+
self::refresh();
30+
$this->versions = self::$runtimeVersion;
31+
$this->vendors = self::$runtimeVendors;
32+
}
33+
34+
public function getVendors()
35+
{
36+
return array_keys($this->vendors);
37+
}
38+
39+
/**
40+
* {@inheritdoc}
41+
*/
42+
public function __toString()
43+
{
44+
return __CLASS__;
45+
}
46+
47+
/**
48+
* {@inheritdoc}
49+
*/
50+
public function isFresh($timestamp)
51+
{
52+
self::refresh();
53+
54+
if (self::$runtimeVersion !== $this->versions) {
55+
return false;
56+
}
57+
58+
return self::$runtimeVendors === $this->vendors;
59+
}
60+
61+
public function serialize()
62+
{
63+
return serialize(array($this->versions, $this->vendors));
64+
}
65+
66+
public function unserialize($serialized)
67+
{
68+
list($this->versions, $this->vendors) = unserialize($serialized);
69+
}
70+
71+
private static function refresh()
72+
{
73+
if (null !== self::$runtimeVersion) {
74+
return;
75+
}
76+
77+
self::$runtimeVersion = array();
78+
79+
foreach (get_loaded_extensions() as $ext) {
80+
self::$runtimeVersion[$ext] = phpversion($ext);
81+
}
82+
83+
self::$runtimeVendors = array();
84+
85+
foreach (get_declared_classes() as $class) {
86+
if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) {
87+
$r = new \ReflectionClass($class);
88+
$v = dirname(dirname($r->getFileName())).DIRECTORY_SEPARATOR;
89+
if (file_exists($v.'composer/installed.json')) {
90+
self::$runtimeVendors[$v] = @filemtime($v.'composer/installed.json');
91+
}
92+
}
93+
}
94+
}
95+
}

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ class ReflectionClassResource implements SelfCheckingResourceInterface, \Seriali
1919
private $files = array();
2020
private $className;
2121
private $classReflector;
22+
private $excludedVendors = array();
2223
private $hash;
2324

24-
public function __construct(\ReflectionClass $classReflector)
25+
public function __construct(\ReflectionClass $classReflector, $excludedVendors = array())
2526
{
2627
$this->className = $classReflector->name;
2728
$this->classReflector = $classReflector;
@@ -75,7 +76,15 @@ private function loadFiles(\ReflectionClass $class)
7576
do {
7677
$file = $class->getFileName();
7778
if (false !== $file && file_exists($file)) {
78-
$this->files[$file] = null;
79+
foreach ($this->excludedVendors as $vendor) {
80+
if (0 === strpos($file, $vendor)) {
81+
$file = false;
82+
break;
83+
}
84+
}
85+
if ($file) {
86+
$this->files[$file] = null;
87+
}
7988
}
8089
foreach ($class->getTraits() as $v) {
8190
$this->loadFiles($v);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Config\Tests\Resource;
13+
14+
use Composer\Autoload\ClassLoader;
15+
use Symfony\Component\Config\Resource\ComposerResource;
16+
17+
class ComposerResourceTest extends \PHPUnit_Framework_TestCase
18+
{
19+
public function testGetVendor()
20+
{
21+
$res = new ComposerResource();
22+
23+
$r = new \ReflectionClass(ClassLoader::class);
24+
$found = false;
25+
26+
foreach ($res->getVendors() as $vendor) {
27+
if ($vendor && 0 === strpos($r->getFileName(), $vendor)) {
28+
$found = true;
29+
break;
30+
}
31+
}
32+
33+
$this->assertTrue($found);
34+
}
35+
36+
public function testSerializeUnserialize()
37+
{
38+
$res = new ComposerResource();
39+
$ser = unserialize(serialize($res));
40+
41+
$this->assertTrue($res->isFresh(0));
42+
$this->assertTrue($ser->isFresh(0));
43+
44+
$this->assertEquals($res, $ser);
45+
}
46+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ private function updateDefinition(ContainerBuilder $container, $id, Definition $
6767
try {
6868
$m = new \ReflectionFunction($factory);
6969
if (false !== $m->getFileName() && file_exists($m->getFileName())) {
70-
$container->addResource(new FileResource($m->getFileName()));
70+
$container->fileExists($m->getFileName());
7171
}
7272
} catch (\ReflectionException $e) {
7373
return;

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
2727
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
2828
use Symfony\Component\Config\Resource\ClassExistenceResource;
29+
use Symfony\Component\Config\Resource\ComposerResource;
2930
use Symfony\Component\Config\Resource\DirectoryResource;
3031
use Symfony\Component\Config\Resource\FileExistenceResource;
3132
use Symfony\Component\Config\Resource\FileResource;
@@ -108,6 +109,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
108109
*/
109110
private $envCounters = array();
110111

112+
/**
113+
* @var string[] the list of vendor directories
114+
*/
115+
private $vendors = array();
116+
111117
/**
112118
* Sets the track resources flag.
113119
*
@@ -269,13 +275,13 @@ public function addObjectResource($object)
269275
}
270276
$file = $interface->getFileName();
271277
if (false !== $file && file_exists($file)) {
272-
$this->addResource(new FileResource($file));
278+
$this->fileExists($file);
273279
}
274280
}
275281
do {
276282
$file = $class->getFileName();
277283
if (false !== $file && file_exists($file)) {
278-
$this->addResource(new FileResource($file));
284+
$this->fileExists($file);
279285
}
280286
foreach ($class->getTraitNames() as $name) {
281287
$this->addObjectResource($name);
@@ -337,7 +343,18 @@ public function getReflectionClass($class, $koWithThrowingAutoloader = false)
337343
if (!$classReflector) {
338344
$this->addResource($resource ?: new ClassExistenceResource($class, ClassExistenceResource::EXISTS_KO));
339345
} elseif (!$classReflector->isInternal()) {
340-
$this->addResource(new ReflectionClassResource($classReflector));
346+
$path = $classReflector->getFileName();
347+
348+
foreach ($this->vendors as $vendor) {
349+
if (0 === strpos($path, $vendor)) {
350+
$path = false;
351+
break;
352+
}
353+
}
354+
355+
if ($path) {
356+
$this->addResource(new ReflectionClassResource($classReflector, $this->vendors));
357+
}
341358
}
342359
$this->classReflectors[$class] = $classReflector;
343360
}
@@ -364,6 +381,12 @@ public function fileExists($path, $trackContents = true)
364381
return $exists;
365382
}
366383

384+
foreach ($this->vendors as $vendor) {
385+
if (0 === strpos($path, $vendor)) {
386+
return $exists;
387+
}
388+
}
389+
367390
if (!$exists) {
368391
$this->addResource(new FileExistenceResource($path));
369392

@@ -663,6 +686,10 @@ public function compile()
663686
$compiler = $this->getCompiler();
664687

665688
if ($this->trackResources) {
689+
$resource = new ComposerResource();
690+
$this->vendors = $resource->getVendors();
691+
$this->addResource($resource);
692+
666693
foreach ($compiler->getPassConfig()->getPasses() as $pass) {
667694
$this->addObjectResource($pass);
668695
}

0 commit comments

Comments
 (0)
0