From 604748160df4d1159141b24eaff540b704e50af1 Mon Sep 17 00:00:00 2001 From: Yannik Firre Date: Fri, 13 Aug 2021 09:45:12 +0200 Subject: [PATCH 1/3] ADDED - nested resources --- .../Statements/ResourceGenerator.php | 38 +++++++++++++++---- .../Statements/ResourceGeneratorTest.php | 36 ++++++++++++++++++ tests/fixtures/drafts/resource-nested.yaml | 14 +++++++ .../certificate-with-nested-resource.php | 28 ++++++++++++++ 4 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 tests/fixtures/drafts/resource-nested.yaml create mode 100644 tests/fixtures/resources/certificate-with-nested-resource.php diff --git a/src/Generators/Statements/ResourceGenerator.php b/src/Generators/Statements/ResourceGenerator.php index d2d2d2ef..e6219f36 100644 --- a/src/Generators/Statements/ResourceGenerator.php +++ b/src/Generators/Statements/ResourceGenerator.php @@ -9,6 +9,7 @@ use Blueprint\Models\Statements\ResourceStatement; use Blueprint\Tree; use Illuminate\Filesystem\Filesystem; +use Illuminate\Support\Arr; use Illuminate\Support\Str; class ResourceGenerator implements Generator @@ -39,8 +40,8 @@ public function output(Tree $tree): array $stub = $this->filesystem->stub('resource.stub'); /** - * @var \Blueprint\Models\Controller $controller -*/ + * @var \Blueprint\Models\Controller $controller + */ foreach ($tree->controllers() as $controller) { foreach ($controller->methods() as $method => $statements) { foreach ($statements as $statement) { @@ -90,7 +91,7 @@ protected function populateStub(string $stub, Controller $controller, ResourceSt $stub = str_replace('{{ class }}', $resource->name(), $stub); $stub = str_replace('{{ parentClass }}', $resource->collection() ? 'ResourceCollection' : 'JsonResource', $stub); $stub = str_replace('{{ resource }}', $resource->collection() ? 'resource collection' : 'resource', $stub); - $stub = str_replace('{{ body }}', $this->buildData($resource), $stub); + $stub = str_replace('{{ body }}', $this->buildData($resource, $namespace), $stub); if (Blueprint::supportsReturnTypeHits()) { $stub = str_replace('toArray($request)', 'toArray($request): array', $stub); @@ -98,13 +99,13 @@ protected function populateStub(string $stub, Controller $controller, ResourceSt return $stub; } - protected function buildData(ResourceStatement $resource) + protected function buildData(ResourceStatement $resource, string $namespace) { $context = Str::singular($resource->reference()); /** - * @var \Blueprint\Models\Model $model -*/ + * @var \Blueprint\Models\Model $model + */ $model = $this->tree->modelForContext($context); $data = []; @@ -120,6 +121,27 @@ protected function buildData(ResourceStatement $resource) foreach ($this->visibleColumns($model) as $column) { $data[] = self::INDENT . '\'' . $column . '\' => $this->' . $column . ','; } + + foreach ($model->relationships() as $type => $relationship) { + + $method_name = lcfirst(Str::afterLast(Arr::last($relationship), '\\')); + + $relation_model = $this->tree->modelForContext($method_name); + + if($relation_model === null) { + continue; + } + + if (in_array($type, ['hasMany', 'belongsToMany', 'morphMany'])) { + $relation_resource_name = $relation_model->name() . 'Collection'; + $method_name = Str::plural($method_name); + } else { + $relation_resource_name = $relation_model->name() . 'Resource'; + } + + $data[] = self::INDENT . '\'' . $method_name . '\' => ' . $relation_resource_name . '::make($this->whenLoaded(\'' .$method_name.'\')),'; + } + $data[] = ' ];'; return implode(PHP_EOL, $data); @@ -130,8 +152,8 @@ private function visibleColumns(Model $model) return array_diff( array_keys($model->columns()), [ - 'password', - 'remember_token', + 'password', + 'remember_token', ] ); } diff --git a/tests/Feature/Generators/Statements/ResourceGeneratorTest.php b/tests/Feature/Generators/Statements/ResourceGeneratorTest.php index 6a89984d..0b2dd2f2 100644 --- a/tests/Feature/Generators/Statements/ResourceGeneratorTest.php +++ b/tests/Feature/Generators/Statements/ResourceGeneratorTest.php @@ -136,6 +136,42 @@ public function output_writes_namespaced_classes() ], $this->subject->output($tree)); } + /** + * @test + */ + public function output_writes_nested_resource() + { + $this->filesystem->expects('stub') + ->with('resource.stub') + ->andReturn(file_get_contents('stubs/resource.stub')); + + $this->filesystem->shouldReceive('exists') + ->with('app/Http/Resources/Api') + ->andReturns(false, true); + $this->filesystem->expects('makeDirectory') + ->with('app/Http/Resources/Api', 0755, true); + + $this->filesystem->expects('exists') + ->times(3) + ->with('app/Http/Resources/Api/CertificateResource.php') + ->andReturns(false, true, true); + $this->filesystem->expects('put') + ->with('app/Http/Resources/Api/CertificateResource.php', $this->fixture('resources/certificate-with-nested-resource.php')); + + $this->filesystem->expects('exists') + ->with('app/Http/Resources/Api/CertificateCollection.php') + ->andReturns(false); + $this->filesystem->expects('put') + ->with('app/Http/Resources/Api/CertificateCollection.php', $this->fixture('resources/certificate-collection.php')); + + $tokens = $this->blueprint->parse($this->fixture('drafts/resource-nested.yaml')); + $tree = $this->blueprint->analyze($tokens); + + $this->assertEquals([ + 'created' => ['app/Http/Resources/Api/CertificateCollection.php', 'app/Http/Resources/Api/CertificateResource.php'], + ], $this->subject->output($tree)); + } + /** * @test */ diff --git a/tests/fixtures/drafts/resource-nested.yaml b/tests/fixtures/drafts/resource-nested.yaml new file mode 100644 index 00000000..78248791 --- /dev/null +++ b/tests/fixtures/drafts/resource-nested.yaml @@ -0,0 +1,14 @@ +models: + Certificate: + name: string + reference: string + document: string + expiry_date: date + remarks: text nullable + relationships: + belongsTo: \App\Certificate + hasMany: \App\Certificate + +controllers: + Api/Certificate: + resource: api diff --git a/tests/fixtures/resources/certificate-with-nested-resource.php b/tests/fixtures/resources/certificate-with-nested-resource.php new file mode 100644 index 00000000..883a96fa --- /dev/null +++ b/tests/fixtures/resources/certificate-with-nested-resource.php @@ -0,0 +1,28 @@ + $this->id, + 'name' => $this->name, + 'reference' => $this->reference, + 'document' => $this->document, + 'expiry_date' => $this->expiry_date, + 'remarks' => $this->remarks, + 'certificate' => CertificateResource::make($this->whenLoaded('certificate')), + 'certificates' => CertificateCollection::make($this->whenLoaded('certificates')), + ]; + } +} From 8527c6c6fac3a03a5b65bcc207c0336326fafb39 Mon Sep 17 00:00:00 2001 From: Yannik Firre Date: Fri, 13 Aug 2021 09:47:43 +0200 Subject: [PATCH 2/3] FIXED - style --- src/Generators/Statements/ResourceGenerator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Generators/Statements/ResourceGenerator.php b/src/Generators/Statements/ResourceGenerator.php index e6219f36..6221bdc2 100644 --- a/src/Generators/Statements/ResourceGenerator.php +++ b/src/Generators/Statements/ResourceGenerator.php @@ -128,7 +128,7 @@ protected function buildData(ResourceStatement $resource, string $namespace) $relation_model = $this->tree->modelForContext($method_name); - if($relation_model === null) { + if ($relation_model === null) { continue; } From 551ebf4a9f577aed72cefb0ce948710fd0ed7d6e Mon Sep 17 00:00:00 2001 From: Yannik Firre Date: Fri, 13 Aug 2021 09:50:09 +0200 Subject: [PATCH 3/3] FIXED - style --- src/Generators/Statements/ResourceGenerator.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Generators/Statements/ResourceGenerator.php b/src/Generators/Statements/ResourceGenerator.php index 6221bdc2..a08c304d 100644 --- a/src/Generators/Statements/ResourceGenerator.php +++ b/src/Generators/Statements/ResourceGenerator.php @@ -45,7 +45,7 @@ public function output(Tree $tree): array foreach ($tree->controllers() as $controller) { foreach ($controller->methods() as $method => $statements) { foreach ($statements as $statement) { - if (! $statement instanceof ResourceStatement) { + if (!$statement instanceof ResourceStatement) { continue; } @@ -55,7 +55,7 @@ public function output(Tree $tree): array continue; } - if (! $this->filesystem->exists(dirname($path))) { + if (!$this->filesystem->exists(dirname($path))) { $this->filesystem->makeDirectory(dirname($path), 0755, true); } @@ -91,7 +91,7 @@ protected function populateStub(string $stub, Controller $controller, ResourceSt $stub = str_replace('{{ class }}', $resource->name(), $stub); $stub = str_replace('{{ parentClass }}', $resource->collection() ? 'ResourceCollection' : 'JsonResource', $stub); $stub = str_replace('{{ resource }}', $resource->collection() ? 'resource collection' : 'resource', $stub); - $stub = str_replace('{{ body }}', $this->buildData($resource, $namespace), $stub); + $stub = str_replace('{{ body }}', $this->buildData($resource), $stub); if (Blueprint::supportsReturnTypeHits()) { $stub = str_replace('toArray($request)', 'toArray($request): array', $stub); @@ -99,7 +99,7 @@ protected function populateStub(string $stub, Controller $controller, ResourceSt return $stub; } - protected function buildData(ResourceStatement $resource, string $namespace) + protected function buildData(ResourceStatement $resource) { $context = Str::singular($resource->reference()); @@ -123,7 +123,6 @@ protected function buildData(ResourceStatement $resource, string $namespace) } foreach ($model->relationships() as $type => $relationship) { - $method_name = lcfirst(Str::afterLast(Arr::last($relationship), '\\')); $relation_model = $this->tree->modelForContext($method_name); @@ -139,7 +138,7 @@ protected function buildData(ResourceStatement $resource, string $namespace) $relation_resource_name = $relation_model->name() . 'Resource'; } - $data[] = self::INDENT . '\'' . $method_name . '\' => ' . $relation_resource_name . '::make($this->whenLoaded(\'' .$method_name.'\')),'; + $data[] = self::INDENT . '\'' . $method_name . '\' => ' . $relation_resource_name . '::make($this->whenLoaded(\'' . $method_name . '\')),'; } $data[] = ' ];';