diff --git a/src/MultipleDirClassSet.php b/src/MultipleDirClassSet.php new file mode 100644 index 00000000..0d9907d1 --- /dev/null +++ b/src/MultipleDirClassSet.php @@ -0,0 +1,56 @@ +directoryList = $directoryList; + $this->exclude = []; + } + + public static function fromDir(string ...$directoryList): self + { + return new self(...$directoryList); + } + + public function excludePath(string $pattern): ClassSetInterface + { + $this->exclude[] = Glob::toRegex($pattern); + + return $this; + } + + public function getDir(): string + { + return implode(', ', $this->directoryList); + } + + public function getIterator(): \Traversable + { + $finder = (new Finder()) + ->files() + ->in($this->directoryList) + ->name('*.php') + ->sortByName() + ->followLinks() + ->ignoreUnreadableDirs(true) + ->ignoreVCS(true); + + if ($this->exclude) { + $finder->notPath($this->exclude); + } + + return $finder; + } +} diff --git a/tests/Unit/MultipleDirClassSetTest.php b/tests/Unit/MultipleDirClassSetTest.php new file mode 100644 index 00000000..2e9e0391 --- /dev/null +++ b/tests/Unit/MultipleDirClassSetTest.php @@ -0,0 +1,128 @@ +createMvcProjectStructure(); + + $set = MultipleDirClassSet::fromDir($path . '/Controller', $path . '/Model') + ->excludePath("Repository"); + + $expected = [ + $path . '/Controller/CatalogController.php', + $path . '/Controller/Foo.php', + $path . '/Controller/ProductsController.php', + $path . '/Controller/UserController.php', + $path . '/Controller/YieldController.php', + $path . '/Model/Catalog.php', + $path . '/Model/Products.php', + $path . '/Model/User.php', + ]; + $actual = array_values(array_map(function ($item) { + /** @var SplFileInfo $item */ + return $item->getPathname(); + }, iterator_to_array($set))); + self::assertEquals($expected, $actual); + } + + public function test_can_exclude_files_or_directories(): void + { + $path = $this->createMvcProjectStructure(); + + $set = MultipleDirClassSet::fromDir($path) + ->excludePath('Model') + ->excludePath('ContainerAwareInterface'); + + $expected = [ + 'Controller/CatalogController.php', + 'Controller/Foo.php', + 'Controller/ProductsController.php', + 'Controller/UserController.php', + 'Controller/YieldController.php', + 'Services/UserService.php', + 'View/CatalogView.php', + 'View/ProductView.php', + 'View/UserView.php', + ]; + + $actual = array_values(array_map(function ($item) { + /** @var SplFileInfo $item */ + return $item->getRelativePathname(); + }, iterator_to_array($set))); + + self::assertEquals($expected, $actual); + } + + public function test_can_exclude_glob_patterns(): void + { + $path = $this->createMvcProjectStructure(); + + $set = MultipleDirClassSet::fromDir($path) + ->excludePath('*Catalog*'); + + $expected = [ + 'ContainerAwareInterface.php', + 'Controller/Foo.php', + 'Controller/ProductsController.php', + 'Controller/UserController.php', + 'Controller/YieldController.php', + 'Model/Products.php', + 'Model/Repository/ProductsRepository.php', + 'Model/Repository/UserRepository.php', + 'Model/User.php', + 'Services/UserService.php', + 'View/ProductView.php', + 'View/UserView.php', + ]; + + $actual = array_values(array_map(function ($item) { + return $item->getRelativePathname(); + }, iterator_to_array($set))); + + self::assertEquals($expected, $actual); + } + + protected function createMvcProjectStructure(): string + { + $structure = [ + 'Controller' => [ + 'CatalogController.php' => '', + 'Foo.php' => '', + 'ProductsController.php' => '', + 'UserController.php' => '', + 'YieldController.php' => '', + ], + 'Model' => [ + 'Repository' => [ + 'CatalogRepository.php' => '', + 'ProductsRepository.php' => '', + 'UserRepository.php' => '', + ], + 'Catalog.php' => '', + 'Products.php' => '', + 'User.php' => '', + ], + 'Services' => [ + 'UserService.php' => '', + ], + 'View' => [ + 'CatalogView.php' => '', + 'ProductView.php' => '', + 'UserView.php' => '', + ], + 'ContainerAwareInterface.php' => '', + ]; + + return vfsStream::setup('root', null, $structure)->url(); + } +}