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

Skip to content

Commit 0a834df

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

File tree

13 files changed

+225
-46
lines changed

13 files changed

+225
-46
lines changed

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

Lines changed: 17 additions & 20 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,28 @@ 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-
}
277-
278-
$container->addResource(new FileResource($resource));
279-
280271
$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';
287-
}
288272

289-
// add the directory itself as a resource
290-
$container->addResource(new FileResource($dir));
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 closest existing directory as a resource
281+
$resource = $dir.'/'.$configPath;
282+
while (!is_dir($resource)) {
283+
$resource = dirname($resource);
284+
}
285+
$container->fileExists($resource, false);
291286

292-
if (is_dir($dir.'/'.$this->getMappingObjectDefaultName())) {
293-
return 'annotation';
287+
return $container->fileExists($dir.'/'.$this->getMappingObjectDefaultName(), false) ? 'annotation' : null;
294288
}
289+
$container->fileExists($dir.'/'.$configPath, false);
290+
291+
return $driver;
295292
}
296293

297294
/**

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()));
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) && false !== strpbrk(substr($file, strlen($vendor), 1), '/'.DIRECTORY_SEPARATOR)) {
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: 42 additions & 9 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;
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,15 @@ 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+
if ($this->inVendors($path)) {
349+
$path = false;
350+
}
351+
352+
if ($path) {
353+
$this->addResource(new ReflectionClassResource($classReflector, $this->vendors));
354+
}
341355
}
342356
$this->classReflectors[$class] = $classReflector;
343357
}
@@ -364,18 +378,20 @@ public function fileExists($path, $trackContents = true)
364378
return $exists;
365379
}
366380

381+
if ($this->inVendors($path)) {
382+
return $exists;
383+
}
384+
367385
if (!$exists) {
368386
$this->addResource(new FileExistenceResource($path));
369387

370388
return $exists;
371389
}
372390

373-
if ($trackContents) {
374-
if (is_file($path)) {
375-
$this->addResource(new FileResource($path));
376-
} else {
377-
$this->addResource(new DirectoryResource($path, is_string($trackContents) ? $trackContents : null));
378-
}
391+
if ($trackContents && is_dir($path)) {
392+
$this->addResource(new DirectoryResource($path, is_string($trackContents) ? $trackContents : null));
393+
} elseif ($trackContents || is_dir($path)) {
394+
$this->addResource(new FileResource($path));
379395
}
380396

381397
return $exists;
@@ -1488,4 +1504,21 @@ private function getExpressionLanguage()
14881504

14891505
return $this->expressionLanguage;
14901506
}
1507+
1508+
private function inVendors($path)
1509+
{
1510+
if (null === $this->vendors) {
1511+
$resource = new ComposerResource();
1512+
$this->vendors = $resource->getVendors();
1513+
$this->addResource($resource);
1514+
}
1515+
1516+
foreach ($this->vendors as $vendor) {
1517+
if (0 === strpos($path, $vendor) && false !== strpbrk(substr($path, strlen($vendor), 1), '/'.DIRECTORY_SEPARATOR)) {
1518+
return true;
1519+
}
1520+
}
1521+
1522+
return false;
1523+
}
14911524
}

src/Symfony/Component/DependencyInjection/Loader/DirectoryLoader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public function load($file, $type = null)
2727
{
2828
$file = rtrim($file, '/');
2929
$path = $this->locator->locate($file);
30-
$this->container->addResource(new DirectoryResource($path));
30+
$this->container->fileExists($path, false);
3131

3232
foreach (scandir($path) as $dir) {
3333
if ('.' !== $dir[0]) {

src/Symfony/Component/DependencyInjection/Loader/IniFileLoader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public function load($resource, $type = null)
2929
{
3030
$path = $this->locator->locate($resource);
3131

32-
$this->container->addResource(new FileResource($path));
32+
$this->container->fileExists($path);
3333

3434
// first pass to catch parsing errors
3535
$result = parse_ini_file($path, true);

src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function load($resource, $type = null)
3434

3535
$path = $this->locator->locate($resource);
3636
$this->setCurrentDir(dirname($path));
37-
$this->container->addResource(new FileResource($path));
37+
$this->container->fileExists($path);
3838

3939
include $path;
4040
}

0 commit comments

Comments
 (0)
0