diff --git a/src/ComposerRequireChecker/FileLocator/LocateAllFilesByExtension.php b/src/ComposerRequireChecker/FileLocator/LocateAllFilesByExtension.php index 36ce93f6..8e07316c 100644 --- a/src/ComposerRequireChecker/FileLocator/LocateAllFilesByExtension.php +++ b/src/ComposerRequireChecker/FileLocator/LocateAllFilesByExtension.php @@ -24,6 +24,8 @@ private function filterFilesByExtension(Traversable $files, string $fileExtensio { $extensionMatcher = '/.*' . preg_quote($fileExtension) . '$/'; + $blacklist = $this->prepareBlacklistPatterns($blacklist); + /* @var $file \SplFileInfo */ foreach ($files as $file) { if ($blacklist && preg_match('{('.implode('|', $blacklist).')}', $file->getPathname())) { @@ -37,4 +39,19 @@ private function filterFilesByExtension(Traversable $files, string $fileExtensio yield $file->getPathname(); } } + + private function prepareBlacklistPatterns(?array $blacklistPaths) + { + if ($blacklistPaths === null) { + return $blacklistPaths; + } + + foreach ($blacklistPaths as &$path) { + $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/'))); + $path = str_replace('\\*\\*', '.+?', $path); + $path = str_replace('\\*', '[^/]+?', $path); + } + + return $blacklistPaths; + } } diff --git a/test/ComposerRequireCheckerTest/FileLocator/LocateComposerPackageSourceFilesTest.php b/test/ComposerRequireCheckerTest/FileLocator/LocateComposerPackageSourceFilesTest.php index 7f057323..32302af6 100644 --- a/test/ComposerRequireCheckerTest/FileLocator/LocateComposerPackageSourceFilesTest.php +++ b/test/ComposerRequireCheckerTest/FileLocator/LocateComposerPackageSourceFilesTest.php @@ -145,19 +145,82 @@ public function testFromPsr4WithNestedDirectoryAlternativeDirectorySeparator() $this->assertContains($this->root->getChild('src/MyNamespace/MyClassA.php')->url(), $files); } - public function testFromPsr4WithExcludeFromClassmap() + /** + * @dataProvider provideExcludePattern + */ + public function testFromPsr4WithExcludeFromClassmap(array $excludedPattern, array $expectedFiles) { + $excludedPatternJson = json_encode($excludedPattern); + vfsStream::create([ - 'composer.json' => '{"autoload": {"psr-4": {"MyNamespace\\\\": "./"}, "exclude-from-classmap": ["/tests/"]}}', - 'MyClass.php' => ' '{"autoload": {"psr-4": {"MyNamespace\\\\": ""}, "exclude-from-classmap": ' . $excludedPatternJson . '}}', + 'ClassA.php' => ' [ - 'MyClassTest.php' => ' ' [ + 'Tests' => [ + 'BTest.php' => ' [ + 'ClassB.php' => ' [ + 'CTest.php' => 'files($this->root->getChild('composer.json')->url()); - $this->assertCount(1, $files); + $this->assertCount(count($expectedFiles), $files); + foreach ($expectedFiles as $expectedFile) { + $this->assertContains($this->root->getChild($expectedFile)->url(), $files); + } + } + + /** + * @return array[] + */ + public function provideExcludePattern(): array + { + return [ + 'No exclude pattern' => [ + [], + [ + 'ClassA.php', + 'tests/ATest.php', + 'foo/Tests/BTest.php', + 'foo/src/ClassB.php', + 'foo/src/Tests/CTest.php', + + ], + ], + 'Exclude single directory by pattern' => [ + ['/tests/'], + [ + 'ClassA.php', + 'foo/Tests/BTest.php', + 'foo/src/ClassB.php', + 'foo/src/Tests/CTest.php', + ], + ], + 'Exclude all subdirectories by pattern' => [ + ['/**Tests/'], + [ + 'ClassA.php', + 'tests/ATest.php', + 'foo/src/ClassB.php', + ], + ], + 'Combine multiple patterns' => [ + ['/tests/', '/**Tests/'], + [ + 'ClassA.php', + 'foo/src/ClassB.php', + ], + ], + ]; } /**