diff --git a/src/Factory.php b/src/Factory.php index a2ebce6..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; @@ -92,7 +96,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 +107,48 @@ private function resolveWildcards(array $paths): array return array_values(array_filter(array_merge(...$_paths))); } + + /** + * @see https://gist.github.com/funkjedi/3feee27d873ae2297b8e2370a7082aad + * + * @return list + */ + 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)); + } + } + + 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 new file mode 100644 index 0000000..e42bdc2 --- /dev/null +++ b/tests/fixture/a/c/d/i/PrefixSuffix.php @@ -0,0 +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 new file mode 100644 index 0000000..e42bdc2 --- /dev/null +++ b/tests/fixture/b/e/g/i/PrefixSuffix.php @@ -0,0 +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 new file mode 100644 index 0000000..e42bdc2 --- /dev/null +++ b/tests/fixture/b/e/i/PrefixSuffix.php @@ -0,0 +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 new file mode 100644 index 0000000..e42bdc2 --- /dev/null +++ b/tests/fixture/b/f/h/i/PrefixSuffix.php @@ -0,0 +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 3200790..722194e 100644 --- a/tests/unit/FacadeTest.php +++ b/tests/unit/FacadeTest.php @@ -41,11 +41,15 @@ public static function provider(): array $fixtureDirectoryRealpath . '/a/c/d/Prefix.php', $fixtureDirectoryRealpath . '/a/c/d/PrefixSuffix.php', $fixtureDirectoryRealpath . '/a/c/d/Suffix.php', + $fixtureDirectoryRealpath . '/a/c/d/i/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/e/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/e/g/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/e/g/i/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/e/i/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/f/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/f/h/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/f/h/i/PrefixSuffix.php', ], __DIR__ . '/../fixture', '', @@ -59,6 +63,8 @@ public static function provider(): array $fixtureDirectoryRealpath . '/b/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/e/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/e/g/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/e/g/i/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/e/i/PrefixSuffix.php', ], __DIR__ . '/../fixture', '', @@ -76,11 +82,15 @@ public static function provider(): array $fixtureDirectoryRealpath . '/a/c/PrefixSuffix.php', $fixtureDirectoryRealpath . '/a/c/d/Prefix.php', $fixtureDirectoryRealpath . '/a/c/d/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/a/c/d/i/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/e/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/e/g/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/e/g/i/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/e/i/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/f/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/f/h/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/f/h/i/PrefixSuffix.php', ], __DIR__ . '/../fixture', '', @@ -95,11 +105,15 @@ public static function provider(): array $fixtureDirectoryRealpath . '/a/c/Suffix.php', $fixtureDirectoryRealpath . '/a/c/d/PrefixSuffix.php', $fixtureDirectoryRealpath . '/a/c/d/Suffix.php', + $fixtureDirectoryRealpath . '/a/c/d/i/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/e/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/e/g/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/e/g/i/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/e/i/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/f/PrefixSuffix.php', $fixtureDirectoryRealpath . '/b/f/h/PrefixSuffix.php', + $fixtureDirectoryRealpath . '/b/f/h/i/PrefixSuffix.php', ], __DIR__ . '/../fixture', 'Suffix.php', @@ -115,12 +129,33 @@ public static function provider(): array $fixtureDirectoryRealpath . '/a/c/d/Prefix.php', $fixtureDirectoryRealpath . '/a/c/d/PrefixSuffix.php', $fixtureDirectoryRealpath . '/a/c/d/Suffix.php', + $fixtureDirectoryRealpath . '/a/c/d/i/PrefixSuffix.php', ], __DIR__ . '/../fixture/*/c', '', '', [], ], + 'globstar, filter prefix: no, filter suffix: no, excludes: none' => [ + [ + + $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', + '', + '', + [], + ], + 'invalid path, filter prefix: no, filter suffix: no, excludes: none' => [ + [], + __DIR__ . '/../fixture/**/this/path/does/not/exists', + '', + '', + [], + ], ]; }