From 1540fe4939f37bb325b84b59491632b9db795503 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 21 Nov 2024 16:15:31 +0600 Subject: [PATCH 01/15] feat: Use reflection to detect model relations refs: https://github.com/RonasIT/laravel-entity-generator/issues/50 --- src/Generators/AbstractTestsGenerator.php | 51 +++++++++++++++++------ src/Generators/FactoryGenerator.php | 51 +++++++++++++++++------ 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/src/Generators/AbstractTestsGenerator.php b/src/Generators/AbstractTestsGenerator.php index 780f889d..c944be4d 100644 --- a/src/Generators/AbstractTestsGenerator.php +++ b/src/Generators/AbstractTestsGenerator.php @@ -4,11 +4,15 @@ use DateTime; use Illuminate\Database\Eloquent\Factory as LegacyFactories; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Arr; use Illuminate\Support\Str; use RonasIT\Support\Events\SuccessCreateMessage; use RonasIT\Support\Exceptions\CircularRelationsFoundedException; +use ReflectionClass; +use ReflectionMethod; use RonasIT\Support\Exceptions\ClassNotExistsException; +use Throwable; abstract class AbstractTestsGenerator extends EntityGenerator { @@ -242,20 +246,11 @@ protected function buildRelationsTree($models): array return array_unique($models); } - protected function getRelatedModels($model) + protected function getRelatedModels($model): array { - $content = $this->getModelClassContent($model); + $class = $this->getModelClass($model); - preg_match_all('/(?<=belongsTo\().*(?=::class)/', $content, $matches); - - return head($matches); - } - - protected function getModelClassContent($model): string - { - $path = base_path("{$this->paths['models']}/{$model}.php"); - - if (!$this->classExists('models', $model)) { + if (!class_exists($this->getModelClass($model))) { $this->throwFailureException( ClassNotExistsException::class, "Cannot create {$model} Model cause {$model} Model does not exists.", @@ -263,7 +258,37 @@ protected function getModelClassContent($model): string ); } - return file_get_contents($path); + $instance = new $class(); + + $publicMethods = (new ReflectionClass($class))->getMethods(ReflectionMethod::IS_PUBLIC); + + $methods = array_filter($publicMethods, fn ($method) => + $method->class === $class + && !$method->getParameters() + && $method->getName() !== 'getRelationships' + ); + + $relatedModels = []; + + foreach ($methods as $method) { + try { + $methodName = $method->getName(); + + $methodReturn = $instance->$methodName(); + + if (!$methodReturn instanceof BelongsTo) { + continue; + } + } catch (Throwable) { + continue; + } + + $relationModel = get_class($methodReturn->getRelated()); + + $relatedModels[] = class_basename($relationModel); + } + + return $relatedModels; } protected function canGenerateUserData(): bool diff --git a/src/Generators/FactoryGenerator.php b/src/Generators/FactoryGenerator.php index f0a9b6a4..9d3672d2 100644 --- a/src/Generators/FactoryGenerator.php +++ b/src/Generators/FactoryGenerator.php @@ -3,6 +3,7 @@ namespace RonasIT\Support\Generators; use Faker\Generator as Faker; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Arr; use Illuminate\Support\Str; use RonasIT\Support\Exceptions\ModelFactoryNotFound; @@ -11,6 +12,9 @@ use RonasIT\Support\Exceptions\ClassAlreadyExistsException; use RonasIT\Support\Events\SuccessCreateMessage; use Exception; +use ReflectionClass; +use ReflectionMethod; +use Throwable; class FactoryGenerator extends EntityGenerator { @@ -246,20 +250,11 @@ protected function getModelClass($model): string return "{$modelNamespace}\\{$model}"; } - protected function getRelatedModels($model) + protected function getRelatedModels($model): array { - $content = $this->getModelClassContent($model); + $class = $this->getModelClass($model); - preg_match_all('/(?<=belongsTo\().*(?=::class)/', $content, $matches); - - return head($matches); - } - - protected function getModelClassContent($model): string - { - $path = base_path("{$this->paths['models']}/{$model}.php"); - - if (!$this->classExists('models', $model)) { + if (!class_exists($this->getModelClass($model))) { $this->throwFailureException( ClassNotExistsException::class, "Cannot create {$model} Model cause {$model} Model does not exists.", @@ -267,6 +262,36 @@ protected function getModelClassContent($model): string ); } - return file_get_contents($path); + $instance = new $class(); + + $publicMethods = (new ReflectionClass($class))->getMethods(ReflectionMethod::IS_PUBLIC); + + $methods = array_filter($publicMethods, fn ($method) => + $method->class === $class + && !$method->getParameters() + && $method->getName() !== 'getRelationships' + ); + + $relatedModels = []; + + foreach ($methods as $method) { + try { + $methodName = $method->getName(); + + $methodReturn = $instance->$methodName(); + + if (!$methodReturn instanceof BelongsTo) { + continue; + } + } catch (Throwable) { + continue; + } + + $relationModel = get_class($methodReturn->getRelated()); + + $relatedModels[] = class_basename($relationModel); + } + + return $relatedModels; } } From eec1fc5c8601350eec26a72b30ad86f07e077445 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 21 Nov 2024 17:39:55 +0600 Subject: [PATCH 02/15] fix: tests refs: https://github.com/RonasIT/laravel-entity-generator/issues/50 --- src/Generators/AbstractTestsGenerator.php | 2 +- src/Generators/FactoryGenerator.php | 2 +- tests/NovaTestGeneratorTest.php | 11 ++++++++++- tests/Support/GeneratorMockTrait.php | 22 +++++++++++++--------- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/Generators/AbstractTestsGenerator.php b/src/Generators/AbstractTestsGenerator.php index c944be4d..ec405264 100644 --- a/src/Generators/AbstractTestsGenerator.php +++ b/src/Generators/AbstractTestsGenerator.php @@ -250,7 +250,7 @@ protected function getRelatedModels($model): array { $class = $this->getModelClass($model); - if (!class_exists($this->getModelClass($model))) { + if (!class_exists($class)) { $this->throwFailureException( ClassNotExistsException::class, "Cannot create {$model} Model cause {$model} Model does not exists.", diff --git a/src/Generators/FactoryGenerator.php b/src/Generators/FactoryGenerator.php index 9d3672d2..0b3b0315 100644 --- a/src/Generators/FactoryGenerator.php +++ b/src/Generators/FactoryGenerator.php @@ -254,7 +254,7 @@ protected function getRelatedModels($model): array { $class = $this->getModelClass($model); - if (!class_exists($this->getModelClass($model))) { + if (!class_exists($class)) { $this->throwFailureException( ClassNotExistsException::class, "Cannot create {$model} Model cause {$model} Model does not exists.", diff --git a/tests/NovaTestGeneratorTest.php b/tests/NovaTestGeneratorTest.php index 3159b47e..2a763eb2 100644 --- a/tests/NovaTestGeneratorTest.php +++ b/tests/NovaTestGeneratorTest.php @@ -2,12 +2,14 @@ namespace RonasIT\Support\Tests; +use App\Models\WelcomeBonus; use Illuminate\Support\Facades\Event; use RonasIT\Support\Events\SuccessCreateMessage; use RonasIT\Support\Exceptions\ClassAlreadyExistsException; use RonasIT\Support\Exceptions\ClassNotExistsException; use RonasIT\Support\Generators\NovaTestGenerator; use RonasIT\Support\Tests\Support\NovaTestGeneratorTest\NovaTestGeneratorMockTrait; +use Laravel\Nova\NovaServiceProvider; class NovaTestGeneratorTest extends TestCase { @@ -54,7 +56,14 @@ className: ClassAlreadyExistsException::class, public function testSuccess() { - $this->mockNovaServiceProviderExists(); + $this->mockClassExistsFunction( + [ + 'class' => NovaServiceProvider::class, + ], + [ + 'class' => WelcomeBonus::class, + ], + ); $this->mockFilesystem(); $this->mockNovaRequestClassCall(); diff --git a/tests/Support/GeneratorMockTrait.php b/tests/Support/GeneratorMockTrait.php index f40e718b..a94b9370 100644 --- a/tests/Support/GeneratorMockTrait.php +++ b/tests/Support/GeneratorMockTrait.php @@ -2,24 +2,28 @@ namespace RonasIT\Support\Tests\Support; +use Illuminate\Support\Arr; use Laravel\Nova\NovaServiceProvider; trait GeneratorMockTrait { - public function mockClassExistsFunction(string $className, bool $result = true, bool $autoloadArg = true): void + public function mockClassExistsFunction(...$rawCallChain): void { - $this->mockNativeFunction('\RonasIT\Support\Generators', [ - $this->functionCall( - name: 'class_exists', - arguments: [$className, $autoloadArg], - result: $result, - ), - ]); + $callChain = array_map(fn ($call) => $this->functionCall( + name: 'class_exists', + arguments: [$call['class'], true], + result: Arr::get($call, 'result', true), + ), $rawCallChain); + + $this->mockNativeFunction('\RonasIT\Support\Generators', $callChain); } public function mockNovaServiceProviderExists(bool $result = true): void { - $this->mockClassExistsFunction(NovaServiceProvider::class, $result); + $this->mockClassExistsFunction([ + 'class' => NovaServiceProvider::class, + 'result' => $result, + ]); } public function classExistsMethodCall(array $arguments, bool $result = true): array From 82e5640807cafad438dad0b0cb2de125180fa696 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 21 Nov 2024 19:41:41 +0600 Subject: [PATCH 03/15] feat: add transaction refs: https://github.com/RonasIT/laravel-entity-generator/issues/50 --- src/Generators/AbstractTestsGenerator.php | 5 +++++ src/Generators/FactoryGenerator.php | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/Generators/AbstractTestsGenerator.php b/src/Generators/AbstractTestsGenerator.php index ec405264..bcab7a34 100644 --- a/src/Generators/AbstractTestsGenerator.php +++ b/src/Generators/AbstractTestsGenerator.php @@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Factory as LegacyFactories; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use RonasIT\Support\Events\SuccessCreateMessage; use RonasIT\Support\Exceptions\CircularRelationsFoundedException; @@ -270,6 +271,8 @@ protected function getRelatedModels($model): array $relatedModels = []; + DB::beginTransaction(); + foreach ($methods as $method) { try { $methodName = $method->getName(); @@ -288,6 +291,8 @@ protected function getRelatedModels($model): array $relatedModels[] = class_basename($relationModel); } + DB::rollBack(); + return $relatedModels; } diff --git a/src/Generators/FactoryGenerator.php b/src/Generators/FactoryGenerator.php index 0b3b0315..b4a0a090 100644 --- a/src/Generators/FactoryGenerator.php +++ b/src/Generators/FactoryGenerator.php @@ -5,6 +5,7 @@ use Faker\Generator as Faker; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use RonasIT\Support\Exceptions\ModelFactoryNotFound; use RonasIT\Support\Exceptions\ClassNotExistsException; @@ -274,6 +275,8 @@ protected function getRelatedModels($model): array $relatedModels = []; + DB::beginTransaction(); + foreach ($methods as $method) { try { $methodName = $method->getName(); @@ -292,6 +295,8 @@ protected function getRelatedModels($model): array $relatedModels[] = class_basename($relationModel); } + DB::rollBack(); + return $relatedModels; } } From ea354c214b93ba5593f65b2ab1f43c61524fd5b8 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 22 Nov 2024 10:44:11 +0600 Subject: [PATCH 04/15] fix: tests refs: https://github.com/RonasIT/laravel-entity-generator/issues/50 --- src/Generators/AbstractTestsGenerator.php | 6 +----- src/Generators/FactoryGenerator.php | 6 +----- tests/NovaTestGeneratorTest.php | 6 ++++++ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/Generators/AbstractTestsGenerator.php b/src/Generators/AbstractTestsGenerator.php index bcab7a34..422a861f 100644 --- a/src/Generators/AbstractTestsGenerator.php +++ b/src/Generators/AbstractTestsGenerator.php @@ -263,11 +263,7 @@ protected function getRelatedModels($model): array $publicMethods = (new ReflectionClass($class))->getMethods(ReflectionMethod::IS_PUBLIC); - $methods = array_filter($publicMethods, fn ($method) => - $method->class === $class - && !$method->getParameters() - && $method->getName() !== 'getRelationships' - ); + $methods = array_filter($publicMethods, fn ($method) => $method->class === $class && !$method->getParameters()); $relatedModels = []; diff --git a/src/Generators/FactoryGenerator.php b/src/Generators/FactoryGenerator.php index b4a0a090..130dbdf0 100644 --- a/src/Generators/FactoryGenerator.php +++ b/src/Generators/FactoryGenerator.php @@ -267,11 +267,7 @@ protected function getRelatedModels($model): array $publicMethods = (new ReflectionClass($class))->getMethods(ReflectionMethod::IS_PUBLIC); - $methods = array_filter($publicMethods, fn ($method) => - $method->class === $class - && !$method->getParameters() - && $method->getName() !== 'getRelationships' - ); + $methods = array_filter($publicMethods, fn ($method) => $method->class === $class && !$method->getParameters()); $relatedModels = []; diff --git a/tests/NovaTestGeneratorTest.php b/tests/NovaTestGeneratorTest.php index 2a763eb2..9139db52 100644 --- a/tests/NovaTestGeneratorTest.php +++ b/tests/NovaTestGeneratorTest.php @@ -10,6 +10,7 @@ use RonasIT\Support\Generators\NovaTestGenerator; use RonasIT\Support\Tests\Support\NovaTestGeneratorTest\NovaTestGeneratorMockTrait; use Laravel\Nova\NovaServiceProvider; +use Mockery; class NovaTestGeneratorTest extends TestCase { @@ -56,6 +57,11 @@ className: ClassAlreadyExistsException::class, public function testSuccess() { + $mock = Mockery::mock('alias:Illuminate\Support\Facades\DB'); + $mock + ->shouldReceive('beginTransaction', 'rollBack') + ->once(); + $this->mockClassExistsFunction( [ 'class' => NovaServiceProvider::class, From cae2ef3858be95557f50d654e5d0599f43c15d80 Mon Sep 17 00:00:00 2001 From: roman Date: Fri, 22 Nov 2024 10:57:10 +0600 Subject: [PATCH 05/15] feat: add argument type refs: https://github.com/RonasIT/laravel-entity-generator/issues/50 --- src/Generators/AbstractTestsGenerator.php | 2 +- src/Generators/FactoryGenerator.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Generators/AbstractTestsGenerator.php b/src/Generators/AbstractTestsGenerator.php index 422a861f..6e1a5281 100644 --- a/src/Generators/AbstractTestsGenerator.php +++ b/src/Generators/AbstractTestsGenerator.php @@ -247,7 +247,7 @@ protected function buildRelationsTree($models): array return array_unique($models); } - protected function getRelatedModels($model): array + protected function getRelatedModels(string $model): array { $class = $this->getModelClass($model); diff --git a/src/Generators/FactoryGenerator.php b/src/Generators/FactoryGenerator.php index 130dbdf0..10aa5cc9 100644 --- a/src/Generators/FactoryGenerator.php +++ b/src/Generators/FactoryGenerator.php @@ -251,7 +251,7 @@ protected function getModelClass($model): string return "{$modelNamespace}\\{$model}"; } - protected function getRelatedModels($model): array + protected function getRelatedModels(string $model): array { $class = $this->getModelClass($model); From d677caa887168e7d562414dc0f531eb108ae231f Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 26 Nov 2024 11:06:30 +0600 Subject: [PATCH 06/15] refactor: code refs: https://github.com/RonasIT/laravel-entity-generator/issues/50 --- src/Generators/AbstractTestsGenerator.php | 47 +------------------- src/Generators/EntityGenerator.php | 51 ++++++++++++++++++++++ src/Generators/FactoryGenerator.php | 52 +---------------------- 3 files changed, 53 insertions(+), 97 deletions(-) diff --git a/src/Generators/AbstractTestsGenerator.php b/src/Generators/AbstractTestsGenerator.php index 6e1a5281..fd819eb1 100644 --- a/src/Generators/AbstractTestsGenerator.php +++ b/src/Generators/AbstractTestsGenerator.php @@ -224,7 +224,7 @@ protected function generateFixture($fixtureName, $data): void protected function buildRelationsTree($models): array { foreach ($models as $model) { - $relations = $this->getRelatedModels($model); + $relations = $this->getRelatedModels($model, 'Test'); $relationsWithFactories = $this->getModelsWithFactories($relations); if (empty($relationsWithFactories)) { @@ -247,51 +247,6 @@ protected function buildRelationsTree($models): array return array_unique($models); } - protected function getRelatedModels(string $model): array - { - $class = $this->getModelClass($model); - - if (!class_exists($class)) { - $this->throwFailureException( - ClassNotExistsException::class, - "Cannot create {$model} Model cause {$model} Model does not exists.", - "Create a {$model} Model by himself or run command 'php artisan make:entity {$model} --only-model'." - ); - } - - $instance = new $class(); - - $publicMethods = (new ReflectionClass($class))->getMethods(ReflectionMethod::IS_PUBLIC); - - $methods = array_filter($publicMethods, fn ($method) => $method->class === $class && !$method->getParameters()); - - $relatedModels = []; - - DB::beginTransaction(); - - foreach ($methods as $method) { - try { - $methodName = $method->getName(); - - $methodReturn = $instance->$methodName(); - - if (!$methodReturn instanceof BelongsTo) { - continue; - } - } catch (Throwable) { - continue; - } - - $relationModel = get_class($methodReturn->getRelated()); - - $relatedModels[] = class_basename($relationModel); - } - - DB::rollBack(); - - return $relatedModels; - } - protected function canGenerateUserData(): bool { return $this->classExists('models', 'User') diff --git a/src/Generators/EntityGenerator.php b/src/Generators/EntityGenerator.php index 7d62c35a..8670e8c0 100644 --- a/src/Generators/EntityGenerator.php +++ b/src/Generators/EntityGenerator.php @@ -2,9 +2,15 @@ namespace RonasIT\Support\Generators; +use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; +use RonasIT\Support\Exceptions\ClassNotExistsException; +use Throwable; +use ReflectionMethod; +use ReflectionClass; /** * @property Filesystem $fs @@ -157,4 +163,49 @@ protected function throwFailureException($exceptionClass, $failureMessage, $reco { throw new $exceptionClass("{$failureMessage} {$recommendedMessage}"); } + + protected function getRelatedModels(string $model, string $classType): array + { + $class = $this->getModelClass($model); + + if (!class_exists($class)) { + $this->throwFailureException( + ClassNotExistsException::class, + "Cannot create {$model}{$classType} cause {$model} Model does not exists.", + "Create a {$model} Model by himself or run command 'php artisan make:entity {$model} --only-model'." + ); + } + + $instance = new $class(); + + $publicMethods = (new ReflectionClass($class))->getMethods(ReflectionMethod::IS_PUBLIC); + + $methods = array_filter($publicMethods, fn ($method) => $method->class === $class && !$method->getParameters()); + + $relatedModels = []; + + DB::beginTransaction(); + + foreach ($methods as $method) { + try { + $methodName = $method->getName(); + + $methodReturn = $instance->$methodName(); + + if (!$methodReturn instanceof BelongsTo) { + continue; + } + } catch (Throwable) { + continue; + } + + $relationModel = get_class($methodReturn->getRelated()); + + $relatedModels[] = class_basename($relationModel); + } + + DB::rollBack(); + + return $relatedModels; + } } diff --git a/src/Generators/FactoryGenerator.php b/src/Generators/FactoryGenerator.php index 10aa5cc9..4ae01174 100644 --- a/src/Generators/FactoryGenerator.php +++ b/src/Generators/FactoryGenerator.php @@ -3,9 +3,7 @@ namespace RonasIT\Support\Generators; use Faker\Generator as Faker; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Arr; -use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use RonasIT\Support\Exceptions\ModelFactoryNotFound; use RonasIT\Support\Exceptions\ClassNotExistsException; @@ -13,9 +11,6 @@ use RonasIT\Support\Exceptions\ClassAlreadyExistsException; use RonasIT\Support\Events\SuccessCreateMessage; use Exception; -use ReflectionClass; -use ReflectionMethod; -use Throwable; class FactoryGenerator extends EntityGenerator { @@ -117,7 +112,7 @@ protected function prepareEmptyFactory(): void protected function checkExistRelatedModelsFactories(): bool { $modelFactoryContent = file_get_contents($this->paths['factory']); - $relatedModels = $this->getRelatedModels($this->model); + $relatedModels = $this->getRelatedModels($this->model, 'Factory'); $modelNamespace = $this->getOrCreateNamespace('models'); foreach ($relatedModels as $relatedModel) { @@ -250,49 +245,4 @@ protected function getModelClass($model): string return "{$modelNamespace}\\{$model}"; } - - protected function getRelatedModels(string $model): array - { - $class = $this->getModelClass($model); - - if (!class_exists($class)) { - $this->throwFailureException( - ClassNotExistsException::class, - "Cannot create {$model} Model cause {$model} Model does not exists.", - "Create a {$model} Model by himself or run command 'php artisan make:entity {$model} --only-model'." - ); - } - - $instance = new $class(); - - $publicMethods = (new ReflectionClass($class))->getMethods(ReflectionMethod::IS_PUBLIC); - - $methods = array_filter($publicMethods, fn ($method) => $method->class === $class && !$method->getParameters()); - - $relatedModels = []; - - DB::beginTransaction(); - - foreach ($methods as $method) { - try { - $methodName = $method->getName(); - - $methodReturn = $instance->$methodName(); - - if (!$methodReturn instanceof BelongsTo) { - continue; - } - } catch (Throwable) { - continue; - } - - $relationModel = get_class($methodReturn->getRelated()); - - $relatedModels[] = class_basename($relationModel); - } - - DB::rollBack(); - - return $relatedModels; - } } From 31857aa339f3336f993aaca3457a596bc9a3cf33 Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 26 Nov 2024 11:14:03 +0600 Subject: [PATCH 07/15] refactor: code refs: https://github.com/RonasIT/laravel-entity-generator/issues/50 --- src/Generators/AbstractTestsGenerator.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Generators/AbstractTestsGenerator.php b/src/Generators/AbstractTestsGenerator.php index fd819eb1..1125fa74 100644 --- a/src/Generators/AbstractTestsGenerator.php +++ b/src/Generators/AbstractTestsGenerator.php @@ -4,16 +4,10 @@ use DateTime; use Illuminate\Database\Eloquent\Factory as LegacyFactories; -use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Support\Arr; -use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use RonasIT\Support\Events\SuccessCreateMessage; use RonasIT\Support\Exceptions\CircularRelationsFoundedException; -use ReflectionClass; -use ReflectionMethod; -use RonasIT\Support\Exceptions\ClassNotExistsException; -use Throwable; abstract class AbstractTestsGenerator extends EntityGenerator { From 620041e056a8671a0120d47e02a3c7d10537514b Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 26 Nov 2024 14:14:19 +0600 Subject: [PATCH 08/15] refactor: code refs: https://github.com/RonasIT/laravel-entity-generator/issues/50 --- src/Generators/AbstractTestsGenerator.php | 2 +- src/Generators/EntityGenerator.php | 14 +++++++------- src/Generators/FactoryGenerator.php | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Generators/AbstractTestsGenerator.php b/src/Generators/AbstractTestsGenerator.php index 1125fa74..b842c594 100644 --- a/src/Generators/AbstractTestsGenerator.php +++ b/src/Generators/AbstractTestsGenerator.php @@ -218,7 +218,7 @@ protected function generateFixture($fixtureName, $data): void protected function buildRelationsTree($models): array { foreach ($models as $model) { - $relations = $this->getRelatedModels($model, 'Test'); + $relations = $this->getRelatedModels($model, $this->getTestClassName()); $relationsWithFactories = $this->getModelsWithFactories($relations); if (empty($relationsWithFactories)) { diff --git a/src/Generators/EntityGenerator.php b/src/Generators/EntityGenerator.php index 8670e8c0..354db3ee 100644 --- a/src/Generators/EntityGenerator.php +++ b/src/Generators/EntityGenerator.php @@ -164,23 +164,23 @@ protected function throwFailureException($exceptionClass, $failureMessage, $reco throw new $exceptionClass("{$failureMessage} {$recommendedMessage}"); } - protected function getRelatedModels(string $model, string $classType): array + protected function getRelatedModels(string $model, string $creatableClass): array { - $class = $this->getModelClass($model); + $modelClass = $this->getModelClass($model); - if (!class_exists($class)) { + if (!class_exists($modelClass)) { $this->throwFailureException( ClassNotExistsException::class, - "Cannot create {$model}{$classType} cause {$model} Model does not exists.", + "Cannot create {$creatableClass} cause {$model} Model does not exists.", "Create a {$model} Model by himself or run command 'php artisan make:entity {$model} --only-model'." ); } - $instance = new $class(); + $instance = new $modelClass(); - $publicMethods = (new ReflectionClass($class))->getMethods(ReflectionMethod::IS_PUBLIC); + $publicMethods = (new ReflectionClass($modelClass))->getMethods(ReflectionMethod::IS_PUBLIC); - $methods = array_filter($publicMethods, fn ($method) => $method->class === $class && !$method->getParameters()); + $methods = array_filter($publicMethods, fn ($method) => $method->class === $modelClass && !$method->getParameters()); $relatedModels = []; diff --git a/src/Generators/FactoryGenerator.php b/src/Generators/FactoryGenerator.php index 4ae01174..ebd829d2 100644 --- a/src/Generators/FactoryGenerator.php +++ b/src/Generators/FactoryGenerator.php @@ -112,7 +112,7 @@ protected function prepareEmptyFactory(): void protected function checkExistRelatedModelsFactories(): bool { $modelFactoryContent = file_get_contents($this->paths['factory']); - $relatedModels = $this->getRelatedModels($this->model, 'Factory'); + $relatedModels = $this->getRelatedModels($this->model, "{$this->model}Factory"); $modelNamespace = $this->getOrCreateNamespace('models'); foreach ($relatedModels as $relatedModel) { From 49d1d5bcbb4cd25a7c9964eff562635bc8ced029 Mon Sep 17 00:00:00 2001 From: roman Date: Tue, 26 Nov 2024 14:21:07 +0600 Subject: [PATCH 09/15] refactor: code refs: https://github.com/RonasIT/laravel-entity-generator/issues/50 --- src/Generators/EntityGenerator.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Generators/EntityGenerator.php b/src/Generators/EntityGenerator.php index 354db3ee..9c7bd6e5 100644 --- a/src/Generators/EntityGenerator.php +++ b/src/Generators/EntityGenerator.php @@ -170,9 +170,9 @@ protected function getRelatedModels(string $model, string $creatableClass): arra if (!class_exists($modelClass)) { $this->throwFailureException( - ClassNotExistsException::class, - "Cannot create {$creatableClass} cause {$model} Model does not exists.", - "Create a {$model} Model by himself or run command 'php artisan make:entity {$model} --only-model'." + exceptionClass: ClassNotExistsException::class, + failureMessage: "Cannot create {$creatableClass} cause {$model} Model does not exists.", + recommendedMessage: "Create a {$model} Model by himself or run command 'php artisan make:entity {$model} --only-model'.", ); } From f397ce6e0d896836c2f8dc2eea5e114240844f74 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 28 Nov 2024 11:00:40 +0600 Subject: [PATCH 10/15] refactor: get model namespace from path refs: https://github.com/RonasIT/laravel-entity-generator/issues/100 --- composer.json | 1 - src/Generators/AbstractTestsGenerator.php | 40 ++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 66949218..25c8ad02 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,6 @@ "psr-4": { "RonasIT\\Support\\Tests\\": "tests/", "RonasIT\\Support\\Tests\\Support\\": "tests/Support/", - "App\\Models\\": "tests/Support/Models/", "App\\Nova\\": "tests/Support/Nova/" }, "files": [ diff --git a/src/Generators/AbstractTestsGenerator.php b/src/Generators/AbstractTestsGenerator.php index b842c594..55ac397a 100644 --- a/src/Generators/AbstractTestsGenerator.php +++ b/src/Generators/AbstractTestsGenerator.php @@ -163,7 +163,9 @@ protected function buildEntityObject($model): array protected function getModelClass($model): string { - return "App\\Models\\{$model}"; + $path = "{$this->paths['models']}/{$model}"; + + return Str::ucfirst(str_replace('/', '\\', trim($path, '/'))); } protected function getModelFields($model): array @@ -262,4 +264,40 @@ private function filterBadModelField($fields): array self::UPDATED_AT, ]); } + + public function extractNamespace(string $file) : string + { + $contents = file_exists($file) ? file_get_contents($file) : $file; + $namespace = $class = ''; + $getting_namespace = $getting_class = false; + + foreach (token_get_all($contents) as $token) { + + if (is_array($token) && $token[0] == T_NAMESPACE) { + $getting_namespace = true; + } + + if (is_array($token) && $token[0] == T_CLASS) { + $getting_class = true; + } + + // While we're grabbing the namespace name... + if ($getting_namespace === true) { + if (is_array($token) && in_array($token[0], [T_STRING, T_NS_SEPARATOR])) { + $namespace .= $token[1]; + } else if ($token === ';') { + $getting_namespace = false; + } + } + + if ($getting_class === true) { + if (is_array($token) && $token[0] == T_STRING) { + $class = $token[1]; + break; + } + } + } + + return $namespace ? $namespace . '\\' . $class : $class; + } } From 540e864e438240bd7c3cd4754d6f93499d1b3ad2 Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 28 Nov 2024 15:14:14 +0600 Subject: [PATCH 11/15] fix: code refs: https://github.com/RonasIT/laravel-entity-generator/issues/100 --- composer.json | 1 + src/Generators/AbstractTestsGenerator.php | 36 ----------------------- 2 files changed, 1 insertion(+), 36 deletions(-) diff --git a/composer.json b/composer.json index 25c8ad02..66949218 100644 --- a/composer.json +++ b/composer.json @@ -38,6 +38,7 @@ "psr-4": { "RonasIT\\Support\\Tests\\": "tests/", "RonasIT\\Support\\Tests\\Support\\": "tests/Support/", + "App\\Models\\": "tests/Support/Models/", "App\\Nova\\": "tests/Support/Nova/" }, "files": [ diff --git a/src/Generators/AbstractTestsGenerator.php b/src/Generators/AbstractTestsGenerator.php index 55ac397a..a6473702 100644 --- a/src/Generators/AbstractTestsGenerator.php +++ b/src/Generators/AbstractTestsGenerator.php @@ -264,40 +264,4 @@ private function filterBadModelField($fields): array self::UPDATED_AT, ]); } - - public function extractNamespace(string $file) : string - { - $contents = file_exists($file) ? file_get_contents($file) : $file; - $namespace = $class = ''; - $getting_namespace = $getting_class = false; - - foreach (token_get_all($contents) as $token) { - - if (is_array($token) && $token[0] == T_NAMESPACE) { - $getting_namespace = true; - } - - if (is_array($token) && $token[0] == T_CLASS) { - $getting_class = true; - } - - // While we're grabbing the namespace name... - if ($getting_namespace === true) { - if (is_array($token) && in_array($token[0], [T_STRING, T_NS_SEPARATOR])) { - $namespace .= $token[1]; - } else if ($token === ';') { - $getting_namespace = false; - } - } - - if ($getting_class === true) { - if (is_array($token) && $token[0] == T_STRING) { - $class = $token[1]; - break; - } - } - } - - return $namespace ? $namespace . '\\' . $class : $class; - } } From 190ec0da31b40c27e7dccf19cc5d863805a586db Mon Sep 17 00:00:00 2001 From: roman Date: Thu, 28 Nov 2024 16:36:20 +0600 Subject: [PATCH 12/15] refactor: code refs: https://github.com/RonasIT/laravel-entity-generator/issues/50 --- tests/NovaTestGeneratorTest.php | 10 +++------- tests/Support/GeneratorMockTrait.php | 27 ++++++++++++++------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/tests/NovaTestGeneratorTest.php b/tests/NovaTestGeneratorTest.php index 9139db52..5356e61b 100644 --- a/tests/NovaTestGeneratorTest.php +++ b/tests/NovaTestGeneratorTest.php @@ -62,13 +62,9 @@ public function testSuccess() ->shouldReceive('beginTransaction', 'rollBack') ->once(); - $this->mockClassExistsFunction( - [ - 'class' => NovaServiceProvider::class, - ], - [ - 'class' => WelcomeBonus::class, - ], + $this->mockNativeGeneratorFunctions( + $this->nativeClassExistsMethodCall([NovaServiceProvider::class, true]), + $this->nativeClassExistsMethodCall([WelcomeBonus::class, true]), ); $this->mockFilesystem(); diff --git a/tests/Support/GeneratorMockTrait.php b/tests/Support/GeneratorMockTrait.php index a94b9370..5933ed8d 100644 --- a/tests/Support/GeneratorMockTrait.php +++ b/tests/Support/GeneratorMockTrait.php @@ -2,28 +2,20 @@ namespace RonasIT\Support\Tests\Support; -use Illuminate\Support\Arr; use Laravel\Nova\NovaServiceProvider; trait GeneratorMockTrait { - public function mockClassExistsFunction(...$rawCallChain): void + public function mockNativeGeneratorFunctions(...$functionCalls): void { - $callChain = array_map(fn ($call) => $this->functionCall( - name: 'class_exists', - arguments: [$call['class'], true], - result: Arr::get($call, 'result', true), - ), $rawCallChain); - - $this->mockNativeFunction('\RonasIT\Support\Generators', $callChain); + $this->mockNativeFunction('\RonasIT\Support\Generators', $functionCalls); } public function mockNovaServiceProviderExists(bool $result = true): void { - $this->mockClassExistsFunction([ - 'class' => NovaServiceProvider::class, - 'result' => $result, - ]); + $this->mockNativeGeneratorFunctions( + $this->nativeClassExistsMethodCall([NovaServiceProvider::class, true], $result), + ); } public function classExistsMethodCall(array $arguments, bool $result = true): array @@ -35,6 +27,15 @@ public function classExistsMethodCall(array $arguments, bool $result = true): ar ]; } + public function nativeClassExistsMethodCall(array $arguments, bool $result = true): array + { + return [ + 'function' => 'class_exists', + 'arguments' => $arguments, + 'result' => $result, + ]; + } + public function mockPhpFileContent(): string { return ' Date: Fri, 29 Nov 2024 12:56:54 +0600 Subject: [PATCH 13/15] refactor: code refs: https://github.com/RonasIT/laravel-entity-generator/issues/100 --- composer.json | 1 - tests/NovaTestGeneratorTest.php | 6 +++++- tests/Support/Models/WelcomeBonus.php | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 66949218..25c8ad02 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,6 @@ "psr-4": { "RonasIT\\Support\\Tests\\": "tests/", "RonasIT\\Support\\Tests\\Support\\": "tests/Support/", - "App\\Models\\": "tests/Support/Models/", "App\\Nova\\": "tests/Support/Nova/" }, "files": [ diff --git a/tests/NovaTestGeneratorTest.php b/tests/NovaTestGeneratorTest.php index 5356e61b..c1ebeccc 100644 --- a/tests/NovaTestGeneratorTest.php +++ b/tests/NovaTestGeneratorTest.php @@ -2,7 +2,7 @@ namespace RonasIT\Support\Tests; -use App\Models\WelcomeBonus; +use RonasIT\Support\Tests\Support\Models\WelcomeBonus; use Illuminate\Support\Facades\Event; use RonasIT\Support\Events\SuccessCreateMessage; use RonasIT\Support\Exceptions\ClassAlreadyExistsException; @@ -57,6 +57,10 @@ className: ClassAlreadyExistsException::class, public function testSuccess() { + config([ + 'entity-generator.paths.models' => 'RonasIT/Support/Tests/Support/Models', + ]); + $mock = Mockery::mock('alias:Illuminate\Support\Facades\DB'); $mock ->shouldReceive('beginTransaction', 'rollBack') diff --git a/tests/Support/Models/WelcomeBonus.php b/tests/Support/Models/WelcomeBonus.php index bf20ee9b..dcc84688 100644 --- a/tests/Support/Models/WelcomeBonus.php +++ b/tests/Support/Models/WelcomeBonus.php @@ -1,6 +1,6 @@ Date: Fri, 29 Nov 2024 13:40:51 +0600 Subject: [PATCH 14/15] refactor: code refs: https://github.com/RonasIT/laravel-entity-generator/issues/100 --- src/Generators/AbstractTestsGenerator.php | 7 ------- src/Generators/EntityGenerator.php | 7 +++++++ src/Generators/FactoryGenerator.php | 7 ------- 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/Generators/AbstractTestsGenerator.php b/src/Generators/AbstractTestsGenerator.php index a6473702..46dc0e1c 100644 --- a/src/Generators/AbstractTestsGenerator.php +++ b/src/Generators/AbstractTestsGenerator.php @@ -161,13 +161,6 @@ protected function buildEntityObject($model): array return $result; } - protected function getModelClass($model): string - { - $path = "{$this->paths['models']}/{$model}"; - - return Str::ucfirst(str_replace('/', '\\', trim($path, '/'))); - } - protected function getModelFields($model): array { $modelClass = $this->getModelClass($model); diff --git a/src/Generators/EntityGenerator.php b/src/Generators/EntityGenerator.php index 9c7bd6e5..105c473c 100644 --- a/src/Generators/EntityGenerator.php +++ b/src/Generators/EntityGenerator.php @@ -208,4 +208,11 @@ protected function getRelatedModels(string $model, string $creatableClass): arra return $relatedModels; } + + protected function getModelClass(string $model): string + { + $modelNamespace = $this->getOrCreateNamespace('models'); + + return "{$modelNamespace}\\{$model}"; + } } diff --git a/src/Generators/FactoryGenerator.php b/src/Generators/FactoryGenerator.php index ebd829d2..5ac02bb7 100644 --- a/src/Generators/FactoryGenerator.php +++ b/src/Generators/FactoryGenerator.php @@ -238,11 +238,4 @@ protected function getFactoryPattern($model): string return "/{$modelNamespace}.*{$return}/sU"; } - - protected function getModelClass($model): string - { - $modelNamespace = $this->getOrCreateNamespace('models'); - - return "{$modelNamespace}\\{$model}"; - } } From e6bac358901134b8d282b2dd8283216e07e92617 Mon Sep 17 00:00:00 2001 From: DenTray Date: Mon, 2 Dec 2024 14:20:31 +0600 Subject: [PATCH 15/15] Apply suggestions from code review --- src/Generators/EntityGenerator.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/Generators/EntityGenerator.php b/src/Generators/EntityGenerator.php index 105c473c..937c11a4 100644 --- a/src/Generators/EntityGenerator.php +++ b/src/Generators/EntityGenerator.php @@ -188,20 +188,16 @@ protected function getRelatedModels(string $model, string $creatableClass): arra foreach ($methods as $method) { try { - $methodName = $method->getName(); + $result = call_user_func([$instance, $method->getName()]); - $methodReturn = $instance->$methodName(); - - if (!$methodReturn instanceof BelongsTo) { + if (!$result instanceof BelongsTo) { continue; } } catch (Throwable) { continue; } - $relationModel = get_class($methodReturn->getRelated()); - - $relatedModels[] = class_basename($relationModel); + $relatedModels[] = class_basename(get_class($result->getRelated())); } DB::rollBack();