Skip to content

Commit f9eaa9c

Browse files
committed
Spike on model generators
1 parent 2c7ab48 commit f9eaa9c

File tree

9 files changed

+295
-0
lines changed

9 files changed

+295
-0
lines changed

src/Generators/Generator.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Blueprint\Generators;
4+
5+
use Blueprint\Lexers\ModelLexer;
6+
7+
class Generator
8+
{
9+
public static function generate(array $registry)
10+
{
11+
$generator = new MigrationGenerator();
12+
$generator->output($registry);
13+
14+
$generator = new ModelGenerator();
15+
$generator->output($registry);
16+
}
17+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
namespace Blueprint\Generators;
4+
5+
use Blueprint\Model;
6+
use Illuminate\Support\Str;
7+
8+
class MigrationGenerator
9+
{
10+
public function output(array $tree)
11+
{
12+
// TODO: what if changing an existing model
13+
$stub = file_get_contents('stubs/migration.stub');
14+
15+
/** @var \Blueprint\Model $model */
16+
foreach ($tree['models'] as $model) {
17+
file_put_contents(
18+
$this->getPath($model),
19+
$this->populateStub($stub, $model)
20+
);
21+
}
22+
}
23+
24+
protected function populateStub(string $stub, Model $model)
25+
{
26+
$stub = str_replace('DummyClass', $this->getClassName($model), $stub);
27+
$stub = str_replace('DummyTable', $model->tableName(), $stub);
28+
$stub = str_replace('// definition...', $this->buildDefinition($model), $stub);
29+
30+
return $stub;
31+
}
32+
33+
protected function buildDefinition(Model $model)
34+
{
35+
$definition = '';
36+
37+
/** @var \Blueprint\Column $column */
38+
foreach ($model->columns() as $column) {
39+
$definition .= '$table->' . $column->dataType() . "('{$column->name()}'";
40+
if (!empty($column->attributes())) {
41+
// TODO: what about set and enum?
42+
$definition .= ', ' . implode(', ', $column->attributes());
43+
}
44+
$definition .= ')';
45+
46+
foreach ($column->modifiers() as $modifier) {
47+
if (is_array($modifier)) {
48+
// TODO: properly handle quoted values
49+
$definition .= "->" . key($modifier) . "(" . current($modifier) . ")";
50+
} else {
51+
$definition .= '->' . $modifier . '()';
52+
}
53+
}
54+
55+
$definition .= ';' . PHP_EOL;
56+
}
57+
58+
if ($model->usesTimestamps()) {
59+
$definition .= '$table->timestamps();' . PHP_EOL;
60+
}
61+
62+
return $definition;
63+
}
64+
65+
protected function getClassName(Model $model)
66+
{
67+
return 'Create' . Str::studly($model->tableName()) . 'Table';
68+
}
69+
70+
protected function getPath(Model $model)
71+
{
72+
return 'build/' . date('Y_m_d_His') . '_create_' . $model->tableName() . '_table.php';
73+
}
74+
}

src/Generators/ModelGenerator.php

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
3+
namespace Blueprint\Generators;
4+
5+
use Blueprint\Column;
6+
use Blueprint\Model;
7+
8+
class ModelGenerator
9+
{
10+
public function output(array $tree)
11+
{
12+
// TODO: what if changing an existing model
13+
$stub = file_get_contents('stubs/model/class.stub');
14+
15+
/** @var \Blueprint\Model $model */
16+
foreach ($tree['models'] as $model) {
17+
file_put_contents(
18+
$this->getPath($model),
19+
$this->populateStub($stub, $model)
20+
);
21+
}
22+
}
23+
24+
protected function populateStub(string $stub, Model $model)
25+
{
26+
$stub = str_replace('DummyNamespace', 'App', $stub);
27+
$stub = str_replace('DummyClass', $model->name(), $stub);
28+
$stub = str_replace('// properties...', $this->buildProperties($model), $stub);
29+
30+
return $stub;
31+
}
32+
33+
private function buildProperties(Model $model)
34+
{
35+
$properties = '';
36+
37+
$property = $this->fillableColumns($model->columns());
38+
if (!empty($property)) {
39+
$properties .= str_replace('[]', $this->pretty_print_array($property, false), $this->propertyStub('fillable'));
40+
}
41+
42+
$property = $this->castableColumns($model->columns());
43+
if (!empty($property)) {
44+
$properties .= str_replace('[]', $this->pretty_print_array($property), $this->propertyStub('casts'));
45+
}
46+
47+
$property = $this->dateColumns($model->columns());
48+
if (!empty($property)) {
49+
$properties .= str_replace('[]', $this->pretty_print_array($property, false), $this->propertyStub('dates'));
50+
}
51+
52+
return $properties;
53+
}
54+
55+
protected function getPath(Model $model)
56+
{
57+
return 'build/' . $model->name() . '.php';
58+
}
59+
60+
private function fillableColumns(array $columns)
61+
{
62+
return array_diff(array_keys($columns), [
63+
'id',
64+
'password',
65+
'deleted_at',
66+
'created_at',
67+
'updated_at'
68+
]);
69+
}
70+
71+
private function castableColumns(array $columns)
72+
{
73+
return array_filter(array_map(
74+
function (Column $column) {
75+
return $this->castForColumn($column);
76+
}, $columns));
77+
}
78+
79+
private function dateColumns(array $columns)
80+
{
81+
return array_map(
82+
function (Column $column) {
83+
return $column->name();
84+
},
85+
array_filter($columns, function (Column $column) {
86+
return stripos($column->dataType(), 'datetime') !== false
87+
|| stripos($column->dataType(), 'timestamp') !== false;
88+
}));
89+
}
90+
91+
private function castForColumn(Column $column)
92+
{
93+
if (stripos($column->dataType(), 'integer') || $column->dataType() === 'id') {
94+
return 'integer';
95+
}
96+
97+
if (in_array($column->dataType(), ['boolean', 'double', 'float'])) {
98+
return strtolower($column->dataType());
99+
}
100+
101+
if (in_array($column->dataType(), ['decimal', 'unsignedDecimal'])) {
102+
if ($column->attributes()) {
103+
return 'decimal:' . $column->attributes()[1];
104+
}
105+
106+
return 'decimal';
107+
}
108+
109+
return null;
110+
}
111+
112+
private function pretty_print_array(array $data, $assoc = true)
113+
{
114+
$output = var_export($data, true);
115+
$output = preg_replace(['/^array\s\(/', "/\)$/"], ['[', ']'], $output);
116+
117+
if (!$assoc) {
118+
$output = preg_replace('/^(\s+)[^=]+=>\s+/m', '$1', $output);
119+
}
120+
121+
return $output;
122+
}
123+
124+
private function propertyStub(string $stub)
125+
{
126+
static $stubs = [];
127+
128+
if (empty($stubs[$stub])) {
129+
$stubs[$stub] = file_get_contents('stubs/model/'. $stub .'.stub');
130+
}
131+
132+
return $stubs[$stub];
133+
}
134+
}

stubs/factory.stub

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
/** @var \Illuminate\Database\Eloquent\Factory $factory */
4+
5+
use App\Model;
6+
use Faker\Generator as Faker;
7+
8+
$factory->define(Model::class, function (Faker $faker) {
9+
return [
10+
//
11+
];
12+
});

stubs/migration.stub

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
class DummyClass extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::create('DummyTable', function (Blueprint $table) {
17+
// definition...
18+
});
19+
}
20+
21+
/**
22+
* Reverse the migrations.
23+
*
24+
* @return void
25+
*/
26+
public function down()
27+
{
28+
Schema::dropIfExists('DummyTable');
29+
}
30+
}

stubs/model/casts.stub

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/**
2+
* The attributes that should be cast to native types.
3+
*
4+
* @var array
5+
*/
6+
protected $casts = [];

stubs/model/class.stub

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace DummyNamespace;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
class DummyClass extends Model
8+
{
9+
// properties...
10+
}

stubs/model/dates.stub

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/**
2+
* The attributes that should be mutated to dates.
3+
*
4+
* @var array
5+
*/
6+
protected $dates = [];

stubs/model/fillable.stub

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/**
2+
* The attributes that are mass assignable.
3+
*
4+
* @var array
5+
*/
6+
protected $fillable = [];

0 commit comments

Comments
 (0)