app->singleton(ModuleManager::class, function ($app) { return new ModuleManager(); }); } /** * Bootstrap services. */ public function boot(): void { // Carica automaticamente le route dei moduli attivi $this->loadModuleRoutes(); // Carica le view dei moduli $this->loadModuleViews(); // Carica le translations dei moduli $this->loadModuleTranslations(); // Carica le configurazioni dei moduli $this->loadModuleConfigs(); } /** * Carica le route dei moduli attivi */ protected function loadModuleRoutes(): void { $moduleManager = $this->app->make(ModuleManager::class); $activeModuleNames = $this->getActiveModuleNames(); if (empty($activeModuleNames)) { return; } foreach ($activeModuleNames as $moduleName) { $routesPath = app_path("Modules/{$moduleName}/Routes/web.php"); if (File::exists($routesPath)) { // Carica le routes con middleware web (che include già il prefisso admin nel file) Route::middleware('web')->group($routesPath); } // Carica anche le API routes se esistono $apiRoutesPath = app_path("Modules/{$moduleName}/Routes/api.php"); if (File::exists($apiRoutesPath)) { Route::middleware('api') ->prefix('api') ->group($apiRoutesPath); } } } /** * Carica le view dei moduli */ protected function loadModuleViews(): void { $activeModuleNames = $this->getActiveModuleNames(); if (empty($activeModuleNames)) { return; } foreach ($activeModuleNames as $moduleName) { $viewsPath = app_path("Modules/{$moduleName}/Views"); if (File::isDirectory($viewsPath)) { // Approccio diretto: registra il namespace usando View::addNamespace $namespace = 'modules.' . strtolower($moduleName); try { // Usa View::addNamespace per registrare direttamente view()->addNamespace($namespace, $viewsPath); Log::info("Registrato namespace view diretto: {$namespace} -> {$viewsPath}"); // Per compatibilità, registra anche con trattini se necessario if ($moduleName === 'StampeRate') { view()->addNamespace('modules.stampe-rate', $viewsPath); Log::info("Registrato namespace compatibilità: modules.stampe-rate -> {$viewsPath}"); } } catch (\Exception $e) { Log::error("Errore registrazione namespace {$namespace}: " . $e->getMessage()); } } } } /** * Carica le traduzioni dei moduli */ protected function loadModuleTranslations(): void { $activeModuleNames = $this->getActiveModuleNames(); if (empty($activeModuleNames)) { return; } foreach ($activeModuleNames as $moduleName) { $langPath = app_path("Modules/{$moduleName}/Lang"); if (File::isDirectory($langPath)) { $this->loadTranslationsFrom($langPath, strtolower($moduleName)); } } } /** * Carica le configurazioni dei moduli */ protected function loadModuleConfigs(): void { $activeModuleNames = $this->getActiveModuleNames(); if (empty($activeModuleNames)) { return; } foreach ($activeModuleNames as $moduleName) { $configPath = app_path("Modules/{$moduleName}/Config"); if (File::isDirectory($configPath)) { $configFiles = File::files($configPath); foreach ($configFiles as $file) { $configName = strtolower($moduleName) . '.' . pathinfo($file->getFilename(), PATHINFO_FILENAME); $this->mergeConfigFrom($file->getPathname(), $configName); } } } } /** * Ottiene la lista dei moduli attivi dal database in modo sicuro. */ protected function getActiveModuleNames(): array { if ($this->activeModuleNames !== null) { return $this->activeModuleNames; } if (!$this->modulesTableExists()) { return $this->activeModuleNames = []; } try { return $this->activeModuleNames = DB::table('modules') ->where('status', 'active') ->pluck('name') ->toArray(); } catch (\Throwable $e) { Log::warning('ModuleServiceProvider: impossibile caricare moduli attivi', [ 'error' => $e->getMessage(), ]); return $this->activeModuleNames = []; } } protected function modulesTableExists(): bool { try { return DB::connection()->getSchemaBuilder()->hasTable('modules'); } catch (\Throwable $e) { Log::notice('ModuleServiceProvider: schema builder non disponibile', [ 'error' => $e->getMessage(), ]); return false; } } }