1
|
|
|
<?php |
2
|
|
|
declare(strict_types=1); |
3
|
|
|
|
4
|
|
|
|
5
|
|
|
namespace Xervice\DataProvider\Business\Model\Generator; |
6
|
|
|
|
7
|
|
|
|
8
|
|
|
use Nette\PhpGenerator\ClassType; |
9
|
|
|
use Nette\PhpGenerator\Helpers; |
10
|
|
|
use Nette\PhpGenerator\PhpNamespace; |
11
|
|
|
use Xervice\DataProvider\Business\Model\DataProvider\DataProviderInterface; |
12
|
|
|
use Xervice\DataProvider\Business\Model\Parser\DataProviderParserInterface; |
13
|
|
|
|
14
|
|
|
class DataProviderGenerator implements DataProviderGeneratorInterface |
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* @var \Xervice\DataProvider\Business\Model\Parser\DataProviderParserInterface |
18
|
|
|
*/ |
19
|
|
|
private $parser; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* @var FileWriterInterface |
23
|
|
|
*/ |
24
|
|
|
private $fileWriter; |
25
|
|
|
|
26
|
|
|
/** |
27
|
|
|
* @var string |
28
|
|
|
*/ |
29
|
|
|
private $namespace; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var string |
33
|
|
|
*/ |
34
|
|
|
private $dataProviderExtends; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* DataProviderGenerator constructor. |
38
|
|
|
* |
39
|
|
|
* @param \Xervice\DataProvider\Business\Model\Parser\DataProviderParserInterface $parser |
40
|
|
|
* @param FileWriterInterface $fileWriter |
41
|
|
|
* @param string $namespace |
42
|
|
|
*/ |
43
|
10 |
|
public function __construct( |
44
|
|
|
DataProviderParserInterface $parser, |
45
|
|
|
FileWriterInterface $fileWriter, |
46
|
|
|
string $namespace, |
47
|
|
|
string $dataProviderExtends |
48
|
|
|
) { |
49
|
10 |
|
$this->parser = $parser; |
50
|
10 |
|
$this->fileWriter = $fileWriter; |
51
|
10 |
|
$this->namespace = $namespace; |
52
|
10 |
|
$this->dataProviderExtends = $dataProviderExtends; |
53
|
10 |
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @return array |
57
|
|
|
* @throws \Nette\InvalidArgumentException |
58
|
|
|
*/ |
59
|
10 |
|
public function generate(): array |
60
|
|
|
{ |
61
|
10 |
|
$fileGenerated = []; |
62
|
|
|
|
63
|
10 |
|
foreach ($this->parser->getDataProvider() as $providerName => $providerData) { |
64
|
10 |
|
$namespace = new PhpNamespace($this->namespace); |
65
|
10 |
|
$dataProvider = $this->createDataProviderClass($providerName, $providerData, $namespace); |
66
|
10 |
|
$classContent = (string)$namespace; |
67
|
10 |
|
$classContent = str_replace('\?', '?', $classContent); |
68
|
10 |
|
$classContent = Helpers::tabsToSpaces($classContent, 4); |
69
|
10 |
|
$this->fileWriter->writeToFile($dataProvider->getName() . '.php', $classContent); |
70
|
10 |
|
$fileGenerated[] = $dataProvider->getName() . '.php'; |
71
|
|
|
} |
72
|
|
|
|
73
|
10 |
|
return $fileGenerated; |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @param string $provider |
78
|
|
|
* @param \Nette\PhpGenerator\PhpNamespace $namespace |
79
|
|
|
* |
80
|
|
|
* @return ClassType |
81
|
|
|
* @throws \Nette\InvalidArgumentException |
82
|
|
|
*/ |
83
|
10 |
|
private function createNewDataProvider($provider, PhpNamespace $namespace): ClassType |
84
|
|
|
{ |
85
|
10 |
|
$dataProvider = $namespace->addClass($provider . 'DataProvider'); |
86
|
|
|
$dataProvider |
87
|
10 |
|
->setFinal() |
88
|
10 |
|
->setExtends($this->dataProviderExtends) |
89
|
10 |
|
->setImplements( |
90
|
|
|
[ |
91
|
10 |
|
DataProviderInterface::class |
92
|
|
|
] |
93
|
|
|
) |
94
|
10 |
|
->setComment('Auto generated data provider') |
95
|
|
|
; |
96
|
|
|
|
97
|
10 |
|
return $dataProvider; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* @param \Nette\PhpGenerator\ClassType $dataProvider |
102
|
|
|
* @param array $element |
103
|
|
|
* @param array $configs |
104
|
|
|
*/ |
105
|
10 |
|
private function addGetter(ClassType $dataProvider, array $element, array $configs): void |
106
|
|
|
{ |
107
|
10 |
|
$dataProvider->addMethod('get' . $this->formatElementName($element['name'], $configs)) |
108
|
10 |
|
->addComment('@return ' . $element['type']) |
109
|
10 |
|
->setVisibility('public') |
110
|
10 |
|
->setBody('return $this->' . $element['name'] . ';') |
111
|
10 |
|
->setReturnType($this->getTypeHint($element['type'], $element['allownull'])) |
112
|
|
|
; |
113
|
10 |
|
} |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* @param \Nette\PhpGenerator\ClassType $dataProvider |
117
|
|
|
* @param array $element |
118
|
|
|
* @param array $configs |
119
|
|
|
*/ |
120
|
10 |
|
private function addUnsetter(ClassType $dataProvider, array $element, array $configs): void |
121
|
|
|
{ |
122
|
10 |
|
$dataProvider->addMethod('unset' . $this->formatElementName($element['name'], $configs)) |
123
|
10 |
|
->addComment('@return ' . $dataProvider->getName()) |
124
|
10 |
|
->setVisibility('public') |
125
|
10 |
|
->setBody('$this->' . $element['name'] . ' = null;' . PHP_EOL . PHP_EOL . 'return $this;') |
126
|
|
|
; |
127
|
10 |
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* @param \Nette\PhpGenerator\ClassType $dataProvider |
131
|
|
|
* @param array $element |
132
|
|
|
* @param array $configs |
133
|
|
|
*/ |
134
|
10 |
|
private function addHas(ClassType $dataProvider, array $element, array $configs): void |
135
|
|
|
{ |
136
|
10 |
|
$dataProvider->addMethod('has' . $this->formatElementName($element['name'], $configs)) |
137
|
10 |
|
->addComment('@return bool') |
138
|
10 |
|
->setVisibility('public') |
139
|
10 |
|
->setBody( |
140
|
10 |
|
'return ($this->' . $element['name'] . ' !== null && $this->' . $element['name'] . ' !== []);' |
141
|
|
|
) |
142
|
|
|
; |
143
|
10 |
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* @param \Nette\PhpGenerator\ClassType $dataProvider |
147
|
|
|
* @param array $element |
148
|
|
|
* @param array $configs |
149
|
|
|
*/ |
150
|
10 |
|
private function addSetter(ClassType $dataProvider, array $element, array $configs): void |
151
|
|
|
{ |
152
|
10 |
|
$setter = $dataProvider->addMethod('set' . $this->formatElementName($element['name'], $configs)) |
153
|
10 |
|
->addComment( |
154
|
10 |
|
'@param ' . $element['type'] . ' $' |
155
|
10 |
|
. $element['name'] |
156
|
|
|
) |
157
|
10 |
|
->addComment('@return ' . $dataProvider->getName()) |
158
|
10 |
|
->setVisibility('public') |
159
|
10 |
|
->setBody( |
160
|
10 |
|
'$this->' . $element['name'] . ' = $' . $element['name'] . ';' . PHP_EOL . PHP_EOL |
161
|
10 |
|
. 'return $this;' |
162
|
|
|
) |
163
|
|
|
; |
164
|
|
|
|
165
|
10 |
|
$param = $setter->addParameter($element['name']) |
|
|
|
|
166
|
10 |
|
->setTypeHint($this->getTypeHint($element['type'], $element['allownull'])) |
167
|
|
|
; |
168
|
10 |
|
if ($element['default']) { |
169
|
10 |
|
$default = $this->getDefaultValue($element); |
170
|
10 |
|
$param->setDefaultValue($default); |
171
|
|
|
} |
172
|
10 |
|
elseif ($element['allownull']) { |
173
|
10 |
|
$param->setDefaultValue(null); |
174
|
|
|
} |
175
|
10 |
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* @param array $element |
179
|
|
|
* @param \Nette\PhpGenerator\ClassType $dataProvider |
180
|
|
|
* @param array $configs |
181
|
|
|
*/ |
182
|
10 |
|
private function addSingleSetter(array $element, ClassType $dataProvider, array $configs): void |
183
|
|
|
{ |
184
|
10 |
|
if (isset($element['singleton']) && $element['singleton'] !== '') { |
185
|
10 |
|
$methodName = $configs['convertUnderlines'] |
186
|
|
|
? $this->convertUnderlines($element['singleton']) |
187
|
10 |
|
: $element['singleton']; |
188
|
|
|
|
189
|
|
|
$singleSetter = $dataProvider |
190
|
10 |
|
->addMethod('add' . $methodName) |
191
|
10 |
|
->addComment( |
192
|
10 |
|
'@param ' . $element['singleton_type'] . ' $' |
193
|
10 |
|
. $element['singleton'] |
194
|
|
|
) |
195
|
10 |
|
->addComment('@return ' . $dataProvider->getName()) |
196
|
10 |
|
->setVisibility('public') |
197
|
10 |
|
->setBody( |
198
|
10 |
|
sprintf( |
199
|
10 |
|
'$this->%s[] = $%s; return $this;', |
200
|
10 |
|
$element['name'], |
201
|
10 |
|
$element['singleton'] |
202
|
|
|
) |
203
|
|
|
) |
204
|
|
|
; |
205
|
|
|
|
206
|
10 |
|
$singleSetter->addParameter($element['singleton']) |
|
|
|
|
207
|
10 |
|
->setTypeHint($element['singleton_type']) |
208
|
|
|
; |
209
|
|
|
} |
210
|
10 |
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* @param \Nette\PhpGenerator\ClassType $dataProvider |
214
|
|
|
* @param array $element |
215
|
|
|
*/ |
216
|
10 |
|
private function addProperty(ClassType $dataProvider, array $element): void |
217
|
|
|
{ |
218
|
10 |
|
$property = $dataProvider->addProperty($element['name']) |
219
|
10 |
|
->setVisibility('protected') |
220
|
10 |
|
->addComment('@var ' . $element['type']) |
221
|
|
|
; |
222
|
|
|
|
223
|
10 |
|
if ($element['default']) { |
224
|
10 |
|
$default = $this->getDefaultValue($element); |
225
|
10 |
|
$property->setValue($default); |
226
|
|
|
} |
227
|
10 |
|
elseif (strpos($element['type'], '[]') !== false) { |
228
|
10 |
|
$property->setValue([]); |
229
|
|
|
} |
230
|
10 |
|
} |
231
|
|
|
|
232
|
|
|
/** |
233
|
|
|
* @param string $type |
234
|
|
|
* @param bool $allowNull |
235
|
|
|
* |
236
|
|
|
* @return string |
237
|
|
|
*/ |
238
|
10 |
|
private function getTypeHint(string $type, bool $allowNull = null): string |
239
|
|
|
{ |
240
|
10 |
|
if (strpos($type, '[]') !== false) { |
241
|
10 |
|
$type = 'array'; |
242
|
|
|
} |
243
|
|
|
|
244
|
10 |
|
if ($allowNull === true) { |
245
|
10 |
|
$type = '?' . $type; |
246
|
|
|
} |
247
|
|
|
|
248
|
10 |
|
return $type; |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
/** |
252
|
|
|
* @param \Nette\PhpGenerator\ClassType $dataProvider |
253
|
|
|
* @param array $elements |
254
|
|
|
*/ |
255
|
10 |
|
private function addElementsGetter(ClassType $dataProvider, array $elements): void |
256
|
|
|
{ |
257
|
10 |
|
$dataProvider->addMethod('getElements') |
258
|
10 |
|
->setReturnType('array') |
259
|
10 |
|
->setVisibility('protected') |
260
|
10 |
|
->addComment('@return array') |
261
|
10 |
|
->setBody('return ' . var_export($elements, true) . ';') |
262
|
|
|
; |
263
|
10 |
|
} |
264
|
|
|
|
265
|
|
|
/** |
266
|
|
|
* @param string $providerName |
267
|
|
|
* @param array $providerData |
268
|
|
|
* @param \Nette\PhpGenerator\PhpNamespace $namespace |
269
|
|
|
* |
270
|
|
|
* @return \Nette\PhpGenerator\ClassType |
271
|
|
|
*/ |
272
|
10 |
|
private function createDataProviderClass( |
273
|
|
|
string $providerName, |
274
|
|
|
array $providerData, |
275
|
|
|
PhpNamespace $namespace |
276
|
|
|
): ClassType { |
277
|
10 |
|
$dataProvider = $this->createNewDataProvider($providerName, $namespace); |
278
|
10 |
|
$providerElements = $providerData['elements']; |
279
|
|
|
|
280
|
10 |
|
foreach ($providerElements as $element) { |
281
|
10 |
|
$this->addProperty($dataProvider, $element); |
282
|
10 |
|
$this->addGetter($dataProvider, $element, $providerData['configs']); |
283
|
10 |
|
$this->addSetter($dataProvider, $element, $providerData['configs']); |
284
|
10 |
|
$this->addUnsetter($dataProvider, $element, $providerData['configs']); |
285
|
10 |
|
$this->addHas($dataProvider, $element, $providerData['configs']); |
286
|
10 |
|
$this->addSingleSetter($element, $dataProvider, $providerData['configs']); |
287
|
|
|
|
288
|
|
|
} |
289
|
|
|
|
290
|
10 |
|
$this->addElementsGetter($dataProvider, $providerElements); |
291
|
10 |
|
return $dataProvider; |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
/** |
295
|
|
|
* @param array $element |
296
|
|
|
* |
297
|
|
|
* @return bool |
298
|
|
|
*/ |
299
|
10 |
|
private function getDefaultValue($element) |
300
|
|
|
{ |
301
|
10 |
|
$default = $element['default']; |
302
|
|
|
|
303
|
10 |
|
switch ($element['type']) { |
304
|
10 |
|
case 'bool': |
305
|
10 |
|
case 'boolean': |
306
|
|
|
{ |
307
|
10 |
|
$default = $default === 'false' ? false : $default; |
308
|
10 |
|
$default = $default === 'true' ? true : $default; |
309
|
|
|
} |
310
|
10 |
|
break; |
311
|
|
|
|
312
|
10 |
|
case 'array': |
313
|
|
|
{ |
314
|
10 |
|
$default = []; |
315
|
|
|
} |
316
|
10 |
|
break; |
317
|
|
|
|
318
|
10 |
|
case 'string': |
319
|
|
|
{ |
320
|
10 |
|
$default = $default === '\'\'' ? '' : $default; |
321
|
|
|
} |
322
|
10 |
|
break; |
323
|
|
|
} |
324
|
|
|
|
325
|
10 |
|
settype($default, $element['type']); |
326
|
10 |
|
return $default; |
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
/** |
330
|
|
|
* @param string $elementName |
331
|
|
|
* |
332
|
|
|
* @return string |
333
|
|
|
*/ |
334
|
10 |
|
private function formatElementName(string $elementName, array $configs): string |
335
|
|
|
{ |
336
|
10 |
|
$elementName = ucfirst($elementName); |
337
|
|
|
|
338
|
10 |
|
if ($configs['convertUnderlines']) { |
339
|
10 |
|
$elementName = $this->convertUnderlines($elementName); |
340
|
|
|
} |
341
|
|
|
|
342
|
10 |
|
return $elementName; |
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
/** |
346
|
|
|
* @param string $methodName |
347
|
|
|
* |
348
|
|
|
* @return string |
349
|
|
|
*/ |
350
|
10 |
|
private function convertUnderlines(string $methodName): string |
351
|
|
|
{ |
352
|
10 |
|
return preg_replace_callback( |
353
|
10 |
|
'@\_([a-z]{1,1})@', |
354
|
|
|
function ($matches) { |
355
|
10 |
|
return strtoupper($matches[1] ?? ''); |
356
|
10 |
|
}, |
357
|
10 |
|
$methodName |
358
|
|
|
); |
359
|
|
|
} |
360
|
|
|
} |
361
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.