Complex classes like Path 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 Path, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
19 | class Path |
||
20 | { |
||
21 | const PLATFORM_UNIX = 'unix'; |
||
22 | const PLATFORM_WINDOWS = 'windows'; |
||
23 | |||
24 | /** |
||
25 | * Separator that is used to render platform-independent representations. |
||
26 | */ |
||
27 | const SEPARATOR = '/'; |
||
28 | |||
29 | /** |
||
30 | * Path scheme, if any was used. |
||
31 | * |
||
32 | * @var string|null |
||
33 | */ |
||
34 | private $scheme; |
||
35 | |||
36 | /** |
||
37 | * Path root. May be null (relative path), empty string (unix root or |
||
38 | * windows path \like\that) or drive name (windows-only). |
||
39 | * |
||
40 | * @var string|null |
||
41 | */ |
||
42 | private $root; |
||
43 | |||
44 | /** |
||
45 | * List of path segments. |
||
46 | * |
||
47 | * @var string[] |
||
48 | */ |
||
49 | private $segments; |
||
50 | |||
51 | /** |
||
52 | * Separator that will be used to assemble path back. |
||
53 | * |
||
54 | * @var string |
||
55 | */ |
||
56 | private $separator; |
||
57 | |||
58 | /** |
||
59 | * @param string|null $scheme |
||
60 | * @param string|null $root |
||
61 | * @param string[] $segments |
||
62 | * @param string $separator |
||
63 | */ |
||
64 | 98 | public function __construct($scheme, $root, array $segments, $separator) |
|
71 | |||
72 | /** |
||
73 | * Parses provided path into {@link Path} instance, acting as a public |
||
74 | * constructor for whole Path class. |
||
75 | * |
||
76 | * @param string $input Path to be parsed |
||
77 | * @param string|null $platform Platform used to determine correct |
||
78 | * algorithm. If omitted/set to null, will be detected automatically. |
||
79 | * |
||
80 | * @return Path |
||
81 | */ |
||
82 | 98 | public static function parse($input, $platform = null) |
|
100 | |||
101 | 98 | protected static function extractScheme($input) |
|
109 | |||
110 | 98 | protected static function stripScheme($input, $scheme) |
|
114 | |||
115 | 98 | protected static function containsRoot(array $segments, $platform) |
|
128 | |||
129 | /** |
||
130 | * Returns platform matching the separator. Exists for 100% coverage :P |
||
131 | * |
||
132 | * @param string $separator |
||
133 | * @return string |
||
134 | */ |
||
135 | 32 | public static function getPlatformBySeparator($separator) |
|
147 | |||
148 | /** |
||
149 | * Detects current platform. |
||
150 | * |
||
151 | * @return string |
||
152 | */ |
||
153 | 31 | public static function detectPlatform() |
|
157 | |||
158 | /** |
||
159 | * Converts input into path. Throws runtime exception if that's not |
||
160 | * possible. |
||
161 | * |
||
162 | * @param Path|string|mixed $input |
||
163 | * @return Path|null |
||
164 | */ |
||
165 | 45 | protected function tryAdapt($input) |
|
177 | |||
178 | /** |
||
179 | * Converts input into path. Throws runtime exception if that's not |
||
180 | * possible. |
||
181 | * |
||
182 | * @param Path|string $input |
||
183 | * @return Path |
||
184 | */ |
||
185 | 35 | protected function adapt($input) |
|
193 | |||
194 | /** |
||
195 | * Creates new path, destroying as much empty ('') and dot-entries |
||
196 | * ('.', '..') as possible, so path 'node/./../leaf' will be truncated |
||
197 | * just to leaf, but 'node/../../leaf' would result in '../leaf'. |
||
198 | * |
||
199 | * @return Path |
||
200 | */ |
||
201 | public function normalize() |
||
225 | |||
226 | /** |
||
227 | * Returns hierarchy branch from the topmost node (root, if present) down |
||
228 | * to current node, so `/a/b/c` will result in `/a`, ` /a/b` and `/a/b/c`, |
||
229 | * and `a/b` in `a` and `a/b`. |
||
230 | * |
||
231 | * @return Path[] |
||
232 | */ |
||
233 | 5 | public function enumerate() |
|
247 | |||
248 | /** |
||
249 | * Returns iterator that will iterate hierarchy branch according to |
||
250 | * {@link #enumerate} rules. |
||
251 | * |
||
252 | * @return Iterator Iterator that emits Path instances. |
||
253 | */ |
||
254 | 5 | public function iterator() |
|
258 | |||
259 | /** |
||
260 | * Returns list of path parents, starting from the topmost one and going |
||
261 | * down one by one, similar to {@link #enumerate}. |
||
262 | * |
||
263 | * @return Path[] |
||
264 | */ |
||
265 | 5 | public function getParents() |
|
271 | |||
272 | /** |
||
273 | * @return bool |
||
274 | */ |
||
275 | 17 | public function isAbsolute() |
|
279 | |||
280 | /** |
||
281 | * @return bool |
||
282 | */ |
||
283 | 9 | public function isRelative() |
|
287 | |||
288 | /** |
||
289 | * @return bool |
||
290 | */ |
||
291 | 26 | public function isRoot() |
|
295 | |||
296 | /** |
||
297 | * Returns true if $other is located on the same hierarchy branch higher |
||
298 | * that current path. |
||
299 | * |
||
300 | * If path schemes differ, or not both paths are relative/absolute, this |
||
301 | * method will instantly return false. |
||
302 | * |
||
303 | * @param Path|string $other |
||
304 | * @return bool |
||
305 | */ |
||
306 | 12 | public function isDescendantOf($other) |
|
327 | |||
328 | /** |
||
329 | * Returns true if $other is located on the same hierarchy branch deeper |
||
330 | * that current path. |
||
331 | * |
||
332 | * If path schemes differ, or not both paths are relative/absolute, this |
||
333 | * method will instantly return false. |
||
334 | * |
||
335 | * @param Path|string $other |
||
336 | * @return bool |
||
337 | */ |
||
338 | 11 | public function isAncestorOf($other) |
|
342 | |||
343 | /** |
||
344 | * Returns true if $other is direct parent of current path. |
||
345 | * |
||
346 | * If path schemes differ, or not both paths are relative/absolute, this |
||
347 | * method will instantly return false. |
||
348 | * |
||
349 | * @param Path|string $other |
||
350 | * @return bool |
||
351 | */ |
||
352 | 13 | public function isChildOf($other) |
|
361 | |||
362 | /** |
||
363 | * Returns true if $other is direct child of current path. |
||
364 | * |
||
365 | * If path schemes differ, or not both paths are relative/absolute, this |
||
366 | * method will instantly return false. |
||
367 | * |
||
368 | * @param Path|string $other |
||
369 | * @return bool |
||
370 | */ |
||
371 | 12 | public function isParentOf($other) |
|
375 | |||
376 | /** |
||
377 | * Returns true if $other is located on the smae hierarchy level. |
||
378 | * |
||
379 | * If path schemes differ, or not both paths are relative/absolute, this |
||
380 | * method will instantly return false. |
||
381 | * |
||
382 | * @param Path|string $other |
||
383 | * @return bool |
||
384 | */ |
||
385 | 11 | public function isSiblingOf($other) |
|
393 | |||
394 | /** |
||
395 | * Returns direct parent of current path. In case of call on root node |
||
396 | * exception will be thrown. |
||
397 | * |
||
398 | * @return Path |
||
399 | */ |
||
400 | 16 | public function getParent() |
|
409 | |||
410 | /** |
||
411 | * Resolves other path against current one (or, in other words, prepends |
||
412 | * current path to provided one). If provided path is absolute, it is |
||
413 | * returned as-is, otherwise it is appended to current one: |
||
414 | * |
||
415 | * /a/b resolve /c/d => /b/c |
||
416 | * /a/b resolve c/d => /a/b/c/d |
||
417 | * a/b resolve c/d => a/b/c/d |
||
418 | * |
||
419 | * @param Path|string $other |
||
420 | * |
||
421 | * @return Path |
||
422 | */ |
||
423 | 8 | public function resolve($other) |
|
433 | |||
434 | /** |
||
435 | * Construct a relative path, trying to subtract current path from provided |
||
436 | * one (thus providing a path required to traverse from current one to |
||
437 | * provided one). If called with an absolute path against relative or vice |
||
438 | * versa, will return other path as is. |
||
439 | * |
||
440 | * @param Path|string $other |
||
441 | * |
||
442 | * @return Path |
||
443 | */ |
||
444 | 14 | public function relativize($other) |
|
477 | |||
478 | /** |
||
479 | * Lexicographically compares one path to another. |
||
480 | * |
||
481 | * @param Path|string|null $other |
||
482 | * @return int |
||
483 | */ |
||
484 | 10 | public function compareTo($other) |
|
513 | |||
514 | /** |
||
515 | * Helper method for {@link #compareTo()} |
||
516 | * |
||
517 | * @param string|null $left |
||
518 | * @param string|null $right |
||
519 | * @return int |
||
520 | */ |
||
521 | 9 | protected function compareStrings($left, $right) |
|
531 | |||
532 | /** |
||
533 | * Compares current path to provided one and tells if they are equal. |
||
534 | * |
||
535 | * @param Path|string|null $other |
||
536 | * @return bool |
||
537 | */ |
||
538 | 10 | public function equals($other) |
|
542 | |||
543 | /** |
||
544 | * @return string|null |
||
545 | */ |
||
546 | 16 | public function getScheme() |
|
550 | |||
551 | /** |
||
552 | * @return string|null |
||
553 | */ |
||
554 | 16 | public function getRoot() |
|
558 | |||
559 | /** |
||
560 | * @return string[] |
||
561 | */ |
||
562 | 18 | public function getSegments() |
|
566 | |||
567 | /** |
||
568 | * @return string |
||
569 | */ |
||
570 | 15 | public function getSeparator() |
|
574 | |||
575 | /** |
||
576 | * @param string|null $scheme |
||
577 | * @return Path |
||
578 | */ |
||
579 | 1 | public function withScheme($scheme) |
|
585 | |||
586 | /** |
||
587 | * @return Path |
||
588 | */ |
||
589 | 1 | public function withoutScheme() |
|
593 | |||
594 | /** |
||
595 | * @param string $root |
||
596 | * @return Path |
||
597 | */ |
||
598 | 1 | public function withRoot($root) |
|
604 | |||
605 | /** |
||
606 | * @return Path |
||
607 | */ |
||
608 | 1 | public function withoutRoot() |
|
612 | |||
613 | /** |
||
614 | * Assembles string representation using provided separator. |
||
615 | * |
||
616 | * @param string $separator |
||
617 | * @return string |
||
618 | */ |
||
619 | 43 | protected function assemble($separator) |
|
630 | |||
631 | /** |
||
632 | * Returns platform-independent representation. |
||
633 | * |
||
634 | * @return string |
||
635 | */ |
||
636 | 43 | public function __toString() |
|
640 | |||
641 | /** |
||
642 | * Returns representation for target platform. |
||
643 | * |
||
644 | * @return string |
||
645 | */ |
||
646 | 13 | public function toPlatformString() |
|
650 | } |
||
651 |