From 71ac6cc87d978ae2648908f4424e394148111e2c Mon Sep 17 00:00:00 2001 From: Sam Maosa Date: Mon, 15 Apr 2024 10:56:48 +0300 Subject: [PATCH] Modifications: Adjust the Path and Namespace generation for laravel-modules v11 - Bug Fix: Fix translation key in cluster generation - Changed and tested Plugin and Cluster Generation - Changed and Tested Resource Generation --- .gitignore | 1 + composer.json | 29 +++++++++++++++---- src/Commands/ModuleFilamentInstallCommand.php | 6 ++-- .../ModuleMakeFilamentClusterCommand.php | 2 +- .../ModuleMakeFilamentPluginCommand.php | 2 +- src/Commands/stubs/filament-cluster.stub | 2 +- src/Concerns/GeneratesModularFiles.php | 12 ++++---- src/Modules.php | 15 ++++++---- src/ModulesPlugin.php | 5 ++-- src/ModulesServiceProvider.php | 24 +++++++-------- tests/ExampleTest.php | 5 ---- tests/ModulesTest.php | 12 ++++++++ tests/TestCase.php | 9 ++++-- 13 files changed, 80 insertions(+), 44 deletions(-) delete mode 100644 tests/ExampleTest.php create mode 100644 tests/ModulesTest.php diff --git a/.gitignore b/.gitignore index 8271e655..a6b54c7a 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ phpunit.xml phpstan.neon testbench.yaml vendor +.phpunit.cache diff --git a/composer.json b/composer.json index 30b71a3e..e9abb97e 100644 --- a/composer.json +++ b/composer.json @@ -23,14 +23,14 @@ "require": { "php": "^8.1", "filament/filament": "^3.0", - "nwidart/laravel-modules": "^10.0", + "nwidart/laravel-modules": "^11.0", "spatie/laravel-package-tools": "^1.15.0" }, "require-dev": { "laravel/pint": "^1.0", - "nunomaduro/collision": "^7.9|^8.1", + "nunomaduro/collision": "^8.1", "nunomaduro/larastan": "^2.0.1", - "orchestra/testbench": "^8.0|^9.0", + "orchestra/testbench": "^9.0", "pestphp/pest": "^2.1", "pestphp/pest-plugin-arch": "^2.0", "pestphp/pest-plugin-laravel": "^2.0", @@ -51,17 +51,34 @@ } }, "scripts": { - "post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi", + "post-autoload-dump": [ + "@clear", + "@prepare", + "@php ./vendor/bin/testbench package:discover --ansi" + ], "analyse": "vendor/bin/phpstan analyse", "test": "vendor/bin/pest", "test-coverage": "vendor/bin/pest --coverage", - "format": "vendor/bin/pint" + "format": "vendor/bin/pint", + "clear": "@php vendor/bin/testbench package:purge-skeleton --ansi", + "prepare": "@php vendor/bin/testbench package:discover --ansi", + "build": "@php vendor/bin/testbench workbench:build --ansi", + "serve": [ + "Composer\\Config::disableProcessTimeout", + "@build", + "@php vendor/bin/testbench serve" + ], + "lint": [ + "@php vendor/bin/pint", + "@php vendor/bin/phpstan analyse" + ] }, "config": { "sort-packages": true, "allow-plugins": { "pestphp/pest-plugin": true, - "phpstan/extension-installer": true + "phpstan/extension-installer": true, + "wikimedia/composer-merge-plugin": true } }, "extra": { diff --git a/src/Commands/ModuleFilamentInstallCommand.php b/src/Commands/ModuleFilamentInstallCommand.php index 5159db36..5e3dec3a 100644 --- a/src/Commands/ModuleFilamentInstallCommand.php +++ b/src/Commands/ModuleFilamentInstallCommand.php @@ -83,7 +83,7 @@ protected function getModule(): \Nwidart\Modules\Module { try { return Module::findOrFail($this->moduleName); - } catch (ModuleNotFoundException | \Throwable $exception) { + } catch (ModuleNotFoundException|\Throwable $exception) { if (confirm("Module $this->moduleName does not exist. Would you like to generate it?", true)) { $this->call('module:make', ['name' => [$this->moduleName]]); @@ -101,9 +101,11 @@ private function ensureFilamentDirectoriesExist(): void } if ($this->cluster) { + $dir = $this->getModule()->appPath('Filament/Clusters'); if (! is_dir($dir = $this->getModule()->appPath('Filament/Clusters'))) { $this->makeDirectory($dir); } + } else { if (! is_dir($dir = $this->getModule()->appPath('Filament/Pages'))) { $this->makeDirectory($dir); @@ -131,7 +133,7 @@ protected function createDefaultFilamentPlugin(): void { $module = $this->getModule(); $this->call('module:make:filament-plugin', [ - 'name' => $module->getStudlyName() . 'Plugin', + 'name' => $module->getStudlyName().'Plugin', 'module' => $module->getStudlyName(), ]); } diff --git a/src/Commands/ModuleMakeFilamentClusterCommand.php b/src/Commands/ModuleMakeFilamentClusterCommand.php index fb419667..7e3b6ad0 100644 --- a/src/Commands/ModuleMakeFilamentClusterCommand.php +++ b/src/Commands/ModuleMakeFilamentClusterCommand.php @@ -17,7 +17,7 @@ class ModuleMakeFilamentClusterCommand extends GeneratorCommand protected function getRelativeNamespace(): string { - return 'App\\Filament\\Clusters'; + return 'Filament\\Clusters'; } protected function getStub(): string diff --git a/src/Commands/ModuleMakeFilamentPluginCommand.php b/src/Commands/ModuleMakeFilamentPluginCommand.php index ee74a59a..1f268974 100644 --- a/src/Commands/ModuleMakeFilamentPluginCommand.php +++ b/src/Commands/ModuleMakeFilamentPluginCommand.php @@ -17,7 +17,7 @@ class ModuleMakeFilamentPluginCommand extends GeneratorCommand protected function getRelativeNamespace(): string { - return 'App\\Filament'; + return 'Filament'; } protected function getStub(): string diff --git a/src/Commands/stubs/filament-cluster.stub b/src/Commands/stubs/filament-cluster.stub index 7a51f8c6..0c7676e3 100644 --- a/src/Commands/stubs/filament-cluster.stub +++ b/src/Commands/stubs/filament-cluster.stub @@ -19,7 +19,7 @@ class {{ class }} extends Cluster public static function getNavigationLabel(): string { - return '__({{ navigationLabel }})'; + return __('{{ navigationLabel }}'); } public static function getNavigationIcon(): ?string diff --git a/src/Concerns/GeneratesModularFiles.php b/src/Concerns/GeneratesModularFiles.php index 529ec945..2fe2d723 100644 --- a/src/Concerns/GeneratesModularFiles.php +++ b/src/Concerns/GeneratesModularFiles.php @@ -19,7 +19,7 @@ protected function getArguments(): array protected function resolveStubPath($stub): string { - return FilamentModules::packagePath('src/Commands/' . trim($stub, DIRECTORY_SEPARATOR)); + return FilamentModules::packagePath('src/Commands/'.trim($stub, DIRECTORY_SEPARATOR)); } public function getModule(): Module @@ -29,7 +29,7 @@ public function getModule(): Module protected function getDefaultNamespace($rootNamespace): string { - return trim($rootNamespace, '\\') . '\\' . trim(Str::replace(DIRECTORY_SEPARATOR, '\\', $this->getRelativeNamespace()), '\\'); + return trim($rootNamespace, '\\').'\\'.trim(Str::replace(DIRECTORY_SEPARATOR, '\\', $this->getRelativeNamespace()), '\\'); } abstract protected function getRelativeNamespace(): string; @@ -41,9 +41,9 @@ protected function rootNamespace(): string protected function getPath($name): string { - $name = Str::replaceFirst($this->rootNamespace(), '', $name); + $name = Str::replaceFirst($this->rootNamespace(), 'app', $name); - return $this->getModule()->getExtraPath(str_replace('\\', '/', $name) . '.php'); + return $this->getModule()->getExtraPath(str_replace('\\', '/', $name).'.php'); } protected function possibleModels() @@ -61,7 +61,7 @@ protected function viewPath($path = ''): string { $views = $this->getModule()->resourcesPath('views'); - return $views . ($path ? DIRECTORY_SEPARATOR . $path : $path); + return $views.($path ? DIRECTORY_SEPARATOR.$path : $path); } protected function buildClass($name) @@ -89,7 +89,7 @@ protected function promptForMissingArgumentsUsing(): array { return [ 'name' => [ - 'What should the ' . strtolower($this->type ?: 'class') . ' be named?', + 'What should the '.strtolower($this->type ?: 'class').' be named?', match ($this->type) { 'Cast' => 'E.g. Json', 'Channel' => 'E.g. OrderChannel', diff --git a/src/Modules.php b/src/Modules.php index bc43c7df..bfec7244 100644 --- a/src/Modules.php +++ b/src/Modules.php @@ -19,11 +19,14 @@ public function getModule(string $name): \Nwidart\Modules\Module public function convertPathToNamespace(string $fullPath): string { $base = str(trim(config('modules.paths.modules', base_path('Modules')), '/')); - $relative = str(trim(config('modules.namespace', 'Modules'), '\\'))->replace('\\', DIRECTORY_SEPARATOR)->toString(); - - return str($fullPath) - ->replace($base, $relative) - ->replace('.php', '') + $relative = str($fullPath)->afterLast($base)->replaceFirst('/app/', '/'); + + return str($relative) + ->ltrim('/') + ->prepend('/') + ->prepend(config('modules.namespace', 'Modules')) + ->replace(DIRECTORY_SEPARATOR, '\\') + ->rtrim('.php') ->explode(DIRECTORY_SEPARATOR) ->map(fn ($piece) => str($piece)->studly()->toString()) ->implode('\\'); @@ -45,6 +48,6 @@ public function execCommand(string $command, ?Command $artisan = null): void public function packagePath(string $path = ''): string { //return the base path of this package - return dirname(__DIR__ . '../') . ($path ? DIRECTORY_SEPARATOR . trim($path, DIRECTORY_SEPARATOR) : ''); + return dirname(__DIR__.'../').($path ? DIRECTORY_SEPARATOR.trim($path, DIRECTORY_SEPARATOR) : ''); } } diff --git a/src/ModulesPlugin.php b/src/ModulesPlugin.php index 7de25762..d65c6a00 100644 --- a/src/ModulesPlugin.php +++ b/src/ModulesPlugin.php @@ -17,7 +17,8 @@ public function register(Panel $panel): void { $panel ->topNavigation(config('filament-modules.clusters.enabled', false) && config('filament-modules.clusters.use-top-navigation', false)); - foreach ($this->getModulePlugins() as $modulePlugin) { + $plugins = $this->getModulePlugins(); + foreach ($plugins as $modulePlugin) { $panel->plugin($modulePlugin::make()); } } @@ -46,7 +47,7 @@ protected function getModulePlugins(): array } // get a glob of all Filament plugins $basePath = str(config('modules.paths.modules', 'Modules')); - $pattern = $basePath . '/*/App/Filament/*Plugin.php'; + $pattern = $basePath.'/*/app/Filament/*Plugin.php'; $pluginPaths = glob($pattern); return collect($pluginPaths)->map(fn ($path) => FilamentModules::convertPathToNamespace($path))->toArray(); diff --git a/src/ModulesServiceProvider.php b/src/ModulesServiceProvider.php index 04df44fc..fdbd873a 100644 --- a/src/ModulesServiceProvider.php +++ b/src/ModulesServiceProvider.php @@ -78,7 +78,7 @@ public function packageBooted(): void // Handle Stubs if (app()->runningInConsole()) { - foreach (app(Filesystem::class)->files(__DIR__ . '/../stubs/') as $file) { + foreach (app(Filesystem::class)->files(__DIR__.'/../stubs/') as $file) { $this->publishes([ $file->getRealPath() => base_path("stubs/modules/{$file->getFilename()}"), ], 'modules-stubs'); @@ -170,44 +170,44 @@ protected function registerModuleMacros(): void $relativeNamespace = str_replace('App\\', '', $relativeNamespace); $relativeNamespace = str_replace('App', '', $relativeNamespace); $relativeNamespace = trim($relativeNamespace, '\\'); - $relativeNamespace = 'App\\' . $relativeNamespace; + $relativeNamespace = '\\'.$relativeNamespace; return $this->namespace($relativeNamespace); }); Module::macro('appPath', function (string $relativePath = '') { - $appPath = $this->getExtraPath('App'); + $appPath = $this->getExtraPath('app'); - return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : ''); + return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : ''); }); Module::macro('databasePath', function (string $relativePath = '') { - $appPath = $this->getExtraPath('Database'); + $appPath = $this->getExtraPath('database'); - return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : ''); + return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : ''); }); Module::macro('resourcesPath', function (string $relativePath = '') { $appPath = $this->getExtraPath('resources'); - return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : ''); + return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : ''); }); Module::macro('migrationsPath', function (string $relativePath = '') { $appPath = $this->databasePath('migrations'); - return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : ''); + return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : ''); }); Module::macro('seedersPath', function (string $relativePath = '') { - $appPath = $this->databasePath('Seeders'); + $appPath = $this->databasePath('seeders'); - return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : ''); + return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : ''); }); Module::macro('factoriesPath', function (string $relativePath = '') { - $appPath = $this->databasePath('Factories'); + $appPath = $this->databasePath('factories'); - return $appPath . ($relativePath ? DIRECTORY_SEPARATOR . $relativePath : ''); + return $appPath.($relativePath ? DIRECTORY_SEPARATOR.$relativePath : ''); }); } } diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php deleted file mode 100644 index 5d363218..00000000 --- a/tests/ExampleTest.php +++ /dev/null @@ -1,5 +0,0 @@ -toBeTrue(); -}); diff --git a/tests/ModulesTest.php b/tests/ModulesTest.php new file mode 100644 index 00000000..e4279b12 --- /dev/null +++ b/tests/ModulesTest.php @@ -0,0 +1,12 @@ +toBeTrue(); +}); + +// test that a module can be generated successfully +it('can generate a module', function () { + $this->artisan('module:make', ['name' => ['Example']]) + ->expectsOutput('Module created successfully.') + ->assertExitCode(0); +}); diff --git a/tests/TestCase.php b/tests/TestCase.php index c6b35099..5468a0ca 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -15,21 +15,25 @@ use Filament\Widgets\WidgetsServiceProvider; use Illuminate\Database\Eloquent\Factories\Factory; use Livewire\LivewireServiceProvider; +use Nwidart\Modules\LaravelModulesServiceProvider; +use Orchestra\Testbench\Concerns\WithWorkbench; use Orchestra\Testbench\TestCase as Orchestra; use RyanChandler\BladeCaptureDirective\BladeCaptureDirectiveServiceProvider; class TestCase extends Orchestra { + use WithWorkbench; + protected function setUp(): void { parent::setUp(); Factory::guessFactoryNamesUsing( - fn (string $modelName) => 'Coolsam\\Modules\\Database\\Factories\\' . class_basename($modelName) . 'Factory' + fn (string $modelName) => 'Coolsam\\Modules\\Database\\Factories\\'.class_basename($modelName).'Factory' ); } - protected function getPackageProviders($app) + protected function getPackageProviders($app): array { return [ ActionsServiceProvider::class, @@ -44,6 +48,7 @@ protected function getPackageProviders($app) SupportServiceProvider::class, TablesServiceProvider::class, WidgetsServiceProvider::class, + LaravelModulesServiceProvider::class, ModulesServiceProvider::class, ]; }