Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions src/Generators/SeederGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php


namespace Blueprint\Generators;

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;
}

public function output(array $tree): array
{
if (empty($tree['seeders'])) {
return [];
}

$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));

$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(\\%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;
}
}
39 changes: 39 additions & 0 deletions src/Lexers/SeederLexer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php


namespace Blueprint\Lexers;

use Blueprint\Contracts\Lexer;
use Blueprint\Models\Statements\DispatchStatement;
use Blueprint\Models\Statements\EloquentStatement;
use Blueprint\Models\Statements\FireStatement;
use Blueprint\Models\Statements\QueryStatement;
use Blueprint\Models\Statements\RedirectStatement;
use Blueprint\Models\Statements\RenderStatement;
use Blueprint\Models\Statements\ResourceStatement;
use Blueprint\Models\Statements\RespondStatement;
use Blueprint\Models\Statements\SendStatement;
use Blueprint\Models\Statements\SessionStatement;
use Blueprint\Models\Statements\ValidateStatement;
use Illuminate\Support\Str;

class SeederLexer implements Lexer
{
public function analyze(array $tokens): array
{
$registry = [
'seeders' => [],
];

if (!empty($tokens['seeders'])) {
$registry['seeders'] = $this->analyzeValue($tokens['seeders']);
}

return $registry;
}

private function analyzeValue($value)
{
return preg_split('/,([ \t]+)?/', $value);
}
}
16 changes: 16 additions & 0 deletions stubs/seeder.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

use Illuminate\Database\Seeder;

class DummyClass extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
//
}
}
22 changes: 22 additions & 0 deletions tests/Feature/BlueprintTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,28 @@ public function it_parses_models()
], $this->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
*/
Expand Down
92 changes: 92 additions & 0 deletions tests/Feature/Generator/SeederGeneratorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php

namespace Tests\Feature\Generators;

use Blueprint\Blueprint;
use Blueprint\Generators\SeederGenerator;
use Carbon\Carbon;
use Illuminate\Support\Facades\App;
use Tests\TestCase;

/**
* @see SeederGenerator
*/
class SeederGeneratorTest extends TestCase
{
/**
* @var Blueprint
*/
private $blueprint;

/** @var SeederGenerator */
private $subject;


private $files;

protected function setUp(): void
{
parent::setUp();

$this->files = \Mockery::mock();

$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);
}

/**
* @test
*/
public function output_generates_nothing_for_empty_tree()
{
$this->files->shouldNotHaveReceived('put');

$this->assertEquals([], $this->subject->output(['seeders' => []]));
}

/**
* @test
*/
public function output_generates_seeders()
{
$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));
}

/**
* @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));
}
}
79 changes: 79 additions & 0 deletions tests/Feature/Lexers/SeederLexerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

namespace Tests\Feature\Lexers;

use Blueprint\Lexers\SeederLexer;
use Blueprint\Models\Statements\DispatchStatement;
use Blueprint\Models\Statements\EloquentStatement;
use Blueprint\Models\Statements\FireStatement;
use Blueprint\Models\Statements\QueryStatement;
use Blueprint\Models\Statements\RedirectStatement;
use Blueprint\Models\Statements\RenderStatement;
use Blueprint\Models\Statements\ResourceStatement;
use Blueprint\Models\Statements\RespondStatement;
use Blueprint\Models\Statements\SendStatement;
use Blueprint\Models\Statements\SessionStatement;
use Blueprint\Models\Statements\ValidateStatement;
use PHPUnit\Framework\TestCase;

/**
* @see SeederLexer
*/
class SeederLexerTest extends TestCase
{
/**
* @var SeederLexer
*/
private $subject;

protected function setUp(): void
{
parent::setUp();

$this->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']);
}
}
2 changes: 1 addition & 1 deletion tests/fixtures/definitions/models-only.bp
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ models:

ModelTwo:
column: datatype
another_column: datatype modifier
another_column: datatype modifier
14 changes: 14 additions & 0 deletions tests/fixtures/definitions/seeders.bp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
models:
Post:
title: string:400
content: longtext
published_at: nullable timestamp

Blog\Comment:
post_id: id
content: longtext
approved: boolean
user_id: id

seeders: Post, Comment

16 changes: 16 additions & 0 deletions tests/fixtures/seeders/CommentSeeder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

use Illuminate\Database\Seeder;

class CommentSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
factory(\App\Blog\Comment::class, 5)->create();
}
}
Loading