139 lines
3.6 KiB
PHP
139 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace Config;
|
|
|
|
use CodeIgniter\Config\BaseConfig;
|
|
use CodeIgniter\Router\RouteCollection;
|
|
|
|
/**
|
|
* Module Loader Configuration
|
|
*
|
|
* Handles automatic discovery and loading of module routes.
|
|
* Each module can contain a Routes.php file that will be automatically loaded.
|
|
*/
|
|
class ModuleLoader extends BaseConfig
|
|
{
|
|
/**
|
|
* Base path for modules directory
|
|
*
|
|
* @var string
|
|
*/
|
|
protected string $modulesPath = APPPATH . 'Modules' . DIRECTORY_SEPARATOR;
|
|
|
|
/**
|
|
* Route file name to look for in each module
|
|
*
|
|
* @var string
|
|
*/
|
|
protected string $routeFileName = 'Routes.php';
|
|
|
|
/**
|
|
* Load all module routes automatically
|
|
*
|
|
* Scans app/Modules/* directories and loads Routes.php from each module
|
|
* if it exists.
|
|
*
|
|
* @param RouteCollection $routes The route collection instance
|
|
* @return void
|
|
*/
|
|
public function loadModuleRoutes(RouteCollection $routes): void
|
|
{
|
|
if (!is_dir($this->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<string, string> 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<string> 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;
|
|
}
|
|
}
|