Total Complexity | 40 |
Total Lines | 262 |
Duplicated Lines | 0 % |
Changes | 2 | ||
Bugs | 0 | Features | 0 |
Complex classes like ModuleManager 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.
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 ModuleManager, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | abstract class ModuleManager |
||
22 | { |
||
23 | /** |
||
24 | * Regenerate menus and actions. |
||
25 | * This is temporary, everything will be cached by user or role. |
||
26 | * |
||
27 | * @return void |
||
28 | */ |
||
29 | public static function regenerate() |
||
30 | { |
||
31 | dump([ |
||
32 | 'acciones' => self::getActions(), |
||
33 | 'menú refactorizado' => self::getArrayMenu(), |
||
34 | 'menú lateral' => self::getArraySidebarMenu() |
||
35 | ]); |
||
36 | } |
||
37 | |||
38 | /** |
||
39 | * Returns an associative array with the actions of each controller, |
||
40 | * the index being the namespace of the controller. |
||
41 | * |
||
42 | * @return array |
||
43 | */ |
||
44 | private static function getActions() |
||
45 | { |
||
46 | $result = []; |
||
47 | $menuOptions = self::iterateFunction('getActions'); |
||
48 | foreach ($menuOptions as $option) { |
||
49 | if ($option === false) { |
||
50 | continue; |
||
51 | } |
||
52 | $result = array_merge($result, $option); |
||
53 | } |
||
54 | return $result; |
||
55 | } |
||
56 | |||
57 | /** |
||
58 | * Generates an array in which each element is the result of calling the |
||
59 | * $function function for each controller in the application. |
||
60 | * |
||
61 | * @param $function |
||
62 | * @return array |
||
63 | */ |
||
64 | private static function iterateFunction($function) |
||
65 | { |
||
66 | $iterate = static::iterate(); |
||
67 | $result = []; |
||
68 | foreach ($iterate as $module) { |
||
69 | $namespace = $module['namespace']; |
||
70 | if (!method_exists($namespace, $function)) { |
||
71 | continue; |
||
72 | } |
||
73 | $result[$namespace] = $namespace::$function(); |
||
74 | } |
||
75 | return $result; |
||
76 | } |
||
77 | |||
78 | private static function iterate() |
||
79 | { |
||
80 | $routes = self::routes(); |
||
81 | $data = []; |
||
82 | foreach ($routes as $route) { |
||
83 | $data = array_merge($data, self::getModuleControllers($route['namespace'], $route['path'])); |
||
84 | } |
||
85 | return $data; |
||
86 | } |
||
87 | |||
88 | /** |
||
89 | * Returns the paths that can contain modules. |
||
90 | * |
||
91 | * @return string[] |
||
92 | */ |
||
93 | private static function routes(): array |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * Returns an array with the module drivers included in the $path folder. |
||
110 | * The array contains the name, namespace and path of those controllers. |
||
111 | * |
||
112 | * @param string $namespace |
||
113 | * @param string $path |
||
114 | * @return array |
||
115 | */ |
||
116 | private static function getModuleControllers(string $namespace, string $path): array |
||
117 | { |
||
118 | $result = []; |
||
119 | if (!is_dir($path)) { |
||
120 | return []; |
||
121 | } |
||
122 | $directories = scandir($path); |
||
123 | foreach ($directories as $directory) { |
||
124 | if ($directory === '.' || $directory === '..' || !is_dir($path . '/' . $directory)) { |
||
125 | continue; |
||
126 | } |
||
127 | $result = array_merge($result, self::getControllers($namespace . '\\' . $directory, $path, $directory)); |
||
128 | } |
||
129 | return $result; |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Returns an array with the specified $path and $directory controllers. |
||
134 | * The array contains the name, namespace and path of those controllers. |
||
135 | * |
||
136 | * @param string $namespace |
||
137 | * @param string $path |
||
138 | * @param string $directory |
||
139 | * @return array |
||
140 | */ |
||
141 | private static function getControllers(string $namespace, string $path, string $directory): array |
||
142 | { |
||
143 | $result = []; |
||
144 | $files = scandir($path . '/' . $directory . '/Controller'); |
||
145 | foreach ($files as $file) { |
||
146 | if ($file === '.' || $file === '..' || !str_ends_with($file, '.php')) { |
||
147 | continue; |
||
148 | } |
||
149 | $name = substr($file, 0, -4); |
||
150 | $result[] = [ |
||
151 | 'name' => $name, |
||
152 | 'namespace' => $namespace . '\\Controller\\' . $name, |
||
153 | 'path' => $path . '/' . $directory . '/Controller/' . $file, |
||
154 | ]; |
||
155 | } |
||
156 | return $result; |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * Regenerate the top menu. |
||
161 | * This is temporary. |
||
162 | * The menus to be displayed will be cached by user or role. |
||
163 | * |
||
164 | * @return array|mixed |
||
165 | */ |
||
166 | public static function getArrayMenu() |
||
167 | { |
||
168 | return self::buildMultiLevelMenu(self::getMenu()); |
||
169 | } |
||
170 | |||
171 | /** |
||
172 | * Converts an array where the index is a menu path with the |
||
173 | * hierarchy separated by pipelines, to a nested array. |
||
174 | * |
||
175 | * @param $menuOptions |
||
176 | * @return array|mixed |
||
177 | */ |
||
178 | private static function buildMultiLevelMenu($menuOptions) |
||
179 | { |
||
180 | $result = []; |
||
181 | |||
182 | foreach ($menuOptions as $option => $value) { |
||
183 | $levels = explode('|', $option); |
||
184 | $numberOfLevels = count($levels); |
||
185 | $currentLevel = &$result; |
||
186 | |||
187 | foreach ($levels as $level) { |
||
188 | $numberOfLevels--; |
||
189 | if ($numberOfLevels === 0) { |
||
190 | $currentLevel[$level] = $value; |
||
191 | continue; |
||
192 | } |
||
193 | if (!isset($currentLevel[$level])) { |
||
194 | $currentLevel[$level] = []; |
||
195 | } |
||
196 | $currentLevel = &$currentLevel[$level]; |
||
197 | } |
||
198 | } |
||
199 | |||
200 | return $result; |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * Obtains an array with all the menu options where the index is the |
||
205 | * option and the value is the url of the controller to be executed. |
||
206 | * |
||
207 | * Example: ['admin|auth'] = "index.php?module=Admin&controller=Auth" |
||
208 | * |
||
209 | * @return array |
||
210 | */ |
||
211 | private static function getMenu() |
||
226 | } |
||
227 | |||
228 | /** |
||
229 | * Returns the URL that runs the controller with the given namespace. |
||
230 | * |
||
231 | * The namespace can be: |
||
232 | * - CoreModules\\<module>\\Controller\\<controller>Controller |
||
233 | * - Modules\\<module>\\Controller\\<controller>Controller |
||
234 | * |
||
235 | * @param $namespace |
||
236 | * @return false|string |
||
237 | */ |
||
238 | public static function getUrl($namespace) |
||
239 | { |
||
240 | $explode = explode('\\', $namespace); |
||
241 | if (count($explode) < 4) { |
||
242 | return false; |
||
243 | } |
||
244 | $name = $explode[3]; |
||
245 | if (!str_ends_with($name, 'Controller')) { |
||
246 | return false; |
||
247 | } |
||
248 | $controller = substr($name, 0, -10); |
||
249 | $module = $explode[1]; |
||
250 | |||
251 | return 'index.php?module=' . $module . '&controller=' . $controller; |
||
252 | } |
||
253 | |||
254 | /** |
||
255 | * Regenerate the sidebar menu. |
||
256 | * This is temporary. |
||
257 | * The menus to be displayed will be cached by user or role. |
||
258 | * |
||
259 | * @return array|mixed |
||
260 | */ |
||
261 | public static function getArraySidebarMenu() |
||
262 | { |
||
263 | return self::buildMultiLevelMenu(self::getSidebarMenu()); |
||
264 | } |
||
265 | |||
266 | private static function getSidebarMenu() |
||
283 | } |
||
284 | } |
||
285 |