Skip to content

Commit 3ca4886

Browse files
[Config][DI] Add ComposerResource to track runtime + vendors
1 parent 8fbaa79 commit 3ca4886

File tree

3 files changed

+152
-2
lines changed

3 files changed

+152
-2
lines changed

Resource/ComposerResource.php

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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 <[email protected]>
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+
self::$runtimeVendors = array();
79+
80+
foreach (get_loaded_extensions() as $ext) {
81+
self::$runtimeVersion[$ext] = phpversion($ext);
82+
}
83+
84+
foreach (get_declared_classes() as $class) {
85+
if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) {
86+
$r = new \ReflectionClass($class);
87+
$v = dirname(dirname($r->getFileName()));
88+
if (file_exists($v.'/composer/installed.json')) {
89+
self::$runtimeVendors[$v] = @filemtime($v.'/composer/installed.json');
90+
}
91+
}
92+
}
93+
}
94+
}

Resource/ReflectionClassResource.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@ 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;
29+
$this->excludedVendors = $excludedVendors;
2830
}
2931

3032
public function isFresh($timestamp)
@@ -75,7 +77,15 @@ private function loadFiles(\ReflectionClass $class)
7577
do {
7678
$file = $class->getFileName();
7779
if (false !== $file && file_exists($file)) {
78-
$this->files[$file] = null;
80+
foreach ($this->excludedVendors as $vendor) {
81+
if (0 === strpos($file, $vendor) && false !== strpbrk(substr($file, strlen($vendor), 1), '/'.DIRECTORY_SEPARATOR)) {
82+
$file = false;
83+
break;
84+
}
85+
}
86+
if ($file) {
87+
$this->files[$file] = null;
88+
}
7989
}
8090
foreach ($class->getTraits() as $v) {
8191
$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 <[email protected]>
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+
}

0 commit comments

Comments
 (0)