diff --git a/src/Generators/Statements/ResourceGenerator.php b/src/Generators/Statements/ResourceGenerator.php index d2d2d2ef..a08c304d 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,12 +40,12 @@ 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) { - if (! $statement instanceof ResourceStatement) { + if (!$statement instanceof ResourceStatement) { continue; } @@ -54,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); } @@ -103,8 +104,8 @@ protected function buildData(ResourceStatement $resource) $context = Str::singular($resource->reference()); /** - * @var \Blueprint\Models\Model $model -*/ + * @var \Blueprint\Models\Model $model + */ $model = $this->tree->modelForContext($context); $data = []; @@ -120,6 +121,26 @@ 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 +151,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')), + ]; + } +}