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

Skip to content

Commit e930f40

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

File tree

7 files changed

+202
-29
lines changed

7 files changed

+202
-29
lines changed

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

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use Symfony\Component\DependencyInjection\ContainerBuilder;
1717
use Symfony\Component\DependencyInjection\Definition;
1818
use Symfony\Component\DependencyInjection\Reference;
19-
use Symfony\Component\Config\Resource\FileResource;
2019

2120
/**
2221
* This abstract classes groups common code that Doctrine Object Manager extensions (ORM, MongoDB, CouchDB) need.
@@ -268,30 +267,30 @@ protected function assertValidMappingConfiguration(array $mappingConfig, $object
268267
*/
269268
protected function detectMetadataDriver($dir, ContainerBuilder $container)
270269
{
271-
// add the closest existing directory as a resource
272270
$configPath = $this->getMappingResourceConfigDirectory();
273-
$resource = $dir.'/'.$configPath;
274-
while (!is_dir($resource)) {
275-
$resource = dirname($resource);
276-
}
271+
$extension = $this->getMappingResourceExtension();
277272

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

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';
283+
return is_dir($dir.'/'.$this->getMappingObjectDefaultName()) ? 'annotation' : null;
287284
}
288285

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';
286+
// add the closest existing directory as a resource
287+
$resource = $dir.'/'.$configPath;
288+
while (!is_dir($resource)) {
289+
$resource = dirname($resource);
294290
}
291+
$container->fileExists($resource);
292+
293+
return $driver;
295294
}
296295

297296
/**

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
use Symfony\Component\DependencyInjection\Exception\LogicException;
2424
use Symfony\Component\DependencyInjection\Reference;
2525
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
26-
use Symfony\Component\Config\Resource\FileResource;
2726
use Symfony\Component\Finder\Finder;
2827
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
2928
use Symfony\Component\Config\FileLocator;
@@ -994,8 +993,7 @@ private function getValidatorMappingFiles(ContainerBuilder $container, array &$f
994993
{
995994
if (interface_exists('Symfony\Component\Form\FormInterface')) {
996995
$reflClass = new \ReflectionClass('Symfony\Component\Form\FormInterface');
997-
$files['xml'][] = $file = dirname($reflClass->getFileName()).'/Resources/config/validation.xml';
998-
$container->addResource(new FileResource($file));
996+
$files['xml'][] = dirname($reflClass->getFileName()).'/Resources/config/validation.xml';
999997
}
1000998

1001999
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
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-
F438 $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 & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

14-
use Symfony\Component\Config\Resource\FileResource;
1514
use Symfony\Component\DependencyInjection\ContainerBuilder;
1615
use Symfony\Component\DependencyInjection\Definition;
1716
use Symfony\Component\DependencyInjection\Reference;
@@ -67,7 +66,7 @@ private function updateDefinition(ContainerBuilder $container, $id, Definition $
6766
try {
6867
$m = new \ReflectionFunction($factory);
6968
if (false !== $m->getFileName() && file_exists($m->getFileName())) {
70-
$container->addResource(new FileResource($m->getFileName()));
69+
$container->fileExists($m->getFileName());
7170
}
7271
} catch (\ReflectionException $e) {
7372
return;

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 30 additions & 3 deletions
10000
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