Complex classes like InnerNode 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 InnerNode, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
13 | abstract class InnerNode extends ArrayNode |
||
14 | { |
||
15 | |||
16 | /** |
||
17 | * An array of all the children. |
||
18 | * |
||
19 | * @var array |
||
20 | */ |
||
21 | protected $children = []; |
||
22 | |||
23 | /** |
||
24 | * Sets the encoding class to this node and propagates it |
||
25 | * to all its children. |
||
26 | * |
||
27 | * @param Encode $encode |
||
28 | * @return void |
||
29 | */ |
||
30 | public function propagateEncoding(Encode $encode) |
||
41 | |||
42 | /** |
||
43 | * Checks if this node has children. |
||
44 | * |
||
45 | * @return bool |
||
46 | */ |
||
47 | public function hasChildren() |
||
51 | |||
52 | /** |
||
53 | * Returns the child by id. |
||
54 | * |
||
55 | * @param int $id |
||
56 | * @return AbstractNode |
||
57 | * @throws ChildNotFoundException |
||
58 | */ |
||
59 | public function getChild($id) |
||
67 | |||
68 | /** |
||
69 | * Returns a new array of child nodes |
||
70 | * |
||
71 | * @return array |
||
72 | */ |
||
73 | public function getChildren() |
||
88 | |||
89 | /** |
||
90 | * Counts children |
||
91 | * |
||
92 | * @return int |
||
93 | */ |
||
94 | public function countChildren() |
||
98 | |||
99 | /** |
||
100 | * Adds a child node to this node and returns the id of the child for this |
||
101 | * parent. |
||
102 | * |
||
103 | * @param AbstractNode $child |
||
104 | * @return bool |
||
105 | * @throws CircularException |
||
106 | */ |
||
107 | public function addChild(AbstractNode $child, $before = null) |
||
175 | |||
176 | /** |
||
177 | * Insert element before child with provided id |
||
178 | * |
||
179 | * @param AbstractNode $child |
||
180 | * @return bool |
||
181 | * @param int $id |
||
182 | */ |
||
183 | public function insertBefore(AbstractNode $child, $id){ |
||
186 | |||
187 | /** |
||
188 | * Insert element before after with provided id |
||
189 | * |
||
190 | * @param AbstractNode $child |
||
191 | * @return bool |
||
192 | * @param int $id |
||
193 | */ |
||
194 | public function insertAfter(AbstractNode $child, $id){ |
||
205 | |||
206 | /** |
||
207 | * Removes the child by id. |
||
208 | * |
||
209 | * @param int $id |
||
210 | * @return $this |
||
211 | */ |
||
212 | public function removeChild($id) |
||
236 | |||
237 | /** |
||
238 | * Check if has next Child |
||
239 | * |
||
240 | * @param $id childId |
||
241 | * @return mixed |
||
242 | */ |
||
243 | public function hasNextChild($id) |
||
248 | |||
249 | /** |
||
250 | * Attempts to get the next child. |
||
251 | * |
||
252 | * @param int $id |
||
253 | * @return AbstractNode |
||
254 | * @uses $this->getChild() |
||
255 | * @throws ChildNotFoundException |
||
256 | */ |
||
257 | public function nextChild($id) |
||
264 | |||
265 | /** |
||
266 | * Attempts to get the previous child. |
||
267 | * |
||
268 | * @param int $id |
||
269 | * @return AbstractNode |
||
270 | * @uses $this->getChild() |
||
271 | * @throws ChildNotFoundException |
||
272 | */ |
||
273 | public function previousChild($id) |
||
280 | |||
281 | /** |
||
282 | * Checks if the given node id is a child of the |
||
283 | * current node. |
||
284 | * |
||
285 | * @param int $id |
||
286 | * @return bool |
||
287 | */ |
||
288 | public function isChild($id) |
||
298 | |||
299 | /** |
||
300 | * Removes the child with id $childId and replace it with the new child |
||
301 | * $newChild. |
||
302 | * |
||
303 | * @param int $childId |
||
304 | * @param AbstractNode $newChild |
||
305 | * @throws ChildNotFoundException |
||
306 | */ |
||
307 | public function replaceChild($childId, AbstractNode $newChild) |
||
332 | |||
333 | /** |
||
334 | * Shortcut to return the first child. |
||
335 | * |
||
336 | * @return AbstractNode |
||
337 | * @uses $this->getChild() |
||
338 | */ |
||
339 | public function firstChild() |
||
346 | |||
347 | /** |
||
348 | * Attempts to get the last child. |
||
349 | * |
||
350 | * @return AbstractNode |
||
351 | */ |
||
352 | public function lastChild() |
||
359 | |||
360 | /** |
||
361 | * Checks if the given node id is a descendant of the |
||
362 | * current node. |
||
363 | * |
||
364 | * @param int $id |
||
365 | * @return bool |
||
366 | */ |
||
367 | public function isDescendant($id) |
||
386 | |||
387 | /** |
||
388 | * Sets the parent node. |
||
389 | * |
||
390 | * @param InnerNode $parent |
||
391 | * @return $this |
||
392 | * @throws CircularException |
||
393 | */ |
||
394 | public function setParent(InnerNode $parent) |
||
403 | } |
||
404 |
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.