Skip to content

Commit 2c7ab48

Browse files
committed
TDD basic lexer
1 parent a63eb00 commit 2c7ab48

File tree

5 files changed

+537
-0
lines changed

5 files changed

+537
-0
lines changed

src/Column.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Blueprint;
4+
5+
class Column
6+
{
7+
private $modifiers;
8+
private $name;
9+
private $dataType;
10+
private $attributes;
11+
12+
public function __construct(string $name, string $dataType = 'string', array $modifiers = [], array $attributes = [])
13+
{
14+
$this->name = $name;
15+
$this->dataType = $dataType;
16+
$this->modifiers = $modifiers;
17+
$this->attributes = $attributes;
18+
}
19+
20+
public function name()
21+
{
22+
return $this->name;
23+
}
24+
25+
public function dataType()
26+
{
27+
return $this->dataType;
28+
}
29+
30+
public function attributes()
31+
{
32+
return $this->attributes;
33+
}
34+
35+
public function modifiers()
36+
{
37+
return $this->modifiers;
38+
}
39+
}

src/Lexers/Lexer.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
4+
namespace Blueprint\Lexers;
5+
6+
class Lexer
7+
{
8+
public static function analyze(array $tokens)
9+
{
10+
$registry = [];
11+
12+
$modelLexer = new ModelLexer();
13+
$registry = array_merge($registry, $modelLexer->analyze($tokens));
14+
15+
return $registry;
16+
}
17+
18+
19+
}

src/Lexers/ModelLexer.php

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
3+
4+
namespace Blueprint\Lexers;
5+
6+
7+
use Blueprint\Column;
8+
use Blueprint\Factories\ModelFactory;
9+
use Blueprint\Model;
10+
11+
class ModelLexer
12+
{
13+
private static $dataTypes = [
14+
'bigIncrements',
15+
'bigInteger',
16+
'binary',
17+
'boolean',
18+
'char',
19+
'date',
20+
'dateTime',
21+
'dateTimeTz',
22+
'decimal',
23+
'double',
24+
'enum',
25+
'float',
26+
'geometry',
27+
'geometryCollection',
28+
'increments',
29+
'integer',
30+
'ipAddress',
31+
'json',
32+
'jsonb',
33+
'lineString',
34+
'longText',
35+
'macAddress',
36+
'mediumIncrements',
37+
'mediumInteger',
38+
'mediumText',
39+
'morphs',
40+
'uuidMorphs',
41+
'multiLineString',
42+
'multiPoint',
43+
'multiPolygon',
44+
'nullableMorphs',
45+
'nullableUuidMorphs',
46+
'nullableTimestamps',
47+
'point',
48+
'polygon',
49+
'rememberToken',
50+
'set',
51+
'smallIncrements',
52+
'smallInteger',
53+
'softDeletes',
54+
'softDeletesTz',
55+
'string',
56+
'text',
57+
'time',
58+
'timeTz',
59+
'timestamp',
60+
'timestampTz',
61+
'timestamps',
62+
'timestampsTz',
63+
'tinyIncrements',
64+
'tinyInteger',
65+
'unsignedBigInteger',
66+
'unsignedDecimal',
67+
'unsignedInteger',
68+
'unsignedMediumInteger',
69+
'unsignedSmallInteger',
70+
'unsignedTinyInteger',
71+
'uuid',
72+
'year'
73+
];
74+
75+
private static $modifiers = [
76+
'autoIncrement',
77+
'charset',
78+
'collation',
79+
'default',
80+
'nullable',
81+
'unsigned',
82+
'useCurrent',
83+
'always'
84+
];
85+
86+
public function analyze(array $tokens)
87+
{
88+
$registry = [
89+
'models' => []
90+
];
91+
92+
if (empty($tokens['models'])) {
93+
return $registry;
94+
}
95+
96+
foreach ($tokens['models'] as $name => $definition) {
97+
$registry['models'][$name] = $this->buildModel($name, $definition);
98+
}
99+
100+
return $registry;
101+
}
102+
103+
private function buildModel(string $name, array $columns)
104+
{
105+
$model = new Model($name);
106+
107+
if (isset($columns['timestamps'])) {
108+
if ($columns['timestamps'] === false) {
109+
$model->disableTimestamps();
110+
}
111+
112+
unset($columns['timestamps']);
113+
}
114+
115+
if (!isset($columns['id'])) {
116+
$column = $this->buildColumn('id', 'id');
117+
$model->addColumn($column);
118+
}
119+
120+
foreach ($columns as $name => $definition) {
121+
$column = $this->buildColumn($name, $definition);
122+
$model->addColumn($column);
123+
}
124+
125+
return $model;
126+
}
127+
128+
private function buildColumn(string $name, string $definition)
129+
{
130+
$data_type = 'string';
131+
$modifiers = [];
132+
133+
$tokens = explode(' ', $definition);
134+
foreach ($tokens as $token) {
135+
[$value, $attributes] = explode(':', $token);
136+
137+
if ($value === 'id') {
138+
$data_type = 'id';
139+
} elseif (in_array($value, self::$dataTypes)) {
140+
$data_type = $value;
141+
if (!empty($attributes)) {
142+
$attributes = explode(',', $attributes);
143+
}
144+
}
145+
146+
if (in_array($value, self::$modifiers)) {
147+
if (empty($attributes)) {
148+
$modifiers[] = $value;
149+
} else {
150+
$modifiers[] = [$value => $attributes];
151+
$attributes = [];
152+
}
153+
}
154+
}
155+
156+
return new Column($name, $data_type, $modifiers, $attributes ?? []);
157+
}
158+
}

src/Model.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
namespace Blueprint;
4+
5+
use Illuminate\Support\Str;
6+
7+
class Model
8+
{
9+
private $name;
10+
private $timestamps = true;
11+
private $columns = [];
12+
13+
/**
14+
* @param $name
15+
*/
16+
public function __construct($name)
17+
{
18+
$this->name = $name;
19+
}
20+
21+
public function name(): string
22+
{
23+
return Str::studly($this->name);
24+
}
25+
26+
public function addColumn(Column $column)
27+
{
28+
$this->columns[$column->name()] = $column;
29+
}
30+
31+
public function columns(): array
32+
{
33+
return $this->columns;
34+
}
35+
36+
public function usesTimestamps()
37+
{
38+
return $this->timestamps;
39+
}
40+
41+
public function disableTimestamps()
42+
{
43+
$this->timestamps = false;
44+
}
45+
46+
public function primaryKey()
47+
{
48+
49+
}
50+
51+
public function tableName()
52+
{
53+
return Str::snake(Str::pluralStudly($this->name));
54+
}
55+
}

0 commit comments

Comments
 (0)