Complex classes like Node 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 Node, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
19 | class Node |
||
20 | { |
||
21 | /** |
||
22 | * Short tags expression, usually used inside attributes and etc. |
||
23 | */ |
||
24 | const SHORT_TAGS = '/\${(?P<name>[a-z0-9_\.\-]+)(?: *\| *(?P<default>[^}]+) *)?}/i'; |
||
25 | |||
26 | /** |
||
27 | * Node name (usually related to block name). |
||
28 | * |
||
29 | * @var string |
||
30 | */ |
||
31 | private $name = ''; |
||
32 | |||
33 | /** |
||
34 | * Indication that node extended parent layout/node, meaning custom blocks can not be rendered |
||
35 | * outside defined parent layout. |
||
36 | * |
||
37 | * @var bool |
||
38 | */ |
||
39 | private $extended = false; |
||
40 | |||
41 | /** |
||
42 | * Set of child nodes being used during rendering. |
||
43 | * |
||
44 | * @var string[]|Node[] |
||
45 | */ |
||
46 | private $nodes = []; |
||
47 | |||
48 | /** |
||
49 | * Set of blocks defined outside parent scope (parent layout blocks), blocks like either dynamic |
||
50 | * or used for internal template reasons. They should not be rendered in plain HTML (but can be |
||
51 | * used by Exporters to render as something else). |
||
52 | * |
||
53 | * @var Node[] |
||
54 | */ |
||
55 | private $outers = []; |
||
56 | |||
57 | /** |
||
58 | * NodeSupervisor responsible for resolve tag behaviours. |
||
59 | * |
||
60 | * @invisible |
||
61 | * @var SupervisorInterface |
||
62 | */ |
||
63 | protected $supervisor = null; |
||
64 | |||
65 | /** |
||
66 | * @param SupervisorInterface $supervisor |
||
67 | * @param string $name |
||
68 | * @param string|array $source String content or array of html tokens. |
||
69 | * @param HtmlTokenizer $tokenizer Html tokens source. |
||
70 | */ |
||
71 | public function __construct( |
||
90 | |||
91 | /** |
||
92 | * @return SupervisorInterface |
||
93 | */ |
||
94 | public function supervisor() |
||
98 | |||
99 | /** |
||
100 | * Create new block under current node. If node extends parent, block will ether replace parent |
||
101 | * content or will be added as outer block (block with parent placeholder). |
||
102 | * |
||
103 | * @param string $name |
||
104 | * @param string|array $source String content or array of html tokens. |
||
105 | * @param array $blocks Used to redefine node content and bypass token parsing. |
||
106 | * @param bool $replace Set to true to send created Node directly to outer blocks. |
||
107 | */ |
||
108 | public function mountBlock($name, $source, $blocks = [], $replace = false) |
||
133 | |||
134 | /** |
||
135 | * Add sub node. |
||
136 | * |
||
137 | * @param Node $node |
||
138 | */ |
||
139 | public function mountNode(Node $node) |
||
143 | |||
144 | /** |
||
145 | * Recursively find a children node by it's name. |
||
146 | * |
||
147 | * @param string $name |
||
148 | * @return Node|null |
||
149 | */ |
||
150 | public function findNode($name) |
||
166 | |||
167 | /** |
||
168 | * Compile node data (inner nodes) into string. |
||
169 | * |
||
170 | * @param array $dynamic All outer blocks will be aggregated in this array (in compiled form). |
||
171 | * @param array $compiled Internal complication memory (method called recursively) |
||
172 | * @return string |
||
173 | */ |
||
174 | public function compile(&$dynamic = [], &$compiled = []) |
||
223 | |||
224 | /** |
||
225 | * Parse set of tokens provided by html Tokenizer and create blocks and other control |
||
226 | * constructions. Basically it will try to created html tree. |
||
227 | * |
||
228 | * @param array $tokens |
||
229 | * @throws StrictModeException |
||
230 | */ |
||
231 | protected function parseTokens(array $tokens) |
||
304 | |||
305 | /** |
||
306 | * Once token content (nested tags and text) is correctly collected we can pass it to supervisor |
||
307 | * to check what we actually should be doing with this token. |
||
308 | * |
||
309 | * @param array $token |
||
310 | * @param array $content |
||
311 | * @param array $closeToken Token described close tag of html element. |
||
312 | */ |
||
313 | protected function mountToken(array $token, array $content = [], array $closeToken = []) |
||
338 | |||
339 | /** |
||
340 | * Register string node content. |
||
341 | * |
||
342 | * @param string|array $content String content or html tokens. |
||
343 | */ |
||
344 | private function mountContent($content) |
||
386 | |||
387 | /** |
||
388 | * Once supervisor defined custom token behaviour we can process it's content accordingly. |
||
389 | * |
||
390 | * @param BehaviourInterface $behaviour |
||
391 | * @param array $content |
||
392 | */ |
||
393 | protected function applyBehaviour(BehaviourInterface $behaviour, array $content = []) |
||
424 | |||
425 | /** |
||
426 | * Replace node content with content provided by external node, external node can still use |
||
427 | * content of parent block by defining block named identical to it's parent. |
||
428 | * |
||
429 | * @param Node $node |
||
430 | */ |
||
431 | private function replaceNode(Node $node) |
||
441 | } |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.