diff --git a/README.md b/README.md index 66a53ee..edc8029 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,21 @@ Choose your module management approach: ```php 'modules' => [ - 'approach' => env('MODULITE_APPROACH', 'panicdevs'), // or 'nwidart' + 'approach' => env('MODULITE_APPROACH', 'panicdevs'), // or 'nwidart' or custom FQCN + 'scan_only_enabled' => true, + 'respect_module_priority' => true, +], +``` + +### Custom Module Resolver (FQCN) + +You can provide your own fully-qualified class name (FQCN) as the module approach. +Your class **must implement** the `PanicDevs\Modulite\Contracts\ModuleResolverInterface`. + +```php +// config/modulite.php +'modules' => [ + 'approach' => \App\CustomModuleResolver::class, 'scan_only_enabled' => true, 'respect_module_priority' => true, ], @@ -367,7 +381,7 @@ public function panel(Panel $panel): Panel ]); } -// ManagerPanelProvider.php +// ManagerPanelProvider.php public function panel(Panel $panel): Panel { return $panel diff --git a/config/modulite.php b/config/modulite.php index 0520245..d75e497 100644 --- a/config/modulite.php +++ b/config/modulite.php @@ -388,10 +388,13 @@ |-------------------------------------------------------------------------- | | Specify which module management system you're using: - | - 'nwidart': Use nwidart/laravel-modules package - | - 'panicdevs': Use panicdevs/modules package + | - 'nwidart' : Use nwidart/laravel-modules package + | - 'panicdevs' : Use panicdevs/modules package + | - custom : Provide your own custom implementation class + | (must implement PanicDevs\Modulite\Contracts\ModuleResolverInterface). | - | This determines how Modulite discovers and interacts with your modules. + | Example: + | 'approach' => \App\CustomModuleResolver::class, | */ 'approach' => env('MODULITE_APPROACH', 'panicdevs'), diff --git a/src/Actions/CreateModuleResolver.php b/src/Actions/CreateModuleResolver.php new file mode 100644 index 0000000..6858ff3 --- /dev/null +++ b/src/Actions/CreateModuleResolver.php @@ -0,0 +1,43 @@ +get('modulite.modules.approach'); + + $defaultApproach = static::getDefaultApproach(); + + $class = !($defaultApproach[$approach] ?? '') ? + (static::approachIsResolvable($approach) ? + $approach : + throw new \Exception( + "Configured module approach [{$approach}] is missing or not resolvable." + )) : + $defaultApproach[$approach]; + + return $app->make($class); + } + + private static function approachIsResolvable(string $approach): bool + { + return + class_exists($approach) && + is_subclass_of($approach, ModuleResolverInterface::class); + } + + private static function getDefaultApproach(): array + { + return [ + 'panicdevs' => PanicDevsModuleResolver::class, + 'nwidart' => nwidartModuleResolver::class, + ]; + } +} diff --git a/src/Console/Commands/ModuliteOptimizeCommand.php b/src/Console/Commands/ModuliteOptimizeCommand.php index 32d2bc5..46f7698 100644 --- a/src/Console/Commands/ModuliteOptimizeCommand.php +++ b/src/Console/Commands/ModuliteOptimizeCommand.php @@ -167,7 +167,7 @@ protected function generatePanelCacheKey(ModuleResolverInterface $moduleResolver $moduleData = $enabledModules->sort()->values()->toArray(); // Include the module resolver approach in cache key - $approach = config('modulite.modules.approach', 'nwidart'); + $approach = config('modulite.modules.approach'); // Include configuration in cache key $configHash = md5(serialize([ diff --git a/src/Console/Commands/ModuliteStatusCommand.php b/src/Console/Commands/ModuliteStatusCommand.php index d18176b..9109c95 100644 --- a/src/Console/Commands/ModuliteStatusCommand.php +++ b/src/Console/Commands/ModuliteStatusCommand.php @@ -5,6 +5,7 @@ namespace PanicDevs\Modulite\Console\Commands; use Illuminate\Console\Command; +use PanicDevs\Modulite\Contracts\ModuleResolverInterface; use PanicDevs\Modulite\Contracts\PanelScannerInterface; /** @@ -40,7 +41,7 @@ public function handle( // Display status $this->displayConfiguration(); - $this->displayModuleStatus($panelScanner); + $this->displayModuleStatus(); $this->displayPanelStatus($panelScanner); $this->displayComponentStatus($componentScanner); $this->displayCacheStatus($cache); @@ -101,32 +102,21 @@ protected function displayConfiguration(): void $this->newLine(); } - protected function displayModuleStatus(PanelScannerInterface $panelScanner): void + protected function displayModuleStatus(): void { $this->info('Module Status:'); - // Get enabled modules using nwidart modules if available - $enabledModules = collect(); + $enabledModules = app(ModuleResolverInterface::class)->getEnabledModules(); - if (class_exists(\Nwidart\Modules\Facades\Module::class)) - { - $enabledModulesArray = \Nwidart\Modules\Facades\Module::allEnabled(); - foreach ($enabledModulesArray as $module) - { - $enabledModules->push($module->getName()); - } + if ($enabledModules->isEmpty()){ + $this->warn('No enabled modules found'); + return; } - if ($enabledModules->isEmpty()) - { - $this->warn('No enabled modules found'); - } else - { - $this->info("Found {$enabledModules->count()} enabled modules:"); - foreach ($enabledModules as $module) - { - $this->line(" • {$module}"); - } + $this->info("Found {$enabledModules->count()} enabled modules:"); + + foreach ($enabledModules as $module) { + $this->line(" • {$module}"); } $this->newLine(); diff --git a/src/Contracts/ModuleResolverInterface.php b/src/Contracts/ModuleResolverInterface.php index 8c3af43..cccda50 100644 --- a/src/Contracts/ModuleResolverInterface.php +++ b/src/Contracts/ModuleResolverInterface.php @@ -52,4 +52,13 @@ public function getSystemType(): string; * @return bool True if system is available, false otherwise */ public function isAvailable(): bool; + + /** + * Determine whether panels should be registered + * before Filament initialization. + * + * @return bool True if panels must be registered before Filament + */ + public function shouldRegisterPanelsBeforeFilament(): bool; + } diff --git a/src/Providers/ModuliteServiceProvider.php b/src/Providers/ModuliteServiceProvider.php index dc17118..fa334a1 100644 --- a/src/Providers/ModuliteServiceProvider.php +++ b/src/Providers/ModuliteServiceProvider.php @@ -8,6 +8,7 @@ use Illuminate\Contracts\Foundation\Application; use Illuminate\Support\Facades\Log; use Illuminate\Support\ServiceProvider; +use PanicDevs\Modulite\Actions\CreateModuleResolver; use PanicDevs\Modulite\Console\Commands\ModuliteClearCacheCommand; use PanicDevs\Modulite\Console\Commands\ModuliteStatusCommand; use PanicDevs\Modulite\Console\Commands\ModuliteOptimizeCommand; @@ -16,8 +17,6 @@ use PanicDevs\Modulite\Contracts\ModuleResolverInterface; use PanicDevs\Modulite\Contracts\PanelScannerInterface; use PanicDevs\Modulite\Services\ComponentDiscoveryService; -use PanicDevs\Modulite\Services\ModuleResolvers\NwidartModuleResolver; -use PanicDevs\Modulite\Services\ModuleResolvers\PanicDevsModuleResolver; use PanicDevs\Modulite\Services\PanelScannerService; use PanicDevs\Modulite\Services\UnifiedCacheManager; use Throwable; @@ -78,14 +77,15 @@ class ModuliteServiceProvider extends ServiceProvider public function register(): void { $this->registerConfiguration(); + $this->registerCoreServices(); - if ('nwidart' === config('modulite.modules.approach')) - { - $this->app->beforeResolving('filament', fn() => $this->registerPanelDiscovery()); - } else - { - $this->registerPanelDiscovery(); - } + + $this->app + ->make(ModuleResolverInterface::class) + ->shouldRegisterPanelsBeforeFilament() ? + $this->app->beforeResolving('filament', fn () => $this->registerPanelDiscovery()): + $this->registerPanelDiscovery(); + $this->registerCacheInvalidationListeners(); } @@ -126,7 +126,10 @@ protected function registerCoreServices(): void }); // Register ModuleResolver based on configuration - $this->app->singleton(ModuleResolverInterface::class, fn(Application $app) => $this->createModuleResolver($app)); + $this->app->singleton( + ModuleResolverInterface::class, + fn(Application $app) => (new CreateModuleResolver())->handle($app) + ); // Register PanelScannerService with dependencies $this->app->singleton(PanelScannerInterface::class, function (Application $app) @@ -244,7 +247,7 @@ protected function generateCacheKey(): string $moduleData = $enabledModules->sort()->values()->toArray(); // Include the module resolver approach in cache key - $approach = config('modulite.modules.approach', 'nwidart'); + $approach = config('modulite.modules.approach'); // Include configuration in cache key $configHash = md5(serialize([ @@ -282,21 +285,6 @@ protected function getModuleManager(Application $app): mixed } } - /** - * Create the appropriate module resolver based on configuration. - */ - protected function createModuleResolver(Application $app): ModuleResolverInterface - { - $approach = $app['config']->get('modulite.modules.approach', 'nwidart'); - - return match ($approach) - { - 'panicdevs' => new PanicDevsModuleResolver($app), - 'nwidart' => new NwidartModuleResolver(), - default => new NwidartModuleResolver(), // Default fallback - }; - } - /** * Register cache invalidation event listeners. * diff --git a/src/Services/ModuleResolvers/NwidartModuleResolver.php b/src/Services/ModuleResolvers/NwidartModuleResolver.php index 07183c4..a6a89ff 100644 --- a/src/Services/ModuleResolvers/NwidartModuleResolver.php +++ b/src/Services/ModuleResolvers/NwidartModuleResolver.php @@ -154,4 +154,15 @@ protected function getFallbackModules(): Collection return $modules; } + + /** + * Determine whether panels should be registered + * before Filament initialization. + * + * @return bool True if panels must be registered before Filament + */ + public function shouldRegisterPanelsBeforeFilament(): bool + { + return true; + } } diff --git a/src/Services/ModuleResolvers/PanicDevsModuleResolver.php b/src/Services/ModuleResolvers/PanicDevsModuleResolver.php index 56e0a19..d96fbe0 100644 --- a/src/Services/ModuleResolvers/PanicDevsModuleResolver.php +++ b/src/Services/ModuleResolvers/PanicDevsModuleResolver.php @@ -144,4 +144,15 @@ protected function getModuleService(): ModuleService return $this->moduleService; } + + /** + * Determine whether panels should be registered + * before Filament initialization. + * + * @return bool True if panels must be registered before Filament + */ + public function shouldRegisterPanelsBeforeFilament(): bool + { + return false; + } }