From 59a74acba5759759ac820dd8a495307af809e323 Mon Sep 17 00:00:00 2001 From: Nicolas D'Amours Date: Tue, 13 Aug 2024 11:44:57 -0400 Subject: [PATCH 1/5] [FEATURE] #82 Added support for globstar when resolving paths in the FileIterator factory. The extended glob function was adapted from funkjedi's implementation: https://gist.github.com/funkjedi/3feee27d873ae2297b8e2370a7082aad Fixed facade test to include newly created fixture directories. --- src/Factory.php | 38 +++++++++++++++++++++++++- tests/fixture/a/c/d/i/PrefixSuffix.php | 1 + tests/fixture/b/e/g/i/PrefixSuffix.php | 1 + tests/fixture/b/e/i/PrefixSuffix.php | 1 + tests/fixture/b/f/h/i/PrefixSuffix.php | 1 + tests/unit/FacadeTest.php | 37 ++++++++++++++++++++++--- 6 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 tests/fixture/a/c/d/i/PrefixSuffix.php create mode 100644 tests/fixture/b/e/g/i/PrefixSuffix.php create mode 100644 tests/fixture/b/e/i/PrefixSuffix.php create mode 100644 tests/fixture/b/f/h/i/PrefixSuffix.php diff --git a/src/Factory.php b/src/Factory.php index a2ebce6..e1ebd82 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -92,7 +92,7 @@ private function resolveWildcards(array $paths): array $_paths = [[]]; foreach ($paths as $path) { - if ($locals = glob($path, GLOB_ONLYDIR)) { + if ($locals = $this->globstar($path)) { $_paths[] = array_map('\realpath', $locals); } else { // @codeCoverageIgnoreStart @@ -103,4 +103,40 @@ private function resolveWildcards(array $paths): array return array_values(array_filter(array_merge(...$_paths))); } + + /** + * @see https://gist.github.com/funkjedi/3feee27d873ae2297b8e2370a7082aad + * @param $pattern + * @param $flags + * @return array|false + */ + private function globstar(string $pattern) { + if (stripos($pattern, '**') === false) { + $files = glob($pattern, GLOB_ONLYDIR); + } else { + $position = stripos($pattern, '**'); + $rootPattern = substr($pattern, 0, $position - 1); + $restPattern = substr($pattern, $position + 2); + + $patterns = [$rootPattern.$restPattern]; + $rootPattern .= '/*'; + + while($dirs = glob($rootPattern, GLOB_ONLYDIR)) { + $rootPattern .= '/*'; + foreach($dirs as $dir) { + $patterns[] = $dir . $restPattern; + } + } + + $files = []; + foreach($patterns as $pat) { + $files = array_merge($files, $this->globstar($pat)); + } + } + + $files = array_unique($files); + sort($files); + + return $files; + } } diff --git a/tests/fixture/a/c/d/i/PrefixSuffix.php b/tests/fixture/a/c/d/i/PrefixSuffix.php new file mode 100644 index 0000000..b3d9bbc --- /dev/null +++ b/tests/fixture/a/c/d/i/PrefixSuffix.php @@ -0,0 +1 @@ + [ + [ + + $fixtureDirectoryRealpath . '/a/c/d/i/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/e/g/i/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/e/i/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/f/h/i/PrefixSuffix.php', + ], + __DIR__ . '/../fixture/**/i', + '', + '', + [] + ], ]; } @@ -140,11 +169,11 @@ protected function tearDown(): void } /** - * @param list $expected + * @param list $expected * @param list|non-empty-string $paths - * @param list|string $suffixes - * @param list|string $prefixes - * @param list $exclude + * @param list|string $suffixes + * @param list|string $prefixes + * @param list $exclude */ #[DataProvider('provider')] public function testSomething(array $expected, array|string $paths, array|string $suffixes, array|string $prefixes, array $exclude): void From 824597eb48004c947a93648bb594a992e0c11e0d Mon Sep 17 00:00:00 2001 From: Nicolas D'Amours Date: Tue, 13 Aug 2024 12:01:57 -0400 Subject: [PATCH 2/5] [FEATURE] #82 Removed unnecessary formatting changes. --- tests/unit/FacadeTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/FacadeTest.php b/tests/unit/FacadeTest.php index 2c3a944..b0c3f99 100644 --- a/tests/unit/FacadeTest.php +++ b/tests/unit/FacadeTest.php @@ -169,11 +169,11 @@ protected function tearDown(): void } /** - * @param list $expected + * @param list $expected * @param list|non-empty-string $paths - * @param list|string $suffixes - * @param list|string $prefixes - * @param list $exclude + * @param list|string $suffixes + * @param list|string $prefixes + * @param list $exclude */ #[DataProvider('provider')] public function testSomething(array $expected, array|string $paths, array|string $suffixes, array|string $prefixes, array $exclude): void From 72f42ffcee75318476a409c3eb6d650958a400c4 Mon Sep 17 00:00:00 2001 From: Nicolas D'Amours Date: Wed, 14 Aug 2024 08:25:57 -0400 Subject: [PATCH 3/5] [FEATURE] #82 Fixed static code analysis errors. --- src/Factory.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index e1ebd82..97180fe 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -106,9 +106,8 @@ private function resolveWildcards(array $paths): array /** * @see https://gist.github.com/funkjedi/3feee27d873ae2297b8e2370a7082aad - * @param $pattern - * @param $flags - * @return array|false + * @param string $pattern + * @return list */ private function globstar(string $pattern) { if (stripos($pattern, '**') === false) { From 21594328f0ef74bb7f2d9bb731ed1667bb5e113e Mon Sep 17 00:00:00 2001 From: Nicolas D'Amours Date: Wed, 14 Aug 2024 11:24:37 -0400 Subject: [PATCH 4/5] [FEATURE] #82 Added check to make sure $files isn't false when sorting the array. Otherwise, we return an empty array. --- src/Factory.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index 97180fe..3e35177 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -133,9 +133,12 @@ private function globstar(string $pattern) { } } - $files = array_unique($files); - sort($files); + if($files !== false) { + $files = array_unique($files); + sort($files); + return $files; + } - return $files; + return []; } } From fa47ef930c642e0ee1337ef554d46a1df1f465e9 Mon Sep 17 00:00:00 2001 From: Nicolas D'Amours Date: Thu, 15 Aug 2024 08:30:41 -0400 Subject: [PATCH 5/5] [FEATURE] #82 Ignore coverage for the last line of the globstar function, since it's only used if the glob function returns an error. Added a test to validate the behaviour of the globstar function when passing non existant glob pattern. Fixed code using php-cs-fixer. Fixed error reported by phpstan. --- src/Factory.php | 28 +++++++++++++++++--------- tests/fixture/a/c/d/i/PrefixSuffix.php | 10 ++++++++- tests/fixture/b/e/g/i/PrefixSuffix.php | 10 ++++++++- tests/fixture/b/e/i/PrefixSuffix.php | 10 ++++++++- tests/fixture/b/f/h/i/PrefixSuffix.php | 10 ++++++++- tests/unit/FacadeTest.php | 10 +++++++-- 6 files changed, 63 insertions(+), 15 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index 3e35177..1b50128 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -13,11 +13,15 @@ use function array_filter; use function array_map; use function array_merge; +use function array_unique; use function array_values; use function glob; use function is_dir; use function is_string; use function realpath; +use function sort; +use function stripos; +use function substr; use AppendIterator; use FilesystemIterator; use RecursiveDirectoryIterator; @@ -106,39 +110,45 @@ private function resolveWildcards(array $paths): array /** * @see https://gist.github.com/funkjedi/3feee27d873ae2297b8e2370a7082aad - * @param string $pattern - * @return list + * + * @return list */ - private function globstar(string $pattern) { + private function globstar(string $pattern) + { if (stripos($pattern, '**') === false) { $files = glob($pattern, GLOB_ONLYDIR); } else { - $position = stripos($pattern, '**'); + $position = stripos($pattern, '**'); $rootPattern = substr($pattern, 0, $position - 1); $restPattern = substr($pattern, $position + 2); - $patterns = [$rootPattern.$restPattern]; + $patterns = [$rootPattern . $restPattern]; $rootPattern .= '/*'; - while($dirs = glob($rootPattern, GLOB_ONLYDIR)) { + while ($dirs = glob($rootPattern, GLOB_ONLYDIR)) { $rootPattern .= '/*'; - foreach($dirs as $dir) { + + foreach ($dirs as $dir) { $patterns[] = $dir . $restPattern; } } $files = []; - foreach($patterns as $pat) { + + foreach ($patterns as $pat) { $files = array_merge($files, $this->globstar($pat)); } } - if($files !== false) { + if ($files !== false) { $files = array_unique($files); sort($files); + return $files; } + // @codeCoverageIgnoreStart return []; + // @codeCoverageIgnoreEnd } } diff --git a/tests/fixture/a/c/d/i/PrefixSuffix.php b/tests/fixture/a/c/d/i/PrefixSuffix.php index b3d9bbc..e42bdc2 100644 --- a/tests/fixture/a/c/d/i/PrefixSuffix.php +++ b/tests/fixture/a/c/d/i/PrefixSuffix.php @@ -1 +1,9 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ diff --git a/tests/fixture/b/e/g/i/PrefixSuffix.php b/tests/fixture/b/e/g/i/PrefixSuffix.php index b3d9bbc..e42bdc2 100644 --- a/tests/fixture/b/e/g/i/PrefixSuffix.php +++ b/tests/fixture/b/e/g/i/PrefixSuffix.php @@ -1 +1,9 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ diff --git a/tests/fixture/b/e/i/PrefixSuffix.php b/tests/fixture/b/e/i/PrefixSuffix.php index b3d9bbc..e42bdc2 100644 --- a/tests/fixture/b/e/i/PrefixSuffix.php +++ b/tests/fixture/b/e/i/PrefixSuffix.php @@ -1 +1,9 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ diff --git a/tests/fixture/b/f/h/i/PrefixSuffix.php b/tests/fixture/b/f/h/i/PrefixSuffix.php index b3d9bbc..e42bdc2 100644 --- a/tests/fixture/b/f/h/i/PrefixSuffix.php +++ b/tests/fixture/b/f/h/i/PrefixSuffix.php @@ -1 +1,9 @@ - + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ diff --git a/tests/unit/FacadeTest.php b/tests/unit/FacadeTest.php index b0c3f99..722194e 100644 --- a/tests/unit/FacadeTest.php +++ b/tests/unit/FacadeTest.php @@ -7,7 +7,6 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ - namespace SebastianBergmann\FileIterator; use function realpath; @@ -148,7 +147,14 @@ public static function provider(): array __DIR__ . '/../fixture/**/i', '', '', - [] + [], + ], + 'invalid path, filter prefix: no, filter suffix: no, excludes: none' => [ + [], + __DIR__ . '/../fixture/**/this/path/does/not/exists', + '', + '', + [], ], ]; }