Complex classes like Menu 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 Menu, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
27 | class Menu |
||
28 | { |
||
29 | /** @var HttpReq */ |
||
30 | protected $req; |
||
31 | |||
32 | /** @var array Will hold the created $context */ |
||
33 | protected $menuContext = []; |
||
34 | |||
35 | /** @var string Used for profile menu for own / any */ |
||
36 | protected $permissionSet; |
||
37 | |||
38 | /** @var bool If we found the menu item selected */ |
||
39 | protected $foundSection = false; |
||
40 | |||
41 | /** @var string Current area */ |
||
42 | protected $currentArea = ''; |
||
43 | |||
44 | /** @var null|string The current subaction of the system */ |
||
45 | protected $currentSubaction = ''; |
||
46 | |||
47 | /** @var array Will hold the selected menu data that is returned to the caller */ |
||
48 | private $includeData = []; |
||
49 | |||
50 | /** @var int Unique menu number */ |
||
51 | private $maxMenuId = 0; |
||
52 | |||
53 | /** @var MenuOptions Holds menu options */ |
||
54 | private $menuOptions; |
||
55 | |||
56 | /** @var array Holds menu definition structure set by addSection */ |
||
57 | private $menuData = []; |
||
58 | |||
59 | /** |
||
60 | * Initial processing for the menu |
||
61 | * |
||
62 | * @param HttpReq|null $req |
||
63 | */ |
||
64 | 41 | public function __construct(HttpReq $req = null) |
|
83 | |||
84 | /** |
||
85 | * Create a menu |
||
86 | * |
||
87 | * @return array |
||
88 | * @throws \Elk_Exception |
||
89 | */ |
||
90 | 40 | public function prepareMenu(): array |
|
119 | |||
120 | /** |
||
121 | * Prepares tabs for the template. |
||
122 | * |
||
123 | * This should be called after the area is dispatched, because areas |
||
124 | * are usually in their own file. Those files, once dispatched to, hold |
||
125 | * some data for the tabs which must be specially combined with subaction |
||
126 | * data for everything to work properly. |
||
127 | * |
||
128 | * Seems complicated, yes. |
||
129 | */ |
||
130 | 1 | public function prepareTabData(): void |
|
149 | |||
150 | /** |
||
151 | * Process the menuData array passed to the class |
||
152 | * |
||
153 | * - Only processes areas that are enabled and that the user has permissions |
||
154 | */ |
||
155 | 39 | protected function processMenuData(): void |
|
170 | |||
171 | /** |
||
172 | * Determines if the user has the permissions to access the section/area |
||
173 | * |
||
174 | * If said item did not provide any permission to check, fullly |
||
175 | * unfettered access is assumed. |
||
176 | * |
||
177 | * The profile areas are a bit different in that each permission is |
||
178 | * divided into two sets: "own" for owner and "any" for everyone else. |
||
179 | * |
||
180 | * @param MenuItem $obj area or section being checked |
||
181 | * |
||
182 | * @return bool |
||
183 | */ |
||
184 | 39 | private function checkPermissions(MenuItem $obj): bool |
|
199 | |||
200 | /** |
||
201 | * Checks if the area has a label or not |
||
202 | * |
||
203 | * @param string $areaId |
||
204 | * @param MenuArea $area |
||
205 | * |
||
206 | * @return bool |
||
207 | */ |
||
208 | 38 | private function areaHasLabel(string $areaId, MenuArea $area): bool |
|
214 | |||
215 | /** |
||
216 | * Main processing for creating the menu items for all sections |
||
217 | * |
||
218 | * @param string $sectionId |
||
219 | * @param MenuSection $section |
||
220 | */ |
||
221 | 38 | protected function processSectionAreas(string $sectionId, MenuSection $section): void |
|
253 | |||
254 | /** |
||
255 | * Checks the menu item to see if it is the currently selected one |
||
256 | * |
||
257 | * @param string $sectionId |
||
258 | * @param string $areaId |
||
259 | * @param MenuArea $area |
||
260 | */ |
||
261 | 38 | private function checkCurrentSection(string $sectionId, string $areaId, MenuArea $area): void |
|
272 | |||
273 | /** |
||
274 | * @param string $sectionId |
||
275 | * @param string $areaId |
||
276 | * @param MenuArea $area |
||
277 | */ |
||
278 | 38 | private function setFirstAreaCurrent(string $sectionId, string $areaId, MenuArea $area): void |
|
286 | |||
287 | /** |
||
288 | * Simply sets the current area |
||
289 | * |
||
290 | * @param string $sectionId |
||
291 | * @param string $areaId |
||
292 | * @param MenuArea $area |
||
293 | */ |
||
294 | 38 | private function setAreaCurrent(string $sectionId, string $areaId, MenuArea $area): void |
|
301 | |||
302 | /** |
||
303 | * @param MenuItem $obj |
||
304 | * @param integer $idx |
||
305 | * |
||
306 | * @return string |
||
307 | */ |
||
308 | 38 | private function parseCounter(MenuItem $obj, int $idx): string |
|
323 | |||
324 | /** |
||
325 | * Sets the various section ID items |
||
326 | * |
||
327 | * What it does: |
||
328 | * - If the ID is not set, sets it and sets the section title |
||
329 | * - Sets the section title |
||
330 | * |
||
331 | * @param string $sectionId |
||
332 | * @param MenuSection $section |
||
333 | */ |
||
334 | 38 | private function setSectionContext(string $sectionId, MenuSection $section): void |
|
344 | |||
345 | /** |
||
346 | * Sets the various area items |
||
347 | * |
||
348 | * What it does: |
||
349 | * - If the ID is not set, sets it and sets the area title |
||
350 | * - Sets the area title |
||
351 | * |
||
352 | * @param string $sectionId |
||
353 | * @param string $areaId |
||
354 | * @param MenuArea $area |
||
355 | */ |
||
356 | 38 | private function setAreaContext(string $sectionId, string $areaId, MenuArea $area): void |
|
364 | |||
365 | /** |
||
366 | * Set the URL for the menu item |
||
367 | * |
||
368 | * @param string $sectionId |
||
369 | * @param string $areaId |
||
370 | * @param MenuArea $area |
||
371 | */ |
||
372 | 38 | private function setAreaUrl(string $sectionId, string $areaId, MenuArea $area): void |
|
380 | |||
381 | /** |
||
382 | * Set the menu icon |
||
383 | * |
||
384 | * @param string $sectionId |
||
385 | * @param string $areaId |
||
386 | * @param MenuArea $area |
||
387 | */ |
||
388 | 38 | private function setAreaIcon(string $sectionId, string $areaId, MenuArea $area): void |
|
410 | |||
411 | /** |
||
412 | * Processes all of the subsections for a menu item |
||
413 | * |
||
414 | * @param string $sectionId |
||
415 | * @param string $areaId |
||
416 | * @param MenuArea $area |
||
417 | */ |
||
418 | 38 | protected function processAreaSubsections(string $sectionId, string $areaId, MenuArea $area): void |
|
444 | |||
445 | /** |
||
446 | * @param string $sectionId |
||
447 | * @param string $areaId |
||
448 | * @param string $subId |
||
449 | * @param MenuSubsection $sub |
||
450 | */ |
||
451 | 38 | private function setSubsSectionUrl(string $sectionId, string $areaId, string $subId, MenuSubsection $sub): void |
|
459 | |||
460 | /** |
||
461 | * Set the current subsection |
||
462 | * |
||
463 | * @param string $subId |
||
464 | * @param MenuSubsection $sub |
||
465 | */ |
||
466 | private function setCurrentSubSection(string $subId, MenuSubsection $sub): void |
||
479 | |||
480 | /** |
||
481 | * Ensures that the current subsection is set. |
||
482 | * |
||
483 | * @param string $areaId |
||
484 | * @param array $subSections |
||
485 | */ |
||
486 | 38 | private function setDefaultSubSection(string $areaId, array $subSections): void |
|
493 | |||
494 | /** |
||
495 | * Checks and updates base and section urls |
||
496 | */ |
||
497 | 39 | private function setActiveButtons(): void |
|
513 | |||
514 | /** |
||
515 | * Add the base menu options for this menu |
||
516 | * |
||
517 | * @param array $menuOptions an array of options that can be used to override some default behaviours. |
||
518 | * It can accept the following indexes: |
||
519 | * - action => overrides the default action |
||
520 | * - current_area => overrides the current area |
||
521 | * - extra_url_parameters => an array or pairs or parameters to be added to the url |
||
522 | * - disable_url_session_check => (boolean) if true the session var/id are omitted from |
||
523 | * the url |
||
524 | * - base_url => an alternative base url |
||
525 | * - menu_type => alternative menu types? |
||
526 | * - can_toggle_drop_down => (boolean) if the menu can "toggle" |
||
527 | * - template_name => an alternative template to load (instead of Generic) |
||
528 | * - layer_name => alternative layer name for the menu |
||
529 | * - hook => hook name to call integrate_ . 'hook name' . '_areas' |
||
530 | * - default_include_dir => directory to include for function support |
||
531 | */ |
||
532 | 41 | public function addOptions(array $menuOptions): void |
|
536 | |||
537 | /** |
||
538 | * @param string $id |
||
539 | * @param MenuSection $section |
||
540 | * |
||
541 | * @return $this |
||
542 | */ |
||
543 | 41 | public function addSection(string $id, MenuSection $section): Menu |
|
549 | |||
550 | /** |
||
551 | * Finalizes items so the computed menu can be used |
||
552 | * |
||
553 | * What it does: |
||
554 | * - Sets the menu layer in the template stack |
||
555 | * - Loads context with the computed menu context |
||
556 | * - Sets current subaction and current max menu id |
||
557 | */ |
||
558 | 38 | public function setContext(): void |
|
575 | |||
576 | /** |
||
577 | * Delete a menu. |
||
578 | * |
||
579 | * Checks to see if this menu been loaded into context |
||
580 | * and, if so, resets $context['max_menu_id'] back to the |
||
581 | * last known menu (if any) and remove the template layer |
||
582 | * if there aren't any other known menus. |
||
583 | */ |
||
584 | 21 | public function destroy(): void |
|
606 | } |
||
607 |