From 6963f23b5f418e7091a7b32f12a00d5a27c3fb31 Mon Sep 17 00:00:00 2001 From: Ayrton Andino Bonazzola <60512432+ayrtonandino@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:44:35 -0300 Subject: [PATCH 1/4] remove ShowModelCommand --- composer.json | 12 +- composer.lock | 170 +++++++++--------- src/Actions/RunModelShowCommand.php | 11 +- src/Commands/ShowModelCommand.php | 63 ------- src/ModelTyperServiceProvider.php | 2 - .../ErrorEmittingConsoleComponentFactory.php | 47 ----- .../Actions/RunModelShowCommandTest.php | 6 +- .../Feature/Console/ShowModelCommandTest.php | 15 -- 8 files changed, 102 insertions(+), 224 deletions(-) delete mode 100644 src/Commands/ShowModelCommand.php delete mode 100644 src/Overrides/ErrorEmittingConsoleComponentFactory.php delete mode 100644 test/Tests/Feature/Console/ShowModelCommandTest.php diff --git a/composer.json b/composer.json index 9932c47..ac59556 100644 --- a/composer.json +++ b/composer.json @@ -15,13 +15,13 @@ ], "require": { "php": "^8.2", - "illuminate/support": "^11.0", - "illuminate/database": "^11.0", - "illuminate/console": "^11.0" + "illuminate/support": "^11.33.0", + "illuminate/database": "^11.33.0", + "illuminate/console": "^11.33.0" }, "require-dev": { - "orchestra/testbench": "^9.0.0", - "phpunit/phpunit": "^11.0.0", + "orchestra/testbench": "^9.6.1", + "phpunit/phpunit": "^11.4.4", "laravel/pint": "^1.18.3", "larastan/larastan": "^3.0.2", "consolidation/robo": "^5.1.0", @@ -29,7 +29,7 @@ "totten/lurkerlite": "^1.3" }, "conflict": { - "laravel/framework": ">=11.33.0" + "laravel/framework": "<11.33.0" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index f4a500b..57a7f8a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "8718ea78c535d960c5e5897d53f7e152", + "content-hash": "58c10dd48ce2110afee66a06bdf5152a", "packages": [ { "name": "brick/math", @@ -1056,23 +1056,23 @@ }, { "name": "laravel/framework", - "version": "v11.32.0", + "version": "v11.34.2", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "bc2aad63f83ee5089be7b21cf29d645ccf31e927" + "reference": "865da6d73dd353f07a7bcbd778c55966a620121f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/bc2aad63f83ee5089be7b21cf29d645ccf31e927", - "reference": "bc2aad63f83ee5089be7b21cf29d645ccf31e927", + "url": "https://api.github.com/repos/laravel/framework/zipball/865da6d73dd353f07a7bcbd778c55966a620121f", + "reference": "865da6d73dd353f07a7bcbd778c55966a620121f", "shasum": "" }, "require": { "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", - "dragonmantank/cron-expression": "^3.3.2", + "dragonmantank/cron-expression": "^3.4", "egulias/email-validator": "^3.2.1|^4.0", "ext-ctype": "*", "ext-filter": "*", @@ -1082,35 +1082,36 @@ "ext-session": "*", "ext-tokenizer": "*", "fruitcake/php-cors": "^1.3", - "guzzlehttp/guzzle": "^7.8", + "guzzlehttp/guzzle": "^7.8.2", "guzzlehttp/uri-template": "^1.0", "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", - "laravel/serializable-closure": "^1.3", + "laravel/serializable-closure": "^1.3|^2.0", "league/commonmark": "^2.2.1", - "league/flysystem": "^3.8.0", + "league/flysystem": "^3.25.1", + "league/flysystem-local": "^3.25.1", "monolog/monolog": "^3.0", - "nesbot/carbon": "^2.72.2|^3.0", + "nesbot/carbon": "^2.72.2|^3.4", "nunomaduro/termwind": "^2.0", "php": "^8.2", "psr/container": "^1.1.1|^2.0.1", "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0|^2.0|^3.0", "ramsey/uuid": "^4.7", - "symfony/console": "^7.0", - "symfony/error-handler": "^7.0", - "symfony/finder": "^7.0", - "symfony/http-foundation": "^7.0", - "symfony/http-kernel": "^7.0", - "symfony/mailer": "^7.0", - "symfony/mime": "^7.0", - "symfony/polyfill-php83": "^1.28", - "symfony/process": "^7.0", - "symfony/routing": "^7.0", - "symfony/uid": "^7.0", - "symfony/var-dumper": "^7.0", + "symfony/console": "^7.0.3", + "symfony/error-handler": "^7.0.3", + "symfony/finder": "^7.0.3", + "symfony/http-foundation": "^7.0.3", + "symfony/http-kernel": "^7.0.3", + "symfony/mailer": "^7.0.3", + "symfony/mime": "^7.0.3", + "symfony/polyfill-php83": "^1.31", + "symfony/process": "^7.0.3", + "symfony/routing": "^7.0.3", + "symfony/uid": "^7.0.3", + "symfony/var-dumper": "^7.0.3", "tijsverkoyen/css-to-inline-styles": "^2.2.5", - "vlucas/phpdotenv": "^5.4.1", - "voku/portable-ascii": "^2.0" + "vlucas/phpdotenv": "^5.6.1", + "voku/portable-ascii": "^2.0.2" }, "conflict": { "mockery/mockery": "1.6.8", @@ -1160,29 +1161,32 @@ }, "require-dev": { "ably/ably-php": "^1.0", - "aws/aws-sdk-php": "^3.235.5", + "aws/aws-sdk-php": "^3.322.9", "ext-gmp": "*", - "fakerphp/faker": "^1.23", - "league/flysystem-aws-s3-v3": "^3.0", - "league/flysystem-ftp": "^3.0", - "league/flysystem-path-prefixing": "^3.3", - "league/flysystem-read-only": "^3.3", - "league/flysystem-sftp-v3": "^3.0", - "mockery/mockery": "^1.6", + "fakerphp/faker": "^1.24", + "guzzlehttp/promises": "^2.0.3", + "guzzlehttp/psr7": "^2.4", + "league/flysystem-aws-s3-v3": "^3.25.1", + "league/flysystem-ftp": "^3.25.1", + "league/flysystem-path-prefixing": "^3.25.1", + "league/flysystem-read-only": "^3.25.1", + "league/flysystem-sftp-v3": "^3.25.1", + "mockery/mockery": "^1.6.10", "nyholm/psr7": "^1.2", - "orchestra/testbench-core": "^9.5", - "pda/pheanstalk": "^5.0", + "orchestra/testbench-core": "^9.6", + "pda/pheanstalk": "^5.0.6", "phpstan/phpstan": "^1.11.5", - "phpunit/phpunit": "^10.5|^11.0", - "predis/predis": "^2.0.2", + "phpunit/phpunit": "^10.5.35|^11.3.6", + "predis/predis": "^2.3", "resend/resend-php": "^0.10.0", - "symfony/cache": "^7.0", - "symfony/http-client": "^7.0", - "symfony/psr-http-message-bridge": "^7.0" + "symfony/cache": "^7.0.3", + "symfony/http-client": "^7.0.3", + "symfony/psr-http-message-bridge": "^7.0.3", + "symfony/translation": "^7.0.3" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", - "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.235.5).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).", "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", "ext-apcu": "Required to use the APC cache driver.", "ext-fileinfo": "Required to use the Filesystem class.", @@ -1196,16 +1200,16 @@ "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", "filp/whoops": "Required for friendly error pages in development (^2.14.3).", "laravel/tinker": "Required to use the tinker console command (^2.0).", - "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", - "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", - "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).", - "league/flysystem-read-only": "Required to use read-only disks (^3.3)", - "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).", + "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", "mockery/mockery": "Required to use mocking (^1.6).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", "phpunit/phpunit": "Required to use assertions and run tests (^10.5|^11.0).", - "predis/predis": "Required to use the predis connector (^2.0.2).", + "predis/predis": "Required to use the predis connector (^2.3).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", @@ -1261,7 +1265,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-11-15T17:04:33+00:00" + "time": "2024-11-27T15:43:57+00:00" }, { "name": "laravel/prompts", @@ -1324,32 +1328,32 @@ }, { "name": "laravel/serializable-closure", - "version": "v1.3.7", + "version": "v2.0.0", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "4f48ade902b94323ca3be7646db16209ec76be3d" + "reference": "0d8d3d8086984996df86596a86dea60398093a81" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/4f48ade902b94323ca3be7646db16209ec76be3d", - "reference": "4f48ade902b94323ca3be7646db16209ec76be3d", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/0d8d3d8086984996df86596a86dea60398093a81", + "reference": "0d8d3d8086984996df86596a86dea60398093a81", "shasum": "" }, "require": { - "php": "^7.3|^8.0" + "php": "^8.1" }, "require-dev": { - "illuminate/support": "^8.0|^9.0|^10.0|^11.0", - "nesbot/carbon": "^2.61|^3.0", - "pestphp/pest": "^1.21.3", - "phpstan/phpstan": "^1.8.2", - "symfony/var-dumper": "^5.4.11|^6.2.0|^7.0.0" + "illuminate/support": "^10.0|^11.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { @@ -1381,7 +1385,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2024-11-14T18:34:49+00:00" + "time": "2024-11-19T01:38:44+00:00" }, { "name": "league/commonmark", @@ -5551,16 +5555,16 @@ }, { "name": "consolidation/config", - "version": "3.0.0", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/consolidation/config.git", - "reference": "248567e6322a89bb9a0d09d72278b7b6f9919d02" + "reference": "0615499781449ab773ffc609b97b934b3357b3f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/consolidation/config/zipball/248567e6322a89bb9a0d09d72278b7b6f9919d02", - "reference": "248567e6322a89bb9a0d09d72278b7b6f9919d02", + "url": "https://api.github.com/repos/consolidation/config/zipball/0615499781449ab773ffc609b97b934b3357b3f9", + "reference": "0615499781449ab773ffc609b97b934b3357b3f9", "shasum": "" }, "require": { @@ -5605,9 +5609,9 @@ "description": "Provide configuration services for a commandline tool.", "support": { "issues": "https://github.com/consolidation/config/issues", - "source": "https://github.com/consolidation/config/tree/3.0.0" + "source": "https://github.com/consolidation/config/tree/3.1.0" }, - "time": "2024-04-05T00:11:32+00:00" + "time": "2024-11-28T14:37:27+00:00" }, { "name": "consolidation/log", @@ -6853,24 +6857,24 @@ }, { "name": "orchestra/testbench", - "version": "v9.6.0", + "version": "v9.6.1", "source": { "type": "git", "url": "https://github.com/orchestral/testbench.git", - "reference": "b93847b61acfb4277149e6aeb1aa75703fd7b10d" + "reference": "97cc0e7cd52540ae9149b4a4fc512b198fed0237" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/testbench/zipball/b93847b61acfb4277149e6aeb1aa75703fd7b10d", - "reference": "b93847b61acfb4277149e6aeb1aa75703fd7b10d", + "url": "https://api.github.com/repos/orchestral/testbench/zipball/97cc0e7cd52540ae9149b4a4fc512b198fed0237", + "reference": "97cc0e7cd52540ae9149b4a4fc512b198fed0237", "shasum": "" }, "require": { "composer-runtime-api": "^2.2", "fakerphp/faker": "^1.23", - "laravel/framework": "^11.31", + "laravel/framework": "^11.33.2", "mockery/mockery": "^1.6.10", - "orchestra/testbench-core": "^9.6", + "orchestra/testbench-core": "^9.6.2", "orchestra/workbench": "^9.8", "php": "^8.2", "phpunit/phpunit": "^10.5.35 || ^11.3.6", @@ -6902,22 +6906,22 @@ ], "support": { "issues": "https://github.com/orchestral/testbench/issues", - "source": "https://github.com/orchestral/testbench/tree/v9.6.0" + "source": "https://github.com/orchestral/testbench/tree/v9.6.1" }, - "time": "2024-11-19T00:21:45+00:00" + "time": "2024-11-20T00:28:28+00:00" }, { "name": "orchestra/testbench-core", - "version": "v9.6.0", + "version": "v9.6.2", "source": { "type": "git", "url": "https://github.com/orchestral/testbench-core.git", - "reference": "22c0253a785494c81ba2a17b5c77e73a23f31a68" + "reference": "a776c94ab989f88e44b3d7f2f9df8e7ccb242974" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/22c0253a785494c81ba2a17b5c77e73a23f31a68", - "reference": "22c0253a785494c81ba2a17b5c77e73a23f31a68", + "url": "https://api.github.com/repos/orchestral/testbench-core/zipball/a776c94ab989f88e44b3d7f2f9df8e7ccb242974", + "reference": "a776c94ab989f88e44b3d7f2f9df8e7ccb242974", "shasum": "" }, "require": { @@ -6928,14 +6932,14 @@ }, "conflict": { "brianium/paratest": "<7.3.0 || >=8.0.0", - "laravel/framework": "<11.31.0 || >=12.0.0", + "laravel/framework": "<11.33.2 || >=12.0.0", "laravel/serializable-closure": "<1.3.0 || >=3.0.0", "nunomaduro/collision": "<8.0.0 || >=9.0.0", "phpunit/phpunit": "<10.5.35 || >=11.0.0 <11.3.6 || >=11.5.0" }, "require-dev": { "fakerphp/faker": "^1.23", - "laravel/framework": "^11.31", + "laravel/framework": "^11.33.2", "laravel/pint": "^1.17", "laravel/serializable-closure": "^1.3 || ^2.0", "mockery/mockery": "^1.6.10", @@ -6949,7 +6953,7 @@ "brianium/paratest": "Allow using parallel tresting (^7.3).", "ext-pcntl": "Required to use all features of the console signal trapping.", "fakerphp/faker": "Allow using Faker for testing (^1.23).", - "laravel/framework": "Required for testing (^11.31).", + "laravel/framework": "Required for testing (^11.33.2).", "mockery/mockery": "Allow using Mockery for testing (^1.6).", "nunomaduro/collision": "Allow using Laravel style tests output and parallel testing (^8.0).", "orchestra/testbench-dusk": "Allow using Laravel Dusk for testing (^9.0).", @@ -6995,7 +6999,7 @@ "issues": "https://github.com/orchestral/testbench/issues", "source": "https://github.com/orchestral/testbench-core" }, - "time": "2024-11-18T12:52:40+00:00" + "time": "2024-11-20T00:25:28+00:00" }, { "name": "orchestra/workbench", @@ -9360,12 +9364,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { "php": "^8.2" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/src/Actions/RunModelShowCommand.php b/src/Actions/RunModelShowCommand.php index 32a63ee..c80633f 100644 --- a/src/Actions/RunModelShowCommand.php +++ b/src/Actions/RunModelShowCommand.php @@ -2,12 +2,12 @@ namespace FumeApp\ModelTyper\Actions; -use FumeApp\ModelTyper\Commands\ShowModelCommand; use FumeApp\ModelTyper\Exceptions\CommandException; use FumeApp\ModelTyper\Exceptions\NestedCommandException; use Illuminate\Console\Command; use Illuminate\Console\OutputStyle; use Illuminate\Contracts\Foundation\Application; +use Illuminate\Database\Console\ShowModelCommand; use Illuminate\Foundation\Testing\Concerns\InteractsWithConsole; use Illuminate\Support\Arr; use Illuminate\Support\Facades\Artisan; @@ -34,22 +34,21 @@ public function __construct(?Application $app = null) */ public function __invoke(string $model, bool $resolveAbstract = false): array { - $relationships = implode(',', Arr::flatten(config('modeltyper.custom_relationships', []))); + // $relationships = implode(',', Arr::flatten(config('modeltyper.custom_relationships', []))); $commandArgs = [ 'model' => $model, '--json' => true, '--no-interaction' => true, - '--throw-exceptions' => true, ]; if ($resolveAbstract) { $commandArgs['--resolve-abstract'] = true; } - if (! empty($relationships)) { - $commandArgs['--custom-relationships'] = $relationships; - } + // if (! empty($relationships)) { + // $commandArgs['--custom-relationships'] = $relationships; + // } $command = ShowModelCommand::class; diff --git a/src/Commands/ShowModelCommand.php b/src/Commands/ShowModelCommand.php deleted file mode 100644 index 315530e..0000000 --- a/src/Commands/ShowModelCommand.php +++ /dev/null @@ -1,63 +0,0 @@ -components = new ErrorEmittingConsoleComponentFactory($this->components, $this->option('throw-exceptions')); // @phpstan-ignore-line - - if ($this->option('custom-relationships')) { - $customRelationships = collect(explode(',', $this->option('custom-relationships')))->map(fn ($method) => trim($method)); - $this->relationMethods = array_merge($this->relationMethods, $customRelationships->toArray()); - } - - return parent::handle(); - } - - /** - * @override - */ - protected function qualifyModel(string $model) - { - $class = parent::qualifyModel($model); - $reflection = new ReflectionClass($class); - - if ($reflection->isInterface() || $reflection->isTrait() || $reflection->isEnum()) { - $msg = "Skipping '$model' as it is an interface/trait/enum."; - $this->components->error($msg, OutputStyle::OUTPUT_NORMAL, AbstractModelException::class); // @phpstan-ignore-line - } - - if ($reflection->isAbstract() && ! $this->option('resolve-abstract')) { - $msg = "Trying to resolve an abstract model '$model' when 'resolve-abstract' option is not enabled."; - $this->components->error($msg, OutputStyle::OUTPUT_NORMAL, AbstractModelException::class); // @phpstan-ignore-line - } - - return $class; - } -} diff --git a/src/ModelTyperServiceProvider.php b/src/ModelTyperServiceProvider.php index 62fb3c5..978704a 100644 --- a/src/ModelTyperServiceProvider.php +++ b/src/ModelTyperServiceProvider.php @@ -3,7 +3,6 @@ namespace FumeApp\ModelTyper; use FumeApp\ModelTyper\Commands\ModelTyperCommand; -use FumeApp\ModelTyper\Commands\ShowModelCommand; use Illuminate\Support\ServiceProvider; class ModelTyperServiceProvider extends ServiceProvider @@ -20,7 +19,6 @@ public function boot(): void if ($this->app->runningInConsole()) { $this->commands([ ModelTyperCommand::class, - ShowModelCommand::class, ]); } diff --git a/src/Overrides/ErrorEmittingConsoleComponentFactory.php b/src/Overrides/ErrorEmittingConsoleComponentFactory.php deleted file mode 100644 index a948839..0000000 --- a/src/Overrides/ErrorEmittingConsoleComponentFactory.php +++ /dev/null @@ -1,47 +0,0 @@ -factory = $factory; - $this->throwExceptions = $throwExceptions; - } - - /** - * Reroute calls to underlying instance unless intercepted by override. - * - * @param array $arguments - */ - public function __call(string $name, array $arguments): mixed - { - if ($name === 'error') { - return $this->emitError(...$arguments); - } - - return $this->factory->$name(...$arguments); - } - - private function emitError(string $message, int $verbosity = OutputInterface::VERBOSITY_NORMAL, ?string $exceptionClass = CommandException::class): int - { - if ($this->throwExceptions) { - throw new $exceptionClass(message: $message); - } - - return Command::FAILURE; - } -} diff --git a/test/Tests/Feature/Actions/RunModelShowCommandTest.php b/test/Tests/Feature/Actions/RunModelShowCommandTest.php index 6e8b71d..a48f73f 100644 --- a/test/Tests/Feature/Actions/RunModelShowCommandTest.php +++ b/test/Tests/Feature/Actions/RunModelShowCommandTest.php @@ -23,11 +23,13 @@ public function test_action_can_be_executed() $this->assertNotEmpty($result); } - public function test_trying_to_execute_action_with_an_absract_model_results_in_exception() + public function test_trying_to_execute_action_with_an_abstract_model_results_in_exception() { + $this->markTestIncomplete(); + $action = app(RunModelShowCommand::class); $this->expectException(NestedCommandException::class); - $result = $action(AbstractModel::class); + $action(AbstractModel::class); } } diff --git a/test/Tests/Feature/Console/ShowModelCommandTest.php b/test/Tests/Feature/Console/ShowModelCommandTest.php deleted file mode 100644 index da23dba..0000000 --- a/test/Tests/Feature/Console/ShowModelCommandTest.php +++ /dev/null @@ -1,15 +0,0 @@ -artisan(ShowModelCommand::class, ['model' => AbstractModel::class])->assertFailed(); - } -} From f324c1c83028b179c3e5a7e7d3085db8183fb2ea Mon Sep 17 00:00:00 2001 From: Ayrton Andino Bonazzola <60512432+ayrtonandino@users.noreply.github.com> Date: Thu, 28 Nov 2024 18:48:41 -0300 Subject: [PATCH 2/4] add ModelInspector --- src/Actions/BuildModelDetails.php | 40 +++++++------------ src/Actions/DetermineAccessorType.php | 18 ++++----- src/Actions/RunModelInspector.php | 26 ++++++++++++ src/Actions/WriteColumnAttribute.php | 1 + src/Overrides/ModelInspector.php | 24 +++++++++++ src/Traits/ModelRefClass.php | 7 ++-- .../Feature/Actions/RunModelInspectorTest.php | 34 ++++++++++++++++ .../Tests/Traits/ResolveClassAsReflection.php | 3 +- 8 files changed, 113 insertions(+), 40 deletions(-) create mode 100644 src/Actions/RunModelInspector.php create mode 100644 src/Overrides/ModelInspector.php create mode 100644 test/Tests/Feature/Actions/RunModelInspectorTest.php diff --git a/src/Actions/BuildModelDetails.php b/src/Actions/BuildModelDetails.php index 8383e62..276ac5e 100644 --- a/src/Actions/BuildModelDetails.php +++ b/src/Actions/BuildModelDetails.php @@ -2,11 +2,10 @@ namespace FumeApp\ModelTyper\Actions; -use FumeApp\ModelTyper\Exceptions\AbstractModelException; -use FumeApp\ModelTyper\Exceptions\NestedCommandException; use FumeApp\ModelTyper\Traits\ClassBaseName; use FumeApp\ModelTyper\Traits\ModelRefClass; use Illuminate\Support\Collection; +use Illuminate\Support\Str; use ReflectionException; use Symfony\Component\Finder\SplFileInfo; @@ -38,7 +37,8 @@ public function __invoke(SplFileInfo $modelFile, bool $resolveAbstract = false): $columns = collect($modelDetails['attributes'])->filter(fn ($att) => in_array($att['name'], $databaseColumns)); $nonColumns = collect($modelDetails['attributes'])->filter(fn ($att) => ! in_array($att['name'], $databaseColumns)); $relations = collect($modelDetails['relations']); - $interfaces = collect($laravelModel->interfaces)->map(fn ($interface, $key) => [ + + $interfaces = collect($laravelModel->interfaces ?? [])->map(fn ($interface, $key) => [ 'name' => $key, 'type' => $interface['type'] ?? 'unknown', 'nullable' => $interface['nullable'] ?? false, @@ -46,15 +46,9 @@ public function __invoke(SplFileInfo $modelFile, bool $resolveAbstract = false): 'forceType' => true, ]); - $imports = $interfaces->filter(function ($interface) { - return isset($interface['import']); - }) - ->map(function ($interface) { - return [ - 'import' => $interface['import'], - 'type' => $interface['type'], - ]; - }) + $imports = $interfaces + ->filter(fn (array $interface): bool => isset($interface['import'])) + ->map(fn (array $interface): array => ['import' => $interface['import'], 'type' => $interface['type']]) ->unique() ->values(); @@ -71,28 +65,22 @@ public function __invoke(SplFileInfo $modelFile, bool $resolveAbstract = false): 'columns' => $columns, 'nonColumns' => $nonColumns, 'relations' => $relations, - 'interfaces' => $interfaces->values(), + 'interfaces' => $interfaces, 'imports' => $imports, ]; } /** - * @throws NestedCommandException + * @return array{"class": class-string<\Illuminate\Database\Eloquent\Model>, database: string, table: string, policy: class-string|null, attributes: \Illuminate\Support\Collection, relations: \Illuminate\Support\Collection, events: \Illuminate\Support\Collection, observers: \Illuminate\Support\Collection, collection: class-string<\Illuminate\Database\Eloquent\Collection<\Illuminate\Database\Eloquent\Model>>, builder: class-string<\Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model>>}|null */ private function getModelDetails(SplFileInfo $modelFile, bool $resolveAbstract): ?array { - $modelFileArg = $modelFile->getRelativePathname(); - $modelFileArg = app()->getNamespace() . $modelFileArg; - $modelFileArg = str_replace('.php', '', $modelFileArg); - - try { - return app(RunModelShowCommand::class)($modelFileArg, $resolveAbstract); - } catch (NestedCommandException $exception) { - if ($exception->wasCausedBy(AbstractModelException::class) && ! $resolveAbstract) { - return null; - } - throw $exception; - } + $modelFile = Str::of(app()->getNamespace()) + ->append($modelFile->getRelativePathname()) + ->replace('.php', '') + ->toString(); + + return app(RunModelInspector::class)($modelFile, $resolveAbstract); } private function overrideCollectionWithInterfaces(Collection $columns, Collection $interfaces): Collection diff --git a/src/Actions/DetermineAccessorType.php b/src/Actions/DetermineAccessorType.php index 6ac4f2a..5aedd6b 100644 --- a/src/Actions/DetermineAccessorType.php +++ b/src/Actions/DetermineAccessorType.php @@ -5,6 +5,7 @@ use Exception; use Illuminate\Support\Str; use ReflectionClass; +use ReflectionException; use ReflectionMethod; class DetermineAccessorType @@ -13,26 +14,25 @@ class DetermineAccessorType * Determine the type of accessor. * * @see https://laravel.com/docs/9.x/eloquent-mutators#defining-an-accessor - * @see https://laravel.com/docs/8.x/eloquent-mutators#defining-an-accessor + * + * @param \ReflectionClass<\Illuminate\Database\Eloquent\Model> $reflectionModel * * @throws Exception */ public function __invoke(ReflectionClass $reflectionModel, string $mutator): ReflectionMethod { + $mutator = Str::studly($mutator); + // Try traditional try { - $accessor = 'get' . Str::studly($mutator) . 'Attribute'; - - return $reflectionModel->getMethod($accessor); - } catch (Exception $e) { + return $reflectionModel->getMethod('get' . $mutator . 'Attribute'); + } catch (ReflectionException $e) { } // Try new try { - $method = Str::studly($mutator); - - return $reflectionModel->getMethod($method); - } catch (Exception $e) { + return $reflectionModel->getMethod($mutator); + } catch (ReflectionException $e) { } throw new Exception('Accessor method for ' . $mutator . ' on model ' . $reflectionModel->getName() . ' does not exist'); diff --git a/src/Actions/RunModelInspector.php b/src/Actions/RunModelInspector.php new file mode 100644 index 0000000..0907abb --- /dev/null +++ b/src/Actions/RunModelInspector.php @@ -0,0 +1,26 @@ +app = $app ?? app(); + } + + /** + * Run internal Laravel ModelInspector class. + * + * @see https://github.com/laravel/framework/blob/11.x/src/Illuminate\Database\Eloquent\ModelInspector.php + * + * @return array{"class": class-string<\Illuminate\Database\Eloquent\Model>, database: string, table: string, policy: class-string|null, attributes: \Illuminate\Support\Collection, relations: \Illuminate\Support\Collection, events: \Illuminate\Support\Collection, observers: \Illuminate\Support\Collection, collection: class-string<\Illuminate\Database\Eloquent\Collection<\Illuminate\Database\Eloquent\Model>>, builder: class-string<\Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model>>}|null + */ + public function __invoke(string $model, bool $resolveAbstract = false): ?array + { + return app(ModelInspector::class)->inspect($model); + } +} diff --git a/src/Actions/WriteColumnAttribute.php b/src/Actions/WriteColumnAttribute.php index bef6fee..3bdd73c 100644 --- a/src/Actions/WriteColumnAttribute.php +++ b/src/Actions/WriteColumnAttribute.php @@ -16,6 +16,7 @@ class WriteColumnAttribute /** * Get model columns and attributes to the output. * + * @param \ReflectionClass<\Illuminate\Database\Eloquent\Model> $reflectionModel * @param array{name: string, type: string, increments: bool, nullable: bool, default: mixed, unique: bool, fillable: bool, hidden?: bool, appended: mixed, cast?: string|null, forceType?: bool} $attribute * @param array $mappings * @return array{array{name: string, type: string}, ReflectionClass|null}|array{string, ReflectionClass|null}|array{null, null} diff --git a/src/Overrides/ModelInspector.php b/src/Overrides/ModelInspector.php new file mode 100644 index 0000000..adf92b5 --- /dev/null +++ b/src/Overrides/ModelInspector.php @@ -0,0 +1,24 @@ +relationMethods = collect(Arr::flatten(config('modeltyper.custom_relationships', []))) + ->map(fn (string $method): string => Str::trim($method)) + ->merge($this->relationMethods) + ->toArray(); + + parent::__construct($app ?? app()); + } +} diff --git a/src/Traits/ModelRefClass.php b/src/Traits/ModelRefClass.php index c7c6871..d49f66c 100644 --- a/src/Traits/ModelRefClass.php +++ b/src/Traits/ModelRefClass.php @@ -9,12 +9,11 @@ trait ModelRefClass /** * Get the reflection interface. * - * @param array $info + * @param array{"class": class-string<\Illuminate\Database\Eloquent\Model>, database: string, table: string, policy: class-string|null, attributes: \Illuminate\Support\Collection, relations: \Illuminate\Support\Collection, events: \Illuminate\Support\Collection, observers: \Illuminate\Support\Collection, collection: class-string<\Illuminate\Database\Eloquent\Collection<\Illuminate\Database\Eloquent\Model>>, builder: class-string<\Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model>>} $info + * @return \ReflectionClass<\Illuminate\Database\Eloquent\Model> */ public function getRefInterface(array $info): ReflectionClass { - $class = $info['class']; - - return new ReflectionClass($class); + return new ReflectionClass($info['class']); } } diff --git a/test/Tests/Feature/Actions/RunModelInspectorTest.php b/test/Tests/Feature/Actions/RunModelInspectorTest.php new file mode 100644 index 0000000..931590f --- /dev/null +++ b/test/Tests/Feature/Actions/RunModelInspectorTest.php @@ -0,0 +1,34 @@ +assertInstanceOf(RunModelInspector::class, resolve(RunModelInspector::class)); + } + + public function test_action_can_be_executed() + { + $action = app(RunModelInspector::class); + $result = $action(User::class); + + $this->assertNotEmpty($result); + } + + public function test_trying_to_execute_action_with_an_abstract_model_results_in_exception() + { + $this->markTestIncomplete(); + + // $action = app(RunModelInspector::class); + + // $this->expectException(NestedCommandException::class); + // $action(AbstractModel::class); + } +} diff --git a/test/Tests/Traits/ResolveClassAsReflection.php b/test/Tests/Traits/ResolveClassAsReflection.php index 013461e..b685bdb 100644 --- a/test/Tests/Traits/ResolveClassAsReflection.php +++ b/test/Tests/Traits/ResolveClassAsReflection.php @@ -9,7 +9,8 @@ trait ResolveClassAsReflection /** * Resolve a class as a ReflectionClass. * - * @param class-string $model + * @param class-string<\Illuminate\Database\Eloquent\Model> $model + * @return \ReflectionClass<\Illuminate\Database\Eloquent\Model> */ public function resolveClassAsReflection(string $model): ReflectionClass { From 865ed37ba1cd286864203863e3fb2f263f4f85d3 Mon Sep 17 00:00:00 2001 From: Ayrton Andino Bonazzola <60512432+ayrtonandino@users.noreply.github.com> Date: Thu, 28 Nov 2024 18:51:28 -0300 Subject: [PATCH 3/4] remove RunModelShowCommand --- src/Actions/RunModelShowCommand.php | 115 ------------------ src/Exceptions/NestedCommandException.php | 14 --- .../Actions/RunModelShowCommandTest.php | 35 ------ 3 files changed, 164 deletions(-) delete mode 100644 src/Actions/RunModelShowCommand.php delete mode 100644 src/Exceptions/NestedCommandException.php delete mode 100644 test/Tests/Feature/Actions/RunModelShowCommandTest.php diff --git a/src/Actions/RunModelShowCommand.php b/src/Actions/RunModelShowCommand.php deleted file mode 100644 index c80633f..0000000 --- a/src/Actions/RunModelShowCommand.php +++ /dev/null @@ -1,115 +0,0 @@ -app = $app ?? app(); - } - - /** - * Run internal Laravel model:show command. - * - * @see https://github.com/laravel/framework/blob/9.x/src/Illuminate/Foundation/Console/ShowModelCommand.php - * - * @return array - * - * @throws NestedCommandException - */ - public function __invoke(string $model, bool $resolveAbstract = false): array - { - // $relationships = implode(',', Arr::flatten(config('modeltyper.custom_relationships', []))); - - $commandArgs = [ - 'model' => $model, - '--json' => true, - '--no-interaction' => true, - ]; - - if ($resolveAbstract) { - $commandArgs['--resolve-abstract'] = true; - } - - // if (! empty($relationships)) { - // $commandArgs['--custom-relationships'] = $relationships; - // } - - $command = ShowModelCommand::class; - - try { - $this->runCommandWithoutMockOutput($command, $commandArgs); - } catch (CommandException $exception) { - $msg = "Command '$command' failed:" . PHP_EOL . $exception->getMessage(); - throw new NestedCommandException($msg, Command::FAILURE, $exception); - } - - $output = Artisan::output(); - - // NOTE this check should not fail under normal circumstances, but might be useful to catch - // unexpected errors if running the command without mock fails for some reason. - if (empty($output)) { - $msg = "Could not resolve types for model '$model', Artisan::output() is empty."; - $msg .= PHP_EOL . 'If you are running tests, make sure to set {public $mockConsoleOutput = false;}'; - throw new NestedCommandException($msg); - } - - return json_decode($output, true); - } - - /** - * Run an Artisan command without testing mock output to prevent the command output - * from being intercepted by mock output handler. Resets the mock output handler after - * command execution so that mock testing is not disturbed. - * - * @param string $command Name of the command to run. - * @param array $args Arguments for the command. - * @return int $exitCode Exit code returned by the command. - */ - private function runCommandWithoutMockOutput(string $command, array $args = []): int - { - $originalOutput = $this->outputMocked() ? $this->app->get(OutputStyle::class) : false; - $this->withoutMockingConsoleOutput(); - - $exitCode = Artisan::call($command, $args); - - if ($originalOutput) { - $this->app->bind(OutputStyle::class, fn () => $originalOutput); - } - - return $exitCode; - } - - /** - * Check if the console output is being mocked. - * - * @return bool $mocked - */ - private function outputMocked(): bool - { - if (! $this->app->runningInConsole()) { - return false; - } - - if (! $this->app->environment('testing')) { - return false; - } - - return $this->app->has(OutputStyle::class); - } -} diff --git a/src/Exceptions/NestedCommandException.php b/src/Exceptions/NestedCommandException.php deleted file mode 100644 index 7b28aa9..0000000 --- a/src/Exceptions/NestedCommandException.php +++ /dev/null @@ -1,14 +0,0 @@ -getPrevious() instanceof $exceptionClass; - } -} diff --git a/test/Tests/Feature/Actions/RunModelShowCommandTest.php b/test/Tests/Feature/Actions/RunModelShowCommandTest.php deleted file mode 100644 index a48f73f..0000000 --- a/test/Tests/Feature/Actions/RunModelShowCommandTest.php +++ /dev/null @@ -1,35 +0,0 @@ -assertInstanceOf(RunModelShowCommand::class, resolve(RunModelShowCommand::class)); - } - - public function test_action_can_be_executed() - { - $action = app(RunModelShowCommand::class); - $result = $action(User::class); - - $this->assertNotEmpty($result); - } - - public function test_trying_to_execute_action_with_an_abstract_model_results_in_exception() - { - $this->markTestIncomplete(); - - $action = app(RunModelShowCommand::class); - - $this->expectException(NestedCommandException::class); - $action(AbstractModel::class); - } -} From 3644f21d8c9ef754c03071d30925e058701be656 Mon Sep 17 00:00:00 2001 From: Ayrton Andino Bonazzola <60512432+ayrtonandino@users.noreply.github.com> Date: Thu, 28 Nov 2024 19:00:47 -0300 Subject: [PATCH 4/4] add param to RunModelInspector --- src/Actions/RunModelInspector.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Actions/RunModelInspector.php b/src/Actions/RunModelInspector.php index 0907abb..6254d71 100644 --- a/src/Actions/RunModelInspector.php +++ b/src/Actions/RunModelInspector.php @@ -17,6 +17,7 @@ public function __construct(protected ?Application $app = null) * * @see https://github.com/laravel/framework/blob/11.x/src/Illuminate\Database\Eloquent\ModelInspector.php * + * @param class-string<\Illuminate\Database\Eloquent\Model> $model * @return array{"class": class-string<\Illuminate\Database\Eloquent\Model>, database: string, table: string, policy: class-string|null, attributes: \Illuminate\Support\Collection, relations: \Illuminate\Support\Collection, events: \Illuminate\Support\Collection, observers: \Illuminate\Support\Collection, collection: class-string<\Illuminate\Database\Eloquent\Collection<\Illuminate\Database\Eloquent\Model>>, builder: class-string<\Illuminate\Database\Eloquent\Builder<\Illuminate\Database\Eloquent\Model>>}|null */ public function __invoke(string $model, bool $resolveAbstract = false): ?array