Skip to content

Commit 55a07ef

Browse files
authored
Merge pull request #208 from RonasIT/203-relationships-annotation
[203]: add model relations property annotations
2 parents bd9e489 + 69628d2 commit 55a07ef

File tree

10 files changed

+123
-19
lines changed

10 files changed

+123
-19
lines changed

src/Generators/ModelGenerator.php

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,18 @@ protected function hasRelations(): bool
3737

3838
protected function getNewModelContent(): string
3939
{
40+
$relations = $this->prepareRelations();
41+
4042
return $this->getStub('model', [
4143
'entity' => $this->model,
4244
'fields' => Arr::collapse($this->fields),
43-
'relations' => $this->prepareRelations(),
45+
'relations' => $relations,
4446
'casts' => $this->getCasts($this->fields),
4547
'namespace' => $this->generateNamespace($this->paths['models'], $this->modelSubFolder),
4648
'importRelations' => $this->getImportedRelations(),
47-
'anotationProperties' => $this->generateAnnotationProperties($this->fields),
49+
'annotationProperties' => $this->generateAnnotationProperties($this->fields, $relations),
4850
'hasCarbonField' => !empty($this->fields['timestamp']) || !empty($this->fields['timestamp-required']),
51+
'hasCollectionType' => !empty($this->relations->hasMany) || !empty($this->relations->belongsToMany),
4952
]);
5053
}
5154

@@ -76,14 +79,19 @@ public function prepareRelatedModels(): void
7679
$this->insertImport($content, $namespace);
7780
}
7881

82+
$relationName = $this->getRelationName($this->model, $types[$type]);
83+
7984
$newRelation = $this->getStub('relation', [
80-
'name' => $this->getRelationName($this->model, $types[$type]),
85+
'name' => $relationName,
8186
'type' => $types[$type],
8287
'entity' => $this->model,
8388
]);
8489

90+
// TODO: use ronasit/larabuilder instead regexp
8591
$fixedContent = preg_replace('/\}$/', "\n {$newRelation}\n}", $content);
8692

93+
$this->insertPropertyAnnotation($fixedContent, $this->getRelationType($this->model, $types[$type]), $relationName);
94+
8795
$this->saveClass('models', $relation, $fixedContent);
8896
}
8997
}
@@ -101,6 +109,7 @@ protected function insertImport(string &$classContent, string $import): void
101109
$import = "use {$import};";
102110

103111
if (!Str::contains($classContent, $import)) {
112+
// TODO: use ronasit/larabuilder instead regexp
104113
$classContent = preg_replace('/(namespace\s+[^;]+;\s*)/', "$1{$import}\n", $classContent, 1);
105114
}
106115
}
@@ -190,7 +199,7 @@ protected function generateClassNamespace(string $className, ?string $folder = n
190199
return "{$path}\\{$psrPath}";
191200
}
192201

193-
protected function generateAnnotationProperties(array $fields): array
202+
protected function generateAnnotationProperties(array $fields, array $relations): array
194203
{
195204
$result = [];
196205

@@ -200,6 +209,10 @@ protected function generateAnnotationProperties(array $fields): array
200209
}
201210
}
202211

212+
foreach ($relations as $relation) {
213+
$result[$relation['name']] = $this->getRelationType($relation['entity'], $relation['type']);
214+
}
215+
203216
return $result;
204217
}
205218

@@ -239,4 +252,29 @@ protected function isRequired(string $typeName): bool
239252
{
240253
return Str::endsWith($typeName, 'required');
241254
}
255+
256+
protected function getRelationType(string $model, string $relation): string
257+
{
258+
if (in_array($relation, self::PLURAL_NUMBER_REQUIRED)) {
259+
return "Collection<{$model}>";
260+
}
261+
262+
return "{$model}|null";
263+
}
264+
265+
protected function insertPropertyAnnotation(string &$content, string $propertyDataType, string $propertyName): void
266+
{
267+
$annotation = "* @property {$propertyDataType} \${$propertyName}";
268+
269+
// TODO: use ronasit/larabuilder instead regexp
270+
if (!Str::contains($content, '/**')) {
271+
$content = preg_replace('/^\s*class[\s\S]+?\{/m', "\n/**\n {$annotation}\n */$0", $content);
272+
} else {
273+
$content = preg_replace('/\*\//m', "{$annotation}\n $0", $content);
274+
}
275+
276+
if (Str::contains($propertyDataType, 'Collection')) {
277+
$this->insertImport($content, 'Illuminate\Database\Eloquent\Collection');
278+
}
279+
}
242280
}

stubs/model.blade.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@
88
@if($hasCarbonField)
99
use Carbon\Carbon;
1010
@endif
11+
@if($hasCollectionType)
12+
use Illuminate\Database\Eloquent\Collection;
13+
@endif
1114

12-
@if(!empty($anotationProperties))
15+
@if(!empty($annotationProperties))
1316
/**
14-
@foreach($anotationProperties as $key => $value)
15-
* @property {{ $value }} ${{ $key }}
17+
@foreach($annotationProperties as $key => $value)
18+
* @property {!! $value !!} ${{ $key }}
1619
@endforeach
1720
*/
1821
@else

tests/ModelGeneratorTest.php

100644100755
Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public function setUp(): void
1919
{
2020
parent::setUp();
2121

22-
$this->mockFilesystem();
22+
$this->mockDefaultFilesystem();
2323
}
2424

2525
public function testModelAlreadyExists()
@@ -41,7 +41,9 @@ className: ResourceAlreadyExistsException::class,
4141

4242
public function testRelationModelMissing()
4343
{
44-
$this->mockFileSystemWithoutCommentModel();
44+
$this->mockFilesystem([
45+
'User.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'),
46+
]);
4547

4648
$this->assertExceptionThrew(
4749
className: ClassNotExistsException::class,
@@ -247,4 +249,22 @@ className: WarningEvent::class,
247249
message: 'Generation of model has been skipped cause the view incorrect_stub from the config entity-generator.stubs.relation is not exists. Please check that config has the correct view name value.',
248250
);
249251
}
252+
253+
public function testAddPropertyAnnotationToRelatedModel()
254+
{
255+
app(ModelGenerator::class)
256+
->setModel('Category')
257+
->setFields([])
258+
->setRelations(new RelationsDTO(
259+
belongsToMany: ['User'],
260+
))
261+
->generate();
262+
263+
$this->assertGeneratedFileEquals('related_model_with_property.php', 'app/Models/User.php');
264+
265+
$this->assertEventPushed(
266+
className: SuccessCreateMessage::class,
267+
message: 'Created a new Model: Category',
268+
);
269+
}
250270
}

tests/Support/Model/ModelMockTrait.php

100644100755
Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,27 +9,24 @@ trait ModelMockTrait
99
{
1010
use GeneratorMockTrait;
1111

12-
13-
public function mockFileSystemWithoutCommentModel(): void
12+
public function mockDefaultFilesystem(): void
1413
{
1514
$fileSystemMock = new FileSystemMock();
1615

1716
$fileSystemMock->models = [
17+
'Comment.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'),
1818
'User.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'),
19+
'Forum/Author.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'),
1920
];
2021

2122
$fileSystemMock->setStructure();
2223
}
2324

24-
public function mockFilesystem(): void
25+
public function mockFilesystem(array $models): void
2526
{
26-
$fileSystemMock = new FileSystemMock;
27+
$fileSystemMock = new FileSystemMock();
2728

28-
$fileSystemMock->models = [
29-
'Comment.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'),
30-
'User.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'),
31-
'Forum/Author.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'),
32-
];
29+
$fileSystemMock->models = $models;
3330

3431
$fileSystemMock->setStructure();
3532
}

tests/fixtures/ModelGeneratorTest/comment_relation_model.php

100644100755
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
use Illuminate\Database\Eloquent\Model;
66
use RonasIT\Support\Traits\ModelTrait;
77

8+
/**
9+
* @property Post|null $post
10+
*/
811
class WelcomeBonus extends Model
912
{
1013
use ModelTrait;

tests/fixtures/ModelGeneratorTest/new_model.php

100644100755
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Database\Eloquent\Model;
66
use RonasIT\Support\Traits\ModelTrait;
77
use Carbon\Carbon;
8+
use Illuminate\Database\Eloquent\Collection;
89

910
/**
1011
* @property int|null $priority
@@ -20,6 +21,8 @@
2021
* @property Carbon|null $updated_at
2122
* @property Carbon $published_at
2223
* @property array $meta
24+
* @property Comment|null $comment
25+
* @property Collection<User> $users
2326
*/
2427
class Post extends Model
2528
{

tests/fixtures/ModelGeneratorTest/new_model_with_many_relations.php

100644100755
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
use Illuminate\Database\Eloquent\Model;
66
use RonasIT\Support\Traits\ModelTrait;
77
use App\Models\User;
8+
use Illuminate\Database\Eloquent\Collection;
89

9-
//TODO: add @property annotation for each model's field
1010
/**
11+
* @property Collection<User> $users
1112
*/
1213
class Post extends Model
1314
{

tests/fixtures/ModelGeneratorTest/new_model_with_subfolers_relations.php

100644100755
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
use Illuminate\Database\Eloquent\Model;
66
use RonasIT\Support\Traits\ModelTrait;
77
use App\Models\Forum\Author;
8+
use Illuminate\Database\Eloquent\Collection;
89

910
/**
1011
* @property string $title
12+
* @property Collection<Author> $authors
1113
*/
1214
class Post extends Model
1315
{

tests/fixtures/ModelGeneratorTest/new_subfolders_model.php

100644100755
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use App\Models\Comment;
88
use App\Models\User;
99
use Carbon\Carbon;
10+
use Illuminate\Database\Eloquent\Collection;
1011

1112
/**
1213
* @property int|null $priority
@@ -22,6 +23,8 @@
2223
* @property Carbon|null $updated_at
2324
* @property Carbon $published_at
2425
* @property array $meta
26+
* @property Comment|null $comment
27+
* @property Collection<User> $users
2528
*/
2629
class Post extends Model
2730
{
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace RonasIT\Support\Tests\Support\Models;
4+
5+
use Illuminate\Database\Eloquent\Collection;
6+
use Illuminate\Database\Eloquent\Model;
7+
use RonasIT\Support\Traits\ModelTrait;
8+
9+
/**
10+
* @property Collection<Category> $categories
11+
*/
12+
class WelcomeBonus extends Model
13+
{
14+
use ModelTrait;
15+
16+
public function getConnectionName(): string
17+
{
18+
return 'pgsql';
19+
}
20+
21+
protected $fillable = [
22+
'title',
23+
'name',
24+
];
25+
26+
public function some_relation()
27+
{
28+
}
29+
30+
public function categories()
31+
{
32+
return $this->belongsToMany(Category::class);
33+
}
34+
}

0 commit comments

Comments
 (0)