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 |
||
38 | class NodesController extends Controller |
||
39 | { |
||
40 | /** |
||
41 | * Displays the index page listing all nodes on the panel. |
||
42 | * |
||
43 | * @param \Illuminate\Http\Request $request |
||
44 | * @return \Illuminate\View\View |
||
45 | */ |
||
46 | View Code Duplication | public function index(Request $request) |
|
56 | |||
57 | /** |
||
58 | * Displays create new node page. |
||
59 | * |
||
60 | * @param \Illuminate\Http\Request $request |
||
61 | * @return \Illuminate\View\View|\Illuminate\Http\RedirectResponse |
||
62 | */ |
||
63 | public function create(Request $request) |
||
64 | { |
||
65 | $locations = Models\Location::all(); |
||
66 | if (! $locations->count()) { |
||
67 | Alert::warning('You must add a location before you can add a new node.')->flash(); |
||
68 | |||
69 | return redirect()->route('admin.locations'); |
||
70 | } |
||
71 | |||
72 | return view('admin.nodes.new', ['locations' => $locations]); |
||
73 | } |
||
74 | |||
75 | /** |
||
76 | * Post controller to create a new node on the system. |
||
77 | * |
||
78 | * @param \Illuminate\Http\Request $request |
||
79 | * @return \Illuminate\Http\RedirectResponse |
||
80 | */ |
||
81 | View Code Duplication | public function store(Request $request) |
|
82 | { |
||
83 | try { |
||
84 | $repo = new NodeRepository; |
||
85 | $node = $repo->create(array_merge( |
||
86 | $request->only([ |
||
87 | 'public', 'disk_overallocate', 'memory_overallocate', |
||
88 | ]), |
||
89 | $request->intersect([ |
||
90 | 'name', 'location_id', 'fqdn', |
||
91 | 'scheme', 'memory', 'disk', |
||
92 | 'daemonBase', 'daemonSFTP', 'daemonListen', |
||
93 | ]) |
||
94 | )); |
||
95 | Alert::success('Successfully created new node that can be configured automatically on your remote machine by visiting the configuration tab. <strong>Before you can add any servers you need to first assign some IP addresses and ports.</strong>')->flash(); |
||
96 | |||
97 | return redirect()->route('admin.nodes.view', $node->id); |
||
98 | } catch (DisplayValidationException $e) { |
||
99 | return redirect()->route('admin.nodes.new')->withErrors(json_decode($e->getMessage()))->withInput(); |
||
100 | } catch (DisplayException $e) { |
||
101 | Alert::danger($e->getMessage())->flash(); |
||
102 | } catch (\Exception $e) { |
||
103 | Log::error($e); |
||
104 | Alert::danger('An unhandled exception occured while attempting to add this node. Please try again.')->flash(); |
||
105 | } |
||
106 | |||
107 | return redirect()->route('admin.nodes.new')->withInput(); |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | * Shows the index overview page for a specific node. |
||
112 | * |
||
113 | * @param \Illuminate\Http\Request $request |
||
114 | * @param int $id |
||
115 | * @return \Illuminate\View\View |
||
116 | */ |
||
117 | public function viewIndex(Request $request, $id) |
||
118 | { |
||
119 | $node = Models\Node::with('location')->withCount('servers')->findOrFail($id); |
||
120 | $stats = collect( |
||
121 | Models\Server::select( |
||
122 | DB::raw('SUM(memory) as memory, SUM(disk) as disk') |
||
123 | )->where('node_id', $node->id)->first() |
||
124 | )->mapWithKeys(function ($item, $key) use ($node) { |
||
125 | $percent = ($item / $node->{$key}) * 100; |
||
126 | |||
127 | return [$key => [ |
||
128 | 'value' => $item, |
||
129 | 'percent' => $percent, |
||
130 | 'css' => ($percent <= 75) ? 'green' : (($percent > 90) ? 'red' : 'yellow'), |
||
131 | ]]; |
||
132 | })->toArray(); |
||
133 | |||
134 | return view('admin.nodes.view.index', ['node' => $node, 'stats' => $stats]); |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * Shows the settings page for a specific node. |
||
139 | * |
||
140 | * @param \Illuminate\Http\Request $request |
||
141 | * @param int $id |
||
142 | * @return \Illuminate\View\View |
||
143 | */ |
||
144 | public function viewSettings(Request $request, $id) |
||
145 | { |
||
146 | return view('admin.nodes.view.settings', [ |
||
147 | 'node' => Models\Node::findOrFail($id), |
||
148 | 'locations' => Models\Location::all(), |
||
149 | ]); |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * Shows the configuration page for a specific node. |
||
154 | * |
||
155 | * @param \Illuminate\Http\Request $request |
||
156 | * @param int $id |
||
157 | * @return \Illuminate\View\View |
||
158 | */ |
||
159 | public function viewConfiguration(Request $request, $id) |
||
160 | { |
||
161 | return view('admin.nodes.view.configuration', [ |
||
162 | 'node' => Models\Node::findOrFail($id), |
||
163 | ]); |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Shows the allocation page for a specific node. |
||
168 | * |
||
169 | * @param \Illuminate\Http\Request $request |
||
170 | * @param int $id |
||
171 | * @return \Illuminate\View\View |
||
172 | */ |
||
173 | public function viewAllocation(Request $request, $id) |
||
174 | { |
||
175 | $node = Models\Node::findOrFail($id); |
||
176 | $node->setRelation('allocations', $node->allocations()->orderBy('ip', 'asc')->orderBy('port', 'asc')->with('server')->paginate(50)); |
||
177 | |||
178 | Javascript::put([ |
||
179 | 'node' => collect($node)->only(['id']), |
||
180 | ]); |
||
181 | |||
182 | return view('admin.nodes.view.allocation', ['node' => $node]); |
||
183 | } |
||
184 | |||
185 | /** |
||
186 | * Shows the server listing page for a specific node. |
||
187 | * |
||
188 | * @param \Illuminate\Http\Request $request |
||
189 | * @param int $id |
||
190 | * @return \Illuminate\View\View |
||
191 | */ |
||
192 | public function viewServers(Request $request, $id) |
||
203 | |||
204 | /** |
||
205 | * Updates settings for a node. |
||
206 | * |
||
207 | * @param \Illuminate\Http\Request $request |
||
208 | * @param int $id |
||
209 | * @return \Illuminate\Http\RedirectResponse |
||
210 | */ |
||
211 | public function updateSettings(Request $request, $id) |
||
238 | |||
239 | /** |
||
240 | * Removes a single allocation from a node. |
||
241 | * |
||
242 | * @param \Illuminate\Http\Request $request |
||
243 | * @param int $node |
||
244 | * @param int $allocation |
||
245 | * @return \Illuminate\Http\Response|\Illuminate\Http\JsonResponse |
||
246 | */ |
||
247 | public function allocationRemoveSingle(Request $request, $node, $allocation) |
||
258 | |||
259 | /** |
||
260 | * Remove all allocations for a specific IP at once on a node. |
||
261 | * |
||
262 | * @param \Illuminate\Http\Request $request |
||
263 | * @param int $node |
||
264 | * @return \Illuminate\Http\RedirectResponse |
||
265 | */ |
||
266 | public function allocationRemoveBlock(Request $request, $node) |
||
277 | |||
278 | /** |
||
279 | * Sets an alias for a specific allocation on a node. |
||
280 | * |
||
281 | * @param \Illuminate\Http\Request $request |
||
282 | * @param int $node |
||
283 | * @return \Illuminate\Http\Response |
||
284 | */ |
||
285 | public function allocationSetAlias(Request $request, $node) |
||
301 | |||
302 | /** |
||
303 | * Creates new allocations on a node. |
||
304 | * |
||
305 | * @param \Illuminate\Http\Request $request |
||
306 | * @param int $node |
||
307 | * @return \Illuminate\Http\RedirectResponse |
||
308 | */ |
||
309 | public function createAllocation(Request $request, $node) |
||
327 | |||
328 | /** |
||
329 | * Deletes a node from the system. |
||
330 | * |
||
331 | * @param \Illuminate\Http\Request $request |
||
332 | * @param int $id |
||
333 | * @return \Illuminate\Http\RedirectResponse |
||
334 | */ |
||
335 | View Code Duplication | public function delete(Request $request, $id) |
|
353 | |||
354 | /** |
||
355 | * Returns the configuration token to auto-deploy a node. |
||
356 | * |
||
357 | * @param \Illuminate\Http\Request $request |
||
358 | * @param int $id |
||
359 | * @return \Illuminate\Http\JsonResponse |
||
360 | */ |
||
361 | public function setToken(Request $request, $id) |
||
372 | } |
||
373 |
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.