Complex classes like Vhost 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 Vhost, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
47 | class Vhost implements VhostInterface |
||
48 | { |
||
49 | /** |
||
50 | * Active account |
||
51 | * |
||
52 | * @var boolean |
||
53 | */ |
||
54 | protected $active = false; |
||
55 | /** |
||
56 | * Primary domain |
||
57 | * |
||
58 | * @var DomainInterface |
||
59 | */ |
||
60 | protected $primaryDomain; |
||
61 | /** |
||
62 | * Secondary domains |
||
63 | * |
||
64 | * @var DomainInterface[] |
||
65 | */ |
||
66 | protected $secondaryDomains = []; |
||
67 | /** |
||
68 | * Document root |
||
69 | * |
||
70 | * @var string |
||
71 | */ |
||
72 | protected $docroot; |
||
73 | /** |
||
74 | * Virtual host type |
||
75 | * |
||
76 | * @var string |
||
77 | */ |
||
78 | protected $type = self::TYPE_APACHE; |
||
79 | /** |
||
80 | * Ports |
||
81 | * |
||
82 | * @var array |
||
83 | */ |
||
84 | protected $ports = []; |
||
85 | /** |
||
86 | * Active PHP version |
||
87 | * |
||
88 | * @var null|string |
||
89 | */ |
||
90 | protected $php = null; |
||
91 | /** |
||
92 | * Absolute URL to redirect to |
||
93 | * |
||
94 | * @var null|string |
||
95 | */ |
||
96 | protected $redirectUrl = null; |
||
97 | /** |
||
98 | * Redirect status code |
||
99 | * |
||
100 | * @var int |
||
101 | */ |
||
102 | protected $redirectStatus = self::REDIRECT_DEFAULT_STATUS; |
||
103 | /** |
||
104 | * Default port for HTTP virtual hosts |
||
105 | * |
||
106 | * @var int |
||
107 | */ |
||
108 | const PORT_HTTP_DEFAULT = 80; |
||
109 | /** |
||
110 | * Default port for HTTPS virtual hosts |
||
111 | * |
||
112 | * @var int |
||
113 | */ |
||
114 | const PORT_HTTPS_DEFAULT = 443; |
||
115 | /** |
||
116 | * Default redirect status |
||
117 | * |
||
118 | * @var int |
||
119 | */ |
||
120 | const REDIRECT_DEFAULT_STATUS = 301; |
||
121 | /** |
||
122 | * HTTP protocol |
||
123 | * |
||
124 | * @var int |
||
125 | */ |
||
126 | const PROTOCOL_HTTP = 1; |
||
127 | /** |
||
128 | * HTTPS protocol |
||
129 | * |
||
130 | * @var int |
||
131 | */ |
||
132 | const PROTOCOL_HTTPS = 2; |
||
133 | /** |
||
134 | * Apache virtual host |
||
135 | * |
||
136 | * @var string |
||
137 | */ |
||
138 | const TYPE_APACHE = 'apache'; |
||
139 | /** |
||
140 | * Supported protocols |
||
141 | * |
||
142 | * @var array |
||
143 | */ |
||
144 | public static $supportedProtocols = [ |
||
145 | self::PROTOCOL_HTTP => 'http', |
||
146 | self::PROTOCOL_HTTPS => 'https', |
||
147 | ]; |
||
148 | /** |
||
149 | * Default protocol ports |
||
150 | * |
||
151 | * @var array |
||
152 | */ |
||
153 | public static $defaultProtocolPorts = [ |
||
154 | self::PROTOCOL_HTTP => self::PORT_HTTP_DEFAULT, |
||
155 | self::PROTOCOL_HTTPS => self::PORT_HTTPS_DEFAULT, |
||
156 | ]; |
||
157 | |||
158 | /** |
||
159 | * Virtual host constructor |
||
160 | * |
||
161 | * @param DomainInterface $primaryDomain Primary domain |
||
162 | * @param string $docroot Document root |
||
163 | * @param string $type Virtual host type |
||
164 | * @internal param int $port Port |
||
165 | */ |
||
166 | 10 | public function __construct(DomainInterface $primaryDomain, $docroot, $type = self::TYPE_APACHE) |
|
172 | |||
173 | /** |
||
174 | * Return whether the account is active |
||
175 | * |
||
176 | * @return boolean Active |
||
177 | */ |
||
178 | public function isActive() |
||
182 | |||
183 | /** |
||
184 | * Set whether the account is active |
||
185 | * |
||
186 | * @param boolean $active Active |
||
187 | * @return VhostInterface Self reference |
||
188 | */ |
||
189 | public function setActive($active) |
||
194 | |||
195 | /** |
||
196 | * Return the primary domain |
||
197 | * |
||
198 | * @return DomainInterface Primary domain |
||
199 | */ |
||
200 | 2 | public function getPrimaryDomain() |
|
204 | |||
205 | /** |
||
206 | * Return the document root |
||
207 | * |
||
208 | * @return string Document root |
||
209 | */ |
||
210 | 1 | public function getDocroot() |
|
214 | |||
215 | /** |
||
216 | * Return the virtual host type |
||
217 | * |
||
218 | * @return string Virtual host type |
||
219 | */ |
||
220 | public function getType() |
||
224 | |||
225 | /** |
||
226 | * Return a ports list |
||
227 | * |
||
228 | * @param int|null $protocol Optional Protocol |
||
229 | * @return array|null Ports list |
||
230 | * @throws \RuntimeException If the requested protocol is unsupported |
||
231 | */ |
||
232 | 3 | public function getPorts($protocol = null) |
|
247 | |||
248 | /** |
||
249 | * Return the secondary domains |
||
250 | * |
||
251 | * @param bool $excludeWildcards Exclude wildcard domains |
||
252 | * @return DomainInterface[] Secondary domains |
||
253 | */ |
||
254 | 1 | public function getSecondaryDomains($excludeWildcards = false) |
|
255 | { |
||
256 | 1 | $secondaryDomains = array_values($this->secondaryDomains); |
|
257 | return $excludeWildcards ? |
||
258 | array_filter($secondaryDomains, function (DomainInterface $domain) { |
||
259 | return !$domain->isWildcard(); |
||
260 | }) : |
||
261 | 1 | $secondaryDomains; |
|
262 | } |
||
263 | |||
264 | /** |
||
265 | * Set the secondary domains |
||
266 | * |
||
267 | * @param DomainInterface[] $secondaryDomains |
||
268 | * @return Vhost Self reference |
||
269 | * @throws \RuntimeException If the domain is invalid |
||
270 | */ |
||
271 | 1 | public function setSecondaryDomains(array $secondaryDomains) |
|
272 | { |
||
273 | 1 | $this->secondaryDomains = []; |
|
274 | /** @var DomainInterface $secondaryDomain */ |
||
275 | 1 | foreach ($secondaryDomains as $secondaryDomain) { |
|
276 | // If the domain is invalid |
||
277 | 1 | if (!is_object($secondaryDomain) |
|
278 | 1 | || !(new \ReflectionClass($secondaryDomain))->implementsInterface(DomainInterface::class) |
|
279 | 1 | ) { |
|
280 | 1 | throw new \RuntimeException(sprintf('Invalid secondary domain "%s"', $secondaryDomain), 1475484852); |
|
281 | } |
||
282 | 1 | $this->secondaryDomains[strval($secondaryDomain)] = $secondaryDomain; |
|
283 | 1 | } |
|
284 | |||
285 | 1 | return $this; |
|
286 | } |
||
287 | |||
288 | /** |
||
289 | * Add a secondary domain |
||
290 | * |
||
291 | * @param DomainInterface $secondaryDomain Secondary domain |
||
292 | * @return Vhost Self reference |
||
293 | */ |
||
294 | 1 | public function addSecondaryDomain(DomainInterface $secondaryDomain) |
|
295 | { |
||
296 | 1 | if (!array_key_exists(strval($secondaryDomain), $this->secondaryDomains)) { |
|
297 | 1 | $this->secondaryDomains[strval($secondaryDomain)] = $secondaryDomain; |
|
298 | 1 | } |
|
299 | 1 | return $this; |
|
300 | } |
||
301 | |||
302 | /** |
||
303 | * Remove a secondary domain |
||
304 | * |
||
305 | * @param DomainInterface $secondaryDomain Secondary domain |
||
306 | * @return Vhost Self reference |
||
307 | */ |
||
308 | 1 | public function removeSecondaryDomain(DomainInterface $secondaryDomain) |
|
313 | |||
314 | /** |
||
315 | * Return the active PHP version |
||
316 | * |
||
317 | * @return null|string Active PHP version |
||
318 | */ |
||
319 | 1 | public function getPhp() |
|
323 | |||
324 | /** |
||
325 | * Set the active PHP version |
||
326 | * |
||
327 | * @param null|string $php Active PHP version |
||
328 | * @return Vhost Self reference |
||
329 | * @throws \RuntimeException If the PHP version is invalid |
||
330 | */ |
||
331 | 1 | public function setPhp($php) |
|
341 | |||
342 | /** |
||
343 | * Enable a port |
||
344 | * |
||
345 | * @param int $protocol Protocol |
||
346 | * @param int $port Optional: Port (defaults to protocol specific port) |
||
347 | * @return Vhost Self reference |
||
348 | * @throws \RuntimeException If the protocol is unsupported |
||
349 | * @throws \RuntimeException If the port is invalid |
||
350 | */ |
||
351 | 2 | public function enablePort($protocol, $port = null) |
|
352 | { |
||
353 | 2 | $protocol = intval($protocol); |
|
354 | |||
355 | // If the protocol is unsupported |
||
356 | 2 | if (empty(self::$supportedProtocols[$protocol])) { |
|
357 | throw new \RuntimeException(sprintf('Invalid protocol "%s"', $protocol), 1475484081); |
||
358 | } |
||
359 | |||
360 | // If the port is invalid |
||
361 | 2 | $port = ($port === null) ? self::$defaultProtocolPorts[$protocol] : intval($port); |
|
362 | 2 | if ($port <= 0) { |
|
363 | 1 | throw new \RuntimeException(sprintf('Invalid port "%s"', $port), 1475502412); |
|
364 | } |
||
365 | |||
366 | // Create the protocol specific port list if necessary |
||
367 | 1 | if (empty($this->ports[$protocol])) { |
|
368 | 1 | $this->ports[$protocol] = []; |
|
369 | 1 | } |
|
370 | |||
371 | // Register the port |
||
372 | 1 | $this->ports[$protocol] = array_unique(array_merge($this->ports[$protocol], [$port])); |
|
373 | 1 | return $this; |
|
374 | } |
||
375 | |||
376 | /** |
||
377 | * Disable a port |
||
378 | * |
||
379 | * @param int $port Port |
||
380 | * @return Vhost Self reference |
||
381 | * @throws \RuntimeException If the port is invalid |
||
382 | */ |
||
383 | 1 | public function disablePort($port) |
|
384 | { |
||
385 | 1 | $port = intval($port); |
|
386 | |||
387 | // If the port is invalid |
||
388 | 1 | if ($port <= 0) { |
|
389 | throw new \RuntimeException(sprintf('Invalid port "%s"', $port), 1475502412); |
||
390 | } |
||
391 | |||
392 | // Run through all protocols and delete the port |
||
393 | 1 | foreach ($this->ports as $protocol => $ports) { |
|
394 | 1 | $this->ports[$protocol] = array_values(array_diff($ports, [$port])); |
|
395 | 1 | } |
|
396 | 1 | return $this; |
|
397 | } |
||
398 | |||
399 | /** |
||
400 | * Disable a supported protocol |
||
401 | * |
||
402 | * @param int $protocol Protocol |
||
403 | * @return Vhost Self reference |
||
404 | * @throws \RuntimeException If the protocol is unsupported |
||
405 | */ |
||
406 | 2 | public function disableProtocol($protocol) |
|
418 | |||
419 | /** |
||
420 | * Return the redirect URL |
||
421 | * |
||
422 | * @return null|string Redirect URL |
||
423 | */ |
||
424 | 1 | public function getRedirectUrl() |
|
428 | |||
429 | /** |
||
430 | * Set the redirect URL |
||
431 | * |
||
432 | * @param null|string $redirectUrl Redirect URL |
||
433 | * @return Vhost Self reference |
||
434 | * @throws \RuntimeException If the redirect URL is invalid |
||
435 | */ |
||
436 | 1 | public function setRedirectUrl($redirectUrl) |
|
437 | { |
||
438 | 1 | $redirectUrl = trim($redirectUrl) ?: null; |
|
439 | |||
440 | // If the redirect URL is invalid |
||
441 | 1 | if (($redirectUrl !== null) && |
|
442 | 1 | (!filter_var($redirectUrl, FILTER_VALIDATE_URL) |
|
443 | 1 | || !in_array(strtolower(parse_url($redirectUrl, PHP_URL_SCHEME)), self::$supportedProtocols)) |
|
444 | 1 | ) { |
|
445 | 1 | throw new \RuntimeException(sprintf('Invalid redirect URL "%s"', $redirectUrl), 1475486589); |
|
446 | } |
||
447 | |||
448 | 1 | $this->redirectUrl = $redirectUrl; |
|
449 | 1 | return $this; |
|
450 | } |
||
451 | |||
452 | /** |
||
453 | * Return the redirect HTTP status code |
||
454 | * |
||
455 | * @return int Redirect HTTP status code |
||
456 | */ |
||
457 | 1 | public function getRedirectStatus() |
|
461 | |||
462 | /** |
||
463 | * Set the redirect HTTP status code |
||
464 | * |
||
465 | * @param int $redirectStatus Redirect HTTP status code |
||
466 | * @return Vhost Self reference |
||
467 | * @throw \RuntimeException If the redirect HTTP status code is invalid |
||
468 | */ |
||
469 | 1 | public function setRedirectStatus($redirectStatus) |
|
478 | } |
||
479 |