From 7d8a3eb0a694acf5775c9a91d04b474f44e70f35 Mon Sep 17 00:00:00 2001 From: Jason McCreary Date: Thu, 14 May 2020 11:41:49 -0400 Subject: [PATCH 1/4] Generate database seeders with new syntax --- src/Generators/SeederGenerator.php | 61 ++++++++++++++ src/Lexers/SeederLexer.php | 39 +++++++++ stubs/seeder.stub | 16 ++++ tests/Feature/BlueprintTest.php | 22 ++++++ .../Feature/Generator/SeederGeneratorTest.php | 74 +++++++++++++++++ tests/Feature/Lexers/SeederLexerTest.php | 79 +++++++++++++++++++ tests/fixtures/definitions/models-only.bp | 2 +- tests/fixtures/definitions/seeders.bp | 14 ++++ tests/fixtures/seeders/CommentSeeder.php | 16 ++++ tests/fixtures/seeders/PostSeeder.php | 16 ++++ 10 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 src/Generators/SeederGenerator.php create mode 100644 src/Lexers/SeederLexer.php create mode 100644 stubs/seeder.stub create mode 100644 tests/Feature/Generator/SeederGeneratorTest.php create mode 100644 tests/Feature/Lexers/SeederLexerTest.php create mode 100644 tests/fixtures/definitions/seeders.bp create mode 100644 tests/fixtures/seeders/CommentSeeder.php create mode 100644 tests/fixtures/seeders/PostSeeder.php diff --git a/src/Generators/SeederGenerator.php b/src/Generators/SeederGenerator.php new file mode 100644 index 00000000..7515a597 --- /dev/null +++ b/src/Generators/SeederGenerator.php @@ -0,0 +1,61 @@ +files = $files; + } + + public function output(array $tree): array + { + if (empty($tree['seeders'])) { + return []; + } + + $output = []; + $stub = $this->files->stub('seeder.stub'); + + foreach ($tree['seeders'] as $model) { + $path = $this->getPath($model); + $this->files->put($path, $this->populateStub($stub, $model)); + + $output['created'][] = $path; + } + + return $output; + } + + private function getPath($model) + { + return 'database/seeds/' . $model . 'Seeder.php'; + } + + protected function populateStub(string $stub, string $model) + { + $stub = str_replace('DummyClass', $this->getClassName($model), $stub); + $stub = str_replace('//', $this->build($model), $stub); + + return $stub; + } + + private function getClassName(string $model) + { + return $model . 'Seeder'; + } + + private function build(string $model) + { + return sprintf('factory(\App\%s::class, 5)->create();', $model); + } +} diff --git a/src/Lexers/SeederLexer.php b/src/Lexers/SeederLexer.php new file mode 100644 index 00000000..33ee3867 --- /dev/null +++ b/src/Lexers/SeederLexer.php @@ -0,0 +1,39 @@ + [], + ]; + + if (!empty($tokens['seeders'])) { + $registry['seeders'] = $this->analyzeValue($tokens['seeders']); + } + + return $registry; + } + + private function analyzeValue($value) + { + return preg_split('/,([ \t]+)?/', $value); + } +} diff --git a/stubs/seeder.stub b/stubs/seeder.stub new file mode 100644 index 00000000..4aa38454 --- /dev/null +++ b/stubs/seeder.stub @@ -0,0 +1,16 @@ +subject->parse($blueprint)); } + public function it_parses_seeders() + { + $blueprint = $this->fixture('definitions/seeders.bp'); + + $this->assertEquals([ + 'models' => [ + 'Post' => [ + 'title' => 'string:400', + 'content' => 'longtext', + 'published_at' => 'nullable timestamp', + ], + 'Comment' => [ + 'post_id' => 'id', + 'content' => 'longtext', + 'approved' => 'boolean', + 'user_id' => 'id', + ], + ], + 'seeders' => 'Post, Comment' + ], $this->subject->parse($blueprint)); + } + /** * @test */ diff --git a/tests/Feature/Generator/SeederGeneratorTest.php b/tests/Feature/Generator/SeederGeneratorTest.php new file mode 100644 index 00000000..ddc9b988 --- /dev/null +++ b/tests/Feature/Generator/SeederGeneratorTest.php @@ -0,0 +1,74 @@ +files = \Mockery::mock(); + + $this->subject = new SeederGenerator($this->files); + + $this->blueprint = new Blueprint(); + $this->blueprint->registerLexer(new \Blueprint\Lexers\SeederLexer()); + $this->blueprint->registerGenerator($this->subject); + } + + /** + * @test + */ + public function output_generates_nothing_for_empty_tree() + { +// $this->files->expects('stub') +// ->with('migration.stub') +// ->andReturn(file_get_contents('stubs/migration.stub')); + + $this->files->shouldNotHaveReceived('put'); + + $this->assertEquals([], $this->subject->output(['seeders' => []])); + } + + /** + * @test + */ + public function output_generates_seeder() + { + $this->files->expects('stub') + ->with('seeder.stub') + ->andReturn(file_get_contents('stubs/seeder.stub')); + + $this->files->expects('put') + ->with('database/seeds/PostSeeder.php', $this->fixture('seeders/PostSeeder.php')); + $this->files->expects('put') + ->with('database/seeds/CommentSeeder.php', $this->fixture('seeders/CommentSeeder.php')); + + $tokens = $this->blueprint->parse($this->fixture('definitions/seeders.bp')); + $tree = $this->blueprint->analyze($tokens); + + $this->assertEquals(['created' => ['database/seeds/PostSeeder.php', 'database/seeds/CommentSeeder.php']], $this->subject->output($tree)); + } + +} diff --git a/tests/Feature/Lexers/SeederLexerTest.php b/tests/Feature/Lexers/SeederLexerTest.php new file mode 100644 index 00000000..abdf1a8d --- /dev/null +++ b/tests/Feature/Lexers/SeederLexerTest.php @@ -0,0 +1,79 @@ +subject = new SeederLexer(); + } + + /** + * @test + */ + public function it_returns_nothing_without_seeders_token() + { + $this->assertEquals([ + 'seeders' => [] + ], $this->subject->analyze([])); + } + + /** + * @test + */ + public function it_returns_seeders() + { + $tokens = [ + 'seeders' => 'Post' + ]; + + $actual = $this->subject->analyze($tokens); + + $this->assertIsArray($actual['seeders']); + $this->assertCount(1, $actual['seeders']); + + $this->assertSame(['Post'], $actual['seeders']); + } + + /** + * @test + */ + public function it_returns_multiple_seeders() + { + $tokens = [ + 'seeders' => 'Post, Comment' + ]; + + $actual = $this->subject->analyze($tokens); + + $this->assertIsArray($actual['seeders']); + $this->assertCount(2, $actual['seeders']); + + $this->assertSame(['Post', 'Comment'], $actual['seeders']); + } +} diff --git a/tests/fixtures/definitions/models-only.bp b/tests/fixtures/definitions/models-only.bp index cccfee8c..d123f579 100644 --- a/tests/fixtures/definitions/models-only.bp +++ b/tests/fixtures/definitions/models-only.bp @@ -4,4 +4,4 @@ models: ModelTwo: column: datatype - another_column: datatype modifier \ No newline at end of file + another_column: datatype modifier diff --git a/tests/fixtures/definitions/seeders.bp b/tests/fixtures/definitions/seeders.bp new file mode 100644 index 00000000..75ab368f --- /dev/null +++ b/tests/fixtures/definitions/seeders.bp @@ -0,0 +1,14 @@ +models: + Post: + title: string:400 + content: longtext + published_at: nullable timestamp + + Comment: + post_id: id + content: longtext + approved: boolean + user_id: id + +seeders: Post, Comment + diff --git a/tests/fixtures/seeders/CommentSeeder.php b/tests/fixtures/seeders/CommentSeeder.php new file mode 100644 index 00000000..dd0e8c05 --- /dev/null +++ b/tests/fixtures/seeders/CommentSeeder.php @@ -0,0 +1,16 @@ +create(); + } +} diff --git a/tests/fixtures/seeders/PostSeeder.php b/tests/fixtures/seeders/PostSeeder.php new file mode 100644 index 00000000..7e085018 --- /dev/null +++ b/tests/fixtures/seeders/PostSeeder.php @@ -0,0 +1,16 @@ +create(); + } +} From 73887490fabe41af8f2589b330123fd9cfde6a84 Mon Sep 17 00:00:00 2001 From: Laravel Shift Date: Thu, 14 May 2020 11:42:10 -0400 Subject: [PATCH 2/4] Apply fixes from StyleCI (#200) --- src/Generators/SeederGenerator.php | 1 - tests/Feature/Generator/SeederGeneratorTest.php | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Generators/SeederGenerator.php b/src/Generators/SeederGenerator.php index 7515a597..52dcf2b1 100644 --- a/src/Generators/SeederGenerator.php +++ b/src/Generators/SeederGenerator.php @@ -3,7 +3,6 @@ namespace Blueprint\Generators; - use Blueprint\Contracts\Generator; use Blueprint\Models\Model; diff --git a/tests/Feature/Generator/SeederGeneratorTest.php b/tests/Feature/Generator/SeederGeneratorTest.php index ddc9b988..58922579 100644 --- a/tests/Feature/Generator/SeederGeneratorTest.php +++ b/tests/Feature/Generator/SeederGeneratorTest.php @@ -70,5 +70,4 @@ public function output_generates_seeder() $this->assertEquals(['created' => ['database/seeds/PostSeeder.php', 'database/seeds/CommentSeeder.php']], $this->subject->output($tree)); } - } From b023783dbbf895d74cd09debb0a39865863f9143 Mon Sep 17 00:00:00 2001 From: Jason McCreary Date: Thu, 14 May 2020 11:45:04 -0400 Subject: [PATCH 3/4] Remove dead code --- tests/Feature/Generator/SeederGeneratorTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/Feature/Generator/SeederGeneratorTest.php b/tests/Feature/Generator/SeederGeneratorTest.php index 58922579..d28290d2 100644 --- a/tests/Feature/Generator/SeederGeneratorTest.php +++ b/tests/Feature/Generator/SeederGeneratorTest.php @@ -42,10 +42,6 @@ protected function setUp(): void */ public function output_generates_nothing_for_empty_tree() { -// $this->files->expects('stub') -// ->with('migration.stub') -// ->andReturn(file_get_contents('stubs/migration.stub')); - $this->files->shouldNotHaveReceived('put'); $this->assertEquals([], $this->subject->output(['seeders' => []])); From fac516d73581d21f7bbae99f6d4233be8141de6e Mon Sep 17 00:00:00 2001 From: Jason McCreary Date: Thu, 14 May 2020 12:39:33 -0400 Subject: [PATCH 4/4] Determine exact model reference --- src/Generators/SeederGenerator.php | 34 ++++++++++++++++++- .../Feature/Generator/SeederGeneratorTest.php | 25 +++++++++++++- tests/fixtures/definitions/seeders.bp | 2 +- tests/fixtures/seeders/CommentSeeder.php | 2 +- 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/src/Generators/SeederGenerator.php b/src/Generators/SeederGenerator.php index 52dcf2b1..fe93580f 100644 --- a/src/Generators/SeederGenerator.php +++ b/src/Generators/SeederGenerator.php @@ -5,12 +5,15 @@ use Blueprint\Contracts\Generator; use Blueprint\Models\Model; +use Illuminate\Support\Str; class SeederGenerator implements Generator { /** @var \Illuminate\Contracts\Filesystem\Filesystem */ private $files; + private $models = []; + public function __construct($files) { $this->files = $files; @@ -25,6 +28,8 @@ public function output(array $tree): array $output = []; $stub = $this->files->stub('seeder.stub'); + $this->registerModels($tree); + foreach ($tree['seeders'] as $model) { $path = $this->getPath($model); $this->files->put($path, $this->populateStub($stub, $model)); @@ -55,6 +60,33 @@ private function getClassName(string $model) private function build(string $model) { - return sprintf('factory(\App\%s::class, 5)->create();', $model); + return sprintf('factory(\\%s::class, 5)->create();', $this->fqcnForContext($model)); + } + + private function registerModels(array $tree) + { + $this->models = array_merge($tree['cache'] ?? [], $tree['models'] ?? []); + } + + private function fqcnForContext(string $context) + { + if (isset($this->models[$context])) { + return $this->models[$context]->fullyQualifiedClassName(); + } + + $matches = array_filter(array_keys($this->models), function ($key) use ($context) { + return Str::endsWith($key, '\\' . Str::studly($context)); + }); + + if (count($matches) === 1) { + return $this->models[current($matches)]->fullyQualifiedClassName(); + } + + $fqn = config('blueprint.namespace'); + if (config('blueprint.models_namespace')) { + $fqn .= '\\' . config('blueprint.models_namespace'); + } + + return $fqn . '\\' . $context; } } diff --git a/tests/Feature/Generator/SeederGeneratorTest.php b/tests/Feature/Generator/SeederGeneratorTest.php index d28290d2..06c5383c 100644 --- a/tests/Feature/Generator/SeederGeneratorTest.php +++ b/tests/Feature/Generator/SeederGeneratorTest.php @@ -33,6 +33,7 @@ protected function setUp(): void $this->subject = new SeederGenerator($this->files); $this->blueprint = new Blueprint(); + $this->blueprint->registerLexer(new \Blueprint\Lexers\ModelLexer()); $this->blueprint->registerLexer(new \Blueprint\Lexers\SeederLexer()); $this->blueprint->registerGenerator($this->subject); } @@ -50,7 +51,7 @@ public function output_generates_nothing_for_empty_tree() /** * @test */ - public function output_generates_seeder() + public function output_generates_seeders() { $this->files->expects('stub') ->with('seeder.stub') @@ -66,4 +67,26 @@ public function output_generates_seeder() $this->assertEquals(['created' => ['database/seeds/PostSeeder.php', 'database/seeds/CommentSeeder.php']], $this->subject->output($tree)); } + + /** + * @test + */ + public function output_generates_seeders_from_traced_models() + { + $this->files->expects('stub') + ->with('seeder.stub') + ->andReturn(file_get_contents('stubs/seeder.stub')); + + $this->files->expects('put') + ->with('database/seeds/PostSeeder.php', $this->fixture('seeders/PostSeeder.php')); + $this->files->expects('put') + ->with('database/seeds/CommentSeeder.php', $this->fixture('seeders/CommentSeeder.php')); + + $tokens = $this->blueprint->parse($this->fixture('definitions/seeders.bp')); + $tree = $this->blueprint->analyze($tokens); + $tree['cache'] = $tree['models']; + unset($tree['models']); + + $this->assertEquals(['created' => ['database/seeds/PostSeeder.php', 'database/seeds/CommentSeeder.php']], $this->subject->output($tree)); + } } diff --git a/tests/fixtures/definitions/seeders.bp b/tests/fixtures/definitions/seeders.bp index 75ab368f..36ea7045 100644 --- a/tests/fixtures/definitions/seeders.bp +++ b/tests/fixtures/definitions/seeders.bp @@ -4,7 +4,7 @@ models: content: longtext published_at: nullable timestamp - Comment: + Blog\Comment: post_id: id content: longtext approved: boolean diff --git a/tests/fixtures/seeders/CommentSeeder.php b/tests/fixtures/seeders/CommentSeeder.php index dd0e8c05..63a631d8 100644 --- a/tests/fixtures/seeders/CommentSeeder.php +++ b/tests/fixtures/seeders/CommentSeeder.php @@ -11,6 +11,6 @@ class CommentSeeder extends Seeder */ public function run() { - factory(\App\Comment::class, 5)->create(); + factory(\App\Blog\Comment::class, 5)->create(); } }