Complex classes like NodeRepository often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use NodeRepository, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
35 | class NodeRepository |
||
36 | { |
||
37 | /** |
||
38 | * Creates a new node on the system. |
||
39 | * |
||
40 | * @param array $data |
||
41 | * @return \Pterodactyl\Models\Node |
||
42 | * |
||
43 | * @throws \Pterodactyl\Exceptions\DisplayException |
||
44 | * @throws \Pterodactyl\Exceptions\DisplayValidationException |
||
45 | */ |
||
46 | public function create(array $data) |
||
47 | { |
||
48 | // Validate Fields |
||
49 | $validator = Validator::make($data, [ |
||
50 | 'name' => 'required|regex:/^([\w .-]{1,100})$/', |
||
51 | 'location_id' => 'required|numeric|min:1|exists:locations,id', |
||
52 | 'public' => 'required|numeric|between:0,1', |
||
53 | 'fqdn' => 'required|string|unique:nodes,fqdn', |
||
54 | 'scheme' => 'required|regex:/^(http(s)?)$/', |
||
55 | 'behind_proxy' => 'required|boolean', |
||
56 | 'memory' => 'required|numeric|min:1', |
||
57 | 'memory_overallocate' => 'required|numeric|min:-1', |
||
58 | 'disk' => 'required|numeric|min:1', |
||
59 | 'disk_overallocate' => 'required|numeric|min:-1', |
||
60 | 'daemonBase' => 'required|regex:/^([\/][\d\w.\-\/]+)$/', |
||
61 | 'daemonSFTP' => 'required|numeric|between:1,65535', |
||
62 | 'daemonListen' => 'required|numeric|between:1,65535', |
||
63 | ]); |
||
64 | |||
65 | // Run validator, throw catchable and displayable exception if it fails. |
||
66 | // Exception includes a JSON result of failed validation rules. |
||
67 | if ($validator->fails()) { |
||
68 | throw new DisplayValidationException(json_encode($validator->errors())); |
||
69 | } |
||
70 | |||
71 | // Verify the FQDN if using SSL |
||
72 | if (filter_var($data['fqdn'], FILTER_VALIDATE_IP) && $data['scheme'] === 'https') { |
||
73 | throw new DisplayException('A fully qualified domain name is required to use a secure comunication method on this node.'); |
||
74 | } |
||
75 | |||
76 | // Verify FQDN is resolvable, or if not using SSL that the IP is valid. |
||
77 | if (! filter_var(gethostbyname($data['fqdn']), FILTER_VALIDATE_IP)) { |
||
78 | throw new DisplayException('The FQDN (or IP Address) provided does not resolve to a valid IP address.'); |
||
79 | } |
||
80 | |||
81 | // Should we be nulling the overallocations? |
||
82 | $data['memory_overallocate'] = ($data['memory_overallocate'] < 0) ? null : $data['memory_overallocate']; |
||
83 | $data['disk_overallocate'] = ($data['disk_overallocate'] < 0) ? null : $data['disk_overallocate']; |
||
84 | |||
85 | // Set the Secret |
||
86 | $uuid = new UuidService; |
||
87 | $data['daemonSecret'] = (string) $uuid->generate('nodes', 'daemonSecret'); |
||
88 | |||
89 | return Models\Node::create($data); |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * Updates a node on the system. |
||
94 | * |
||
95 | * @param int $id |
||
96 | * @param array $data |
||
97 | * @return \Pterodactyl\Models\Node |
||
98 | * |
||
99 | * @throws \Pterodactyl\Exceptions\DisplayException |
||
100 | * @throws \Pterodactyl\Exceptions\DisplayValidationException |
||
101 | */ |
||
102 | public function update($id, array $data) |
||
103 | { |
||
104 | $node = Models\Node::findOrFail($id); |
||
105 | |||
106 | // Validate Fields |
||
107 | $validator = $validator = Validator::make($data, [ |
||
108 | 'name' => 'regex:/^([\w .-]{1,100})$/', |
||
109 | 'location_id' => 'numeric|min:1|exists:locations,id', |
||
110 | 'public' => 'numeric|between:0,1', |
||
111 | 'fqdn' => 'string|unique:nodes,fqdn,' . $id, |
||
112 | 'scheme' => 'regex:/^(http(s)?)$/', |
||
113 | 'behind_proxy' => 'boolean', |
||
114 | 'memory' => 'numeric|min:1', |
||
115 | 'memory_overallocate' => 'numeric|min:-1', |
||
116 | 'disk' => 'numeric|min:1', |
||
117 | 'disk_overallocate' => 'numeric|min:-1', |
||
118 | 'upload_size' => 'numeric|min:0', |
||
119 | 'daemonBase' => 'sometimes|regex:/^([\/][\d\w.\-\/]+)$/', |
||
120 | 'daemonSFTP' => 'numeric|between:1,65535', |
||
121 | 'daemonListen' => 'numeric|between:1,65535', |
||
122 | 'reset_secret' => 'sometimes|nullable|accepted', |
||
123 | ]); |
||
124 | |||
125 | // Run validator, throw catchable and displayable exception if it fails. |
||
126 | // Exception includes a JSON result of failed validation rules. |
||
127 | if ($validator->fails()) { |
||
128 | throw new DisplayValidationException(json_encode($validator->errors())); |
||
129 | } |
||
130 | |||
131 | // Verify the FQDN |
||
132 | if (isset($data['fqdn'])) { |
||
133 | |||
134 | // Verify the FQDN if using SSL |
||
135 | if ((isset($data['scheme']) && $data['scheme'] === 'https') || (! isset($data['scheme']) && $node->scheme === 'https')) { |
||
136 | if (filter_var($data['fqdn'], FILTER_VALIDATE_IP)) { |
||
137 | throw new DisplayException('A fully qualified domain name is required to use secure comunication on this node.'); |
||
138 | } |
||
139 | } |
||
140 | |||
141 | // Verify FQDN is resolvable, or if not using SSL that the IP is valid. |
||
142 | if (! filter_var(gethostbyname($data['fqdn']), FILTER_VALIDATE_IP)) { |
||
143 | throw new DisplayException('The FQDN (or IP Address) provided does not resolve to a valid IP address.'); |
||
144 | } |
||
145 | } |
||
146 | |||
147 | // Should we be nulling the overallocations? |
||
148 | if (isset($data['memory_overallocate'])) { |
||
149 | $data['memory_overallocate'] = ($data['memory_overallocate'] < 0) ? null : $data['memory_overallocate']; |
||
150 | } |
||
151 | |||
152 | if (isset($data['disk_overallocate'])) { |
||
153 | $data['disk_overallocate'] = ($data['disk_overallocate'] < 0) ? null : $data['disk_overallocate']; |
||
154 | } |
||
155 | |||
156 | // Set the Secret |
||
157 | if (isset($data['reset_secret']) && ! is_null($data['reset_secret'])) { |
||
158 | $uuid = new UuidService; |
||
159 | $data['daemonSecret'] = (string) $uuid->generate('nodes', 'daemonSecret'); |
||
160 | unset($data['reset_secret']); |
||
161 | } |
||
162 | |||
163 | $oldDaemonKey = $node->daemonSecret; |
||
164 | $node->update($data); |
||
165 | try { |
||
166 | $node->guzzleClient(['X-Access-Token' => $oldDaemonKey])->request('PATCH', '/config', [ |
||
167 | 'json' => [ |
||
168 | 'web' => [ |
||
169 | 'listen' => $node->daemonListen, |
||
170 | 'ssl' => [ |
||
171 | 'enabled' => (! $node->behind_proxy && $node->scheme === 'https'), |
||
172 | ], |
||
173 | ], |
||
174 | 'sftp' => [ |
||
175 | 'path' => $node->daemonBase, |
||
176 | 'port' => $node->daemonSFTP, |
||
177 | ], |
||
178 | 'remote' => [ |
||
179 | 'base' => config('app.url'), |
||
180 | ], |
||
181 | 'uploads' => [ |
||
182 | 'size_limit' => $node->upload_size, |
||
183 | ], |
||
184 | 'keys' => [ |
||
185 | $node->daemonSecret, |
||
186 | ], |
||
187 | ], |
||
188 | ]); |
||
189 | } catch (\Exception $ex) { |
||
190 | throw new DisplayException('Failed to update the node configuration, however your changes have been saved to the database. You will need to manually update the configuration file for the node to apply these changes.'); |
||
191 | } |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * Adds allocations to a provided node. |
||
196 | * |
||
197 | * @param int $id |
||
198 | * @param array $data |
||
199 | * @return void |
||
200 | * |
||
201 | * @throws \Pterodactyl\Exceptions\DisplayException |
||
202 | * @throws \Pterodactyl\Exceptions\DisplayValidationException |
||
203 | */ |
||
204 | public function addAllocations($id, array $data) |
||
264 | |||
265 | /** |
||
266 | * Deletes a node on the system. |
||
267 | * |
||
268 | * @param int $id |
||
269 | * @return void |
||
270 | * |
||
271 | * @throws \Pterodactyl\Exceptions\DisplayException |
||
272 | */ |
||
273 | public function delete($id) |
||
291 | } |
||
292 |