1
|
|
|
<?php namespace Wn\Generators\Commands; |
2
|
|
|
|
3
|
|
|
use InvalidArgumentException; |
4
|
|
|
use Symfony\Component\Yaml\Yaml; |
5
|
|
|
|
6
|
|
|
|
7
|
|
|
class ResourcesCommand extends BaseCommand { |
8
|
|
|
|
9
|
|
|
protected $signature = 'wn:resources |
10
|
|
|
{files* : Paths to the files containing resources declarations} |
11
|
|
|
{--path= : where to store the model files.} |
12
|
|
|
{--routes= : where to store the routes.} |
13
|
|
|
{--no-routes : do not add routes.} |
14
|
|
|
{--controllers= : where to store the controllers.} |
15
|
|
|
{--no-controllers : do not generate controllers.} |
16
|
|
|
{--no-migration : do not migrate.} |
17
|
|
|
{--check-only : only check supplied files for valide relationships.} |
18
|
|
|
{--skip-check : skip validity check before processing.} |
19
|
|
|
{--force= : override the existing files} |
20
|
|
|
{--force-redefine : Force model redefinition.} |
21
|
|
|
{--laravel= : Use Laravel style route definitions} |
22
|
|
|
'; |
23
|
|
|
|
24
|
|
|
protected $description = 'Generates multiple resources from a couple of files'; |
25
|
|
|
|
26
|
|
|
protected $pivotTables = []; |
27
|
|
|
protected $morphTables = []; |
28
|
|
|
|
29
|
|
|
private $checkedErrors = 0; |
30
|
|
|
private $checkErrors = []; |
31
|
|
|
private $checkInfo = []; |
32
|
|
|
|
33
|
|
|
public function handle() |
34
|
|
|
{ |
35
|
|
|
$files = $this->argument('files'); |
36
|
|
|
$nodes = []; |
37
|
|
|
|
38
|
|
|
if (empty($files)) { |
39
|
|
|
$this->error("No resource file(s) supplied!"); |
40
|
|
|
return; |
41
|
|
|
} |
42
|
|
|
if (is_string($files)) { |
43
|
|
|
$files = [ $files ]; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
foreach ($files as $file) { |
47
|
|
|
$nodes = $this->mergeNodes($nodes, $this->readFile($file), $this->option('force-redefine')); |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
$this->line(''); |
51
|
|
|
$this->info('Bringing models to order...'); |
52
|
|
|
|
53
|
|
|
$nodes = $this->sortDependencies($nodes); |
54
|
|
|
$pivotTables = $this->uniqueArray($this->getTables($nodes, 'pivotTables')); |
55
|
|
|
$morphTables = $this->uniqueArray($this->getTables($nodes, 'morphTables')); |
56
|
|
|
|
57
|
|
|
if (! $this->option('skip-check')) { |
58
|
|
|
$this->info('Checking Relationships...'); |
59
|
|
|
$keys = array_keys($nodes); |
60
|
|
|
foreach ($nodes as $model => $i) { |
61
|
|
|
$this->checkRelations($i['belongsTo'], 'belongsTo', $i['filename'], $i['uniquename'], $keys); |
62
|
|
|
// $this->checkRelations($i['hasManyThrough'], 'hasManyThrough', $file, $model); |
63
|
|
|
} |
64
|
|
|
$this->checkPivotRelations($nodes, $pivotTables, 'pivot'); |
65
|
|
|
$this->checkPivotRelations($nodes, $morphTables, 'morph'); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
View Code Duplication |
if ($this->checkedErrors > 0) { |
|
|
|
|
69
|
|
|
$this->line(''); |
70
|
|
|
if ($this->option('check-only')) { |
71
|
|
|
$this->info('Checking only, we have found ' . $this->checkedErrors . ' errors.'); |
72
|
|
|
} |
73
|
|
|
$this->printErrors(); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
$proceed = (! $this->option('check-only') && $this->checkedErrors == 0) || $this->option('skip-check'); |
77
|
|
View Code Duplication |
if (! $this->option('check-only') && $this->checkedErrors > 0) { |
|
|
|
|
78
|
|
|
$this->line(''); |
79
|
|
|
$proceed = $this->confirm("We have found " . $this->checkedErrors . " errors. Are you sure you want to continue?"); |
80
|
|
|
} |
81
|
|
|
if ($proceed) { |
82
|
|
|
$this->buildResources($nodes); |
83
|
|
|
|
84
|
|
|
// if (!$this->option('no-migration')) { |
85
|
|
|
// $this->call('migrate'); // actually needed for pivot seeders ! |
86
|
|
|
// } |
87
|
|
|
|
88
|
|
|
$this->line(''); |
89
|
|
|
$this->buildTables('Pivot-Table', 'wn:pivot-table', 'model1', 'model2', $pivotTables); |
90
|
|
|
|
91
|
|
|
$this->line(''); |
92
|
|
|
$this->buildTables('Morph-Table', 'wn:morph-table', 'model', 'morphable', $morphTables); |
93
|
|
|
|
94
|
|
|
if (!$this->option('no-migration')) { |
95
|
|
|
$this->call('migrate'); |
96
|
|
|
} |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
protected function uniqueArray($array) |
101
|
|
|
{ |
102
|
|
|
return array_map( |
103
|
|
|
'unserialize', |
104
|
|
|
array_unique(array_map('serialize', $array)) |
105
|
|
|
); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
protected function readFile($file) |
109
|
|
|
{ |
110
|
|
|
$this->info("Reading file ".$file); |
111
|
|
|
|
112
|
|
|
$content = $this->fs->get($file); |
113
|
|
|
$content = Yaml::parse($content); |
114
|
|
|
|
115
|
|
|
$nodes = []; |
116
|
|
|
|
117
|
|
|
foreach ($content as $model => $i){ |
118
|
|
|
/* |
119
|
|
|
$i['modelname'] = as originally in YAML defined |
120
|
|
|
$i['name'] = as originally defined in snake_case |
121
|
|
|
$i['uniquename']= for key in singular studly_case |
122
|
|
|
*/ |
123
|
|
|
$i['filename'] = $file; |
124
|
|
|
$i['modelname'] = $model; |
125
|
|
|
$model = studly_case(str_singular($model)); |
126
|
|
|
$i['uniquename'] = $model; |
127
|
|
|
|
128
|
|
|
$nodes[] = $this->getResourceParams($i); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
return $nodes; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
protected function mergeNodes($nodes, $toMerge, $forceRedefinition = false) { |
135
|
|
|
foreach($toMerge as $node) { |
136
|
|
|
$nodes = $this->mergeNode($nodes, $node, $forceRedefinition); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
return $nodes; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
protected function mergeNode($nodes, $toMerge, $forceRedefinition = false) { |
143
|
|
|
if (empty($nodes[$toMerge['uniquename']]) || $forceRedefinition) { |
144
|
|
|
if (!empty($nodes[$toMerge['uniquename']])) { |
145
|
|
|
$this->checkError($toMerge['uniquename'] . ": forced to redefine (in file " . $nodes[$toMerge['uniquename']]['filename'] . ", redefined from file ".$toMerge['filename'].")"); |
146
|
|
|
} |
147
|
|
|
$nodes[$toMerge['uniquename']] = $toMerge; |
148
|
|
|
} else { |
149
|
|
|
$this->checkError($toMerge['uniquename'] . ": already defined (in file " . $nodes[$toMerge['uniquename']]['filename'] . ", trying to redefine from file ".$toMerge['filename']."; Use --force-redefine to force redefinition)"); |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
return $nodes; |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
protected function getTables($nodes, $key) { |
156
|
|
|
$tables = []; |
157
|
|
|
foreach($nodes as $node) { |
158
|
|
|
if (!empty($node[$key])) { |
159
|
|
|
$tables = array_merge($tables, $node[$key]); |
160
|
|
|
} |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
return $tables; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
protected function buildResources($nodes) |
167
|
|
|
{ |
168
|
|
|
$modelIndex = 0; |
169
|
|
|
$migrationIdLength = strlen((string)count($nodes)); |
170
|
|
|
foreach ($nodes as $i) { |
171
|
|
|
$migrationName = 'Create' . ucwords(str_plural($i['name'])); |
172
|
|
|
$migrationFile = date('Y_m_d_His') . '-' . str_pad($modelIndex , $migrationIdLength, 0, STR_PAD_LEFT) . '_' . snake_case($migrationName) . '_table'; |
173
|
|
|
|
174
|
|
|
$this->line(''); |
175
|
|
|
$this->info('Building Model ' . $i['uniquename']); |
176
|
|
|
|
177
|
|
|
$options = [ |
178
|
|
|
'name' => $i['name'], |
179
|
|
|
'fields' => $i['fields'], |
180
|
|
|
'--add' => $i['add'], |
181
|
|
|
'--has-many' => $i['hasMany'], |
182
|
|
|
'--has-one' => $i['hasOne'], |
183
|
|
|
'--belongs-to' => $i['belongsTo'], |
184
|
|
|
'--belongs-to-many' => $i['belongsToMany'], |
185
|
|
|
'--has-many-through' => $i['hasManyThrough'], |
186
|
|
|
'--morph-to' => $i['morphTo'], |
187
|
|
|
'--morph-many' => $i['morphMany'], |
188
|
|
|
'--morph-to-many' => $i['morphToMany'], |
189
|
|
|
'--morphed-by-many' => $i['morphedByMany'], |
190
|
|
|
'--no-routes' => $this->option('no-routes'), |
191
|
|
|
'--no-controller' => $this->option('no-controllers'), |
192
|
|
|
'--force' => $this->option('force'), |
193
|
|
|
'--migration-file' => $migrationFile, |
194
|
|
|
]; |
195
|
|
|
if ($this->option('laravel')) { |
196
|
|
|
$options['--laravel'] = true; |
197
|
|
|
} |
198
|
|
|
if ($this->option('routes')) { |
199
|
|
|
$options['--routes'] = $this->option('routes'); |
200
|
|
|
} |
201
|
|
|
if ($this->option('controllers')) { |
202
|
|
|
$options['--controller'] = $this->option('controllers'); |
203
|
|
|
} |
204
|
|
|
if ($this->option('path')) { |
205
|
|
|
$options['--path'] = $this->option('path'); |
206
|
|
|
} |
207
|
|
|
|
208
|
|
|
$this->call('wn:resource', $options); |
209
|
|
|
$modelIndex++; |
210
|
|
|
} |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
protected function buildTables($type, $command, $model1, $model2, $tableAssignment) |
214
|
|
|
{ |
215
|
|
|
foreach ($tableAssignment as $tables) { |
216
|
|
|
$this->info('Building '.$type.' ' . $tables[0] . ' - ' . $tables[1]); |
217
|
|
|
$this->call($command, [ |
218
|
|
|
$model1 => $tables[0], |
219
|
|
|
$model2 => $tables[1], |
220
|
|
|
'--force' => $this->option('force') |
221
|
|
|
]); |
222
|
|
|
|
223
|
|
|
// $this->call('wn:pivot-seeder', [ |
224
|
|
|
// 'model1' => $tables[0], |
225
|
|
|
// 'model2' => $tables[1], |
226
|
|
|
// '--force' => $this->option('force') |
227
|
|
|
// ]); |
228
|
|
|
} |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
protected function getResourceParams($i) |
232
|
|
|
{ |
233
|
|
|
$modelName = $i['modelname']; |
234
|
|
|
|
235
|
|
|
$i['filename'] = $i['filename']; |
236
|
|
|
$i['name'] = snake_case($modelName); |
237
|
|
|
$i['modelname'] = $i['modelname']; |
238
|
|
|
$i['uniquename'] = $i['uniquename']; |
239
|
|
|
|
240
|
|
|
foreach(['hasMany', 'hasOne', 'add', 'belongsTo', 'belongsToMany', 'hasManyThrough', 'morphTo', 'morphMany', 'morphToMany', 'morphedByMany'] as $relation){ |
241
|
|
|
if(isset($i[$relation])){ |
242
|
|
|
$i[$relation] = $this->convertArray($i[$relation], ' ', ','); |
243
|
|
|
} else { |
244
|
|
|
$i[$relation] = false; |
245
|
|
|
} |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
if($i['belongsToMany']){ |
249
|
|
|
$i['pivotTables'] = $this->belongsTo($i['name'], $modelName, $i['belongsToMany']); |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
if($i['morphToMany']){ |
253
|
|
|
$i['morphTables'] = $this->morphToMany($modelName, $i['morphToMany']); |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
if($i['morphedByMany']){ |
257
|
|
|
$i['morphTables'] = array_merge($i['morphTables'], $this->morphedByMany($i['name'], $modelName, $i['morphedByMany'])); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
$fields = []; |
261
|
|
|
foreach($i['fields'] as $name => $value) { |
262
|
|
|
$value['name'] = $name; |
263
|
|
|
$fields[] = $this->serializeField($value); |
264
|
|
|
} |
265
|
|
|
$i['fields'] = implode(' ', $fields); |
266
|
|
|
|
267
|
|
|
return $i; |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
protected function parseRelations($parser, $relations, $callback) |
271
|
|
|
{ |
272
|
|
|
$parsedRelations = []; |
273
|
|
|
$relations = $this->getArgumentParser($parser)->parse($relations); |
274
|
|
|
foreach ($relations as $relation){ |
275
|
|
|
$parsedRelations[] = $callback($relation); |
276
|
|
|
} |
277
|
|
|
|
278
|
|
|
return $parsedRelations; |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
protected function getConditionalTableName($condition, $then, $else) |
282
|
|
|
{ |
283
|
|
|
if($condition){ |
284
|
|
|
return snake_case($this->extractClassName($then)); |
285
|
|
|
} else { |
286
|
|
|
return snake_case($this->extractClassName($else)); |
287
|
|
|
} |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
protected function belongsTo($name, $modelName, $belongsTo) |
291
|
|
|
{ |
292
|
|
|
return $this->parseRelations('relations', $belongsTo, function($relation) use ($name, $modelName) { |
293
|
|
|
$table = $this->getConditionalTableName(! $relation['model'], $relation['name'], $relation['model']); |
294
|
|
|
$tables = [ str_singular($table), $name ]; |
295
|
|
|
sort($tables); |
296
|
|
|
$tables[] = $modelName; |
297
|
|
|
return $tables; |
298
|
|
|
}); |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
protected function morphToMany($modelName, $morphToMany) |
302
|
|
|
{ |
303
|
|
|
return $this->parseRelations('relations-morphMany', $morphToMany, function($relation) use ($modelName) { |
304
|
|
|
$name = $this->getConditionalTableName(! $relation['through'], $relation['name'], $relation['model']); |
305
|
|
|
return $this->getMorphableRelation($relation, $name, $modelName); |
306
|
|
|
}); |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
protected function morphedByMany($name, $modelName, $morphedByMany) |
310
|
|
|
{ |
311
|
|
|
return $this->parseRelations('relations-morphMany', $morphedByMany, function($relation) use ($name, $modelName) { |
312
|
|
|
return $this->getMorphableRelation($relation, $name, $modelName); |
313
|
|
|
}); |
314
|
|
|
} |
315
|
|
|
|
316
|
|
|
protected function getMorphableRelation($relation, $relationName, $modelName) { |
317
|
|
|
$morphable = $this->getConditionalTableName(! $relation['through'], $relation['model'], $relation['through']); |
318
|
|
|
return [ str_singular($relationName), str_singular($morphable), $modelName ]; |
319
|
|
|
} |
320
|
|
|
|
321
|
|
|
protected function serializeField($field) |
322
|
|
|
{ |
323
|
|
|
$name = $field['name']; |
324
|
|
|
$schema = $this->convertArray(str_replace(':', '.', $field['schema']), ' ', ':'); |
325
|
|
|
$rules = (isset($field['rules'])) ? $this->convertArray(trim($field['rules']), ' ', '|') : ''; |
326
|
|
|
$tags = !empty($field['tags']) ? $this->convertArray($field['tags'], ' ', ',') : ''; |
327
|
|
|
|
328
|
|
|
$string = "{$name};{$schema};{$rules};{$tags}"; |
329
|
|
|
|
330
|
|
|
if(isset($field['factory']) && !empty($field['factory'])){ |
331
|
|
|
$string .= ';' . $field['factory']; |
332
|
|
|
} |
333
|
|
|
|
334
|
|
|
return $string; |
335
|
|
|
} |
336
|
|
|
|
337
|
|
|
protected function convertArray($list, $old, $new) |
338
|
|
|
{ |
339
|
|
|
return implode($new, array_filter(explode($old, $list), function($item){ |
340
|
|
|
return !empty($item); |
341
|
|
|
})); |
342
|
|
|
} |
343
|
|
|
|
344
|
|
|
private function sortDependencies($nodes) { |
345
|
|
|
$load_order = array(); |
346
|
|
|
$seen = array(); |
347
|
|
|
|
348
|
|
|
foreach($nodes as $key => $item) { |
349
|
|
|
$tmp = $this->getDependencies($nodes, $key, $seen); |
350
|
|
|
|
351
|
|
|
// if($tmp[2] === false) { |
352
|
|
|
$load_order = array_merge($load_order, $tmp[0]); |
353
|
|
|
$seen = $tmp[1]; |
354
|
|
|
// } |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
return $load_order; |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
private function getDependencies($nodes, $key, $seen = array()) { |
361
|
|
|
if(array_key_exists($key, $seen) === true) { |
362
|
|
|
return array(array(), $seen); |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
|
366
|
|
|
if(!empty($nodes[$key])) { |
367
|
|
|
$order = array(); |
368
|
|
|
// $failed = array(); |
369
|
|
|
|
370
|
|
|
if($nodes[$key]['belongsTo']) { |
371
|
|
|
$deps = $this->getArgumentParser('relations')->parse($nodes[$key]['belongsTo']); |
372
|
|
|
foreach($deps as $dependency) { |
373
|
|
|
if(! $dependency['model']){ |
374
|
|
|
$dependency['model'] = $dependency['name']; |
375
|
|
|
} else if(strpos($dependency['model'], '\\') !== false ){ |
376
|
|
|
$dependency['model'] = substr($dependency['model'], strpos($dependency['model'], '\\')+1); // Cut offs first namespace part |
377
|
|
|
} |
378
|
|
|
$dependency['model'] = studly_case(str_singular($dependency['model'])); |
379
|
|
|
if ($dependency['model'] != $key) { |
380
|
|
|
$tmp = $this->getDependencies($nodes, $dependency['model'], $seen); |
381
|
|
|
|
382
|
|
|
$order = array_merge($order, $tmp[0]); |
383
|
|
|
$seen = $tmp[1]; |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
// if($tmp[2] !== false) { |
387
|
|
|
// $failed = array_merge($tmp[2], $failed); |
388
|
|
|
// } |
389
|
|
|
} |
390
|
|
|
} |
391
|
|
|
$seen[$key] = true; |
392
|
|
|
$order[$key] = $nodes[$key]; |
393
|
|
|
// $failed = (count($failed) > 0) ? $failed : false; |
394
|
|
|
|
395
|
|
|
return array($order, $seen);//, $failed |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
return array(array(), $seen);//, array($item) |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
protected function checkError($message, $model = "", $file = "") { |
402
|
|
|
$this->checkErrors[] = array("message" => $message, "model" => $model, "file" => $file); |
403
|
|
|
$this->checkedErrors++; |
404
|
|
|
} |
405
|
|
|
|
406
|
|
|
protected function checkInfo($message, $model = "", $file = "") { |
407
|
|
|
$this->checkInfo[] = array("message" => $message, "model" => $model, "file" => $file); |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
protected function printErrors() { |
411
|
|
|
foreach ($this->checkErrors as $error) { |
412
|
|
|
$this->error($error['message']); |
413
|
|
|
} |
414
|
|
|
foreach ($this->checkInfo as $info) { |
415
|
|
|
$this->info($info['message']); |
416
|
|
|
} |
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
protected function checkRelations($relations, $type, $file, $model, $keys) { |
420
|
|
|
if ($relations) { |
421
|
|
|
$position = array_search($model, $keys); |
422
|
|
|
$relations = $this->getArgumentParser('relations')->parse($relations); |
423
|
|
|
foreach($relations as $relation) { |
424
|
|
|
$rModel = $relation['model'] ? $relation['model'] : $relation['name']; |
425
|
|
|
$search = array_search(studly_case(str_singular($rModel)), $keys); |
426
|
|
|
if (($search === false || $search > $position) && !class_exists($this->prependNamespace($rModel)) && !class_exists($this->prependNamespace($rModel, 'App'))) { |
427
|
|
|
$this->checkError(studly_case(str_singular($rModel)) . ": undefined (used in " . $type . "-relationship of model " . $model . " in file " . $file . ")"); |
428
|
|
|
} else if (class_exists($this->prependNamespace($rModel))) { |
429
|
|
|
$this->checkInfo(studly_case(str_singular($rModel)) . ": already defined in Namespace " . $this->getNamespace() . " (used in " . $type . "-relationship of model " . $model . " in file " . $file . ")"); |
430
|
|
|
} else if (class_exists($this->prependNamespace($rModel, 'App'))) { |
431
|
|
|
$this->checkInfo(studly_case(str_singular($rModel)) . ": already defined in Namespace App\\ (used in " . $type . "-relationship of model " . $model . " in file " . $file . ")"); |
432
|
|
|
} |
433
|
|
|
} |
434
|
|
|
} |
435
|
|
|
} |
436
|
|
|
|
437
|
|
|
protected function checkPivotRelations($nodes, $relations, $relationType) { |
438
|
|
|
if ($relations) { |
439
|
|
|
foreach($relations as $relation) { |
440
|
|
|
$relation['0'] = studly_case(str_singular($relation['0'])); |
441
|
|
|
$relation['1'] = studly_case(str_singular($relation['1'])); |
442
|
|
|
$relation['2'] = studly_case(str_singular($relation['2'])); |
443
|
|
|
|
444
|
|
|
$this->checkRelation($nodes, $relationType, $relation['0'], $relation['2']); |
445
|
|
|
if ($relationType == "pivot") { |
446
|
|
|
$this->checkRelation($nodes, $relationType, $relation['1'], $relation['2']); |
447
|
|
|
} |
448
|
|
|
} |
449
|
|
|
} |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
protected function checkRelation($nodes, $relationType, $relation, $model) { |
453
|
|
|
if (empty($nodes[$relation]) && !class_exists($this->getNamespace() . '\\' . $relation) && !class_exists('App\\' . $relation)) { |
454
|
|
|
$this->checkError($relation . ": undefined (used in " . $relationType . "-based relationship of model " . $model . " in file " . $nodes[$model]['filename'] . ")"); |
455
|
|
|
} else if (class_exists($this->getNamespace() . '\\' . ucwords(camel_case($relation)))) { |
456
|
|
|
$this->checkInfo(studly_case(str_singular($relation)) . ": already defined in Namespace " . $this->getNamespace() . " (used in " . $relationType . "-based relationship of model " . $model . " in file " . $nodes[$model]['filename'] . ")"); |
457
|
|
|
} else if (class_exists('App\\' . ucwords(camel_case($relation)))) { |
458
|
|
|
$this->checkInfo(studly_case(str_singular($relation)) . ": already defined in Namespace App\\ (used in " . $relationType . "-based relationship of model " . $model . " in file " . $nodes[$model]['filename'] . ")"); |
459
|
|
|
} |
460
|
|
|
} |
461
|
|
|
|
462
|
|
|
} |
463
|
|
|
|
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.