1
|
|
|
<?php declare(strict_types=1); |
2
|
|
|
|
3
|
|
|
namespace Modelarium\Laravel\Targets; |
4
|
|
|
|
5
|
|
|
use Formularium\Datatype; |
6
|
|
|
use Formularium\Extradata; |
7
|
|
|
use Formularium\ExtradataParameter; |
8
|
|
|
use Formularium\Field; |
9
|
|
|
use Formularium\Model; |
10
|
|
|
use Illuminate\Support\Str; |
11
|
|
|
use GraphQL\Type\Definition\ListOfType; |
12
|
|
|
use GraphQL\Type\Definition\NonNull; |
13
|
|
|
use GraphQL\Type\Definition\ObjectType; |
14
|
|
|
use GraphQL\Type\Definition\UnionType; |
15
|
|
|
use Modelarium\BaseGenerator; |
16
|
|
|
use Modelarium\Datatypes\Datatype_relationship; |
17
|
|
|
use Modelarium\Datatypes\RelationshipFactory; |
18
|
|
|
use Modelarium\Exception\Exception; |
19
|
|
|
use Modelarium\FormulariumUtils; |
20
|
|
|
use Modelarium\GeneratedCollection; |
21
|
|
|
use Modelarium\GeneratedItem; |
22
|
|
|
use Modelarium\Parser; |
23
|
|
|
use Modelarium\Types\FormulariumScalarType; |
24
|
|
|
use Nette\PhpGenerator\Method; |
25
|
|
|
|
26
|
|
|
class ModelGenerator extends BaseGenerator |
27
|
|
|
{ |
28
|
|
|
/** |
29
|
|
|
* @var string |
30
|
|
|
*/ |
31
|
|
|
protected $stubDir = __DIR__ . "/stubs/"; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @var string |
35
|
|
|
*/ |
36
|
|
|
protected static $modelDir = 'app/Models/'; |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @var ObjectType |
40
|
|
|
*/ |
41
|
|
|
protected $type = null; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* @var \Nette\PhpGenerator\ClassType |
45
|
|
|
*/ |
46
|
|
|
public $class = null; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* fillable attributes |
50
|
|
|
* |
51
|
|
|
* @var array |
52
|
|
|
*/ |
53
|
|
|
public $fillable = []; |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* fillable attributes |
57
|
|
|
* |
58
|
|
|
* @var array |
59
|
|
|
*/ |
60
|
|
|
public $hidden = []; |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* cast attributes |
64
|
|
|
* |
65
|
|
|
* @var array |
66
|
|
|
*/ |
67
|
|
|
public $casts = []; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* |
71
|
|
|
* @var string |
72
|
|
|
*/ |
73
|
|
|
public $parentClassName = '\Illuminate\Database\Eloquent\Model'; |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* fields |
77
|
|
|
* |
78
|
|
|
* @var Model |
79
|
|
|
*/ |
80
|
|
|
public $fModel = null; |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* |
84
|
|
|
* @var array |
85
|
|
|
*/ |
86
|
|
|
public $traits = []; |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* Random generation |
90
|
|
|
* |
91
|
|
|
* @var Method |
92
|
|
|
*/ |
93
|
|
|
protected $methodRandom = null; |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* Do we have a 'can' attribute? |
97
|
|
|
* |
98
|
|
|
* @var boolean |
99
|
|
|
*/ |
100
|
|
|
protected $hasCan = true; |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* If true, we have timestamps on the migration. |
104
|
|
|
* |
105
|
|
|
* @var boolean |
106
|
|
|
*/ |
107
|
|
|
public $migrationTimestamps = false; |
108
|
|
|
|
109
|
10 |
|
public function generate(): GeneratedCollection |
110
|
|
|
{ |
111
|
10 |
|
$this->fModel = Model::create($this->studlyName); |
112
|
10 |
|
$x = new GeneratedCollection([ |
113
|
10 |
|
new GeneratedItem( |
114
|
10 |
|
GeneratedItem::TYPE_MODEL, |
115
|
10 |
|
$this->generateString(), |
116
|
10 |
|
$this->getGenerateFilename() |
117
|
|
|
), |
118
|
10 |
|
new GeneratedItem( |
119
|
10 |
|
GeneratedItem::TYPE_MODEL, |
120
|
10 |
|
$this->templateStub('model'), |
121
|
10 |
|
$this->getGenerateFilename(false), |
122
|
10 |
|
true |
123
|
|
|
) |
124
|
|
|
]); |
125
|
10 |
|
return $x; |
126
|
|
|
} |
127
|
|
|
|
128
|
10 |
|
protected function processField( |
129
|
|
|
string $typeName, |
130
|
|
|
\GraphQL\Type\Definition\FieldDefinition $field, |
131
|
|
|
\GraphQL\Language\AST\NodeList $directives, |
132
|
|
|
bool $isRequired |
133
|
|
|
): void { |
134
|
10 |
|
$fieldName = $field->name; |
135
|
|
|
|
136
|
10 |
|
if ($typeName === 'ID') { |
137
|
10 |
|
return; |
138
|
|
|
} |
139
|
|
|
|
140
|
10 |
|
$scalarType = $this->parser->getScalarType($typeName); |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* @var Field $field |
144
|
|
|
*/ |
145
|
10 |
|
$field = null; |
146
|
10 |
|
if (!$scalarType) { |
147
|
|
|
// probably another model |
148
|
8 |
|
$field = FormulariumUtils::getFieldFromDirectives( |
149
|
8 |
|
$fieldName, |
150
|
8 |
|
$typeName, |
151
|
8 |
|
$directives |
152
|
|
|
); |
153
|
5 |
|
} elseif ($scalarType instanceof FormulariumScalarType) { |
154
|
5 |
|
$field = FormulariumUtils::getFieldFromDirectives( |
155
|
5 |
|
$fieldName, |
156
|
5 |
|
$scalarType->getDatatype()->getName(), |
157
|
5 |
|
$directives |
158
|
|
|
); |
159
|
|
|
} else { |
160
|
|
|
return; |
161
|
|
|
} |
162
|
|
|
|
163
|
10 |
|
if ($isRequired) { |
164
|
10 |
|
$field->setValidatorOption( |
165
|
10 |
|
Datatype::REQUIRED, |
166
|
10 |
|
'value', |
167
|
10 |
|
true |
168
|
|
|
); |
169
|
|
|
} |
170
|
|
|
|
171
|
10 |
|
$this->fModel->appendField($field); |
172
|
10 |
|
} |
173
|
|
|
|
174
|
10 |
|
protected function processFieldDirectives( |
175
|
|
|
\GraphQL\Type\Definition\FieldDefinition $field, |
176
|
|
|
\GraphQL\Language\AST\NodeList $directives |
177
|
|
|
): void { |
178
|
10 |
|
list($type, $isRequired) = Parser::getUnwrappedType($field->type); |
179
|
|
|
|
180
|
10 |
|
foreach ($directives as $directive) { |
181
|
|
|
$name = $directive->name->value; |
182
|
|
|
$className = $this->getDirectiveClass($name); |
183
|
|
|
if ($className) { |
184
|
|
|
$methodName = "$className::processModelFieldDirective"; |
185
|
|
|
/** @phpstan-ignore-next-line */ |
186
|
|
|
$methodName( |
187
|
|
|
$this, |
188
|
|
|
$field, |
189
|
|
|
$directive |
190
|
|
|
); |
191
|
|
|
} |
192
|
|
|
} |
193
|
|
|
|
194
|
10 |
|
$typeName = $type->name; |
195
|
10 |
|
$this->processField($typeName, $field, $directives, $isRequired); |
196
|
10 |
|
} |
197
|
|
|
|
198
|
8 |
|
protected function processRelationship( |
199
|
|
|
\GraphQL\Type\Definition\FieldDefinition $field, |
200
|
|
|
\GraphQL\Language\AST\NodeList $directives |
201
|
|
|
): void { |
202
|
8 |
|
$lowerName = mb_strtolower($this->getInflector()->singularize($field->name)); |
203
|
8 |
|
$lowerNamePlural = $this->getInflector()->pluralize($lowerName); |
204
|
|
|
|
205
|
8 |
|
$targetClass = '\\App\\Models\\' . Str::studly($this->getInflector()->singularize($field->name)); |
206
|
|
|
|
207
|
8 |
|
list($type, $isRequired) = Parser::getUnwrappedType($field->type); |
208
|
8 |
|
$typeName = $type->name; |
209
|
|
|
|
210
|
|
|
// special types that should be skipped. |
211
|
8 |
|
if ($typeName === 'Can') { |
212
|
|
|
$this->hasCan = true; |
213
|
|
|
return; |
214
|
|
|
} |
215
|
|
|
|
216
|
8 |
|
$generateRandom = false; |
217
|
8 |
|
$sourceTypeName = $this->lowerName; |
218
|
8 |
|
$targetTypeName = $lowerName; |
219
|
8 |
|
$relationship = null; |
220
|
8 |
|
$isInverse = false; |
221
|
|
|
|
222
|
8 |
|
foreach ($directives as $directive) { |
223
|
8 |
|
$name = $directive->name->value; |
224
|
8 |
|
$className = $this->getDirectiveClass($name); |
225
|
8 |
|
if ($className) { |
226
|
|
|
$methodName = "$className::processModelFieldDirective"; |
227
|
|
|
/** @phpstan-ignore-next-line */ |
228
|
|
|
$methodName( |
229
|
|
|
$this, |
230
|
|
|
$field, |
231
|
|
|
$directive |
232
|
|
|
); |
233
|
|
|
continue; |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
// TODO: convert to separate classes |
237
|
8 |
|
switch ($name) { |
238
|
8 |
|
case 'belongsTo': |
239
|
4 |
|
$generateRandom = true; |
240
|
4 |
|
$relationship = RelationshipFactory::RELATIONSHIP_ONE_TO_MANY; |
241
|
4 |
|
$isInverse = true; |
242
|
4 |
|
$this->class->addMethod($lowerName) |
243
|
4 |
|
->setPublic() |
244
|
4 |
|
->setReturnType('\\Illuminate\\Database\\Eloquent\\Relations\\BelongsTo') |
245
|
4 |
|
->setBody("return \$this->belongsTo($targetClass::class);"); |
246
|
4 |
|
break; |
247
|
|
|
|
248
|
8 |
|
case 'belongsToMany': |
249
|
1 |
|
$generateRandom = true; |
250
|
1 |
|
$relationship = RelationshipFactory::RELATIONSHIP_MANY_TO_MANY; |
251
|
1 |
|
$isInverse = true; |
252
|
1 |
|
$this->class->addMethod($lowerNamePlural) |
253
|
1 |
|
->setPublic() |
254
|
1 |
|
->setReturnType('\\Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany') |
255
|
1 |
|
->setBody("return \$this->belongsToMany($targetClass::class);"); |
256
|
1 |
|
break; |
257
|
|
|
|
258
|
7 |
|
case 'hasOne': |
259
|
3 |
|
$relationship = RelationshipFactory::RELATIONSHIP_ONE_TO_ONE; |
260
|
3 |
|
$isInverse = false; |
261
|
3 |
|
$this->class->addMethod($lowerName) |
262
|
3 |
|
->setPublic() |
263
|
3 |
|
->setReturnType('\\Illuminate\\Database\\Eloquent\\Relations\\HasOne') |
264
|
3 |
|
->setBody("return \$this->hasOne($targetClass::class);"); |
265
|
3 |
|
break; |
266
|
|
|
|
267
|
7 |
|
case 'hasMany': |
268
|
1 |
|
$relationship = RelationshipFactory::RELATIONSHIP_ONE_TO_MANY; |
269
|
1 |
|
$isInverse = false; |
270
|
1 |
|
$target = $this->getInflector()->singularize($targetClass); |
271
|
1 |
|
$this->class->addMethod($lowerNamePlural) |
272
|
1 |
|
->setPublic() |
273
|
1 |
|
->setReturnType('\\Illuminate\\Database\\Eloquent\\Relations\\HasMany') |
274
|
1 |
|
->setBody("return \$this->hasMany($target::class);"); |
275
|
1 |
|
break; |
276
|
|
|
|
277
|
7 |
|
case 'morphOne': |
278
|
7 |
|
case 'morphMany': |
279
|
7 |
|
case 'morphToMany': |
280
|
3 |
|
if ($name === 'morphOne') { |
281
|
1 |
|
$relationship = RelationshipFactory::MORPH_ONE_TO_ONE; |
282
|
|
|
} else { |
283
|
2 |
|
$relationship = RelationshipFactory::MORPH_ONE_TO_MANY; |
284
|
|
|
} |
285
|
3 |
|
$isInverse = false; |
286
|
|
|
|
287
|
3 |
|
$targetType = $this->parser->getType($typeName); |
288
|
3 |
|
if (!$targetType) { |
289
|
|
|
throw new Exception("Cannot get type {$typeName} as a relationship to {$this->baseName}"); |
290
|
3 |
|
} elseif (!($targetType instanceof ObjectType)) { |
291
|
|
|
throw new Exception("{$typeName} is not a type for a relationship to {$this->baseName}"); |
292
|
|
|
} |
293
|
3 |
|
$targetField = null; |
294
|
3 |
|
foreach ($targetType->getFields() as $subField) { |
295
|
3 |
|
$subDir = Parser::getDirectives($subField->astNode->directives); |
296
|
3 |
|
if (array_key_exists('morphTo', $subDir) || array_key_exists('morphedByMany', $subDir)) { |
297
|
3 |
|
$targetField = $subField->name; |
298
|
3 |
|
break; |
299
|
|
|
} |
300
|
|
|
} |
301
|
3 |
|
if (!$targetField) { |
302
|
|
|
throw new Exception("{$targetType} does not have a '@morphTo' or '@morphToMany' field"); |
303
|
|
|
} |
304
|
|
|
|
305
|
3 |
|
$this->class->addMethod($field->name) |
306
|
|
|
// TODO: return type |
307
|
3 |
|
->setPublic() |
308
|
3 |
|
->setBody("return \$this->{$name}($typeName::class, '$targetField');"); |
309
|
3 |
|
break; |
310
|
|
|
|
311
|
7 |
|
case 'morphTo': |
312
|
2 |
|
$relationship = RelationshipFactory::MORPH_ONE_TO_MANY; // TODO |
313
|
2 |
|
$isInverse = true; |
314
|
2 |
|
$this->class->addMethod($field->name) |
315
|
2 |
|
->setReturnType('\\Illuminate\\Database\\Eloquent\\Relations\\MorphTo') |
316
|
2 |
|
->setPublic() |
317
|
2 |
|
->setBody("return \$this->morphTo();"); |
318
|
2 |
|
break; |
319
|
|
|
|
320
|
5 |
|
case 'morphedByMany': |
321
|
1 |
|
$relationship = RelationshipFactory::MORPH_MANY_TO_MANY; // TODO |
322
|
1 |
|
$isInverse = true; |
323
|
1 |
|
$typeMap = $this->parser->getSchema()->getTypeMap(); |
324
|
|
|
|
325
|
1 |
|
foreach ($typeMap as $name => $object) { |
326
|
1 |
|
if (!($object instanceof ObjectType) || $name === 'Query' || $name === 'Mutation' || $name === 'Subscription') { |
327
|
1 |
|
continue; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* @var ObjectType $object |
332
|
|
|
*/ |
333
|
|
|
|
334
|
1 |
|
if (str_starts_with((string)$name, '__')) { |
335
|
|
|
// internal type |
336
|
1 |
|
continue; |
337
|
|
|
} |
338
|
|
|
|
339
|
1 |
|
foreach ($object->getFields() as $subField) { |
340
|
1 |
|
$subDirectives = Parser::getDirectives($subField->astNode->directives); |
341
|
|
|
|
342
|
1 |
|
if (!array_key_exists('morphToMany', $subDirectives)) { |
343
|
1 |
|
continue; |
344
|
|
|
} |
345
|
|
|
|
346
|
1 |
|
$methodName = $this->getInflector()->pluralize(mb_strtolower((string)$name)); |
347
|
1 |
|
$this->class->addMethod($methodName) |
348
|
1 |
|
->setReturnType('\\Illuminate\\Database\\Eloquent\\Relations\\MorphToMany') |
349
|
1 |
|
->setPublic() |
350
|
1 |
|
->setBody("return \$this->morphedByMany($name::class, '$lowerName');"); |
351
|
|
|
} |
352
|
|
|
} |
353
|
1 |
|
break; |
354
|
|
|
|
355
|
|
|
default: |
356
|
4 |
|
break; |
357
|
|
|
} |
358
|
|
|
} |
359
|
8 |
|
if (!$relationship) { |
360
|
|
|
// TODO: generate a warning, perhaps? |
361
|
|
|
// throw new Exception("Could not find a relationship in {$typeName} for {$field->name} in {$sourceTypeName}"); |
362
|
|
|
return; |
363
|
|
|
} |
364
|
|
|
|
365
|
8 |
|
$relationshipDatatype = "relationship:" . ($isInverse ? "inverse:" : "") . |
366
|
8 |
|
"$relationship:$sourceTypeName:$targetTypeName"; |
367
|
|
|
|
368
|
8 |
|
$this->processField($relationshipDatatype, $field, $directives, $isRequired); |
369
|
|
|
|
370
|
8 |
|
if ($generateRandom) { |
371
|
5 |
|
if ($relationship == RelationshipFactory::RELATIONSHIP_MANY_TO_MANY || $relationship == RelationshipFactory::MORPH_MANY_TO_MANY) { |
372
|
|
|
// TODO: do we generate it? seed should do it? |
373
|
|
|
} else { |
374
|
4 |
|
$this->methodRandom->addBody( |
375
|
4 |
|
'$data["' . $lowerName . '_id"] = function () {' . "\n" . |
376
|
4 |
|
' return factory(' . $targetClass . '::class)->create()->id;' . "\n" . |
377
|
4 |
|
'};' |
378
|
|
|
); |
379
|
|
|
} |
380
|
|
|
} |
381
|
8 |
|
} |
382
|
|
|
|
383
|
10 |
|
protected function processDirectives( |
384
|
|
|
\GraphQL\Language\AST\NodeList $directives |
385
|
|
|
): void { |
386
|
10 |
|
foreach ($directives as $directive) { |
387
|
1 |
|
$name = $directive->name->value; |
388
|
1 |
|
$this->fModel->appendExtradata(FormulariumUtils::directiveToExtradata($directive)); |
389
|
|
|
|
390
|
1 |
|
$className = $this->getDirectiveClass($name); |
391
|
1 |
|
if ($className) { |
392
|
1 |
|
$methodName = "$className::processModelTypeDirective"; |
393
|
|
|
/** @phpstan-ignore-next-line */ |
394
|
1 |
|
$methodName( |
395
|
1 |
|
$this, |
396
|
|
|
$directive |
397
|
|
|
); |
398
|
|
|
} |
399
|
|
|
} |
400
|
10 |
|
} |
401
|
|
|
|
402
|
10 |
|
public function generateString(): string |
403
|
|
|
{ |
404
|
10 |
|
$namespace = new \Nette\PhpGenerator\PhpNamespace('App\\Models'); |
405
|
10 |
|
$namespace->addUse('\\Illuminate\\Database\\Eloquent\\Relations\\BelongsTo'); |
406
|
10 |
|
$namespace->addUse('\\Illuminate\\Database\\Eloquent\\Relations\\HasOne'); |
407
|
10 |
|
$namespace->addUse('\\Illuminate\\Database\\Eloquent\\Relations\\HasMany'); |
408
|
10 |
|
$namespace->addUse('\\Illuminate\\Database\\Eloquent\\Relations\\MorphTo'); |
409
|
10 |
|
$namespace->addUse('\\Illuminate\\Database\\Eloquent\\Relations\\MorphOne'); |
410
|
10 |
|
$namespace->addUse('\\Illuminate\\Database\\Eloquent\\Relations\\MorphToMany'); |
411
|
10 |
|
$namespace->addUse('\\Illuminate\\Support\\Facades\\Auth'); |
412
|
10 |
|
$namespace->addUse('\\Formularium\\Exception\\NoRandomException'); |
413
|
10 |
|
$namespace->addUse('\\Modelarium\\Laravel\\Datatypes\\Datatype_relationship'); |
414
|
|
|
|
415
|
10 |
|
$this->class = $namespace->addClass('Base' . $this->studlyName); |
416
|
10 |
|
$this->class |
417
|
10 |
|
->addComment("This file was automatically generated by Modelarium.") |
418
|
10 |
|
->setAbstract(); |
419
|
|
|
|
420
|
10 |
|
$this->methodRandom = new Method('getRandomData'); |
421
|
10 |
|
$this->methodRandom->addBody( |
422
|
10 |
|
'$data = static::getFormularium()->getRandom(get_called_class() . \'::getRandomFieldData\');' . "\n" |
423
|
|
|
); |
424
|
|
|
|
425
|
10 |
|
$this->processGraphql(); |
426
|
|
|
|
427
|
|
|
// this might have changed |
428
|
10 |
|
$this->class->setExtends($this->parentClassName); |
429
|
|
|
|
430
|
10 |
|
foreach ($this->traits as $trait) { |
431
|
1 |
|
$this->class->addTrait($trait); |
432
|
|
|
} |
433
|
|
|
|
434
|
10 |
|
$this->class->addProperty('fillable') |
435
|
10 |
|
->setProtected() |
436
|
10 |
|
->setValue($this->fillable) |
437
|
10 |
|
->setComment("The attributes that are mass assignable.\n@var array") |
438
|
10 |
|
->setInitialized(); |
439
|
|
|
|
440
|
10 |
|
$this->class->addProperty('hidden') |
441
|
10 |
|
->setProtected() |
442
|
10 |
|
->setValue($this->hidden) |
443
|
10 |
|
->setComment("The attributes that should be hidden for arrays.\n@var array") |
444
|
10 |
|
->setInitialized(); |
445
|
|
|
|
446
|
10 |
|
if (!$this->migrationTimestamps) { |
447
|
9 |
|
$this->class->addProperty('timestamps') |
448
|
9 |
|
->setPublic() |
449
|
9 |
|
->setValue(false) |
450
|
9 |
|
->setComment("Do not set timestamps.\n@var boolean") |
451
|
9 |
|
->setInitialized(); |
452
|
|
|
} |
453
|
|
|
|
454
|
10 |
|
if ($this->casts) { |
|
|
|
|
455
|
|
|
$this->class->addProperty('casts') |
456
|
|
|
->setProtected() |
457
|
|
|
->setValue($this->casts) |
458
|
|
|
->setComment("The attributes that should be cast.\n@var array") |
459
|
|
|
->setInitialized(); |
460
|
|
|
} |
461
|
|
|
|
462
|
10 |
|
$this->class->addMethod('getFields') |
463
|
10 |
|
->setPublic() |
464
|
10 |
|
->setStatic() |
465
|
10 |
|
->setReturnType('array') |
466
|
10 |
|
->addComment('@return array') |
467
|
10 |
|
->addBody( |
468
|
10 |
|
"return ?;\n", |
469
|
|
|
[ |
470
|
10 |
|
$this->fModel->serialize() |
471
|
|
|
] |
472
|
|
|
); |
473
|
|
|
|
474
|
10 |
|
$this->class->addMethod('getFormularium') |
475
|
10 |
|
->setPublic() |
476
|
10 |
|
->setStatic() |
477
|
10 |
|
->setReturnType('\Formularium\Model') |
478
|
10 |
|
->addComment('@return \Formularium\Model') |
479
|
10 |
|
->addBody( |
480
|
|
|
'$model = \Formularium\Model::fromStruct(static::getFields());' . "\n" . |
481
|
10 |
|
'return $model;', |
482
|
|
|
[ |
483
|
|
|
//$this->studlyName, |
484
|
10 |
|
] |
485
|
|
|
); |
486
|
|
|
|
487
|
10 |
|
$this->methodRandom |
488
|
10 |
|
->addComment('@return array') |
489
|
10 |
|
->setPublic() |
490
|
10 |
|
->setStatic() |
491
|
10 |
|
->setReturnType('array') |
492
|
10 |
|
->addBody('return $data;'); |
493
|
10 |
|
$this->class->addMember($this->methodRandom); |
494
|
|
|
|
495
|
10 |
|
$this->class->addMethod('getRandomFieldData') |
496
|
10 |
|
->setPublic() |
497
|
10 |
|
->setStatic() |
498
|
10 |
|
->addComment("Filters fields and generate random data. Throw NoRandomException for fields you don't want to generate random data, or return a valid value.") |
499
|
10 |
|
->addBody(' |
500
|
|
|
$d = $f->getDatatype(); |
501
|
|
|
if ($d instanceof Datatype_relationship) { |
502
|
|
|
throw new NoRandomException($f->getName()); |
503
|
|
|
} |
504
|
|
|
return $f->getDatatype()->getRandom();') |
505
|
10 |
|
->addParameter('f')->setType('Formularium\Field'); |
506
|
|
|
|
507
|
|
|
// TODO perhaps we can use PolicyGenerator->policyClasses to auto generate |
508
|
10 |
|
if ($this->hasCan) { |
509
|
10 |
|
$this->class->addMethod('getCanAttribute') |
510
|
10 |
|
->setPublic() |
511
|
10 |
|
->setReturnType('array') |
512
|
10 |
|
->addComment("Returns the policy permissions for actions such as editing or deleting.\n@return \Formularium\Model") |
513
|
10 |
|
->addBody( |
514
|
10 |
|
'$policy = new \\App\\Policies\\' . $this->studlyName . 'Policy();' . "\n" . |
515
|
10 |
|
'$user = Auth::user();' . "\n" . |
516
|
10 |
|
'return [' . "\n" . |
517
|
10 |
|
' //[ "ability" => "create", "value" => $policy->create($user) ]' . "\n" . |
518
|
10 |
|
'];' |
519
|
|
|
); |
520
|
|
|
} |
521
|
|
|
|
522
|
10 |
|
$printer = new \Nette\PhpGenerator\PsrPrinter; |
523
|
10 |
|
return $this->phpHeader() . $printer->printNamespace($namespace); |
524
|
|
|
} |
525
|
|
|
|
526
|
10 |
|
protected function processGraphql(): void |
527
|
|
|
{ |
528
|
10 |
|
foreach ($this->type->getFields() as $field) { |
529
|
10 |
|
$directives = $field->astNode->directives; |
530
|
|
|
if ( |
531
|
10 |
|
($field->type instanceof ObjectType) || |
532
|
10 |
|
($field->type instanceof ListOfType) || |
533
|
10 |
|
($field->type instanceof UnionType) || |
534
|
10 |
|
($field->type instanceof NonNull && ( |
535
|
10 |
|
($field->type->getWrappedType() instanceof ObjectType) || |
536
|
10 |
|
($field->type->getWrappedType() instanceof ListOfType) || |
537
|
10 |
|
($field->type->getWrappedType() instanceof UnionType) |
538
|
|
|
)) |
539
|
|
|
) { |
540
|
|
|
// relationship |
541
|
8 |
|
$this->processRelationship($field, $directives); |
542
|
|
|
} else { |
543
|
10 |
|
$this->processFieldDirectives($field, $directives); |
544
|
|
|
} |
545
|
|
|
} |
546
|
|
|
|
547
|
|
|
/** |
548
|
|
|
* @var \GraphQL\Language\AST\NodeList|null |
549
|
|
|
*/ |
550
|
10 |
|
$directives = $this->type->astNode->directives; |
551
|
10 |
|
if ($directives) { |
552
|
10 |
|
$this->processDirectives($directives); |
|
|
|
|
553
|
|
|
} |
554
|
10 |
|
} |
555
|
|
|
|
556
|
10 |
|
public function getGenerateFilename(bool $base = true): string |
557
|
|
|
{ |
558
|
10 |
|
return $this->getBasePath(self::$modelDir . '/' . ($base ? 'Base' : '') . $this->studlyName . '.php'); |
559
|
|
|
} |
560
|
|
|
|
561
|
|
|
public static function setModelDir(string $dir): void |
562
|
|
|
{ |
563
|
|
|
self::$modelDir = $dir; |
564
|
|
|
} |
565
|
|
|
} |
566
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.