1
|
|
|
<?php |
2
|
|
|
declare(strict_types=1); |
3
|
|
|
|
4
|
|
|
namespace DDDGen; |
5
|
|
|
|
6
|
|
|
use Assert\Assert; |
7
|
|
|
use DDDGen\VO\FQCN; |
8
|
|
|
use DDDGen\VO\Layer; |
9
|
|
|
use DDDGen\VO\Primitive; |
10
|
|
|
|
11
|
|
|
final class Generator |
12
|
|
|
{ |
13
|
|
|
/** @var Layer[] */ |
14
|
|
|
private $layers; |
15
|
|
|
/** @var Primitive[] */ |
16
|
|
|
private $primitives; |
17
|
|
|
/** @var array of placeholders which can be replaced in stub files */ |
18
|
|
|
private $placeholders = []; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* Generator constructor. |
22
|
|
|
* |
23
|
|
|
* @param Layer[] $layers |
24
|
|
|
* @param Primitive[] $primitives |
25
|
|
|
*/ |
26
|
2 |
|
public function __construct(array $layers, array $primitives) |
27
|
|
|
{ |
28
|
2 |
|
$this->layers = $layers; |
29
|
2 |
|
$this->primitives = $primitives; |
30
|
|
|
|
31
|
2 |
|
$this->validate(); |
32
|
2 |
|
} |
33
|
|
|
|
34
|
|
|
|
35
|
2 |
|
private function validate() |
36
|
|
|
{ |
37
|
2 |
|
Assert::thatAll($this->primitives)->isInstanceOf(Primitive::class); |
38
|
2 |
|
Assert::thatAll($this->layers)->isInstanceOf(Layer::class); |
39
|
|
|
|
40
|
2 |
|
Assert::that(count($this->layers))->min(1); |
41
|
2 |
|
Assert::that(count($this->primitives))->min(1); |
42
|
2 |
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Generate command will generate files from stubs and put them to target folders |
46
|
|
|
* |
47
|
|
|
* |
48
|
|
|
* @param string $layer_name f.e. app or infrastructure |
49
|
|
|
* @param string $primitive_name f.e. event |
50
|
|
|
* @param FQCN $qcn f.e. Some/Namespaced/Name |
51
|
|
|
* |
52
|
|
|
* @return array of generated files |
53
|
|
|
*/ |
54
|
2 |
|
public function generate($layer_name, $primitive_name, FQCN $qcn): array |
55
|
|
|
{ |
56
|
2 |
|
$generated_stubs = $this->generateDry($layer_name, $primitive_name, $qcn); |
57
|
|
|
|
58
|
2 |
|
foreach ($generated_stubs as $target_path => $stub_file) { |
59
|
2 |
|
$this->writeStubs($target_path, $stub_file); |
60
|
|
|
} |
61
|
|
|
|
62
|
2 |
|
return $generated_stubs; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* generateDry - prepare map of new final files to source stubs |
67
|
|
|
* |
68
|
|
|
* @param string $layer_name f.e. app or infrastructure |
69
|
|
|
* @param string $primitive_name f.e. event |
70
|
|
|
* @param FQCN $qcn f.e. Some/Namespaced/Name |
71
|
|
|
* |
72
|
|
|
* @return array |
73
|
|
|
*/ |
74
|
2 |
|
public function generateDry($layer_name, $primitive_name, FQCN $qcn): array |
75
|
|
|
{ |
76
|
2 |
|
$primitive = $this->getPrimitiveByName($primitive_name); |
77
|
2 |
|
$layer = $this->getLayerByName($layer_name); |
78
|
|
|
|
79
|
2 |
|
$this->updatePlaceholders( |
80
|
|
|
[ |
81
|
|
|
// default for given layer |
82
|
2 |
|
"/*<BASE_TEST_NAMESPACE>*/" => $layer->getTestsFqcn()->getFqcn(), |
83
|
2 |
|
"/*<BASE_SRC_NAMESPACE>*/" => $layer->getSrcFqcn()->getFqcn(), |
84
|
|
|
|
85
|
2 |
|
"/*<LAYER>*/" => $layer->getName(), |
86
|
2 |
|
"/*<PRIMITIVE>*/" => $primitive_name, |
87
|
|
|
|
88
|
2 |
|
"/*<PSR4_NAMESPACE>*/" => $qcn->getFqcn(), |
89
|
2 |
|
"/*<PSR4_NAMESPACE_BASE>*/" => $qcn->getBasePart(), |
90
|
2 |
|
"/*<PSR4_NAMESPACE_LAST>*/" => $qcn->getLastPart(), |
91
|
|
|
|
92
|
|
|
]); |
93
|
2 |
|
$generated_stubs = $this->generateStubs($primitive, $layer, $qcn); |
94
|
|
|
|
95
|
2 |
|
return $generated_stubs; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
|
99
|
|
|
/** |
100
|
|
|
* generateStubs for given primitive in given layer |
101
|
|
|
* |
102
|
|
|
* |
103
|
|
|
* @param Primitive $primitive |
104
|
|
|
* @param Layer $layer |
105
|
|
|
* @param FQCN $qcn |
106
|
|
|
* |
107
|
|
|
* @return array [final_path => stub_file] |
108
|
|
|
*/ |
109
|
2 |
|
private function generateStubs($primitive, $layer, $qcn): array |
110
|
|
|
{ |
111
|
2 |
|
$generated_stubs = []; |
112
|
|
|
|
113
|
|
|
// |
114
|
|
|
// 1. SRC stubs |
115
|
|
|
// |
116
|
2 |
View Code Duplication |
foreach ($primitive->getSrcStubs() as $filename => $stub) { |
|
|
|
|
117
|
|
|
|
118
|
2 |
|
$filename = $this->replacePlaceholdersInText($filename); |
119
|
2 |
|
if (!preg_match("#\\.php$#", $filename)) { |
120
|
2 |
|
$filename .= ".php"; |
121
|
|
|
} |
122
|
|
|
|
123
|
2 |
|
$target_path = $layer->getSrcDir() |
124
|
2 |
|
. DIRECTORY_SEPARATOR . $qcn->toPSR4Path() |
125
|
2 |
|
. DIRECTORY_SEPARATOR . $filename; |
126
|
|
|
|
127
|
2 |
|
$generated_stubs[$target_path] = $stub; |
128
|
|
|
|
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
|
132
|
|
|
// |
133
|
|
|
// 2. TEST stubs |
134
|
|
|
// |
135
|
2 |
View Code Duplication |
foreach ($primitive->getTestStubs() as $filename => $stub) { |
|
|
|
|
136
|
|
|
|
137
|
2 |
|
$filename = $this->replacePlaceholdersInText($filename); |
138
|
2 |
|
if (!preg_match("#\\.php$#", $filename)) { |
139
|
2 |
|
$filename .= ".php"; |
140
|
|
|
} |
141
|
|
|
|
142
|
2 |
|
$target_path = $layer->getTestsDir() |
143
|
2 |
|
. DIRECTORY_SEPARATOR . $qcn->toPSR4Path() |
144
|
2 |
|
. DIRECTORY_SEPARATOR . $filename; |
145
|
|
|
|
146
|
2 |
|
$generated_stubs[$target_path] = $stub; |
147
|
|
|
} |
148
|
|
|
|
149
|
2 |
|
return $generated_stubs; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* writeStubs to final files |
154
|
|
|
* |
155
|
|
|
* |
156
|
|
|
* @param string $target_path |
157
|
|
|
* @param string $source_file |
158
|
|
|
* |
159
|
|
|
* @return void |
160
|
|
|
*/ |
161
|
2 |
|
private function writeStubs(string $target_path, string $source_file): void |
162
|
|
|
{ |
163
|
2 |
|
@mkdir(dirname($target_path), 0775, true); |
|
|
|
|
164
|
|
|
|
165
|
|
|
|
166
|
2 |
|
$this->updatePlaceholders([ |
167
|
2 |
|
"/*<FILENAME>*/" => preg_replace("#\.php$#", "", basename($target_path)), |
168
|
|
|
]); |
169
|
2 |
|
$content = $this->replacePlaceholdersInText(file_get_contents($source_file)); |
170
|
|
|
|
171
|
|
|
|
172
|
|
|
//var_dump($content); |
173
|
2 |
|
file_put_contents($target_path, $content); |
174
|
2 |
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* getPrimitiveByName |
178
|
|
|
* |
179
|
|
|
* |
180
|
|
|
* @param string $name |
181
|
|
|
* |
182
|
|
|
* @throws \Exception |
183
|
|
|
* |
184
|
|
|
* @return Primitive |
185
|
|
|
*/ |
186
|
2 |
|
private function getPrimitiveByName(string $name): Primitive |
187
|
|
|
{ |
188
|
2 |
|
foreach ($this->primitives as $primitive) { |
189
|
2 |
|
if ($primitive->getName() == $name) { |
190
|
2 |
|
return $primitive; |
191
|
|
|
} |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
throw new \Exception("Primitive not found"); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
/** |
198
|
|
|
* updatePlaceholders |
199
|
|
|
* |
200
|
|
|
* |
201
|
|
|
* @param array $placeholders |
202
|
|
|
* |
203
|
|
|
* @return void |
204
|
|
|
*/ |
205
|
2 |
|
private function updatePlaceholders(array $placeholders): void |
206
|
|
|
{ |
207
|
2 |
|
Assert::thatAll($placeholders)->string(); |
208
|
|
|
|
209
|
2 |
|
$this->placeholders = array_merge($this->placeholders, $placeholders); |
210
|
2 |
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* replacePlaceholders |
214
|
|
|
* |
215
|
|
|
* |
216
|
|
|
* @param $text |
217
|
|
|
* |
218
|
|
|
* @return string |
219
|
|
|
*/ |
220
|
2 |
|
private function replacePlaceholdersInText($text): string |
221
|
|
|
{ |
222
|
2 |
|
$text = str_replace(array_keys($this->placeholders), $this->placeholders, $text); |
223
|
|
|
|
224
|
2 |
|
return $text; |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
|
228
|
2 |
|
public function getLayerByName(string $name): Layer |
229
|
|
|
{ |
230
|
2 |
|
foreach ($this->layers as $layer) { |
231
|
2 |
|
if ($layer->getName() == $name) { |
232
|
2 |
|
return $layer; |
233
|
|
|
} |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
throw new \Exception("Layer with name $name was not found"); |
237
|
|
|
} |
238
|
|
|
} |
239
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.