From a4b4e66596278eee50353babd8870446db38a250 Mon Sep 17 00:00:00 2001 From: Mohammad Zahed Date: Sat, 24 Feb 2024 14:57:16 +0300 Subject: [PATCH] using scouts for discovery --- composer.json | 39 ++- config/modules.php | 161 +++++++--- phpstan-baseline.neon | 9 +- src/Commands/CacheCommand.php | 43 +++ src/Commands/ClearCommand.php | 41 +++ src/Concerns/FindsSeeder.php | 27 -- src/Concerns/GetsSchedules.php | 31 -- src/Concerns/SupportsCommand.php | 30 -- src/Concerns/SupportsConfig.php | 26 -- src/Concerns/SupportsFactory.php | 25 -- src/Concerns/SupportsHelpers.php | 16 - src/Concerns/SupportsLivewire.php | 34 -- src/Concerns/SupportsMigration.php | 17 - src/Concerns/SupportsNova.php | 38 --- src/Concerns/SupportsPolicy.php | 25 -- src/Concerns/SupportsRoutes.php | 60 ---- src/Concerns/SupportsServiceProviders.php | 30 -- src/Concerns/SupportsTranslation.php | 17 - src/Concerns/SupportsView.php | 31 -- src/Contracts/BaseScout.php | 114 +++++++ src/Contracts/ModuleClassScout.php | 22 ++ src/Contracts/ModuleDirectoryScout.php | 23 ++ src/Contracts/ModuleFileScout.php | 22 ++ src/Enums/AssetType.php | 88 ++++++ src/Modules.php | 99 +++--- src/ModulesServiceProvider.php | 293 +++++++++++++++--- src/Scouts/CommandsScout.php | 28 ++ src/Scouts/ConfigsScout.php | 14 + src/Scouts/HelpersScout.php | 14 + src/Scouts/LivewireComponentsScout.php | 28 ++ src/Scouts/MigrationsScout.php | 14 + src/Scouts/NovaResourcesScout.php | 32 ++ src/Scouts/RoutesScout.php | 14 + src/Scouts/SchedulesScout.php | 28 ++ src/Scouts/SeedersScout.php | 33 ++ src/Scouts/ServiceProvidersScout.php | 28 ++ src/Scouts/TranslationsScout.php | 14 + src/Scouts/ViewsScout.php | 14 + tests/ExampleTest.php | 5 - tests/Feature/CommandsTest.php | 12 + tests/Feature/ConfigsTest.php | 5 + tests/Feature/HelpersTest.php | 8 + tests/Feature/LivewireComponentsTest.php | 13 + tests/Feature/MigrationsTest.php | 12 + tests/Feature/NovaResourcesTest.php | 5 + tests/Feature/SchedulesTest.php | 5 + tests/Feature/SeedersTest.php | 12 + tests/Feature/ServiceProvidersTest.php | 12 + tests/Feature/TranslationsTest.php | 13 + tests/Feature/ViewsTest.php | 5 + tests/Pest.php | 3 +- tests/TestCase.php | 7 + workbench/Modules/First/Config/first.php | 5 + .../Console/Commands/DeleteUsersCommand.php | 18 ++ .../First/Database/Factories/UserFactory.php | 18 ++ .../2024_02_21_144905_create_users_table.php | 22 ++ .../Database/Seeders/FirstDatabaseSeeder.php | 15 + .../First/Database/Seeders/UserSeeder.php | 14 + workbench/Modules/First/Helpers/Shared.php | 8 + workbench/Modules/First/Models/User.php | 11 + .../Modules/First/Policies/UserPolicy.php | 10 + .../First/Providers/UserServiceProvider.php | 9 + workbench/Modules/First/Resources/lang/en.php | 5 + .../Console/Commands/DeleteTeamsCommand.php | 18 ++ .../Second/Database/Factories/TeamFactory.php | 18 ++ .../2024_02_22_144905_create_teams_table.php | 22 ++ ...2024_03_22_144905_create_backups_table.php | 22 ++ .../Database/Seeders/SecondDatabaseSeeder.php | 15 + .../Database/Seeders/TeamDatabaseSeeder.php | 14 + workbench/Modules/Second/Helpers.php | 8 + .../Modules/Second/Livewire/ListUsers.php | 14 + workbench/Modules/Second/Models/Team.php | 11 + .../Second/Providers/TeamServiceProvider.php | 9 + .../Modules/Second/Resources/lang/en.php | 5 + .../views/livewire/list-users.blade.php | 3 + workbench/app/Models/Test.php | 11 + workbench/app/Policies/TestPolicy.php | 10 + .../Providers/WorkbenchServiceProvider.php | 14 +- workbench/bootstrap/cache/.gitignore | 2 + workbench/config/modules.php | 14 + workbench/database/factories/TestFactory.php | 18 ++ 81 files changed, 1522 insertions(+), 580 deletions(-) create mode 100644 src/Commands/CacheCommand.php create mode 100644 src/Commands/ClearCommand.php delete mode 100644 src/Concerns/FindsSeeder.php delete mode 100644 src/Concerns/GetsSchedules.php delete mode 100644 src/Concerns/SupportsCommand.php delete mode 100644 src/Concerns/SupportsConfig.php delete mode 100644 src/Concerns/SupportsFactory.php delete mode 100644 src/Concerns/SupportsHelpers.php delete mode 100644 src/Concerns/SupportsLivewire.php delete mode 100644 src/Concerns/SupportsMigration.php delete mode 100644 src/Concerns/SupportsNova.php delete mode 100644 src/Concerns/SupportsPolicy.php delete mode 100644 src/Concerns/SupportsRoutes.php delete mode 100644 src/Concerns/SupportsServiceProviders.php delete mode 100644 src/Concerns/SupportsTranslation.php delete mode 100644 src/Concerns/SupportsView.php create mode 100644 src/Contracts/BaseScout.php create mode 100644 src/Contracts/ModuleClassScout.php create mode 100644 src/Contracts/ModuleDirectoryScout.php create mode 100644 src/Contracts/ModuleFileScout.php create mode 100644 src/Enums/AssetType.php create mode 100644 src/Scouts/CommandsScout.php create mode 100644 src/Scouts/ConfigsScout.php create mode 100644 src/Scouts/HelpersScout.php create mode 100644 src/Scouts/LivewireComponentsScout.php create mode 100644 src/Scouts/MigrationsScout.php create mode 100644 src/Scouts/NovaResourcesScout.php create mode 100644 src/Scouts/RoutesScout.php create mode 100644 src/Scouts/SchedulesScout.php create mode 100644 src/Scouts/SeedersScout.php create mode 100644 src/Scouts/ServiceProvidersScout.php create mode 100644 src/Scouts/TranslationsScout.php create mode 100644 src/Scouts/ViewsScout.php delete mode 100644 tests/ExampleTest.php create mode 100644 tests/Feature/CommandsTest.php create mode 100644 tests/Feature/ConfigsTest.php create mode 100644 tests/Feature/HelpersTest.php create mode 100644 tests/Feature/LivewireComponentsTest.php create mode 100644 tests/Feature/MigrationsTest.php create mode 100644 tests/Feature/NovaResourcesTest.php create mode 100644 tests/Feature/SchedulesTest.php create mode 100644 tests/Feature/SeedersTest.php create mode 100644 tests/Feature/ServiceProvidersTest.php create mode 100644 tests/Feature/TranslationsTest.php create mode 100644 tests/Feature/ViewsTest.php create mode 100644 workbench/Modules/First/Config/first.php create mode 100644 workbench/Modules/First/Console/Commands/DeleteUsersCommand.php create mode 100644 workbench/Modules/First/Database/Factories/UserFactory.php create mode 100644 workbench/Modules/First/Database/Migrations/2024_02_21_144905_create_users_table.php create mode 100644 workbench/Modules/First/Database/Seeders/FirstDatabaseSeeder.php create mode 100644 workbench/Modules/First/Database/Seeders/UserSeeder.php create mode 100644 workbench/Modules/First/Helpers/Shared.php create mode 100644 workbench/Modules/First/Models/User.php create mode 100644 workbench/Modules/First/Policies/UserPolicy.php create mode 100644 workbench/Modules/First/Providers/UserServiceProvider.php create mode 100644 workbench/Modules/First/Resources/lang/en.php create mode 100644 workbench/Modules/Second/Console/Commands/DeleteTeamsCommand.php create mode 100644 workbench/Modules/Second/Database/Factories/TeamFactory.php create mode 100644 workbench/Modules/Second/Database/Migrations/2024_02_22_144905_create_teams_table.php create mode 100644 workbench/Modules/Second/Database/Migrations/sub/2024_03_22_144905_create_backups_table.php create mode 100644 workbench/Modules/Second/Database/Seeders/SecondDatabaseSeeder.php create mode 100644 workbench/Modules/Second/Database/Seeders/TeamDatabaseSeeder.php create mode 100644 workbench/Modules/Second/Helpers.php create mode 100644 workbench/Modules/Second/Livewire/ListUsers.php create mode 100644 workbench/Modules/Second/Models/Team.php create mode 100644 workbench/Modules/Second/Providers/TeamServiceProvider.php create mode 100644 workbench/Modules/Second/Resources/lang/en.php create mode 100644 workbench/Modules/Second/Resources/views/livewire/list-users.blade.php create mode 100644 workbench/app/Models/Test.php create mode 100644 workbench/app/Policies/TestPolicy.php create mode 100644 workbench/bootstrap/cache/.gitignore create mode 100644 workbench/config/modules.php create mode 100644 workbench/database/factories/TestFactory.php diff --git a/composer.json b/composer.json index 9f3f7b1..2708b26 100644 --- a/composer.json +++ b/composer.json @@ -19,13 +19,15 @@ "php": "^8.1", "illuminate/contracts": "^10.0", "spatie/laravel-package-tools": "^1.14.0", - "spatie/php-structure-discoverer": "^2.1" + "spatie/php-structure-discoverer": "^2.1", + "spatie/regex": "^3.1" }, "require-dev": { + "larastan/larastan": "^2.0.1", "laravel/pint": "^1.0", + "livewire/livewire": "^3.4", "nunomaduro/collision": "^7.8", - "larastan/larastan": "^2.0.1", - "orchestra/testbench": "^8.8", + "orchestra/testbench": "^8.21", "pestphp/pest": "^2.20", "pestphp/pest-plugin-arch": "^2.5", "pestphp/pest-plugin-laravel": "^2.0", @@ -42,26 +44,39 @@ "autoload-dev": { "psr-4": { "Mozex\\Modules\\Tests\\": "tests/", - "Workbench\\App\\": "workbench/app/" + "App\\": "workbench/app/", + "Modules\\": "workbench/Modules/", + "Database\\Factories\\": "workbench/database/factories/" } }, "scripts": { - "post-autoload-dump": "@composer run prepare", - "clear": "@php vendor/bin/testbench package:purge-laravel-modules --ansi", - "prepare": "@php vendor/bin/testbench package:discover --ansi", - "build": [ - "@composer run prepare", - "@php vendor/bin/testbench workbench:build --ansi" + "post-autoload-dump": [ + "@clear", + "@prepare", + "@composer run prepare" ], + "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", "start": [ "Composer\\Config::disableProcessTimeout", "@composer run build", "@php vendor/bin/testbench serve" ], - "analyse": "vendor/bin/phpstan analyse", + "analyse": "vendor/bin/phpstan analyse --memory-limit=-1", + "baseline": "@analyse --allow-empty-baseline --generate-baseline", "test": "vendor/bin/pest", "test-coverage": "vendor/bin/pest --coverage", - "format": "vendor/bin/pint" + "format": "vendor/bin/pint", + "serve": [ + "Composer\\Config::disableProcessTimeout", + "@build", + "@php vendor/bin/testbench serve" + ], + "lint": [ + "@php vendor/bin/pint", + "@php vendor/bin/phpstan analyse" + ] }, "config": { "sort-packages": true, diff --git a/config/modules.php b/config/modules.php index a74d8f4..eeb8b39 100644 --- a/config/modules.php +++ b/config/modules.php @@ -1,58 +1,117 @@ [ - 'Modules/*/Database/Migrations', - [ - 'pattern' => 'Modules/*/Database/Migrations/*', - 'flags' => GLOB_ONLYDIR, + 'modules_directory' => 'Modules', + 'modules_namespace' => 'Modules\\', + 'assets' => [ + AssetType::Commands->value => [ + 'active' => true, + 'patterns' => [ + '*/Console/Commands', + ], + ], + AssetType::Migrations->value => [ + 'active' => true, + 'patterns' => [ + '*/Database/Migrations', + ], + ], + AssetType::Helpers->value => [ + 'active' => true, + 'patterns' => [ + '*/Helpers/*.php', + '*/Helpers.php', + ], + ], + AssetType::ServiceProviders->value => [ + 'active' => true, + 'patterns' => [ + '*/Providers', + ], + ], + AssetType::Seeders->value => [ + 'active' => true, + 'patterns' => [ + '*/Database/Seeders', + ], + ], + AssetType::Translations->value => [ + 'active' => true, + 'patterns' => [ + '*/Resources/lang', + ], + ], + AssetType::Schedules->value => [ + 'active' => true, + 'patterns' => [ + '*/Console', + ], + ], + AssetType::Configs->value => [ + 'active' => true, + 'patterns' => [ + '*/Config/*.php', + ], + ], + AssetType::Views->value => [ + 'active' => true, + 'patterns' => [ + '*/Resources/views', + ], + ], + AssetType::Routes->value => [ + 'active' => true, + 'patterns' => [ + '*/Routes/*.php', + ], + 'groups' => [ + 'api' => [ + 'prefix' => 'api', + 'middlewares' => ['api'], + ], + 'web' => [ + 'middlewares' => ['web'], + ], + // 'localized' => [ + // 'middlewares' => [ + // 'web', + // 'localeSessionRedirect', + // 'localizationRedirect', + // ], + // 'prefix' => LaravelLocalization::setLocale() + // ] + ], + ], + AssetType::Models->value => [ + 'namespace' => 'Models\\', + ], + AssetType::Factories->value => [ + 'active' => true, + 'namespace' => 'Database\\Factories\\', + ], + AssetType::Policies->value => [ + 'active' => true, + 'namespace' => 'Policies\\', + ], + AssetType::LivewireComponents->value => [ + 'active' => false, + 'patterns' => [ + '*/Livewire', + ], + ], + AssetType::NovaResources->value => [ + 'active' => false, + 'patterns' => [ + '*/Nova', + ], ], ], - 'seeder_patterns' => [ - 'Modules/*/Database/Seeders/*DatabaseSeeder.php', - ], - 'route_patterns' => [ - 'Modules/*/Routes/*.php', - 'routes/Modules/*/*.php', - ], - 'view_patterns' => [ - 'Modules/*/Resources/views', - 'resources/Modules/*/views', - ], - 'translation_patterns' => [ - 'Modules/*/Resources/lang', - 'resources/Modules/*/lang', - 'lang/Modules/*/', - ], - 'config_patterns' => [ - 'Modules/*/Config/*.php', - 'config/Modules/*/*.php', - ], - 'command_patterns' => [ - 'Modules/*/Console/Commands/*.php', - ], - 'nova_resource_patterns' => [ - 'Modules/*/Nova/*.php', - ], - 'livewire_component_patterns' => [ - 'Modules/*/Livewire/*.php', - ], - 'helper_patterns' => [ - 'Modules/*/Helpers/*.php', - 'Modules/*/Helpers.php', - ], - 'service_provider_patterns' => [ - 'Modules/*/Providers/*.php', - ], - 'kernel_patterns' => [ - 'Modules/*/Console/Kernel.php', - ], - 'api_middleware' => [ - 'api', - ], - 'default_middleware' => [ - 'web', + 'modules' => [ + // 'Shared' => [ + // 'active' => true, + // 'order' => 1, // Optional + // ], ], - 'route_groups' => [], - 'modules' => [], ]; diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index ef8e5d7..afba433 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,5 +1,10 @@ parameters: ignoreErrors: + - + message: "#^Unsafe usage of new static\\(\\)\\.$#" + count: 1 + path: src/Contracts/BaseScout.php + - message: "#^Call to static method resources\\(\\) on an unknown class Laravel\\\\Nova\\\\Nova\\.$#" count: 1 @@ -8,9 +13,9 @@ parameters: - message: "#^Class Laravel\\\\Nova\\\\Actions\\\\ActionResource not found\\.$#" count: 1 - path: src/ModulesServiceProvider.php + path: src/Scouts/NovaResourcesScout.php - message: "#^Class Laravel\\\\Nova\\\\Resource not found\\.$#" count: 1 - path: src/ModulesServiceProvider.php + path: src/Scouts/NovaResourcesScout.php diff --git a/src/Commands/CacheCommand.php b/src/Commands/CacheCommand.php new file mode 100644 index 0000000..2ac8c0b --- /dev/null +++ b/src/Commands/CacheCommand.php @@ -0,0 +1,43 @@ +classes() + ->extending(BaseScout::class) + ->custom(fn (DiscoveredClass $structure) => ! $structure->isAbstract) + ->get(), + callback: function (string $scout, $progress) { + /** @var BaseScout $discoverer */ + $discoverer = app($scout); + + if ($discoverer->asset()->isDeactive()) { + return; + } + + $progress->label("Caching {$discoverer->asset()->title()}"); + + $discoverer->cacheDriver()->forget($discoverer->identifier()); + + $discoverer->cache(); + }, + ); + } +} diff --git a/src/Commands/ClearCommand.php b/src/Commands/ClearCommand.php new file mode 100644 index 0000000..e063204 --- /dev/null +++ b/src/Commands/ClearCommand.php @@ -0,0 +1,41 @@ +classes() + ->extending(BaseScout::class) + ->custom(fn (DiscoveredClass $structure) => ! $structure->isAbstract) + ->get(), + callback: function (string $scout, $progress) { + /** @var BaseScout $discoverer */ + $discoverer = app($scout); + + if ($discoverer->asset()->isDeactive()) { + return; + } + + $progress->label("Clearing {$discoverer->asset()->title()}"); + + $discoverer->cacheDriver()->forget($discoverer->identifier()); + }, + ); + } +} diff --git a/src/Concerns/FindsSeeder.php b/src/Concerns/FindsSeeder.php deleted file mode 100644 index 5776b7c..0000000 --- a/src/Concerns/FindsSeeder.php +++ /dev/null @@ -1,27 +0,0 @@ -getModulesAssets(config('modules.seeder_patterns')) - ->map($this->makeNamespaceForAsset(...)) - ->filter($this->isSeeder(...)) - ->toArray(); - } - - /** - * @throws ReflectionException - */ - public function isSeeder(string $namespace): bool - { - return is_subclass_of($namespace, Seeder::class) - && ! (new ReflectionClass($namespace))->isAbstract(); - } -} diff --git a/src/Concerns/GetsSchedules.php b/src/Concerns/GetsSchedules.php deleted file mode 100644 index ff02018..0000000 --- a/src/Concerns/GetsSchedules.php +++ /dev/null @@ -1,31 +0,0 @@ -map(Modules::makeNamespaceForAsset(...)) - ->filter($this->isKernel(...)) - ->each(function (string $namespace) use ($schedule) { - (new $namespace)->schedule($schedule); - }); - } - - /** - * @throws ReflectionException - */ - public function isKernel(string $namespace): bool - { - return is_subclass_of($namespace, ConsoleKernel::class) - && ! (new ReflectionClass($namespace))->isAbstract(); - } -} diff --git a/src/Concerns/SupportsCommand.php b/src/Concerns/SupportsCommand.php deleted file mode 100644 index 0e30d0d..0000000 --- a/src/Concerns/SupportsCommand.php +++ /dev/null @@ -1,30 +0,0 @@ -commands( - Modules::getModulesAssets(config('modules.command_patterns')) - ->map(Modules::makeNamespaceForAsset(...)) - ->filter($this->isCommand(...)) - ->toArray() - ); - } - - /** - * @throws ReflectionException - */ - public function isCommand(string $namespace): bool - { - return is_subclass_of($namespace, Command::class) - && ! (new ReflectionClass($namespace))->isAbstract(); - } -} diff --git a/src/Concerns/SupportsConfig.php b/src/Concerns/SupportsConfig.php deleted file mode 100644 index 9968093..0000000 --- a/src/Concerns/SupportsConfig.php +++ /dev/null @@ -1,26 +0,0 @@ -each(function (array $asset): void { - $fileName = basename($asset['path'], '.php'); - $targetFileName = $fileName === 'config' ? $asset['module'] : $fileName; - - $this->publishes([ - $asset['path'] => config_path("{$targetFileName}.php"), - ], 'config'); - - $this->mergeConfigWithProiorityFrom( - $asset['path'], - $fileName === 'config' ? $asset['module'] : $fileName - ); - }); - } -} diff --git a/src/Concerns/SupportsFactory.php b/src/Concerns/SupportsFactory.php deleted file mode 100644 index 79353dd..0000000 --- a/src/Concerns/SupportsFactory.php +++ /dev/null @@ -1,25 +0,0 @@ -each(function (array $asset): void { - require_once $asset['path']; - }); - } -} diff --git a/src/Concerns/SupportsLivewire.php b/src/Concerns/SupportsLivewire.php deleted file mode 100644 index 7f6c537..0000000 --- a/src/Concerns/SupportsLivewire.php +++ /dev/null @@ -1,34 +0,0 @@ -map(Modules::makeNamespaceForAsset(...)) - ->filter($this->isLivewireComponent(...)) - ->each(function (string $namespace): void { - Livewire::component( - str(class_basename($namespace))->kebab()->toString(), - $namespace - ); - }); - } - - /** - * @throws ReflectionException - */ - public function isLivewireComponent(string $namespace): bool - { - return is_subclass_of($namespace, Component::class) - && ! (new ReflectionClass($namespace))->isAbstract(); - } -} diff --git a/src/Concerns/SupportsMigration.php b/src/Concerns/SupportsMigration.php deleted file mode 100644 index d5e3770..0000000 --- a/src/Concerns/SupportsMigration.php +++ /dev/null @@ -1,17 +0,0 @@ -loadMigrationsFrom( - Modules::getModulesAssets(config('modules.migration_patterns')) - ->pluck('path') - ->toArray() - ); - } -} diff --git a/src/Concerns/SupportsNova.php b/src/Concerns/SupportsNova.php deleted file mode 100644 index 0e9ee8e..0000000 --- a/src/Concerns/SupportsNova.php +++ /dev/null @@ -1,38 +0,0 @@ -map(Modules::makeNamespaceForAsset(...)) - ->filter($this->isNovaResource(...)) - ->sort() - ->all() - ); - }); - } - } - - /** - * @throws ReflectionException - */ - public function isNovaResource(string $namespace): bool - { - return is_subclass_of($namespace, Resource::class) - && ! (new ReflectionClass($namespace))->isAbstract() - && ! is_subclass_of($namespace, ActionResource::class); - } -} diff --git a/src/Concerns/SupportsPolicy.php b/src/Concerns/SupportsPolicy.php deleted file mode 100644 index 381679c..0000000 --- a/src/Concerns/SupportsPolicy.php +++ /dev/null @@ -1,25 +0,0 @@ -each(function (array $asset): void { - $groupName = File::name($asset['path']); - - if ($groupName === 'api') { - $group = [ - 'middleware' => config('modules.api_middleware', []), - 'prefix' => 'api', - ]; - } else { - $group = [ - 'middleware' => array_merge( - config('modules.default_middleware', []), - config('modules.route_groups')[$groupName]['middleware'] ?? [] - ), - 'as' => config('modules.route_groups')[$groupName]['as'] ?? '', - 'prefix' => config('modules.route_groups')[$groupName]['prefix'] ?? '', - ]; - - if ($groupName === 'localized' - || (config('modules.route_groups')[$groupName]['localized'] ?? false)) { - $group['middleware'] = array_merge($group['middleware'], [ - 'localeSessionRedirect', - 'localizationRedirect', - ]); - - $group['prefix'] = sprintf( - '%s/%s', - LaravelLocalization::setLocale(), - ltrim( - $group['prefix'], - '/' - ) - ); - - if ($group['prefix'] == '/') { - $group['prefix'] = ''; - } - } - } - - Route::group(array_filter($group), function () use ($asset): void { - $this->loadRoutesFrom($asset['path']); - }); - }); - } -} diff --git a/src/Concerns/SupportsServiceProviders.php b/src/Concerns/SupportsServiceProviders.php deleted file mode 100644 index af8b215..0000000 --- a/src/Concerns/SupportsServiceProviders.php +++ /dev/null @@ -1,30 +0,0 @@ -map(Modules::makeNamespaceForAsset(...)) - ->filter($this->isServiceProvider(...)) - ->each(function (string $namespace) { - $this->app->register($namespace); - }); - } - - /** - * @throws ReflectionException - */ - public function isServiceProvider(string $namespace): bool - { - return is_subclass_of($namespace, ServiceProvider::class) - && ! (new ReflectionClass($namespace))->isAbstract(); - } -} diff --git a/src/Concerns/SupportsTranslation.php b/src/Concerns/SupportsTranslation.php deleted file mode 100644 index 4e8efaf..0000000 --- a/src/Concerns/SupportsTranslation.php +++ /dev/null @@ -1,17 +0,0 @@ -each(function (array $asset): void { - $this->loadTranslationsFrom($asset['path'], $asset['module']); - $this->loadJsonTranslationsFrom($asset['path']); - }); - } -} diff --git a/src/Concerns/SupportsView.php b/src/Concerns/SupportsView.php deleted file mode 100644 index 59d8459..0000000 --- a/src/Concerns/SupportsView.php +++ /dev/null @@ -1,31 +0,0 @@ -each(function (array $asset): void { - $this->publishes([ - $asset['path'] => resource_path('views/vendor/'.$asset['module']), - ], ['views', "{$asset['module']}-module-views"]); - - /** @var array $viewPaths */ - $viewPaths = Config::get('view.paths'); - - $this->loadViewsFrom( - collect($viewPaths) - ->filter(fn (string $path) => is_dir("{$path}/vendor/{$asset['module']}")) - ->map(fn (string $path) => "{$path}/vendor/{$asset['module']}") - ->push($asset['path']) - ->toArray(), - $asset['module'] - ); - }); - } -} diff --git a/src/Contracts/BaseScout.php b/src/Contracts/BaseScout.php new file mode 100644 index 0000000..07f6ef7 --- /dev/null +++ b/src/Contracts/BaseScout.php @@ -0,0 +1,114 @@ +asset()->value, + ), + ); + } + + public function get(): array + { + if ($this->isCached()) { + return $this->cacheDriver()->get($this->identifier()); + } + + return $this->getWithoutCache(); + } + + /** + * @return Collection + */ + public function collect(): Collection + { + return collect($this->get()); + } + + public function cache(): array + { + $structures = $this->getWithoutCache(); + + $this->cacheDriver()->put( + $this->identifier(), + $structures + ); + + return $structures; + } + + public function clear(): static + { + $this->cacheDriver()->forget($this->identifier()); + + return $this; + } + + public function isCached(): bool + { + return $this->cacheDriver()->has($this->identifier()); + } + + protected function patterns(): array + { + return collect($this->asset()->patterns()) + ->map(Modules::modulesPath(...)) + ->toArray(); + } + + public function transform(array $result): array + { + return collect($result) + ->map( + function (string $item) { + if ((is_dir($item) || is_file($item)) && ! class_exists($item)) { + return [ + 'module' => Modules::moduleNameFromPath($item), + 'path' => realpath($item), + ]; + } + + return [ + 'module' => Modules::moduleNameFromNamespace($item), + 'namespace' => $item, + ]; + } + ) + ->sortBy( + fn (array $asset) => (int) (config('modules.modules', [])[$asset['module']]['order'] ?? 9999) + ) + ->filter( + fn (array $asset) => config('modules.modules', [])[$asset['module']]['active'] ?? true + ) + ->values() + ->toArray(); + } + + abstract public function asset(): AssetType; + + abstract public function getWithoutCache(): array; +} diff --git a/src/Contracts/ModuleClassScout.php b/src/Contracts/ModuleClassScout.php new file mode 100644 index 0000000..ea9b460 --- /dev/null +++ b/src/Contracts/ModuleClassScout.php @@ -0,0 +1,22 @@ +definition()->getWithoutCache(); + } catch (DirectoryNotFoundException) { + return []; + } + + return $this->transform($result); + } + + abstract protected function definition(): Discover; +} diff --git a/src/Contracts/ModuleDirectoryScout.php b/src/Contracts/ModuleDirectoryScout.php new file mode 100644 index 0000000..56a9be2 --- /dev/null +++ b/src/Contracts/ModuleDirectoryScout.php @@ -0,0 +1,23 @@ +patterns()) + ->each(fn (string $pattern) => $assets->push( + ...glob( + pattern: $pattern, + flags: GLOB_ONLYDIR + ) + )); + + return $this->transform( + $assets->toArray() + ); + } +} diff --git a/src/Contracts/ModuleFileScout.php b/src/Contracts/ModuleFileScout.php new file mode 100644 index 0000000..e547920 --- /dev/null +++ b/src/Contracts/ModuleFileScout.php @@ -0,0 +1,22 @@ +patterns()) + ->each(fn (string $pattern) => $assets->push( + ...glob( + pattern: $pattern, + ) + )); + + return $this->transform( + $assets->toArray() + ); + } +} diff --git a/src/Enums/AssetType.php b/src/Enums/AssetType.php new file mode 100644 index 0000000..2da8d3b --- /dev/null +++ b/src/Enums/AssetType.php @@ -0,0 +1,88 @@ + CommandsScout::create(), + self::Migrations => MigrationsScout::create(), + self::Helpers => HelpersScout::create(), + self::ServiceProviders => ServiceProvidersScout::create(), + self::Seeders => SeedersScout::create(), + self::Translations => TranslationsScout::create(), + self::Schedules => SchedulesScout::create(), + self::Configs => ConfigsScout::create(), + self::Views => ViewsScout::create(), + self::Routes => RoutesScout::create(), + self::LivewireComponents => LivewireComponentsScout::create(), + self::NovaResources => NovaResourcesScout::create(), + default => null, + }; + } + + /** + * @return array{active?: bool, patterns?: array, namespace?: string, groups?: array} + */ + public function config(): array + { + return config('modules.assets')[$this->value] ?? []; + } + + public function isActive(): bool + { + return $this->config()['active'] ?? false; + } + + public function isDeactive(): bool + { + return ! $this->isActive(); + } + + /** + * @return array + */ + public function patterns(): ?array + { + return $this->config()['patterns'] ?? null; + } + + public function title(): string + { + return str($this->value) + ->replace('-', ' ') + ->title(); + } +} diff --git a/src/Modules.php b/src/Modules.php index 8a763c8..c4ee882 100644 --- a/src/Modules.php +++ b/src/Modules.php @@ -2,72 +2,67 @@ namespace Mozex\Modules; -use Illuminate\Support\Collection; -use Mozex\Modules\Concerns\FindsSeeder; -use Mozex\Modules\Concerns\GetsSchedules; +use Mozex\Modules\Enums\AssetType; +use Spatie\Regex\Regex; class Modules { - use FindsSeeder; - use GetsSchedules; + public string $base_path; - /** - * @return Collection - */ - public function getModulesAssets(array $patterns): Collection + public function __construct() { - $assets = collect(); - - foreach ($patterns as $pattern) { - if (is_array($pattern)) { - $flags = $pattern['flags'] ?? 0; - $pattern = $pattern['pattern']; - } - - $assets->push( - ...glob( - pattern: base_path($pattern), - flags: $flags ?? 0 - ) - ); - } + $this->base_path = base_path(); + } - return $assets - ->map(function (string $path) { - preg_match( - '/Modules\/(.*?)\//', - $path, - $result - ); + public function setBasePath(string $path): void + { + $this->base_path = $path; + } - return [ - 'module' => mb_strtolower($result[1]), - 'path' => $path, - 'order' => (int) (config('modules.modules', [])[$result[1]]['order'] ?? 9999), - ]; - }) - ->filter($this->isModuleActive(...)) - ->sortBy('order'); + public function basePath(string $path = ''): string + { + return sprintf( + '%s/%s', + rtrim($this->base_path, '/'), + ltrim($path, '/') + ); } - public function isModuleActive(array $asset): bool + public function modulesPath(string $path = ''): string { - $module = config('modules.modules', [])[$asset['module']] ?? null; + return $this->basePath( + sprintf( + '%s/%s', + config('modules.modules_directory'), + ltrim($path, '/') + ) + ); + } - if (empty($module) || ! is_array($module) || ! isset($module['active'])) { - return true; - } + public function moduleNameFromNamespace(string $namespace): string + { + return Regex::match( + pattern: '/'.config('modules.modules_directory').'\\\\(.*?)\\\\/', + subject: $namespace + )->groupOr(1, ''); + } - return $module['active']; + public function moduleNameFromPath(string $path): ?string + { + return Regex::match( + pattern: '/'.config('modules.modules_directory').'\/(.*?)\//', + subject: $path + )->groupOr(1, ''); } - public function makeNamespaceForAsset(array $asset): string + public function seeders(): array { - return str($asset['path']) - ->after(realpath(base_path()).DIRECTORY_SEPARATOR) - ->replace(['/', '.php'], ['\\', '']) - ->explode('\\') - ->map(ucfirst(...)) - ->implode('\\'); + if (AssetType::Seeders->isDeactive()) { + return []; + } + + return AssetType::Seeders->scout()->collect() + ->pluck('namespace') + ->toArray(); } } diff --git a/src/ModulesServiceProvider.php b/src/ModulesServiceProvider.php index bd4c163..c618e2e 100644 --- a/src/ModulesServiceProvider.php +++ b/src/ModulesServiceProvider.php @@ -2,57 +2,49 @@ namespace Mozex\Modules; -use Illuminate\Contracts\Container\BindingResolutionException; +use Illuminate\Console\Scheduling\Schedule; +use Illuminate\Contracts\Auth\Access\Gate as GateInstance; use Illuminate\Contracts\Foundation\CachesConfiguration; -use Mozex\Modules\Concerns\SupportsCommand; -use Mozex\Modules\Concerns\SupportsConfig; -use Mozex\Modules\Concerns\SupportsFactory; -use Mozex\Modules\Concerns\SupportsHelpers; -use Mozex\Modules\Concerns\SupportsLivewire; -use Mozex\Modules\Concerns\SupportsMigration; -use Mozex\Modules\Concerns\SupportsNova; -use Mozex\Modules\Concerns\SupportsPolicy; -use Mozex\Modules\Concerns\SupportsRoutes; -use Mozex\Modules\Concerns\SupportsServiceProviders; -use Mozex\Modules\Concerns\SupportsTranslation; -use Mozex\Modules\Concerns\SupportsView; +use Illuminate\Database\Eloquent\Factories\Factory; +use Illuminate\Support\Facades\File; +use Illuminate\Support\Facades\Gate; +use Illuminate\Support\Facades\Route; +use Illuminate\Support\Str; +use Laravel\Nova\Nova; +use Livewire\Livewire; +use Mozex\Modules\Commands\CacheCommand; +use Mozex\Modules\Commands\ClearCommand; +use Mozex\Modules\Enums\AssetType; +use Mozex\Modules\Facades\Modules; +use ReflectionMethod; +use ReflectionProperty; use Spatie\LaravelPackageTools\Package; use Spatie\LaravelPackageTools\PackageServiceProvider; class ModulesServiceProvider extends PackageServiceProvider { - use SupportsCommand; - use SupportsConfig; - use SupportsFactory; - use SupportsHelpers; - use SupportsLivewire; - use SupportsMigration; - use SupportsNova; - use SupportsPolicy; - use SupportsRoutes; - use SupportsServiceProviders; - use SupportsTranslation; - use SupportsView; - public function configurePackage(Package $package): void { $package ->name('laravel-modules') - ->hasConfigFile(); + ->hasConfigFile() + ->hasCommand(CacheCommand::class) + ->hasCommand(ClearCommand::class); } public function packageBooted(): void { - $this->bootRoutes(); + $this->bootCommands(); $this->bootMigrations(); - $this->bootFactories(); - $this->bootPolicies(); $this->bootTranslations(); $this->bootConfigs(); $this->bootViews(); - $this->bootCommands(); - $this->bootNova(); + $this->bootFactories(); + $this->bootPolicies(); + $this->bootRoutes(); + $this->bootSchedules(); $this->bootLivewire(); + $this->bootNova(); } public function packageRegistered(): void @@ -61,18 +53,239 @@ public function packageRegistered(): void $this->registerServicePorviders(); } - /** - * @throws BindingResolutionException - */ - protected function mergeConfigWithProiorityFrom(string $path, string $key): void + protected function bootCommands(): void + { + if (! $this->app->runningInConsole()) { + return; + } + + if (AssetType::Commands->isDeactive()) { + return; + } + + $this->commands( + AssetType::Commands->scout()->collect() + ->pluck('namespace') + ->toArray() + ); + } + + protected function bootMigrations(): void + { + if (AssetType::Migrations->isDeactive()) { + return; + } + + $this->loadMigrationsFrom( + AssetType::Migrations->scout()->collect() + ->pluck('path') + ->toArray() + ); + } + + protected function bootTranslations(): void + { + if (AssetType::Translations->isDeactive()) { + return; + } + + AssetType::Translations->scout()->collect() + ->each(function (array $asset): void { + $this->loadTranslationsFrom($asset['path'], $asset['module']); + $this->loadJsonTranslationsFrom($asset['path']); + }); + } + + protected function bootConfigs(): void { + if (AssetType::Configs->isDeactive()) { + return; + } + if (! ($this->app instanceof CachesConfiguration && $this->app->configurationIsCached())) { $config = $this->app->make('config'); - $config->set($key, array_merge( - $config->get($key, []), - require $path - )); + AssetType::Configs->scout()->collect() + ->each(function (array $asset) use ($config): void { + $key = File::name($asset['path']); + + $config->set($key, array_merge( + $config->get($key, []), + require $asset['path'] + )); + }); + } + } + + protected function bootViews(): void + { + if (AssetType::Views->isDeactive()) { + return; } + + AssetType::Views->scout()->collect() + ->each(function (array $asset): void { + $this->loadViewsFrom($asset['path'], $asset['module']); + }); + } + + protected function bootFactories(): void + { + if (AssetType::Factories->isDeactive()) { + return; + } + + Factory::guessFactoryNamesUsing(function (string $modelName) { + if ($module = Modules::moduleNameFromNamespace($modelName)) { + return sprintf( + '%s%s\\%s%sFactory', + config('modules.modules_namespace'), + $module, + AssetType::Factories->config()['namespace'], + Str::after( + subject: $modelName, + search: sprintf( + '%s%s\\%s', + config('modules.modules_namespace'), + $module, + AssetType::Models->config()['namespace'] + ) + ) + ); + } + + (new ReflectionProperty(Factory::class, 'factoryNameResolver')) + ->setValue(null); + + return Factory::resolveFactoryName($modelName); + }); + } + + protected function bootPolicies(): void + { + if (AssetType::Policies->isDeactive()) { + return; + } + + Gate::guessPolicyNamesUsing(function (string $modelName) { + if ($module = Modules::moduleNameFromNamespace($modelName)) { + return sprintf( + '%s%s\\%s%sPolicy', + config('modules.modules_namespace'), + $module, + AssetType::Policies->config()['namespace'], + Str::after( + subject: $modelName, + search: sprintf( + '%s%s\\%s', + config('modules.modules_namespace'), + $module, + AssetType::Models->config()['namespace'] + ) + ) + ); + } + + $gate = $this->app->make(GateInstance::class); + + (new ReflectionProperty($gate, 'guessPolicyNamesUsingCallback')) + ->setValue($gate, null); + + $reflection = (new ReflectionMethod($gate, 'guessPolicyName')); + + return $reflection->invoke($gate, $modelName); + }); + } + + protected function bootRoutes(): void + { + if (AssetType::Routes->isDeactive()) { + return; + } + + AssetType::Routes->scout()->collect() + ->each(function (array $asset): void { + $group = File::name($asset['path']); + + Route::middleware(AssetType::Routes->config()['groups'][$group]['middlewares'] ?? []) + ->prefix(AssetType::Routes->config()['groups'][$group]['prefix'] ?? '') + ->group($asset['path']); + }); + } + + protected function bootSchedules(): void + { + if (AssetType::Schedules->isDeactive()) { + return; + } + + $this->callAfterResolving(Schedule::class, function (Schedule $schedule) { + AssetType::Schedules->scout()->collect() + ->each(function (array $asset) use ($schedule) { + (new $asset['namespace'])->schedule($schedule); + }); + }); + } + + protected function bootLivewire(): void + { + if (! class_exists(Livewire::class)) { + return; + } + + if (AssetType::LivewireComponents->isDeactive()) { + return; + } + + AssetType::LivewireComponents->scout()->collect() + ->each(function (array $asset): void { + Livewire::component( + str(class_basename($asset['namespace']))->kebab()->toString(), + $asset['namespace'] + ); + }); + } + + protected function bootNova(): void + { + if (! class_exists(Nova::class)) { + return; + } + + if (AssetType::NovaResources->isDeactive()) { + return; + } + + Nova::serving(function (): void { + Nova::resources( + AssetType::NovaResources->scout()->collect() + ->pluck('namespace') + ->toArray() + ); + }); + } + + protected function registerHelpers(): void + { + if (AssetType::Helpers->isDeactive()) { + return; + } + + AssetType::Helpers->scout()->collect() + ->each(function (array $asset): void { + require_once $asset['path']; + }); + } + + protected function registerServicePorviders(): void + { + if (AssetType::ServiceProviders->isDeactive()) { + return; + } + + AssetType::ServiceProviders->scout()->collect() + ->each(function (array $asset) { + $this->app->register($asset['namespace']); + }); } } diff --git a/src/Scouts/CommandsScout.php b/src/Scouts/CommandsScout.php new file mode 100644 index 0000000..cb90c03 --- /dev/null +++ b/src/Scouts/CommandsScout.php @@ -0,0 +1,28 @@ +patterns()) + ->parallel() + ->classes() + ->extending(Command::class) + ->custom(fn (DiscoveredClass $structure) => ! $structure->isAbstract) + ->sortBy(Sort::Name); + } +} diff --git a/src/Scouts/ConfigsScout.php b/src/Scouts/ConfigsScout.php new file mode 100644 index 0000000..6dde934 --- /dev/null +++ b/src/Scouts/ConfigsScout.php @@ -0,0 +1,14 @@ +patterns()) + ->parallel() + ->classes() + ->extending(Component::class) + ->custom(fn (DiscoveredClass $structure) => ! $structure->isAbstract) + ->sortBy(Sort::Name); + } +} diff --git a/src/Scouts/MigrationsScout.php b/src/Scouts/MigrationsScout.php new file mode 100644 index 0000000..37465fa --- /dev/null +++ b/src/Scouts/MigrationsScout.php @@ -0,0 +1,14 @@ +patterns()) + ->parallel() + ->classes() + ->extending(Resource::class) + ->custom( + fn (DiscoveredClass $structure) => ! $structure->isAbstract + && ! in_array(ActionResource::class, $structure->extendsChain) + ) + ->sortBy(Sort::Name); + } +} diff --git a/src/Scouts/RoutesScout.php b/src/Scouts/RoutesScout.php new file mode 100644 index 0000000..79430f5 --- /dev/null +++ b/src/Scouts/RoutesScout.php @@ -0,0 +1,14 @@ +patterns()) + ->parallel() + ->classes() + ->extending(ConsoleKernel::class) + ->custom(fn (DiscoveredClass $structure) => ! $structure->isAbstract) + ->sortBy(Sort::Name); + } +} diff --git a/src/Scouts/SeedersScout.php b/src/Scouts/SeedersScout.php new file mode 100644 index 0000000..0f0ddbe --- /dev/null +++ b/src/Scouts/SeedersScout.php @@ -0,0 +1,33 @@ +patterns()) + ->parallel() + ->classes() + ->custom( + fn (DiscoveredStructure $structure) => $structure->name == Modules::moduleNameFromNamespace($structure->namespace).'DatabaseSeeder' + ) + ->extending(Seeder::class) + ->custom(fn (DiscoveredClass $structure) => ! $structure->isAbstract) + ->sortBy(Sort::Name); + } +} diff --git a/src/Scouts/ServiceProvidersScout.php b/src/Scouts/ServiceProvidersScout.php new file mode 100644 index 0000000..246f4f4 --- /dev/null +++ b/src/Scouts/ServiceProvidersScout.php @@ -0,0 +1,28 @@ +patterns()) + ->parallel() + ->classes() + ->extending(ServiceProvider::class) + ->custom(fn (DiscoveredClass $structure) => ! $structure->isAbstract) + ->sortBy(Sort::Name); + } +} diff --git a/src/Scouts/TranslationsScout.php b/src/Scouts/TranslationsScout.php new file mode 100644 index 0000000..f03a18f --- /dev/null +++ b/src/Scouts/TranslationsScout.php @@ -0,0 +1,14 @@ +toBeTrue(); -}); diff --git a/tests/Feature/CommandsTest.php b/tests/Feature/CommandsTest.php new file mode 100644 index 0000000..499e3a6 --- /dev/null +++ b/tests/Feature/CommandsTest.php @@ -0,0 +1,12 @@ +collect() + ->each(function (array $asset) use ($commands) { + expect($commands)->toHaveKey((new $asset['namespace'])->getName()); + }); +}); diff --git a/tests/Feature/ConfigsTest.php b/tests/Feature/ConfigsTest.php new file mode 100644 index 0000000..0c200e5 --- /dev/null +++ b/tests/Feature/ConfigsTest.php @@ -0,0 +1,5 @@ +skip(); diff --git a/tests/Feature/HelpersTest.php b/tests/Feature/HelpersTest.php new file mode 100644 index 0000000..3bd2aad --- /dev/null +++ b/tests/Feature/HelpersTest.php @@ -0,0 +1,8 @@ +toBe('First Helper') + ->and(secondHelper()) + ->toBe('Second Helper'); +}); diff --git a/tests/Feature/LivewireComponentsTest.php b/tests/Feature/LivewireComponentsTest.php new file mode 100644 index 0000000..0ac67b0 --- /dev/null +++ b/tests/Feature/LivewireComponentsTest.php @@ -0,0 +1,13 @@ +collect() + ->each(function (array $asset) use ($components) { + expect($components->getName($asset['namespace']))->not->toBeNull(); + }); +}); diff --git a/tests/Feature/MigrationsTest.php b/tests/Feature/MigrationsTest.php new file mode 100644 index 0000000..d879b03 --- /dev/null +++ b/tests/Feature/MigrationsTest.php @@ -0,0 +1,12 @@ +paths(); + + MigrationsScout::create()->collect() + ->each(function (array $asset) use ($migrations) { + expect($migrations)->toContain($asset['path']); + }); +}); diff --git a/tests/Feature/NovaResourcesTest.php b/tests/Feature/NovaResourcesTest.php new file mode 100644 index 0000000..44b224f --- /dev/null +++ b/tests/Feature/NovaResourcesTest.php @@ -0,0 +1,5 @@ +skip(); diff --git a/tests/Feature/SchedulesTest.php b/tests/Feature/SchedulesTest.php new file mode 100644 index 0000000..56d2543 --- /dev/null +++ b/tests/Feature/SchedulesTest.php @@ -0,0 +1,5 @@ +skip(); diff --git a/tests/Feature/SeedersTest.php b/tests/Feature/SeedersTest.php new file mode 100644 index 0000000..b7eec63 --- /dev/null +++ b/tests/Feature/SeedersTest.php @@ -0,0 +1,12 @@ +toHaveCount(2) + ->toContain(FirstDatabaseSeeder::class) + ->toContain(SecondDatabaseSeeder::class); +}); diff --git a/tests/Feature/ServiceProvidersTest.php b/tests/Feature/ServiceProvidersTest.php new file mode 100644 index 0000000..4c9d0b9 --- /dev/null +++ b/tests/Feature/ServiceProvidersTest.php @@ -0,0 +1,12 @@ +getLoadedProviders(); + + ServiceProvidersScout::create()->collect() + ->each(function (array $asset) use ($serviceProviders) { + expect($serviceProviders)->toHaveKey($asset['namespace']); + }); +}); diff --git a/tests/Feature/TranslationsTest.php b/tests/Feature/TranslationsTest.php new file mode 100644 index 0000000..90e62b8 --- /dev/null +++ b/tests/Feature/TranslationsTest.php @@ -0,0 +1,13 @@ +getLoader(); + + TranslationsScout::create()->collect() + ->each(function (array $asset) use ($loader) { + expect($loader->namespaces())->toHaveKey($asset['module'])->toContain($asset['path']) + ->and($loader->jsonPaths())->toContain($asset['path']); + }); +}); diff --git a/tests/Feature/ViewsTest.php b/tests/Feature/ViewsTest.php new file mode 100644 index 0000000..5e03ab5 --- /dev/null +++ b/tests/Feature/ViewsTest.php @@ -0,0 +1,5 @@ +skip(); diff --git a/tests/Pest.php b/tests/Pest.php index 947c48e..4943602 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -2,4 +2,5 @@ use Mozex\Modules\Tests\TestCase; -uses(TestCase::class)->in(__DIR__); +uses(TestCase::class) + ->in(__DIR__); diff --git a/tests/TestCase.php b/tests/TestCase.php index 2c8bb77..af4498a 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -2,14 +2,21 @@ namespace Mozex\Modules\Tests; +use App\Providers\WorkbenchServiceProvider; +use Livewire\LivewireServiceProvider; use Mozex\Modules\ModulesServiceProvider; +use Orchestra\Testbench\Concerns\WithWorkbench; use Orchestra\Testbench\TestCase as Orchestra; class TestCase extends Orchestra { + use WithWorkbench; + protected function getPackageProviders($app): array { return [ + WorkbenchServiceProvider::class, + LivewireServiceProvider::class, ModulesServiceProvider::class, ]; } diff --git a/workbench/Modules/First/Config/first.php b/workbench/Modules/First/Config/first.php new file mode 100644 index 0000000..ca5d8ed --- /dev/null +++ b/workbench/Modules/First/Config/first.php @@ -0,0 +1,5 @@ + fake()->name(), + ]; + } +} diff --git a/workbench/Modules/First/Database/Migrations/2024_02_21_144905_create_users_table.php b/workbench/Modules/First/Database/Migrations/2024_02_21_144905_create_users_table.php new file mode 100644 index 0000000..51e15e4 --- /dev/null +++ b/workbench/Modules/First/Database/Migrations/2024_02_21_144905_create_users_table.php @@ -0,0 +1,22 @@ +id(); + $table->string('name'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('users'); + } +}; diff --git a/workbench/Modules/First/Database/Seeders/FirstDatabaseSeeder.php b/workbench/Modules/First/Database/Seeders/FirstDatabaseSeeder.php new file mode 100644 index 0000000..0c85ec9 --- /dev/null +++ b/workbench/Modules/First/Database/Seeders/FirstDatabaseSeeder.php @@ -0,0 +1,15 @@ +call([ + UserSeeder::class, + ]); + } +} diff --git a/workbench/Modules/First/Database/Seeders/UserSeeder.php b/workbench/Modules/First/Database/Seeders/UserSeeder.php new file mode 100644 index 0000000..ea3b80d --- /dev/null +++ b/workbench/Modules/First/Database/Seeders/UserSeeder.php @@ -0,0 +1,14 @@ +create(); + } +} diff --git a/workbench/Modules/First/Helpers/Shared.php b/workbench/Modules/First/Helpers/Shared.php new file mode 100644 index 0000000..f4d69d7 --- /dev/null +++ b/workbench/Modules/First/Helpers/Shared.php @@ -0,0 +1,8 @@ + fake()->name(), + ]; + } +} diff --git a/workbench/Modules/Second/Database/Migrations/2024_02_22_144905_create_teams_table.php b/workbench/Modules/Second/Database/Migrations/2024_02_22_144905_create_teams_table.php new file mode 100644 index 0000000..d12d62c --- /dev/null +++ b/workbench/Modules/Second/Database/Migrations/2024_02_22_144905_create_teams_table.php @@ -0,0 +1,22 @@ +id(); + $table->string('name'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('taems'); + } +}; diff --git a/workbench/Modules/Second/Database/Migrations/sub/2024_03_22_144905_create_backups_table.php b/workbench/Modules/Second/Database/Migrations/sub/2024_03_22_144905_create_backups_table.php new file mode 100644 index 0000000..b1369ac --- /dev/null +++ b/workbench/Modules/Second/Database/Migrations/sub/2024_03_22_144905_create_backups_table.php @@ -0,0 +1,22 @@ +id(); + $table->string('name'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('backups'); + } +}; diff --git a/workbench/Modules/Second/Database/Seeders/SecondDatabaseSeeder.php b/workbench/Modules/Second/Database/Seeders/SecondDatabaseSeeder.php new file mode 100644 index 0000000..c019290 --- /dev/null +++ b/workbench/Modules/Second/Database/Seeders/SecondDatabaseSeeder.php @@ -0,0 +1,15 @@ +call([ + TeamDatabaseSeeder::class, + ]); + } +} diff --git a/workbench/Modules/Second/Database/Seeders/TeamDatabaseSeeder.php b/workbench/Modules/Second/Database/Seeders/TeamDatabaseSeeder.php new file mode 100644 index 0000000..f022607 --- /dev/null +++ b/workbench/Modules/Second/Database/Seeders/TeamDatabaseSeeder.php @@ -0,0 +1,14 @@ +create(); + } +} diff --git a/workbench/Modules/Second/Helpers.php b/workbench/Modules/Second/Helpers.php new file mode 100644 index 0000000..777fd25 --- /dev/null +++ b/workbench/Modules/Second/Helpers.php @@ -0,0 +1,8 @@ + + + diff --git a/workbench/app/Models/Test.php b/workbench/app/Models/Test.php new file mode 100644 index 0000000..9a9ae4e --- /dev/null +++ b/workbench/app/Models/Test.php @@ -0,0 +1,11 @@ + [ + 'First' => [ + 'active' => true, + 'order' => 2, + ], + 'Second' => [ + 'active' => true, + 'order' => 1, + ], + ], +]; diff --git a/workbench/database/factories/TestFactory.php b/workbench/database/factories/TestFactory.php new file mode 100644 index 0000000..25a09d5 --- /dev/null +++ b/workbench/database/factories/TestFactory.php @@ -0,0 +1,18 @@ + fake()->name(), + ]; + } +}