diff --git a/CHANGELOG.md b/CHANGELOG.md index c4ba7c5..168869a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. This projec ## Unreleased +## [3.3.0] - 2024-03-03 + +### Added + +- [#272](https://github.com/laravel-json-api/laravel/pull/272) Added a model property type-hint to the resource stub and + allowed it to be replaced via a model option on the command. + ## [3.2.0] - 2024-02-14 ### Added diff --git a/src/Console/Concerns/ReplacesModel.php b/src/Console/Concerns/ReplacesModel.php new file mode 100644 index 0000000..753fc86 --- /dev/null +++ b/src/Console/Concerns/ReplacesModel.php @@ -0,0 +1,58 @@ +qualifyModel($model); + } + + $model = class_basename($model); + + $replace = [ + '{{ namespacedModel }}' => $namespacedModel, + '{{namespacedModel}}' => $namespacedModel, + '{{ model }}' => $model, + '{{model}}' => $model, + ]; + + return str_replace( + array_keys($replace), array_values($replace), $stub + ); + } +} diff --git a/src/Console/MakeResource.php b/src/Console/MakeResource.php index efb53cc..7c1d996 100644 --- a/src/Console/MakeResource.php +++ b/src/Console/MakeResource.php @@ -19,10 +19,12 @@ namespace LaravelJsonApi\Laravel\Console; +use LaravelJsonApi\Laravel\Console\Concerns\ReplacesModel; use Symfony\Component\Console\Input\InputOption; class MakeResource extends GeneratorCommand { + use ReplacesModel; /** * @var string @@ -52,6 +54,18 @@ protected function getStub() return $this->resolveStubPath('resource.stub'); } + /** + * @inheritDoc + */ + protected function buildClass($name) + { + $stub = parent::buildClass($name); + + $model = $this->option('model') ?: $this->guessModel(); + + return $this->replaceModel($stub, $model); + } + /** * @inheritDoc */ @@ -59,8 +73,8 @@ protected function getOptions() { return [ ['force', null, InputOption::VALUE_NONE, 'Create the class even if the resource already exists'], + ['model', 'm', InputOption::VALUE_REQUIRED, 'The model that the resource applies to.'], ['server', 's', InputOption::VALUE_REQUIRED, 'The JSON:API server the resource exists in.'], ]; } - } diff --git a/src/Console/MakeSchema.php b/src/Console/MakeSchema.php index d371e8b..79b83a4 100644 --- a/src/Console/MakeSchema.php +++ b/src/Console/MakeSchema.php @@ -19,7 +19,7 @@ namespace LaravelJsonApi\Laravel\Console; -use Illuminate\Support\Str; +use LaravelJsonApi\Laravel\Console\Concerns\ReplacesModel; use Symfony\Component\Console\Input\InputOption; use function array_keys; use function array_values; @@ -27,6 +27,7 @@ class MakeSchema extends GeneratorCommand { + use ReplacesModel; /** * @var string @@ -47,7 +48,7 @@ class MakeSchema extends GeneratorCommand * @var string */ protected $classType = 'Schema'; - + /** * @inheritDoc */ @@ -65,7 +66,7 @@ protected function getStub() */ protected function buildClass($name) { - $stub = parent::buildClass($name); + $stub = $this->replaceSchema(parent::buildClass($name)); $model = $this->option('model') ?: $this->guessModel(); @@ -77,24 +78,11 @@ protected function buildClass($name) * @param string $model * @return string */ - protected function replaceModel(string $stub, string $model): string + protected function replaceSchema(string $stub): string { - $model = str_replace('/', '\\', $model); - - if (Str::startsWith($model, '\\')) { - $namespacedModel = trim($model, '\\'); - } else { - $namespacedModel = $this->qualifyModel($model); - } - - $model = class_basename($model); $schema = $this->option('proxy') ? 'ProxySchema' : 'Schema'; $replace = [ - '{{ namespacedModel }}' => $namespacedModel, - '{{namespacedModel}}' => $namespacedModel, - '{{ model }}' => $model, - '{{model}}' => $model, '{{ schema }}' => $schema, '{{schema}}' => $schema, ]; @@ -117,5 +105,4 @@ protected function getOptions() ['server', 's', InputOption::VALUE_REQUIRED, 'The JSON:API server the schema exists in.'], ]; } - } diff --git a/stubs/resource.stub b/stubs/resource.stub index 0263f81..b8ab023 100644 --- a/stubs/resource.stub +++ b/stubs/resource.stub @@ -2,9 +2,13 @@ namespace {{ namespace }}; +use {{ namespacedModel }}; use Illuminate\Http\Request; use LaravelJsonApi\Core\Resources\JsonApiResource; +/** + * @property {{ model }} $resource + */ class {{ class }} extends JsonApiResource { @@ -17,8 +21,8 @@ class {{ class }} extends JsonApiResource public function attributes($request): iterable { return [ - 'createdAt' => $this->created_at, - 'updatedAt' => $this->updated_at, + 'createdAt' => $this->resource->created_at, + 'updatedAt' => $this->resource->updated_at, ]; } diff --git a/tests/lib/Integration/Console/MakeResourceTest.php b/tests/lib/Integration/Console/MakeResourceTest.php index 6cd48e0..0abc975 100644 --- a/tests/lib/Integration/Console/MakeResourceTest.php +++ b/tests/lib/Integration/Console/MakeResourceTest.php @@ -25,7 +25,6 @@ class MakeResourceTest extends TestCase { - /** * @return void */ @@ -60,6 +59,33 @@ public function test(): void $this->assertResourceCreated(); } + public function testModelWithoutNamespace(): void + { + config()->set('jsonapi.servers', [ + 'v1' => Server::class, + ]); + + $result = $this->artisan('jsonapi:resource posts --model BlogPost'); + + $this->assertSame(0, $result); + $this->assertResourceCreated('App\Models\BlogPost', 'BlogPost'); + } + + public function testModelWithNamespace(): void + { + config()->set('jsonapi.servers', [ + 'v1' => Server::class, + ]); + + $result = $this->artisan('jsonapi:resource', [ + 'name' => 'posts', + '--model' => '\App\Foo\Bar\BlogPost', + ]); + + $this->assertSame(0, $result); + $this->assertResourceCreated('App\Foo\Bar\BlogPost', 'BlogPost'); + } + public function testServer(): void { config()->set('jsonapi.servers', [ @@ -104,9 +130,14 @@ public function testInvalidServer(): void } /** + * @param string $namespacedModel + * @param string $model * @return void */ - private function assertResourceCreated(): void + private function assertResourceCreated( + string $namespacedModel = 'App\Models\Post', + string $model = 'Post' + ): void { $this->assertFileExists($path = app_path('JsonApi/V1/Posts/PostResource.php')); $content = file_get_contents($path); @@ -115,6 +146,8 @@ private function assertResourceCreated(): void 'namespace App\JsonApi\V1\Posts;', 'use LaravelJsonApi\Core\Resources\JsonApiResource;', 'class PostResource extends JsonApiResource', + "use {$namespacedModel};", + "@property {$model} \$resource", ]; foreach ($tests as $expected) {
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: