Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9190e10

Browse filesBrowse files
[Config] Fix resource tracking with new GlobResource
1 parent 85e2d2f commit 9190e10
Copy full SHA for 9190e10

File tree

11 files changed

+320
-75
lines changed
Filter options

11 files changed

+320
-75
lines changed

‎src/Symfony/Component/Config/Exception/FileLocatorFileNotFoundException.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Config/Exception/FileLocatorFileNotFoundException.php
+13Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,17 @@
1818
*/
1919
class FileLocatorFileNotFoundException extends \InvalidArgumentException
2020
{
21+
private $paths;
22+
23+
public function __construct($message = '', $code = 0, $previous = null, array $paths = array())
24+
{
25+
parent::__construct($message, $code, $previous);
26+
27+
$this->paths = $paths;
28+
}
29+
30+
public function getPaths()
31+
{
32+
return $this->paths;
33+
}
2134
}

‎src/Symfony/Component/Config/FileLocator.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Config/FileLocator.php
+5-3Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public function locate($name, $currentPath = null, $first = true)
4343

4444
if ($this->isAbsolutePath($name)) {
4545
if (!file_exists($name)) {
46-
throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist.', $name));
46+
throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist.', $name), 0, null, array($name));
4747
}
4848

4949
return $name;
@@ -56,19 +56,21 @@ public function locate($name, $currentPath = null, $first = true)
5656
}
5757

5858
$paths = array_unique($paths);
59-
$filepaths = array();
59+
$filepaths = $notfound = array();
6060

6161
foreach ($paths as $path) {
6262
if (@file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) {
6363
if (true === $first) {
6464
return $file;
6565
}
6666
$filepaths[] = $file;
67+
} else {
68+
$notfound[] = $file;
6769
}
6870
}
6971

7072
if (!$filepaths) {
71-
throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist (in: %s).', $name, implode(', ', $paths)));
73+
throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist (in: %s).', $name, implode(', ', $paths)), 0, null, $notfound);
7274
}
7375

7476
return $filepaths;

‎src/Symfony/Component/Config/Loader/FileLoader.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Config/Loader/FileLoader.php
+21-59Lines changed: 21 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
use Symfony\Component\Config\Exception\FileLoaderLoadException;
1616
use Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException;
1717
use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
18-
use Symfony\Component\Finder\Finder;
19-
use Symfony\Component\Finder\Glob;
18+
use Symfony\Component\Config\Resource\FileExistenceResource;
19+
use Symfony\Component\Config\Resource\GlobResource;
2020

2121
/**
2222
* FileLoader is the abstract class used by all built-in loaders that are file based.
@@ -85,9 +85,13 @@ public function import($resource, $type = null, $ignoreErrors = false, $sourceRe
8585
{
8686
$ret = array();
8787
$ct = 0;
88-
foreach ($this->glob($resource, false, $_, $ignoreErrors) as $resource => $info) {
89-
++$ct;
88+
if (!is_string($resource) || false === strpbrk($resource, '*?{[')) {
9089
$ret[] = $this->doImport($resource, $type, $ignoreErrors, $sourceResource);
90+
} else {
91+
foreach ($this->glob($resource, false, $_, $ignoreErrors) as $path => $info) {
92+
++$ct;
93+
$ret[] = $this->doImport($path, $type, $ignoreErrors, $sourceResource);
94+
}
9195
}
9296

9397
return $ct > 1 ? $ret : (isset($ret[0]) ? $ret[0] : null);
@@ -96,24 +100,17 @@ public function import($resource, $type = null, $ignoreErrors = false, $sourceRe
96100
/**
97101
* @internal
98102
*/
99-
protected function glob($resource, $recursive, &$prefix = null, $ignoreErrors = false)
103+
protected function glob($pattern, $recursive, &$resource = null, $ignoreErrors = false)
100104
{
101-
if (strlen($resource) === $i = strcspn($resource, '*?{[')) {
102-
if (!$recursive) {
103-
$prefix = null;
104-
105-
yield $resource => new \SplFileInfo($resource);
106-
107-
return;
108-
}
109-
$prefix = $resource;
110-
$resource = '';
105+
if (strlen($pattern) === $i = strcspn($pattern, '*?{[')) {
106+
$prefix = $pattern;
107+
$pattern = '';
111108
} elseif (0 === $i) {
112109
$prefix = '.';
113-
$resource = '/'.$resource;
110+
$pattern = '/'.$pattern;
114111
} else {
115-
$prefix = dirname(substr($resource, 0, 1 + $i));
116-
$resource = substr($resource, strlen($prefix));
112+
$prefix = dirname(substr($pattern, 0, 1 + $i));
113+
$pattern = substr($pattern, strlen($prefix));
117114
}
118115

119116
try {
@@ -123,52 +120,17 @@ protected function glob($resource, $recursive, &$prefix = null, $ignoreErrors =
123120
throw $e;
124121
}
125122

126-
return;
127-
}
128-
$prefix = realpath($prefix) ?: $prefix;
129-
130-
if (false === strpos($resource, '/**/') && (defined('GLOB_BRACE') || false === strpos($resource, '{'))) {
131-
foreach (glob($prefix.$resource, defined('GLOB_BRACE') ? GLOB_BRACE : 0) as $path) {
132-
if ($recursive && is_dir($path)) {
133-
$files = iterator_to_array(new \RecursiveIteratorIterator(
134-
new \RecursiveCallbackFilterIterator(
135-
new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS),
136-
function (\SplFileInfo $file) { return '.' !== $file->getBasename()[0]; }
137-
),
138-
\RecursiveIteratorIterator::LEAVES_ONLY
139-
));
140-
uasort($files, function (\SplFileInfo $a, \SplFileInfo $b) {
141-
return (string) $a > (string) $b ? 1 : -1;
142-
});
143-
144-
foreach ($files as $path => $info) {
145-
if ($info->isFile()) {
146-
yield $path => $info;
147-
}
148-
}
149-
} elseif (is_file($path)) {
150-
yield $path => new \SplFileInfo($path);
151-
}
123+
$resource = array();
124+
foreach ($e->getPaths() as $path) {
125+
$resource[] = new FileExistenceResource($path);
152126
}
153127

154128
return;
155129
}
130+
$resource = new GlobResource($prefix, $pattern, $recursive);
156131

157-
if (!class_exists(Finder::class)) {
158-
throw new \LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.', $resource));
159-
}
160-
161-
$finder = new Finder();
162-
$regex = Glob::toRegex($resource);
163-
if ($recursive) {
164-
$regex = substr_replace($regex, '(/|$)', -2, 1);
165-
}
166-
167-
$prefixLen = strlen($prefix);
168-
foreach ($finder->followLinks()->sortByName()->in($prefix) as $path => $info) {
169-
if (preg_match($regex, substr($path, $prefixLen)) && $info->isFile()) {
170-
yield $path => $info;
171-
}
132+
foreach ($resource as $path => $info) {
133+
yield $path => $info;
172134
}
173135
}
174136

+153Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
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+
use Symfony\Component\Finder\Finder;
15+
use Symfony\Component\Finder\Glob;
16+
17+
/**
18+
* GlobResource represents a set of resources stored on the filesystem.
19+
*
20+
* Only existence/removal is tracked (not mtimes.)
21+
*
22+
* @author Nicolas Grekas <p@tchwork.com>
23+
*/
24+
class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface, \Serializable
25+
{
26+
private $prefix;
27+
private $pattern;
28+
private $recursive;
29+
private $hash;
30+
31+
/**
32+
* Constructor.
33+
*
34+
* @param string $prefix A directory prefix
35+
* @param string $pattern A glob pattern
36+
* @param bool $recursive Whether directories should be scanned recursively or not
37+
*
38+
* @throws \InvalidArgumentException
39+
*/
40+
public function __construct($prefix, $pattern, $recursive)
41+
{
42+
$this->prefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : false);
43+
$this->pattern = $pattern;
44+
$this->recursive = $recursive;
45+
46+
if (false === $this->prefix) {
47+
throw new \InvalidArgumentException(sprintf('The path "%s" does not exist.', $prefix));
48+
}
49+
}
50+
51+
public function getPrefix()
52+
{
53+
return $this->prefix;
54+
}
55+
56+
/**
57+
* {@inheritdoc}
58+
*/
59+
public function __toString()
60+
{
61+
return 'glob.'.$this->prefix.$this->pattern.(int) $this->recursive;
62+
}
63+
64+
/**
65+
* {@inheritdoc}
66+
*/
67+
public function isFresh($timestamp)
68+
{
69+
$hash = $this->computeHash();
70+
71+
if (null === $this->hash) {
72+
$this->hash = $hash;
73+
}
74+
75+
return $this->hash === $hash;
76+
}
77+
78+
public function serialize()
79+
{
80+
if (null === $this->hash) {
81+
$this->hash = $this->computeHash();
82+
}
83+
84+
return serialize(array($this->prefix, $this->pattern, $this->recursive, $this->hash));
85+
}
86+
87+
public function unserialize($serialized)
88+
{
89+
list($this->prefix, $this->pattern, $this->recursive, $this->hash) = unserialize($serialized);
90+
}
91+
92+
public function getIterator()
93+
{
94+
if (!file_exists($this->prefix) || (!$this->recursive && '' === $this->pattern)) {
95+
return;
96+
}
97+
98+
if (false === strpos($this->pattern, '/**/') && (defined('GLOB_BRACE') || false === strpos($this->pattern, '{'))) {
99+
foreach (glob($this->prefix.$this->pattern, defined('GLOB_BRACE') ? GLOB_BRACE : 0) as $path) {
100+
if ($this->recursive && is_dir($path)) {
101+
$files = iterator_to_array(new \RecursiveIteratorIterator(
102+
new \RecursiveCallbackFilterIterator(
103+
new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS),
104+
function (\SplFileInfo $file) { return '.' !== $file->getBasename()[0]; }
105+
),
106+
\RecursiveIteratorIterator::LEAVES_ONLY
107+
));
108+
uasort($files, function (\SplFileInfo $a, \SplFileInfo $b) {
109+
return (string) $a > (string) $b ? 1 : -1;
110+
});
111+
112+
foreach ($files as $path => $info) {
113+
if ($info->isFile()) {
114+
yield $path => $info;
115+
}
116+
}
117+
} elseif (is_file($path)) {
118+
yield $path => new \SplFileInfo($path);
119+
}
120+
}
121+
122+
return;
123+
}
124+
125+
if (!class_exists(Finder::class)) {
126+
throw new \LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.', $this->pattern));
127+
}
128+
129+
$finder = new Finder();
130+
$regex = Glob::toRegex($this->pattern);
131+
if ($this->recursive) {
132+
$regex = substr_replace($regex, '(/|$)', -2, 1);
133+
}
134+
135+
$prefixLen = strlen($this->prefix);
136+
foreach ($finder->followLinks()->sortByName()->in($this->prefix) as $path => $info) {
137+
if (preg_match($regex, substr($path, $prefixLen)) && $info->isFile()) {
138+
yield $path => $info;
139+
}
140+
}
141+
}
142+
143+
private function computeHash()
144+
{
145+
$hash = hash_init('md5');
146+
147+
foreach ($this->getIterator() as $path => $info) {
148+
hash_update($hash, $path."\n");
149+
}
150+
151+
return hash_final($hash);
152+
}
153+
}

‎src/Symfony/Component/Config/Tests/Fixtures/Resource/.hiddenFile

Copy file name to clipboardExpand all lines: src/Symfony/Component/Config/Tests/Fixtures/Resource/.hiddenFile
Whitespace-only changes.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.