Files
presensi/app/Config/ModuleLoader.php
2026-03-05 14:37:36 +07:00

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;
}
}