Complex classes like Route 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 Route, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class Route |
||
24 | { |
||
25 | |||
26 | /** |
||
27 | * @var Collector |
||
28 | */ |
||
29 | |||
30 | protected $collector; |
||
31 | |||
32 | /** |
||
33 | * @var string |
||
34 | */ |
||
35 | |||
36 | protected $method; |
||
37 | |||
38 | /** |
||
39 | * @var string |
||
40 | */ |
||
41 | |||
42 | protected $pattern; |
||
43 | |||
44 | /** |
||
45 | * @var callable |
||
46 | */ |
||
47 | |||
48 | protected $action; |
||
49 | |||
50 | /** |
||
51 | * @var string |
||
52 | */ |
||
53 | |||
54 | protected $namespace = ""; |
||
55 | |||
56 | /** |
||
57 | * @var string[] |
||
58 | */ |
||
59 | |||
60 | protected $params = []; |
||
61 | |||
62 | /** |
||
63 | * Defaults are parameters set by the user, and don't |
||
64 | * appear on the pattern. |
||
65 | * |
||
66 | * @var array |
||
67 | */ |
||
68 | |||
69 | protected $defaults = []; |
||
70 | |||
71 | /** |
||
72 | * Metadata can be set to be used on filters, dispatch strategies |
||
73 | * or anywhere the route object is used. |
||
74 | * |
||
75 | * @var array |
||
76 | */ |
||
77 | |||
78 | protected $metadata = []; |
||
79 | |||
80 | /** |
||
81 | * @var string|StrategyInterface |
||
82 | */ |
||
83 | |||
84 | protected $strategy; |
||
85 | |||
86 | /** |
||
87 | * Blocked routes are dynamic routes selected to pass by the matcher. |
||
88 | * |
||
89 | * @var boolean |
||
90 | */ |
||
91 | |||
92 | protected $blocked = false; |
||
93 | |||
94 | /** |
||
95 | * The matcher that dispatched this route. |
||
96 | * |
||
97 | * @var Matcher $matcher |
||
98 | */ |
||
99 | |||
100 | protected $matcher; |
||
101 | |||
102 | /** |
||
103 | * The function used to create controllers from name. |
||
104 | * |
||
105 | * @var callable |
||
106 | */ |
||
107 | |||
108 | protected $controllerCreationFunction; |
||
109 | |||
110 | /** |
||
111 | * @param Collector $collector |
||
112 | * @param string $method |
||
113 | * @param string $pattern |
||
114 | * @param callable $action |
||
115 | */ |
||
116 | |||
117 | 50 | public function __construct(Collector $collector, $method, $pattern, $action) |
|
124 | |||
125 | /** |
||
126 | * Clone this route and set it into the collector. |
||
127 | * |
||
128 | * @return Route |
||
129 | */ |
||
130 | |||
131 | 4 | public function reset() |
|
137 | |||
138 | /** |
||
139 | * Remove this route from the collector. |
||
140 | * |
||
141 | * @return self |
||
142 | */ |
||
143 | |||
144 | 6 | public function forget() |
|
149 | |||
150 | /** |
||
151 | * Execute the route action, if no strategy was provided the action |
||
152 | * will be executed by the call_user_func PHP function. |
||
153 | * |
||
154 | * @param callable $container |
||
155 | * @throws BadRouteException |
||
156 | * @return mixed |
||
157 | */ |
||
158 | |||
159 | 16 | public function call(callable $container = null) |
|
175 | |||
176 | /** |
||
177 | * Seek for dynamic content in one callable. This allow to use parameters defined on pattern on callable |
||
178 | * definition, eg. "get" "/{resource:string+}/{slug:slug+}" "{resource}::find". |
||
179 | * |
||
180 | * This will snakecase the resource parameter and deal with as a controller, then call the find method. |
||
181 | * A request for "/articles/my-first-article" will execute find method of Articles controller with only |
||
182 | * "my-first-article" as parameter. |
||
183 | * |
||
184 | * @param callable $callable |
||
185 | * @param callable $container |
||
186 | * |
||
187 | * @return callable |
||
188 | */ |
||
189 | |||
190 | 16 | private function buildCallable($callable, $container) |
|
206 | |||
207 | /** |
||
208 | * Get the controller object. |
||
209 | * |
||
210 | * @param string $controller |
||
211 | * @param callable $container |
||
212 | * |
||
213 | * @return Object |
||
214 | */ |
||
215 | |||
216 | 10 | private function parseCallableController($controller, $container) |
|
224 | |||
225 | /** |
||
226 | * Parse and replace dynamic content on route action. |
||
227 | * |
||
228 | * @param string $fragment Part of callable |
||
229 | * @return string |
||
230 | */ |
||
231 | |||
232 | 10 | private function parseCallablePlaceholders($fragment) |
|
244 | |||
245 | /** |
||
246 | * Execute the route action with the given strategy. |
||
247 | * |
||
248 | * @throws BadRouteException |
||
249 | * @return mixed |
||
250 | */ |
||
251 | |||
252 | 6 | private function callWithStrategy() |
|
264 | |||
265 | /** |
||
266 | * @return Collector |
||
267 | */ |
||
268 | |||
269 | 1 | public function getCollector() |
|
273 | |||
274 | /** |
||
275 | * @return string |
||
276 | */ |
||
277 | |||
278 | public function getMethod() |
||
282 | |||
283 | /** |
||
284 | * @return string |
||
285 | */ |
||
286 | |||
287 | 29 | public function getPattern() |
|
291 | |||
292 | /** |
||
293 | * @return string[] |
||
294 | */ |
||
295 | |||
296 | public function getSegments() |
||
300 | |||
301 | /** |
||
302 | * @return callable |
||
303 | */ |
||
304 | |||
305 | 10 | public function getAction() |
|
309 | |||
310 | /** |
||
311 | * @return string |
||
312 | */ |
||
313 | |||
314 | public function getNamespace() |
||
318 | |||
319 | /** |
||
320 | * @return string[] |
||
321 | */ |
||
322 | |||
323 | 29 | public function getParams() |
|
327 | |||
328 | /** |
||
329 | * @param string $key |
||
330 | * @return string |
||
331 | */ |
||
332 | |||
333 | public function getParam($key) |
||
337 | |||
338 | /** |
||
339 | * Return defaults and params merged in one array. |
||
340 | * |
||
341 | * @return array |
||
342 | */ |
||
343 | |||
344 | 3 | public function getMergedParams() |
|
348 | |||
349 | /** |
||
350 | * @return array |
||
351 | */ |
||
352 | |||
353 | 1 | public function getDefaults() |
|
357 | |||
358 | /** |
||
359 | * @param string $key |
||
360 | * @return mixed |
||
361 | */ |
||
362 | |||
363 | 1 | public function getDefault($key) |
|
367 | |||
368 | /** |
||
369 | * @return array |
||
370 | */ |
||
371 | |||
372 | 1 | public function getMetadataArray() |
|
376 | |||
377 | /** |
||
378 | * @param string $key |
||
379 | * @return mixed |
||
380 | */ |
||
381 | |||
382 | 1 | public function getMetadata($key) |
|
386 | |||
387 | /** |
||
388 | * @return string|null |
||
389 | */ |
||
390 | |||
391 | 2 | public function getStrategy() |
|
399 | |||
400 | /** |
||
401 | * @return StrategyInterface|string |
||
402 | */ |
||
403 | |||
404 | 1 | public function getRawStrategy() |
|
408 | |||
409 | /** |
||
410 | * @return Matcher |
||
411 | */ |
||
412 | |||
413 | 1 | public function getMatcher() |
|
417 | |||
418 | /** |
||
419 | * Verify if a Route have already been blocked. |
||
420 | * |
||
421 | * @return boolean |
||
422 | */ |
||
423 | |||
424 | 29 | public function getBlock() |
|
428 | |||
429 | /** |
||
430 | * Blocking a route indicate that that route have been selected and |
||
431 | * parsed, now it will be given to the matcher. |
||
432 | * |
||
433 | * @param bool $blocked |
||
434 | * @return self |
||
435 | */ |
||
436 | |||
437 | 29 | public function setBlock($blocked) |
|
442 | |||
443 | /** |
||
444 | * @param string $method |
||
445 | * @return Route |
||
446 | */ |
||
447 | |||
448 | 1 | public function setMethod($method) |
|
454 | |||
455 | /** |
||
456 | * @param string $pattern |
||
457 | * @return Route |
||
458 | */ |
||
459 | |||
460 | 3 | public function setPattern($pattern) |
|
466 | |||
467 | /** |
||
468 | * @param string $pattern |
||
469 | * @return self |
||
470 | */ |
||
471 | |||
472 | 29 | public function setPatternWithoutReset($pattern) |
|
477 | |||
478 | /** |
||
479 | * @param string $action |
||
480 | * @return self |
||
481 | */ |
||
482 | |||
483 | 3 | public function setAction($action) |
|
488 | |||
489 | /** |
||
490 | * @param string $namespace |
||
491 | * @return self |
||
492 | */ |
||
493 | |||
494 | 1 | public function setNamespace($namespace) |
|
499 | |||
500 | /** |
||
501 | * @param string[] $params |
||
502 | * @return self |
||
503 | */ |
||
504 | |||
505 | 30 | public function setParams(array $params) |
|
510 | |||
511 | /** |
||
512 | * @param string $key |
||
513 | * @param string $value |
||
514 | * |
||
515 | * @return self |
||
516 | */ |
||
517 | |||
518 | public function setParam($key, $value) |
||
523 | |||
524 | /** |
||
525 | * @param mixed[] $defaults |
||
526 | * @return self |
||
527 | */ |
||
528 | |||
529 | 5 | public function setDefaults(array $defaults) |
|
534 | |||
535 | /** |
||
536 | * @param string $key |
||
537 | * @param mixed $value |
||
538 | * |
||
539 | * @return self |
||
540 | */ |
||
541 | |||
542 | 1 | public function setDefault($key, $value) |
|
547 | |||
548 | /** |
||
549 | * @param mixed[] $metadata |
||
550 | * @return self |
||
551 | */ |
||
552 | |||
553 | 5 | public function setMetadataArray(array $metadata) |
|
558 | |||
559 | /** |
||
560 | * @param string $key |
||
561 | * @param mixed $value |
||
562 | * |
||
563 | * @return $this |
||
564 | */ |
||
565 | |||
566 | 1 | public function setMetadata($key, $value) |
|
571 | |||
572 | /** |
||
573 | * @param null|string|StrategyInterface $strategy |
||
574 | * @return self |
||
575 | */ |
||
576 | |||
577 | 17 | public function setStrategy($strategy) |
|
582 | |||
583 | /** |
||
584 | * @param Matcher $matcher |
||
585 | * @return self |
||
586 | */ |
||
587 | |||
588 | 42 | public function setMatcher(Matcher $matcher) |
|
593 | |||
594 | /** |
||
595 | * Set a constraint to a token in the route pattern. |
||
596 | * |
||
597 | * @param string $token |
||
598 | * @param string $regex |
||
599 | * |
||
600 | * @return self |
||
601 | */ |
||
602 | |||
603 | 1 | public function setConstraint($token, $regex) |
|
617 | |||
618 | /** |
||
619 | * @param string $key |
||
620 | * @return bool |
||
621 | */ |
||
622 | |||
623 | public function hasParam($key) |
||
627 | |||
628 | /** |
||
629 | * @param string $key |
||
630 | * @return bool |
||
631 | */ |
||
632 | |||
633 | public function hasDefault($key) |
||
637 | |||
638 | /** |
||
639 | * @param string $key |
||
640 | * @return bool |
||
641 | */ |
||
642 | |||
643 | public function hasMetadata($key) |
||
647 | |||
648 | } |
||
649 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.