Complex classes like Document 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 Document, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class Document extends DOMDocument{ |
||
24 | use Magic; |
||
25 | |||
26 | const NODE_CLASSES = [ |
||
27 | 'Attr', |
||
28 | 'CharacterData', |
||
29 | 'Comment', |
||
30 | 'DocumentFragment', |
||
31 | 'DocumentType', |
||
32 | 'Element', |
||
33 | 'Text', |
||
34 | ]; |
||
35 | |||
36 | /** |
||
37 | * Document constructor. |
||
38 | * |
||
39 | * @param string $content |
||
40 | * @param bool $xml |
||
41 | * @param string|null $version |
||
42 | * @param string|null $encoding |
||
43 | */ |
||
44 | 42 | public function __construct($content = null, $xml = false, $version = '1.0', $encoding = 'UTF-8'){ |
|
56 | |||
57 | |||
58 | /********* |
||
59 | * magic * |
||
60 | *********/ |
||
61 | |||
62 | 1 | public function magic_get_title(){ |
|
65 | |||
66 | 1 | public function magic_set_title(string $title){ |
|
77 | |||
78 | |||
79 | /******** |
||
80 | * ugly * |
||
81 | ********/ |
||
82 | |||
83 | 2 | public function _loadDocument($content, $xml){ |
|
92 | |||
93 | 1 | public function _loadDocumentString(string $documentSource, bool $xml = false){ |
|
102 | |||
103 | /** |
||
104 | * @param mixed $content |
||
105 | * |
||
106 | * @return \chillerlan\PrototypeDOM\NodeList |
||
107 | * @throws \Exception |
||
108 | */ |
||
109 | 8 | public function _toNodeList($content):NodeList{ |
|
122 | |||
123 | /** |
||
124 | * @param string $content |
||
125 | * |
||
126 | * @return \chillerlan\PrototypeDOM\NodeList |
||
127 | */ |
||
128 | 8 | public function _HTMLFragmentToNodeList(string $content):NodeList{ |
|
134 | |||
135 | /** |
||
136 | * @param array $array |
||
137 | * |
||
138 | * @return \chillerlan\PrototypeDOM\NodeList |
||
139 | */ |
||
140 | 3 | public function _arrayToNodeList(array $array):NodeList{ |
|
149 | |||
150 | |||
151 | /*********** |
||
152 | * generic * |
||
153 | ***********/ |
||
154 | |||
155 | /** |
||
156 | * @param string $selector |
||
157 | * @param string $axis |
||
158 | * |
||
159 | * @return string |
||
160 | */ |
||
161 | 41 | public function selector2xpath(string $selector, string $axis = '//'):string{ |
|
164 | |||
165 | /** |
||
166 | * @param string $xpath |
||
167 | * @param \DOMNode|null $contextNode |
||
168 | * |
||
169 | * @return \chillerlan\PrototypeDOM\NodeList |
||
170 | */ |
||
171 | 41 | public function query(string $xpath, DOMNode $contextNode = null):NodeList{ |
|
174 | |||
175 | /** |
||
176 | * @param string $selector |
||
177 | * @param \DOMNode|null $contextNode |
||
178 | * @param string $axis |
||
179 | * |
||
180 | * @return \chillerlan\PrototypeDOM\NodeList |
||
181 | */ |
||
182 | 41 | public function querySelectorAll(string $selector, DOMNode $contextNode = null, string $axis = 'descendant-or-self::'):NodeList{ |
|
185 | |||
186 | /** |
||
187 | * @param string|array $selectors |
||
188 | * @param \DOMNode|null $contextNode |
||
189 | * @param string $axis |
||
190 | * |
||
191 | * @return \chillerlan\PrototypeDOM\Document |
||
192 | */ |
||
193 | 1 | public function removeElementsBySelector($selectors, DOMNode $contextNode = null, string $axis = 'descendant-or-self::'):Document{ |
|
206 | |||
207 | /** |
||
208 | * @param \chillerlan\PrototypeDOM\NodeList $nodeList |
||
209 | * |
||
210 | * @return \chillerlan\PrototypeDOM\Document |
||
211 | */ |
||
212 | 2 | public function insertNodeList(NodeList $nodeList):Document{ |
|
221 | |||
222 | /************* |
||
223 | * prototype * |
||
224 | *************/ |
||
225 | |||
226 | /** |
||
227 | * @link http://api.prototypejs.org/dom/Element/inspect/ |
||
228 | * |
||
229 | * @param \DOMNode|null $context |
||
230 | * @param bool $xml |
||
231 | * |
||
232 | * @return string |
||
233 | */ |
||
234 | 8 | public function inspect(DOMNode $context = null, $xml = false):string{ |
|
239 | |||
240 | /** |
||
241 | * @link http://api.prototypejs.org/dom/Element/select/ |
||
242 | * |
||
243 | * @param string|array $selectors |
||
244 | * @param \DOMNode|null $contextNode |
||
245 | * @param string $axis |
||
246 | * @param int $nodeType |
||
247 | * |
||
248 | * @return \chillerlan\PrototypeDOM\NodeList |
||
249 | */ |
||
250 | 41 | public function select($selectors = null, DOMNode $contextNode = null, string $axis = 'descendant-or-self::', int $nodeType = XML_ELEMENT_NODE):NodeList{ |
|
276 | |||
277 | /** |
||
278 | * @link http://api.prototypejs.org/dom/Element/recursivelyCollect/ |
||
279 | * |
||
280 | * @param \chillerlan\PrototypeDOM\Node\PrototypeNode $element |
||
281 | * @param string $property |
||
282 | * @param int $maxLength |
||
283 | * @param int $nodeType |
||
284 | * |
||
285 | * @return \chillerlan\PrototypeDOM\NodeList |
||
286 | */ |
||
287 | 3 | public function recursivelyCollect(PrototypeNode $element, string $property, int $maxLength = -1, int $nodeType = XML_ELEMENT_NODE):NodeList{ |
|
308 | |||
309 | /** |
||
310 | * @param \chillerlan\PrototypeDOM\Node\PrototypeNode $element |
||
311 | * @param string $property |
||
312 | * @param string|null $selector |
||
313 | * @param int $index |
||
314 | * @param int $nodeType |
||
315 | * |
||
316 | * @return \chillerlan\PrototypeDOM\Node\PrototypeElement|null |
||
317 | */ |
||
318 | 4 | public function _recursivelyFind(PrototypeNode $element, string $property, string $selector = null, int $index = 0, int $nodeType = XML_ELEMENT_NODE){ |
|
336 | |||
337 | /** |
||
338 | * @link http://api.prototypejs.org/dom/Element/match/ |
||
339 | * |
||
340 | * @param \chillerlan\PrototypeDOM\Node\PrototypeNode $element |
||
341 | * @param string $selector |
||
342 | * |
||
343 | * @return bool |
||
344 | */ |
||
345 | 4 | public function match(PrototypeNode $element, string $selector):bool{ |
|
357 | |||
358 | /** |
||
359 | * @link http://api.prototypejs.org/dom/Element/new/ |
||
360 | * |
||
361 | * @param string $tag |
||
362 | * @param array|null $attributes |
||
363 | * |
||
364 | * @return \chillerlan\PrototypeDOM\Node\Element |
||
365 | */ |
||
366 | 6 | public function newElement(string $tag, array $attributes = null):Element{ |
|
376 | |||
377 | } |
||
378 |
As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next
break
.There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.
To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.