Complex classes like AgileDashboardRouter 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 AgileDashboardRouter, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 31 | class AgileDashboardRouter { |
||
| 32 | |||
| 33 | /** |
||
| 34 | * @var Plugin |
||
| 35 | */ |
||
| 36 | private $plugin; |
||
| 37 | |||
| 38 | /** |
||
| 39 | * @param Service |
||
| 40 | */ |
||
| 41 | private $service; |
||
| 42 | |||
| 43 | /** |
||
| 44 | * @var Planning_MilestoneFactory |
||
| 45 | */ |
||
| 46 | private $milestone_factory; |
||
| 47 | |||
| 48 | /** |
||
| 49 | * @var PlanningFactory |
||
| 50 | */ |
||
| 51 | private $planning_factory; |
||
| 52 | |||
| 53 | /** |
||
| 54 | * @var Planning_ShortAccessFactory |
||
| 55 | */ |
||
| 56 | private $planning_shortaccess_factory; |
||
| 57 | |||
| 58 | /** |
||
| 59 | * @var Planning_MilestoneControllerFactory |
||
| 60 | */ |
||
| 61 | private $milestone_controller_factory; |
||
| 62 | |||
| 63 | /** |
||
| 64 | * @var ProjectManager |
||
| 65 | */ |
||
| 66 | private $project_manager; |
||
| 67 | |||
| 68 | /** |
||
| 69 | * @var AgileDashboard_XMLFullStructureExporter |
||
| 70 | */ |
||
| 71 | private $xml_exporter; |
||
| 72 | |||
| 73 | /** @var AgileDashboard_KanbanManager */ |
||
| 74 | private $kanban_manager; |
||
| 75 | |||
| 76 | /** @var AgileDashboard_ConfigurationManager */ |
||
| 77 | private $config_manager; |
||
| 78 | |||
| 79 | /** @var AgileDashboard_KanbanFactory */ |
||
| 80 | private $kanban_factory; |
||
| 81 | |||
| 82 | /** @var PlanningPermissionsManager */ |
||
| 83 | private $planning_permissions_manager; |
||
| 84 | |||
| 85 | /** @var AgileDashboard_HierarchyChecker */ |
||
| 86 | private $hierarchy_checker; |
||
| 87 | |||
| 88 | public function __construct( |
||
| 89 | Plugin $plugin, |
||
| 90 | Planning_MilestoneFactory $milestone_factory, |
||
| 91 | PlanningFactory $planning_factory, |
||
| 92 | Planning_ShortAccessFactory $planning_shortaccess_factory, |
||
| 93 | Planning_MilestoneControllerFactory $milestone_controller_factory, |
||
| 94 | ProjectManager $project_manager, |
||
| 95 | AgileDashboard_XMLFullStructureExporter $xml_exporter, |
||
| 96 | AgileDashboard_KanbanManager $kanban_manager, |
||
| 97 | AgileDashboard_ConfigurationManager $config_manager, |
||
| 98 | AgileDashboard_KanbanFactory $kanban_factory, |
||
| 99 | PlanningPermissionsManager $planning_permissions_manager, |
||
| 100 | AgileDashboard_HierarchyChecker $hierarchy_checker |
||
| 101 | ) { |
||
| 102 | $this->plugin = $plugin; |
||
| 103 | $this->milestone_factory = $milestone_factory; |
||
| 104 | $this->planning_factory = $planning_factory; |
||
| 105 | $this->planning_shortaccess_factory = $planning_shortaccess_factory; |
||
| 106 | $this->milestone_controller_factory = $milestone_controller_factory; |
||
| 107 | $this->project_manager = $project_manager; |
||
| 108 | $this->xml_exporter = $xml_exporter; |
||
| 109 | $this->kanban_manager = $kanban_manager; |
||
| 110 | $this->config_manager = $config_manager; |
||
| 111 | $this->kanban_factory = $kanban_factory; |
||
| 112 | $this->planning_permissions_manager = $planning_permissions_manager; |
||
| 113 | $this->hierarchy_checker = $hierarchy_checker; |
||
| 114 | } |
||
| 115 | |||
| 116 | /** |
||
| 117 | * Routes the given request to the appropriate controller. |
||
| 118 | * |
||
| 119 | * TODO: |
||
| 120 | * - Use a 'resource' parameter to deduce the controller (e.g. someurl/?resource=planning&id=2 ) |
||
| 121 | * - Pass $request to action methods |
||
| 122 | * |
||
| 123 | * @param Codendi_Request $request |
||
| 124 | */ |
||
| 125 | public function route(Codendi_Request $request) { |
||
| 126 | $planning_controller = $this->buildPlanningController($request); |
||
| 127 | $agile_dashboard_xml_controller = new AgileDashboard_XMLController( |
||
| 128 | $request, |
||
| 129 | $this->planning_factory, |
||
| 130 | $this->milestone_factory, |
||
| 131 | $this->plugin->getThemePath(), |
||
| 132 | $this->kanban_factory |
||
| 133 | ); |
||
| 134 | |||
| 135 | switch($request->get('action')) { |
||
| 136 | case 'show': |
||
| 137 | $this->routeShowPlanning($request); |
||
| 138 | break; |
||
| 139 | case 'show-top': |
||
| 140 | $this->routeShowTopPlanning($request, $planning_controller); |
||
| 141 | break; |
||
| 142 | case 'new': |
||
| 143 | $this->renderAction($planning_controller, 'new_', $request); |
||
| 144 | break; |
||
| 145 | case 'import-form': |
||
| 146 | $this->renderAction($planning_controller, 'importForm', $request); |
||
| 147 | break; |
||
| 148 | case 'export-to-file': |
||
| 149 | $this->executeAction($planning_controller, 'exportToFile'); |
||
| 150 | break; |
||
| 151 | case 'create': |
||
| 152 | $this->executeAction($planning_controller, 'create'); |
||
| 153 | break; |
||
| 154 | case 'edit': |
||
| 155 | $this->renderAction($planning_controller, 'edit', $request); |
||
| 156 | break; |
||
| 157 | case 'update': |
||
| 158 | $this->executeAction($planning_controller, 'update'); |
||
| 159 | break; |
||
| 160 | case 'delete': |
||
| 161 | $this->executeAction($planning_controller, 'delete'); |
||
| 162 | break; |
||
| 163 | case 'admin': |
||
| 164 | if ($this->userIsAdmin($request)) { |
||
| 165 | if ($request->get('pane') === 'kanban') { |
||
| 166 | $this->renderAction($this->buildController($request), 'adminKanban', $request); |
||
| 167 | } else { |
||
| 168 | $this->renderAction($this->buildController($request), 'adminScrum', $request); |
||
| 169 | } |
||
| 170 | } else { |
||
| 171 | $this->renderAction($planning_controller, 'index', $request); |
||
| 172 | } |
||
| 173 | break; |
||
| 174 | case 'export': |
||
| 175 | $this->executeAction($agile_dashboard_xml_controller, 'export'); |
||
| 176 | break; |
||
| 177 | case 'import': |
||
| 178 | $this->executeAction($agile_dashboard_xml_controller, 'import'); |
||
| 179 | break; |
||
| 180 | case 'submilestonedata' : |
||
| 181 | $milestone_controller = $this->milestone_controller_factory->getMilestoneController($request); |
||
| 182 | $this->executeAction($milestone_controller, 'submilestonedata'); |
||
| 183 | break; |
||
| 184 | case 'get-more-milestones': |
||
| 185 | $this->executeAction($planning_controller, 'getMoreMilestones'); |
||
| 186 | break; |
||
| 187 | case 'solve-inconsistencies': |
||
| 188 | $milestone_controller = $this->milestone_controller_factory->getMilestoneController($request); |
||
| 189 | $this->executeAction($milestone_controller, 'solveInconsistencies'); |
||
| 190 | break; |
||
| 191 | case 'updateConfiguration': |
||
| 192 | $this->executeAction($this->buildController($request), 'updateConfiguration'); |
||
| 193 | break; |
||
| 194 | case 'createKanban': |
||
| 195 | $this->executeAction($this->buildController($request), 'createKanban'); |
||
| 196 | break; |
||
| 197 | case 'showKanban': |
||
| 198 | $header_options = array( |
||
| 199 | 'body_class' => array('agiledashboard_kanban'), |
||
| 200 | Layout::INCLUDE_FAT_COMBINED => false, |
||
| 201 | ); |
||
| 202 | $this->renderAction($this->buildController($request), 'showKanban', $request, array(), $header_options); |
||
| 203 | break; |
||
| 204 | case 'index': |
||
| 205 | default: |
||
| 206 | $header_options = array( |
||
| 207 | 'body_class' => array('agiledashboard_homepage') |
||
| 208 | ); |
||
| 209 | $this->renderAction($planning_controller, 'index', $request, array(), $header_options); |
||
| 210 | } |
||
| 211 | } |
||
| 212 | |||
| 213 | /** |
||
| 214 | * Returns the page title according to the current controller action name. |
||
| 215 | * |
||
| 216 | * TODO: |
||
| 217 | * - Use a layout template, and move title retrieval to the appropriate presenters. |
||
| 218 | * |
||
| 219 | * @param string $action_name The controller action name (e.g. index, show...). |
||
| 220 | * |
||
| 221 | * @return string |
||
| 222 | */ |
||
| 223 | private function getHeaderTitle($action_name) { |
||
| 224 | $header_title = array( |
||
| 225 | 'index' => $GLOBALS['Language']->getText('plugin_agiledashboard', 'service_lbl_key'), |
||
| 226 | 'exportToFile' => $GLOBALS['Language']->getText('plugin_agiledashboard', 'service_lbl_key'), |
||
| 227 | 'adminScrum' => $GLOBALS['Language']->getText('plugin_agiledashboard', 'AdminScrum'), |
||
| 228 | 'adminKanban' => $GLOBALS['Language']->getText('plugin_agiledashboard', 'AdminKanban'), |
||
| 229 | 'new_' => $GLOBALS['Language']->getText('plugin_agiledashboard', 'planning_new'), |
||
| 230 | 'importForm' => $GLOBALS['Language']->getText('plugin_agiledashboard', 'planning_new'), |
||
| 231 | 'edit' => $GLOBALS['Language']->getText('plugin_agiledashboard', 'planning_edit'), |
||
| 232 | 'show' => $GLOBALS['Language']->getText('plugin_agiledashboard', 'planning_show'), |
||
| 233 | 'showTop' => $GLOBALS['Language']->getText('plugin_agiledashboard', 'planning_show'), |
||
| 234 | 'showKanban' => $GLOBALS['Language']->getText('plugin_agiledashboard', 'kanban_show') |
||
| 235 | ); |
||
| 236 | |||
| 237 | return $header_title[$action_name]; |
||
| 238 | } |
||
| 239 | |||
| 240 | /** |
||
| 241 | * Retrieves the Agile Dashboard Service instance matching the request group id. |
||
| 242 | * |
||
| 243 | * @param Codendi_Request $request |
||
| 244 | * |
||
| 245 | * @return Service |
||
| 246 | */ |
||
| 247 | private function getService(Codendi_Request $request) { |
||
| 248 | if ($this->service == null) { |
||
| 249 | $project = $request->getProject(); |
||
| 250 | $this->service = $project->getService('plugin_agiledashboard'); |
||
| 251 | } |
||
| 252 | return $this->service; |
||
| 253 | } |
||
| 254 | |||
| 255 | /** |
||
| 256 | * Renders the top banner + navigation for all Agile Dashboard pages. |
||
| 257 | * |
||
| 258 | * @param MVC2_Controller $controller The controller instance |
||
| 259 | * @param Codendi_Request $request The request |
||
| 260 | * @param string $title The page title |
||
| 261 | */ |
||
| 262 | private function displayHeader(MVC2_Controller $controller, |
||
| 263 | Codendi_Request $request, |
||
| 264 | $title, |
||
| 265 | array $header_options = array()) { |
||
| 266 | $service = $this->getService($request); |
||
| 267 | if (! $service) { |
||
| 268 | exit_error( |
||
| 269 | $GLOBALS['Language']->getText('global', 'error'), |
||
| 270 | $GLOBALS['Language']->getText( |
||
| 271 | 'project_service', |
||
| 272 | 'service_not_used', |
||
| 273 | $GLOBALS['Language']->getText('plugin_agiledashboard', 'service_lbl_key')) |
||
| 274 | ); |
||
| 275 | } |
||
| 276 | |||
| 277 | $toolbar = array(); |
||
| 278 | $breadcrumbs = $controller->getBreadcrumbs($this->plugin->getPluginPath()); |
||
| 279 | if ($this->userIsAdmin($request)) { |
||
| 280 | $toolbar[] = array( |
||
| 281 | 'title' => $GLOBALS['Language']->getText('global', 'Admin'), |
||
| 282 | 'url' => AGILEDASHBOARD_BASE_URL .'/?'. http_build_query(array( |
||
| 283 | 'group_id' => $request->get('group_id'), |
||
| 284 | 'action' => 'admin', |
||
| 285 | )) |
||
| 286 | ); |
||
| 287 | } |
||
| 288 | $service->displayHeader($title, $breadcrumbs->getCrumbs(), $toolbar, $header_options); |
||
| 289 | } |
||
| 290 | |||
| 291 | private function userIsAdmin(Codendi_Request $request) { |
||
| 294 | |||
| 295 | /** |
||
| 296 | * Renders the bottom footer for all Agile Dashboard pages. |
||
| 297 | * |
||
| 298 | * @param Codendi_Request $request |
||
| 299 | */ |
||
| 300 | private function displayFooter(Codendi_Request $request) { |
||
| 303 | |||
| 304 | /** |
||
| 305 | * Builds a new Planning_Controller instance. |
||
| 306 | * |
||
| 307 | * @param Codendi_Request $request |
||
| 308 | * |
||
| 309 | * @return Planning_Controller |
||
| 310 | */ |
||
| 311 | protected function buildPlanningController(Codendi_Request $request) { |
||
| 328 | |||
| 329 | protected function buildController(Codendi_Request $request) { |
||
| 341 | |||
| 342 | /** |
||
| 343 | * Renders the given controller action, with page header/footer. |
||
| 344 | * |
||
| 345 | * @param MVC2_Controller $controller The controller instance. |
||
| 346 | * @param string $action_name The controller action name (e.g. index, show...). |
||
| 347 | * @param Codendi_Request $request The request |
||
| 348 | * @param array $args Arguments to pass to the controller action method. |
||
| 349 | */ |
||
| 350 | protected function renderAction(MVC2_Controller $controller, |
||
| 362 | |||
| 363 | /** |
||
| 364 | * Executes the given controller action, without rendering page header/footer. |
||
| 365 | * Useful for actions ending with a redirection instead of page rendering. |
||
| 366 | * |
||
| 367 | * @param MVC2_Controller $controller The controller instance. |
||
| 368 | * @param string $action_name The controller action name (e.g. index, show...). |
||
| 369 | * @param array $args Arguments to pass to the controller action method. |
||
| 370 | */ |
||
| 371 | protected function executeAction(MVC2_Controller $controller, |
||
| 377 | |||
| 378 | /** |
||
| 379 | * Routes some milestone-related requests. |
||
| 380 | * |
||
| 381 | * TODO: |
||
| 382 | * - merge into AgileDashboardRouter::route() |
||
| 383 | * |
||
| 384 | * @param Codendi_Request $request |
||
| 385 | */ |
||
| 386 | public function routeShowPlanning(Codendi_Request $request) { |
||
| 403 | |||
| 404 | public function routeShowTopPlanning(Codendi_Request $request, $default_controller) { |
||
| 444 | } |
||
| 445 |
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.