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 b9f7909

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

File tree

11 files changed

+324
-73
lines changed
Filter options

11 files changed

+324
-73
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
+22-57Lines changed: 22 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
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\Config\Resource\FileExistenceResource;
19+
use Symfony\Component\Config\Resource\GlobResource;
20+
use Symfony\Component\Config\Resource\ResourceInterface;
1821
use Symfony\Component\Finder\Finder;
1922
use Symfony\Component\Finder\Glob;
2023

@@ -85,9 +88,13 @@ public function import($resource, $type = null, $ignoreErrors = false, $sourceRe
8588
{
8689
$ret = array();
8790
$ct = 0;
88-
foreach ($this->glob($resource, false, $_, $ignoreErrors) as $resource => $info) {
89-
++$ct;
91+
if (!is_string($resource) || false === strpbrk($resource, '*?{[')) {
9092
$ret[] = $this->doImport($resource, $type, $ignoreErrors, $sourceResource);
93+
} else {
94+
foreach ($this->glob($resource, false, $_, $ignoreErrors) as $path => $info) {
95+
++$ct;
96+
$ret[] = $this->doImport($path, $type, $ignoreErrors, $sourceResource);
97+
}
9198
}
9299

93100
return $ct > 1 ? $ret : (isset($ret[0]) ? $ret[0] : null);
@@ -96,24 +103,17 @@ public function import($resource, $type = null, $ignoreErrors = false, $sourceRe
96103
/**
97104
* @internal
98105
*/
99-
protected function glob($resource, $recursive, &$prefix = null, $ignoreErrors = false)
106+
protected function glob($pattern, $recursive, &$resource = null, $ignoreErrors = false)
100107
{
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 = '';
108+
if (strlen($pattern) === $i = strcspn($pattern, '*?{[')) {
109+
$prefix = $pattern;
110+
$pattern = '';
111111
} elseif (0 === $i) {
112112
$prefix = '.';
113-
$resource = '/'.$resource;
113+
$pattern = '/'.$pattern;
114114
} else {
115-
$prefix = dirname(substr($resource, 0, 1 + $i));
116-
$resource = substr($resource, strlen($prefix));
115+
$prefix = dirname(substr($pattern, 0, 1 + $i));
116+
$pattern = substr($pattern, strlen($prefix));
117117
}
118118

119119
try {
@@ -123,52 +123,17 @@ protected function glob($resource, $recursive, &$prefix = null, $ignoreErrors =
123123
throw $e;
124124
}
125125

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-
}
126+
$resource = array();
127+
foreach ($e->getPaths() as $path) {
128+
$resource[] = new FileExistenceResource($path);
152129
}
153130

154131
return;
155132
}
133+
$resource = new GlobResource($prefix, $pattern, $recursive);
156134

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-
}
135+
foreach ($resource as $path => $info) {
136+
yield $path => $info;
172137
}
173138
}
174139

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

‎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.