modulesPath)) { return; } // Get all module directories $modules = $this->getModuleDirectories(); foreach ($modules as $moduleName => $modulePath) { $routeFile = $modulePath . DIRECTORY_SEPARATOR . $this->routeFileName; if (file_exists($routeFile)) { $this->loadModuleRouteFile($routeFile, $routes, $moduleName); } } } /** * Get all module directories * * @return array Array of module name => module path */ protected function getModuleDirectories(): array { $modules = []; $dirs = scandir($this->modulesPath); foreach ($dirs as $dir) { if ($dir === '.' || $dir === '..') { continue; } $modulePath = $this->modulesPath . $dir; if (is_dir($modulePath)) { $modules[$dir] = $modulePath; } } return $modules; } /** * Load a module route file * * @param string $routeFile Full path to Routes.php file * @param RouteCollection $routes The route collection instance * @param string $moduleName Name of the module * @return void */ protected function loadModuleRouteFile(string $routeFile, RouteCollection $routes, string $moduleName): void { // Include the route file // The route file should use the $routes variable passed to it if (file_exists($routeFile)) { // Make $routes available in the included file's scope // Extract to current scope so Routes.php can access $routes variable extract(['routes' => $routes], EXTR_SKIP); require $routeFile; } } /** * Get list of available modules * * @return array List of module names */ public function getAvailableModules(): array { return array_keys($this->getModuleDirectories()); } /** * Check if a module exists * * @param string $moduleName Name of the module * @return bool */ public function moduleExists(string $moduleName): bool { $modulePath = $this->modulesPath . $moduleName; return is_dir($modulePath); } /** * Get module path * * @param string $moduleName Name of the module * @return string|null Module path or null if not found */ public function getModulePath(string $moduleName): ?string { if (!$this->moduleExists($moduleName)) { return null; } return $this->modulesPath . $moduleName; } }