Skip to content

Commit e2bd53a

Browse files
authored
Merge branch 'master' into add-resource-not-exists-exception
2 parents f246aa0 + 55a07ef commit e2bd53a

File tree

12 files changed

+150
-30
lines changed

12 files changed

+150
-30
lines changed

src/Commands/MakeEntityCommand.php

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ public function handle(): void
124124
$this->checkConfigs();
125125
$this->listenEvents();
126126
$this->parseRelations();
127+
$this->entityName = $this->convertToPascalCase($this->entityName);
127128

128129
try {
129130
$this->generate();
@@ -238,19 +239,20 @@ protected function getCrudOptions(): array
238239
protected function parseRelations(): void
239240
{
240241
$this->relations = new RelationsDTO(
241-
hasOne: $this->trimRelations($this->option('has-one')),
242-
hasMany: $this->trimRelations($this->option('has-many')),
243-
belongsTo: $this->trimRelations($this->option('belongs-to')),
244-
belongsToMany: $this->trimRelations($this->option('belongs-to-many')),
242+
hasOne: $this->prepareRelations($this->option('has-one')),
243+
hasMany: $this->prepareRelations($this->option('has-many')),
244+
belongsTo: $this->prepareRelations($this->option('belongs-to')),
245+
belongsToMany: $this->prepareRelations($this->option('belongs-to-many')),
245246
);
246247
}
247248

248-
protected function trimRelations(array $relations): array
249+
protected function prepareRelations(array $relations): array
249250
{
250-
return array_map(
251-
callback: fn ($relation) => Str::trim($relation, '/'),
252-
array: $relations,
253-
);
251+
return array_map(function ($relation) {
252+
$relation = Str::trim($relation, '/');
253+
254+
return $this->convertToPascalCase($relation);
255+
}, $relations);
254256
}
255257

256258
protected function getFields(): array
@@ -305,4 +307,15 @@ protected function listenEvents(): void
305307
listener: fn (WarningEvent $event) => $this->warn($event->message),
306308
);
307309
}
310+
311+
protected function convertToPascalCase(string $entityName): string
312+
{
313+
$pascalEntityName = Str::studly($entityName);
314+
315+
if ($entityName !== $pascalEntityName) {
316+
$this->info("{$entityName} was converted to {$pascalEntityName}");
317+
}
318+
319+
return $pascalEntityName;
320+
}
308321
}

src/Generators/EntityGenerator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public function setCrudOptions(array $crudOptions): self
5454

5555
public function setModel(string $model): self
5656
{
57-
$this->model = Str::studly($model);
57+
$this->model = $model;
5858

5959
return $this;
6060
}

src/Generators/ModelGenerator.php

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

3737
protected function getNewModelContent(): string
3838
{
39+
$relations = $this->prepareRelations();
40+
3941
return $this->getStub('model', [
4042
'entity' => $this->model,
4143
'fields' => Arr::collapse($this->fields),
42-
'relations' => $this->prepareRelations(),
44+
'relations' => $relations,
4345
'casts' => $this->getCasts($this->fields),
4446
'namespace' => $this->generateNamespace($this->paths['models'], $this->modelSubFolder),
4547
'importRelations' => $this->getImportedRelations(),
46-
'anotationProperties' => $this->generateAnnotationProperties($this->fields),
48+
'annotationProperties' => $this->generateAnnotationProperties($this->fields, $relations),
4749
'hasCarbonField' => !empty($this->fields['timestamp']) || !empty($this->fields['timestamp-required']),
50+
'hasCollectionType' => !empty($this->relations->hasMany) || !empty($this->relations->belongsToMany),
4851
]);
4952
}
5053

@@ -68,14 +71,19 @@ public function prepareRelatedModels(): void
6871
$this->insertImport($content, $namespace);
6972
}
7073

74+
$relationName = $this->getRelationName($this->model, $types[$type]);
75+
7176
$newRelation = $this->getStub('relation', [
72-
'name' => $this->getRelationName($this->model, $types[$type]),
77+
'name' => $relationName,
7378
'type' => $types[$type],
7479
'entity' => $this->model,
7580
]);
7681

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

85+
$this->insertPropertyAnnotation($fixedContent, $this->getRelationType($this->model, $types[$type]), $relationName);
86+
7987
$this->saveClass('models', $relation, $fixedContent);
8088
}
8189
}
@@ -93,6 +101,7 @@ protected function insertImport(string &$classContent, string $import): void
93101
$import = "use {$import};";
94102

95103
if (!Str::contains($classContent, $import)) {
104+
// TODO: use ronasit/larabuilder instead regexp
96105
$classContent = preg_replace('/(namespace\s+[^;]+;\s*)/', "$1{$import}\n", $classContent, 1);
97106
}
98107
}
@@ -182,7 +191,7 @@ protected function generateClassNamespace(string $className, ?string $folder = n
182191
return "{$path}\\{$psrPath}";
183192
}
184193

185-
protected function generateAnnotationProperties(array $fields): array
194+
protected function generateAnnotationProperties(array $fields, array $relations): array
186195
{
187196
$result = [];
188197

@@ -192,6 +201,10 @@ protected function generateAnnotationProperties(array $fields): array
192201
}
193202
}
194203

204+
foreach ($relations as $relation) {
205+
$result[$relation['name']] = $this->getRelationType($relation['entity'], $relation['type']);
206+
}
207+
195208
return $result;
196209
}
197210

@@ -231,4 +244,29 @@ protected function isRequired(string $typeName): bool
231244
{
232245
return Str::endsWith($typeName, 'required');
233246
}
247+
248+
protected function getRelationType(string $model, string $relation): string
249+
{
250+
if (in_array($relation, self::PLURAL_NUMBER_REQUIRED)) {
251+
return "Collection<{$model}>";
252+
}
253+
254+
return "{$model}|null";
255+
}
256+
257+
protected function insertPropertyAnnotation(string &$content, string $propertyDataType, string $propertyName): void
258+
{
259+
$annotation = "* @property {$propertyDataType} \${$propertyName}";
260+
261+
// TODO: use ronasit/larabuilder instead regexp
262+
if (!Str::contains($content, '/**')) {
263+
$content = preg_replace('/^\s*class[\s\S]+?\{/m', "\n/**\n {$annotation}\n */$0", $content);
264+
} else {
265+
$content = preg_replace('/\*\//m', "{$annotation}\n $0", $content);
266+
}
267+
268+
if (Str::contains($propertyDataType, 'Collection')) {
269+
$this->insertImport($content, 'Illuminate\Database\Eloquent\Collection');
270+
}
271+
}
234272
}

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: 26 additions & 3 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: ResourceNotExistsException::class,
@@ -152,7 +154,10 @@ className: SuccessCreateMessage::class,
152154
public function testCreateModelHasMultipleRelationsWithAnotherModel()
153155
{
154156
$this
155-
->artisan('make:entity Forum/Post -A User -E User --only-model')
157+
->artisan('make:entity Forum/post -A user -E /user --only-model')
158+
->expectsOutput('user was converted to User')
159+
->expectsOutput('user was converted to User')
160+
->expectsOutput('post was converted to Post')
156161
->assertSuccessful();
157162

158163
$this->assertGeneratedFileEquals('new_model_with_many_relations.php', 'app/Models/Forum/Post.php');
@@ -243,4 +248,22 @@ className: WarningEvent::class,
243248
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.',
244249
);
245250
}
251+
252+
public function testAddPropertyAnnotationToRelatedModel()
253+
{
254+
app(ModelGenerator::class)
255+
->setModel('Category')
256+
->setFields([])
257+
->setRelations(new RelationsDTO(
258+
belongsToMany: ['User'],
259+
))
260+
->generate();
261+
262+
$this->assertGeneratedFileEquals('related_model_with_property.php', 'app/Models/User.php');
263+
264+
$this->assertEventPushed(
265+
className: SuccessCreateMessage::class,
266+
message: 'Created a new Model: Category',
267+
);
268+
}
246269
}

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
{

0 commit comments

Comments
 (0)