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 | 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 | public static function parse($input, $platform = null) |
||
100 | |||
101 | protected static function extractScheme($input) |
||
109 | |||
110 | protected static function stripScheme($input, $scheme) |
||
114 | |||
115 | 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 | public static function getPlatformBySeparator($separator) |
||
147 | |||
148 | /** |
||
149 | * Detects current platform. |
||
150 | * |
||
151 | * @return string |
||
152 | */ |
||
153 | 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 $input |
||
163 | * @return Path|null |
||
164 | */ |
||
165 | 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 | 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() |
||
223 | |||
224 | /** |
||
225 | * Returns hierarchy branch from the topmost node (root, if present) down |
||
226 | * to current node, so `/a/b/c` will result in `/a`, `/a/b` and `/a/b/c`, |
||
227 | * and `a/b` in `a` and `a/b`. |
||
228 | * |
||
229 | * @return Path[] |
||
230 | */ |
||
231 | public function enumerate() |
||
245 | |||
246 | /** |
||
247 | * Returns iterator that will iterate hierarchy branch according to |
||
248 | * {@link #enumerate} rules. |
||
249 | * |
||
250 | * @return Iterator Iterator that emits Path instances. |
||
251 | */ |
||
252 | public function iterator() |
||
256 | |||
257 | /** |
||
258 | * Returns list of path parents, starting from the topmost one and going |
||
259 | * down one by one, similar to {@link #enumerate}. |
||
260 | * |
||
261 | * @return Path[] |
||
262 | */ |
||
263 | public function getParents() |
||
269 | |||
270 | /** |
||
271 | * @return bool |
||
272 | */ |
||
273 | public function isAbsolute() |
||
277 | |||
278 | /** |
||
279 | * @return bool |
||
280 | */ |
||
281 | public function isRelative() |
||
285 | |||
286 | /** |
||
287 | * @return bool |
||
288 | */ |
||
289 | public function isRoot() |
||
293 | |||
294 | /** |
||
295 | * Returns true if $other is located on the same hierarchy branch higher |
||
296 | * that current path. |
||
297 | * |
||
298 | * If path schemes differ, or not both paths are relative/absolute, this |
||
299 | * method will instantly return false. |
||
300 | * |
||
301 | * @param Path|string $other |
||
302 | * @return bool |
||
303 | */ |
||
304 | public function isDescendantOf($other) |
||
325 | |||
326 | /** |
||
327 | * Returns true if $other is located on the same hierarchy branch deeper |
||
328 | * that current path. |
||
329 | * |
||
330 | * If path schemes differ, or not both paths are relative/absolute, this |
||
331 | * method will instantly return false. |
||
332 | * |
||
333 | * @param Path|string $other |
||
334 | * @return bool |
||
335 | */ |
||
336 | public function isAncestorOf($other) |
||
340 | |||
341 | /** |
||
342 | * Returns true if $other is direct parent of current path. |
||
343 | * |
||
344 | * If path schemes differ, or not both paths are relative/absolute, this |
||
345 | * method will instantly return false. |
||
346 | * |
||
347 | * @param Path|string $other |
||
348 | * @return bool |
||
349 | */ |
||
350 | public function isChildOf($other) |
||
359 | |||
360 | /** |
||
361 | * Returns true if $other is direct child of current path. |
||
362 | * |
||
363 | * If path schemes differ, or not both paths are relative/absolute, this |
||
364 | * method will instantly return false. |
||
365 | * |
||
366 | * @param Path|string $other |
||
367 | * @return bool |
||
368 | */ |
||
369 | public function isParentOf($other) |
||
373 | |||
374 | /** |
||
375 | * Returns true if $other is located on the smae hierarchy level. |
||
376 | * |
||
377 | * If path schemes differ, or not both paths are relative/absolute, this |
||
378 | * method will instantly return false. |
||
379 | * |
||
380 | * @param Path|string $other |
||
381 | * @return bool |
||
382 | */ |
||
383 | public function isSiblingOf($other) |
||
391 | |||
392 | /** |
||
393 | * Returns direct parent of current path. In case of call on root node |
||
394 | * exception will be thrown. |
||
395 | * |
||
396 | * @return Path |
||
397 | */ |
||
398 | public function getParent() |
||
407 | |||
408 | /** |
||
409 | * Resolves other path against current one (or, in other words, prepends |
||
410 | * current path to provided one). If provided path is absolute, it is |
||
411 | * returned as-is, otherwise it is appended to current one: |
||
412 | * |
||
413 | * /a/b resolve /c/d => /b/c |
||
414 | * /a/b resolve c/d => /a/b/c/d |
||
415 | * a/b resolve c/d => a/b/c/d |
||
416 | * |
||
417 | * @param Path|string $other |
||
418 | * |
||
419 | * @return Path |
||
420 | */ |
||
421 | public function resolve($other) |
||
431 | |||
432 | /** |
||
433 | * Construct a relative path, trying to subtract current path from provided |
||
434 | * one (thus providing a path required to traverse from current one to |
||
435 | * provided one). If called with an absolute path against relative or vice |
||
436 | * versa, will return other path as is. |
||
437 | * |
||
438 | * @param Path|string $other |
||
439 | * |
||
440 | * @return Path |
||
441 | */ |
||
442 | public function relativize($other) |
||
471 | |||
472 | /** |
||
473 | * Lexicographically compares one path to another. |
||
474 | * |
||
475 | * @param Path|string $other |
||
476 | * @return int |
||
477 | */ |
||
478 | public function compareTo($other) |
||
507 | |||
508 | /** |
||
509 | * Helper method for {@link #compareTo()} |
||
510 | * |
||
511 | * @param string|null $left |
||
512 | * @param string|null $right |
||
513 | * @return int |
||
514 | */ |
||
515 | protected function compareStrings($left, $right) |
||
525 | |||
526 | /** |
||
527 | * Compares current path to provided one and tells if they are equal. |
||
528 | * |
||
529 | * @param Path|string|null $other |
||
530 | * @return bool |
||
531 | */ |
||
532 | public function equals($other) |
||
536 | |||
537 | /** |
||
538 | * @return string|null |
||
539 | */ |
||
540 | public function getScheme() |
||
544 | |||
545 | /** |
||
546 | * @return string|null |
||
547 | */ |
||
548 | public function getRoot() |
||
552 | |||
553 | /** |
||
554 | * @return string[] |
||
555 | */ |
||
556 | public function getSegments() |
||
560 | |||
561 | /** |
||
562 | * @return string |
||
563 | */ |
||
564 | public function getSeparator() |
||
568 | |||
569 | /** |
||
570 | * @param string|null $scheme |
||
571 | * @return Path |
||
572 | */ |
||
573 | public function withScheme($scheme) |
||
579 | |||
580 | /** |
||
581 | * @return Path |
||
582 | */ |
||
583 | public function withoutScheme() |
||
587 | |||
588 | /** |
||
589 | * @param string $root |
||
590 | * @return Path |
||
591 | */ |
||
592 | public function withRoot($root) |
||
598 | |||
599 | /** |
||
600 | * @return Path |
||
601 | */ |
||
602 | public function withoutRoot() |
||
606 | |||
607 | /** |
||
608 | * Assembles string representation using provided separator. |
||
609 | * |
||
610 | * @param string $separator |
||
611 | * @return string |
||
612 | */ |
||
613 | protected function assemble($separator) |
||
624 | |||
625 | /** |
||
626 | * Returns platform-independent representation. |
||
627 | * |
||
628 | * @return string |
||
629 | */ |
||
630 | public function __toString() |
||
634 | |||
635 | /** |
||
636 | * Returns representation for target platform. |
||
637 | * |
||
638 | * @return string |
||
639 | */ |
||
640 | public function toPlatformString() |
||
644 | } |
||
645 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..