diff --git a/src/Generators/ModelGenerator.php b/src/Generators/ModelGenerator.php index 90aab350..86651d61 100644 --- a/src/Generators/ModelGenerator.php +++ b/src/Generators/ModelGenerator.php @@ -37,15 +37,18 @@ protected function hasRelations(): bool protected function getNewModelContent(): string { + $relations = $this->prepareRelations(); + return $this->getStub('model', [ 'entity' => $this->model, 'fields' => Arr::collapse($this->fields), - 'relations' => $this->prepareRelations(), + 'relations' => $relations, 'casts' => $this->getCasts($this->fields), 'namespace' => $this->generateNamespace($this->paths['models'], $this->modelSubFolder), 'importRelations' => $this->getImportedRelations(), - 'anotationProperties' => $this->generateAnnotationProperties($this->fields), + 'annotationProperties' => $this->generateAnnotationProperties($this->fields, $relations), 'hasCarbonField' => !empty($this->fields['timestamp']) || !empty($this->fields['timestamp-required']), + 'hasCollectionType' => !empty($this->relations->hasMany) || !empty($this->relations->belongsToMany), ]); } @@ -76,14 +79,19 @@ public function prepareRelatedModels(): void $this->insertImport($content, $namespace); } + $relationName = $this->getRelationName($this->model, $types[$type]); + $newRelation = $this->getStub('relation', [ - 'name' => $this->getRelationName($this->model, $types[$type]), + 'name' => $relationName, 'type' => $types[$type], 'entity' => $this->model, ]); + // TODO: use ronasit/larabuilder instead regexp $fixedContent = preg_replace('/\}$/', "\n {$newRelation}\n}", $content); + $this->insertPropertyAnnotation($fixedContent, $this->getRelationType($this->model, $types[$type]), $relationName); + $this->saveClass('models', $relation, $fixedContent); } } @@ -101,6 +109,7 @@ protected function insertImport(string &$classContent, string $import): void $import = "use {$import};"; if (!Str::contains($classContent, $import)) { + // TODO: use ronasit/larabuilder instead regexp $classContent = preg_replace('/(namespace\s+[^;]+;\s*)/', "$1{$import}\n", $classContent, 1); } } @@ -190,7 +199,7 @@ protected function generateClassNamespace(string $className, ?string $folder = n return "{$path}\\{$psrPath}"; } - protected function generateAnnotationProperties(array $fields): array + protected function generateAnnotationProperties(array $fields, array $relations): array { $result = []; @@ -200,6 +209,10 @@ protected function generateAnnotationProperties(array $fields): array } } + foreach ($relations as $relation) { + $result[$relation['name']] = $this->getRelationType($relation['entity'], $relation['type']); + } + return $result; } @@ -239,4 +252,29 @@ protected function isRequired(string $typeName): bool { return Str::endsWith($typeName, 'required'); } + + protected function getRelationType(string $model, string $relation): string + { + if (in_array($relation, self::PLURAL_NUMBER_REQUIRED)) { + return "Collection<{$model}>"; + } + + return "{$model}|null"; + } + + protected function insertPropertyAnnotation(string &$content, string $propertyDataType, string $propertyName): void + { + $annotation = "* @property {$propertyDataType} \${$propertyName}"; + + // TODO: use ronasit/larabuilder instead regexp + if (!Str::contains($content, '/**')) { + $content = preg_replace('/^\s*class[\s\S]+?\{/m', "\n/**\n {$annotation}\n */$0", $content); + } else { + $content = preg_replace('/\*\//m', "{$annotation}\n $0", $content); + } + + if (Str::contains($propertyDataType, 'Collection')) { + $this->insertImport($content, 'Illuminate\Database\Eloquent\Collection'); + } + } } diff --git a/stubs/model.blade.php b/stubs/model.blade.php index 7384db39..844f420d 100644 --- a/stubs/model.blade.php +++ b/stubs/model.blade.php @@ -8,11 +8,14 @@ @if($hasCarbonField) use Carbon\Carbon; @endif +@if($hasCollectionType) +use Illuminate\Database\Eloquent\Collection; +@endif -@if(!empty($anotationProperties)) +@if(!empty($annotationProperties)) /** -@foreach($anotationProperties as $key => $value) - * @property {{ $value }} ${{ $key }} +@foreach($annotationProperties as $key => $value) + * @property {!! $value !!} ${{ $key }} @endforeach */ @else diff --git a/tests/ModelGeneratorTest.php b/tests/ModelGeneratorTest.php old mode 100644 new mode 100755 index a4a28765..c69cc060 --- a/tests/ModelGeneratorTest.php +++ b/tests/ModelGeneratorTest.php @@ -19,7 +19,7 @@ public function setUp(): void { parent::setUp(); - $this->mockFilesystem(); + $this->mockDefaultFilesystem(); } public function testModelAlreadyExists() @@ -41,7 +41,9 @@ className: ResourceAlreadyExistsException::class, public function testRelationModelMissing() { - $this->mockFileSystemWithoutCommentModel(); + $this->mockFilesystem([ + 'User.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'), + ]); $this->assertExceptionThrew( className: ClassNotExistsException::class, @@ -247,4 +249,22 @@ className: WarningEvent::class, 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.', ); } + + public function testAddPropertyAnnotationToRelatedModel() + { + app(ModelGenerator::class) + ->setModel('Category') + ->setFields([]) + ->setRelations(new RelationsDTO( + belongsToMany: ['User'], + )) + ->generate(); + + $this->assertGeneratedFileEquals('related_model_with_property.php', 'app/Models/User.php'); + + $this->assertEventPushed( + className: SuccessCreateMessage::class, + message: 'Created a new Model: Category', + ); + } } diff --git a/tests/Support/Model/ModelMockTrait.php b/tests/Support/Model/ModelMockTrait.php old mode 100644 new mode 100755 index f65f83a2..744569e7 --- a/tests/Support/Model/ModelMockTrait.php +++ b/tests/Support/Model/ModelMockTrait.php @@ -9,27 +9,24 @@ trait ModelMockTrait { use GeneratorMockTrait; - - public function mockFileSystemWithoutCommentModel(): void + public function mockDefaultFilesystem(): void { $fileSystemMock = new FileSystemMock(); $fileSystemMock->models = [ + 'Comment.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'), 'User.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'), + 'Forum/Author.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'), ]; $fileSystemMock->setStructure(); } - public function mockFilesystem(): void + public function mockFilesystem(array $models): void { - $fileSystemMock = new FileSystemMock; + $fileSystemMock = new FileSystemMock(); - $fileSystemMock->models = [ - 'Comment.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'), - 'User.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'), - 'Forum/Author.php' => file_get_contents(getcwd() . '/tests/Support/Models/WelcomeBonus.php'), - ]; + $fileSystemMock->models = $models; $fileSystemMock->setStructure(); } diff --git a/tests/fixtures/ModelGeneratorTest/comment_relation_model.php b/tests/fixtures/ModelGeneratorTest/comment_relation_model.php old mode 100644 new mode 100755 index 1e42f1d6..446326cf --- a/tests/fixtures/ModelGeneratorTest/comment_relation_model.php +++ b/tests/fixtures/ModelGeneratorTest/comment_relation_model.php @@ -5,6 +5,9 @@ use Illuminate\Database\Eloquent\Model; use RonasIT\Support\Traits\ModelTrait; +/** + * @property Post|null $post + */ class WelcomeBonus extends Model { use ModelTrait; diff --git a/tests/fixtures/ModelGeneratorTest/new_model.php b/tests/fixtures/ModelGeneratorTest/new_model.php old mode 100644 new mode 100755 index 739fb44a..fcf29337 --- a/tests/fixtures/ModelGeneratorTest/new_model.php +++ b/tests/fixtures/ModelGeneratorTest/new_model.php @@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Model; use RonasIT\Support\Traits\ModelTrait; use Carbon\Carbon; +use Illuminate\Database\Eloquent\Collection; /** * @property int|null $priority @@ -20,6 +21,8 @@ * @property Carbon|null $updated_at * @property Carbon $published_at * @property array $meta + * @property Comment|null $comment + * @property Collection $users */ class Post extends Model { diff --git a/tests/fixtures/ModelGeneratorTest/new_model_with_many_relations.php b/tests/fixtures/ModelGeneratorTest/new_model_with_many_relations.php old mode 100644 new mode 100755 index d7cf00e6..62dfd92d --- a/tests/fixtures/ModelGeneratorTest/new_model_with_many_relations.php +++ b/tests/fixtures/ModelGeneratorTest/new_model_with_many_relations.php @@ -5,9 +5,10 @@ use Illuminate\Database\Eloquent\Model; use RonasIT\Support\Traits\ModelTrait; use App\Models\User; +use Illuminate\Database\Eloquent\Collection; -//TODO: add @property annotation for each model's field /** + * @property Collection $users */ class Post extends Model { diff --git a/tests/fixtures/ModelGeneratorTest/new_model_with_subfolers_relations.php b/tests/fixtures/ModelGeneratorTest/new_model_with_subfolers_relations.php old mode 100644 new mode 100755 index 8205d5bf..65726408 --- a/tests/fixtures/ModelGeneratorTest/new_model_with_subfolers_relations.php +++ b/tests/fixtures/ModelGeneratorTest/new_model_with_subfolers_relations.php @@ -5,9 +5,11 @@ use Illuminate\Database\Eloquent\Model; use RonasIT\Support\Traits\ModelTrait; use App\Models\Forum\Author; +use Illuminate\Database\Eloquent\Collection; /** * @property string $title + * @property Collection $authors */ class Post extends Model { diff --git a/tests/fixtures/ModelGeneratorTest/new_subfolders_model.php b/tests/fixtures/ModelGeneratorTest/new_subfolders_model.php old mode 100644 new mode 100755 index 5a21ccd0..633820fb --- a/tests/fixtures/ModelGeneratorTest/new_subfolders_model.php +++ b/tests/fixtures/ModelGeneratorTest/new_subfolders_model.php @@ -7,6 +7,7 @@ use App\Models\Comment; use App\Models\User; use Carbon\Carbon; +use Illuminate\Database\Eloquent\Collection; /** * @property int|null $priority @@ -22,6 +23,8 @@ * @property Carbon|null $updated_at * @property Carbon $published_at * @property array $meta + * @property Comment|null $comment + * @property Collection $users */ class Post extends Model { diff --git a/tests/fixtures/ModelGeneratorTest/related_model_with_property.php b/tests/fixtures/ModelGeneratorTest/related_model_with_property.php new file mode 100755 index 00000000..d90fe6c0 --- /dev/null +++ b/tests/fixtures/ModelGeneratorTest/related_model_with_property.php @@ -0,0 +1,34 @@ + $categories + */ +class WelcomeBonus extends Model +{ + use ModelTrait; + + public function getConnectionName(): string + { + return 'pgsql'; + } + + protected $fillable = [ + 'title', + 'name', + ]; + + public function some_relation() + { + } + + public function categories() + { + return $this->belongsToMany(Category::class); + } +} \ No newline at end of file