From 6f7094343ae44c9d66216d1229ab206c77ec035b Mon Sep 17 00:00:00 2001 From: Dan Date: Tue, 9 Apr 2024 02:26:43 +0200 Subject: [PATCH] List sub-classes of Model in path --- src/Actions/AskModelName.php | 2 +- src/Actions/ListModels.php | 29 +++++++++++++------ src/Actions/ParseFqnClassInCode.php | 20 +++++++++++++ tests/Feature/Actions/ListModelsTest.php | 28 +++++++++++------- .../Actions/ParseFqnClassInCodeTest.php | 25 ++++++++++++++++ 5 files changed, 84 insertions(+), 20 deletions(-) create mode 100644 src/Actions/ParseFqnClassInCode.php create mode 100644 tests/Feature/Actions/ParseFqnClassInCodeTest.php diff --git a/src/Actions/AskModelName.php b/src/Actions/AskModelName.php index d2b285c7..f14bd77d 100644 --- a/src/Actions/AskModelName.php +++ b/src/Actions/AskModelName.php @@ -18,7 +18,7 @@ public static function handle(): array { while (self::$model === '') { self::setModel(suggest( - label: 'Select a Model or enter its Name/FQN class.', + label: 'Select a Model or enter its Fully qualified name.', options: ListModels::handle(), required: true, )); diff --git a/src/Actions/ListModels.php b/src/Actions/ListModels.php index 3ca1c8b9..7655a3a4 100644 --- a/src/Actions/ListModels.php +++ b/src/Actions/ListModels.php @@ -9,22 +9,33 @@ final class ListModels { /** - * List files in Models folder + * List files in Models * */ public static function handle(): array { - $modelsFolder = app_path('Models'); + $directories = config('livewire-powergrid.auto_discover_models_paths', [app_path('Models')]); - return collect(File::allFiles($modelsFolder)) + /** @var Array $directories */ + return collect($directories) + ->filter(fn (string $directory) => File::exists($directory)) + ->map(fn (string $directory) => File::allFiles($directory)) + ->flatten() ->reject(fn (SplFileInfo $file): bool => $file->getExtension() != 'php') - ->map(function (SplFileInfo $file): array { - return [ - 'file' => $file->getFilenameWithoutExtension(), - 'path' => 'App\\Models\\' . $file->getFilenameWithoutExtension(), - ]; + + // Get FQN Class from source code + /** @phpstan-ignore-next-line */ + ->map(function (SplFileInfo $file): string { + $sourceCode = strval(file_get_contents($file->getPathname())); + + return rescue(fn () => ParseFqnClassInCode::handle($sourceCode), ''); }) - ->flatten() + //Remove all unqualified PHP files code + ->filter() + + // Remove classes that do not extend an Eloquent Model + /** @phpstan-ignore-next-line */ + ->reject(fn (string $fqnClass) => rescue(fn () => (new \ReflectionClass($fqnClass))->isSubclassOf(\Illuminate\Database\Eloquent\Model::class), false) === false) ->toArray(); } } diff --git a/src/Actions/ParseFqnClassInCode.php b/src/Actions/ParseFqnClassInCode.php new file mode 100644 index 00000000..99194490 --- /dev/null +++ b/src/Actions/ParseFqnClassInCode.php @@ -0,0 +1,20 @@ +artisan('make:model Demo'); -}); +it('list all Eloquent Models in a directory', function () { + app()->config->set('livewire-powergrid.auto_discover_models_paths', [ + 'tests/Concerns/Models', + ]); -test('list models', function () { expect(ListModels::handle())->toBe( [ - 'Demo', - 'App\Models\Demo', + 'PowerComponents\LivewirePowerGrid\Tests\Concerns\Models\Category', + 'PowerComponents\LivewirePowerGrid\Tests\Concerns\Models\Chef', + 'PowerComponents\LivewirePowerGrid\Tests\Concerns\Models\Dish', + 'PowerComponents\LivewirePowerGrid\Tests\Concerns\Models\Restaurant', ] ); }); + +it('will not list non-Eloquent Models', function () { + app()->config->set('livewire-powergrid.auto_discover_models_paths', [ + 'tests/Concerns/Enums', //There are no models in this directory. + + ]); + + expect(ListModels::handle())->toBe([]); +}); diff --git a/tests/Feature/Actions/ParseFqnClassInCodeTest.php b/tests/Feature/Actions/ParseFqnClassInCodeTest.php new file mode 100644 index 00000000..88eb4f13 --- /dev/null +++ b/tests/Feature/Actions/ParseFqnClassInCodeTest.php @@ -0,0 +1,25 @@ +toBe('App\Models\DemoModel'); +}); + +it('throws an exception when namespace cannot be found', function () { + ParseFqnClassInCode::handle('foobar'); +})->throws('could not find a FQN Class is source-code');