Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php namespace Wn\Generators\Commands; |
||
4 | class ModelCommand extends BaseCommand { |
||
5 | |||
6 | protected $signature = 'wn:model |
||
7 | {name : Name of the model.} |
||
8 | {--fillable= : the fillable fields.} |
||
9 | {--guarded= : the guarded fields.} |
||
10 | {--dates= : date fields.} |
||
11 | {--has-many= : hasMany relationships.} |
||
12 | {--has-one= : hasOne relationships.} |
||
13 | {--belongs-to= : belongsTo relationships.} |
||
14 | {--belongs-to-many= : belongsToMany relationships.} |
||
15 | {--images= : images to be associated with model} |
||
16 | {--rules= : fields validation rules.} |
||
17 | {--path=app : where to store the model php file.} |
||
18 | {--soft-deletes= : adds SoftDeletes trait to the model.} |
||
19 | {--parsed : tells the command that arguments have been already parsed. To use when calling the command from an other command and passing the parsed arguments and options} |
||
20 | {--force= : override the existing files} |
||
21 | '; |
||
22 | |||
23 | protected $description = 'Generates a model class for a RESTfull resource'; |
||
24 | |||
25 | public function handle() |
||
26 | { |
||
27 | $name = $this->argument('name'); |
||
28 | $path = $this->option('path'); |
||
|
|||
29 | |||
30 | $content = $this->getTemplate('model') |
||
31 | ->with([ |
||
32 | 'name' => $name, |
||
33 | 'namespace' => $this->getNamespace(), |
||
34 | 'fillable' => $this->getAsArrayFields('fillable'), |
||
35 | 'guarded' => $this->getAsArrayFields('guarded'), |
||
36 | 'dates' => $this->getAsArrayFields('dates'), |
||
37 | 'relations' => $this->getRelations(), |
||
38 | 'images' => $this->getImages('images'), |
||
39 | 'appends' => $this->getAsArrayFields('images'), |
||
40 | 'rules' => $this->getRules(), |
||
41 | 'uses' => $this->getUses() |
||
42 | ]) |
||
43 | ->get(); |
||
44 | |||
45 | $this->save($content, "./App/Models/{$name}.php", "{$name} model"); |
||
46 | } |
||
47 | |||
48 | protected function getAsArrayFields($arg, $isOption = true) |
||
49 | { |
||
50 | $arg = ($isOption) ? $this->option($arg) : $this->argument($arg); |
||
51 | if(is_string($arg)){ |
||
52 | $arg = explode(',', $arg); |
||
53 | } else if(! is_array($arg)) { |
||
54 | $arg = []; |
||
55 | } |
||
56 | return implode(', ', array_map(function($item){ |
||
57 | return '"' . $item . '"'; |
||
58 | }, $arg)); |
||
59 | } |
||
60 | |||
61 | protected function getNamespace() |
||
62 | { |
||
63 | return str_replace(' ', '\\', ucwords(str_replace('/', ' ', $this->option('path')))); |
||
64 | } |
||
65 | |||
66 | protected function getRelations() |
||
67 | { |
||
68 | $relations = array_merge([], |
||
69 | $this->getRelationsByType('hasOne', 'has-one'), |
||
70 | $this->getRelationsByType('hasMany', 'has-many'), |
||
71 | $this->getRelationsByType('belongsTo', 'belongs-to'), |
||
72 | $this->getRelationsByType('belongsToMany', 'belongs-to-many', true) |
||
73 | ); |
||
74 | |||
75 | if(empty($relations)){ |
||
76 | return " // Relationships"; |
||
77 | } |
||
78 | |||
79 | return implode(PHP_EOL, $relations); |
||
80 | } |
||
81 | |||
82 | protected function getImages($option) |
||
83 | { |
||
84 | $images = []; |
||
85 | $option = $this->option($option); |
||
86 | if($option){ |
||
87 | |||
88 | $items = $this->getArgumentParser('images')->parse($option); |
||
89 | |||
90 | $template = 'model/image'; |
||
91 | $template = $this->getTemplate($template); |
||
92 | foreach ($items as $item) { |
||
93 | if(! $item['image']){ |
||
94 | $item['image'] = "get" . str_replace(' ', '', ucwords(str_replace('_', ' ', $item['name']))) . "Attribute"; |
||
95 | } |
||
96 | $images[] = $template->with($item)->get(); |
||
97 | } |
||
98 | } |
||
99 | |||
100 | $media = array_merge([], $images); |
||
101 | |||
102 | if(empty($media)){ |
||
103 | return " // Media methods"; |
||
104 | } |
||
105 | |||
106 | return implode(PHP_EOL, $media); |
||
107 | } |
||
108 | |||
109 | protected function getRelationsByType($type, $option, $withTimestamps = false) |
||
110 | { |
||
111 | $relations = []; |
||
112 | $option = $this->option($option); |
||
113 | if($option){ |
||
114 | |||
115 | $items = $this->getArgumentParser('relations')->parse($option); |
||
116 | |||
117 | $template = ($withTimestamps) ? 'model/relation-with-timestamps' : 'model/relation'; |
||
118 | $template = $this->getTemplate($template); |
||
119 | foreach ($items as $item) { |
||
120 | $item['type'] = $type; |
||
121 | if(! $item['model']){ |
||
122 | $item['model'] = $this->getNamespace() . '\\' . ucwords(\Illuminate\Support\Str::singular($item['name'])); |
||
123 | } else if(strpos($item['model'], '\\') === false ){ |
||
124 | $item['model'] = $this->getNamespace() . '\\' . $item['model']; |
||
125 | } |
||
126 | $relations[] = $template->with($item)->get(); |
||
127 | } |
||
128 | } |
||
129 | return $relations; |
||
130 | } |
||
131 | |||
132 | View Code Duplication | protected function getRules() |
|
133 | { |
||
134 | $rules = $this->option('rules'); |
||
135 | if(! $rules){ |
||
136 | return " // Validation rules"; |
||
137 | } |
||
138 | $items = $rules; |
||
139 | if(! $this->option('parsed')){ |
||
140 | $items = $this->getArgumentParser('rules')->parse($rules); |
||
141 | } |
||
142 | $rules = []; |
||
143 | $template = $this->getTemplate('model/rule'); |
||
144 | foreach ($items as $item) { |
||
145 | $rules[] = $template->with($item)->get(); |
||
146 | } |
||
147 | |||
148 | return implode(PHP_EOL, $rules); |
||
149 | } |
||
150 | |||
151 | protected function getUses() |
||
157 | |||
158 | } |
||
159 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.