Complex classes like RwDispatcher 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 RwDispatcher, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
31 | class RwDispatcher extends HttpDispatcherA { |
||
32 | /** |
||
33 | * @param array $aMaps |
||
34 | * @throws ExceptionError |
||
35 | * @returns ClassMap |
||
36 | */ |
||
37 | 20 | static protected function getCurrentMap($aMaps, $sUri = null) { |
|
|
|||
38 | 20 | if (!is_array($aMaps) || empty($aMaps)) { |
|
39 | 1 | return new ErrorProcessorMap(); |
|
40 | } |
||
41 | |||
42 | 19 | if (is_null($sUri)) { |
|
43 | 19 | $sUri = vsc::getEnv()->getHttpRequest()->getUri(true); |
|
44 | } |
||
45 | 19 | $aRegexes = array_keys($aMaps); |
|
46 | |||
47 | 19 | $aMatches = array(); |
|
48 | 19 | foreach ($aRegexes as $sRegex) { |
|
49 | 19 | $sFullRegex = '#' . str_replace('#', '\#', $sRegex) . '#iu'; // i for insensitive, u for utf8 |
|
50 | try { |
||
51 | 19 | $iMatch = preg_match_all($sFullRegex, $sUri, $aMatches, PREG_SET_ORDER); |
|
52 | 1 | } catch (ExceptionError $e) { |
|
53 | 1 | $f = new ExceptionError( |
|
54 | 1 | $e->getMessage() . '<br/> Offending regular expression: <span style="font-weight:normal">' . $sFullRegex . '</span>', |
|
55 | 1 | $e->getCode()); |
|
56 | 1 | throw $f; |
|
57 | } |
||
58 | 18 | if ($iMatch) { |
|
59 | 18 | $aMatches = array_shift($aMatches); |
|
60 | 18 | $aMatches = array_slice($aMatches, 1); |
|
61 | |||
62 | /* @var MappingA $oMapping */ |
||
63 | 18 | $oMapping = $aMaps[$sRegex]; |
|
64 | 18 | $oMapping->setTaintedVars($aMatches); |
|
65 | 18 | $oMapping->setUrl($sUri); |
|
66 | 18 | $oMapping->getModuleMap()->setUrl($sUri); |
|
67 | 18 | return $oMapping; |
|
68 | } |
||
69 | } |
||
70 | return null; |
||
71 | } |
||
72 | |||
73 | /** |
||
74 | * @returns ModuleMap |
||
75 | * @throws ExceptionSitemap |
||
76 | */ |
||
77 | 2 | public function getCurrentModuleMap() { |
|
78 | 2 | $oProcessorMap = $this->getCurrentProcessorMap(); |
|
79 | 2 | if (ClassMap::isValid($oProcessorMap)) { |
|
80 | 2 | return $this->getCurrentProcessorMap()->getModuleMap(); |
|
81 | } else { |
||
82 | return $this->getSiteMap()->getCurrentModuleMap(); |
||
83 | } |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * @returns ClassMap |
||
88 | * @throws ExceptionSitemap |
||
89 | * @throws ExceptionError |
||
90 | */ |
||
91 | 19 | public function getCurrentProcessorMap() { |
|
92 | 19 | $oProcessorMap = self::getCurrentMap($this->getSiteMap()->getMaps()); |
|
93 | 19 | if (!ClassMap::isValid($oProcessorMap)) { |
|
94 | $oProcessorMap = new ErrorProcessorMap(NotFoundProcessor::class); |
||
95 | } |
||
96 | 19 | return $oProcessorMap; |
|
97 | } |
||
98 | |||
99 | /** |
||
100 | * @returns ClassMap |
||
101 | * @throws ExceptionError |
||
102 | */ |
||
103 | 10 | public function getCurrentControllerMap() { |
|
104 | 10 | $oProcessorMap = $this->getCurrentProcessorMap(); |
|
105 | |||
106 | 10 | $oCurrentMap = null; |
|
107 | // check if the current processor has some set maps |
||
108 | 10 | $aProcessorCtrlMaps = $oProcessorMap->getControllerMaps(); |
|
109 | 10 | if (count($aProcessorCtrlMaps) > 0) { |
|
110 | 1 | $oCurrentMap = self::getCurrentMap($aProcessorCtrlMaps); |
|
111 | 1 | if (ClassMap::isValid($oCurrentMap) && !ErrorControllerMap::isValid($oCurrentMap)) { |
|
112 | 1 | return $oCurrentMap; |
|
113 | } |
||
114 | } |
||
115 | |||
116 | 9 | $oCurrentModule = $oProcessorMap->getModuleMap(); |
|
117 | // merging all controller maps found in the processor map's parent modules |
||
118 | do { |
||
119 | // check the current module for maps |
||
120 | 9 | $aModuleCtrlMaps = $oCurrentModule->getControllerMaps(); |
|
121 | 9 | if (count($aModuleCtrlMaps) > 0) { |
|
122 | 9 | $oCurrentMap = self::getCurrentMap($aModuleCtrlMaps); |
|
123 | } |
||
124 | 9 | $oCurrentModule = $oCurrentModule->getModuleMap(); |
|
125 | 9 | } while (!ClassMap::isValid($oCurrentMap)); |
|
126 | |||
127 | 9 | return $oCurrentMap; |
|
128 | } |
||
129 | |||
130 | /** |
||
131 | * @throws \vsc\application\sitemaps\ExceptionSitemap |
||
132 | * @throws \vsc\presentation\responses\ExceptionResponseError |
||
133 | * @returns FrontControllerA |
||
134 | */ |
||
135 | 1 | public function getFrontController() { |
|
136 | 1 | if (!FrontControllerA::isValid($this->oController)) { |
|
137 | 1 | $oControllerMapping = $this->getCurrentControllerMap(); |
|
138 | |||
139 | 1 | if (ClassMap::isValid($oControllerMapping)) { |
|
140 | 1 | $sControllerName = $oControllerMapping->getPath(); |
|
141 | } |
||
142 | |||
143 | 1 | if (empty($sControllerName)) { |
|
144 | throw new ExceptionResponseError('Could not find the correct front controller', HttpResponseType::NOT_FOUND); |
||
145 | } |
||
146 | |||
147 | /* @var $this->oController FrontControllerA */ |
||
148 | 1 | $this->oController = new $sControllerName(); |
|
149 | 1 | if (FrontControllerA::isValid($this->oController)) { |
|
150 | // adding the map to the controller, allows it to add resources (styles,scripts) from inside it |
||
151 | 1 | $this->oController->setMap($oControllerMapping); |
|
152 | } |
||
153 | } |
||
154 | |||
155 | 1 | return $this->oController; |
|
156 | } |
||
157 | |||
158 | /** |
||
159 | * (non-PHPdoc) |
||
160 | * @see vsc/presentation/dispatchers/HttpDispatcherA::getProcessController() |
||
161 | * @throws ExceptionSitemap |
||
162 | * @throws ExceptionResponseError |
||
163 | * @returns ProcessorA |
||
164 | */ |
||
165 | 3 | public function getProcessController() { |
|
166 | 3 | if (!ProcessorA::isValid($this->oProcessor)) { |
|
167 | 3 | $oProcessorMap = $this->getCurrentProcessorMap(); |
|
168 | 3 | if (!ClassMap::isValid($oProcessorMap)) { |
|
169 | // this mainly means nothing was matched to our url, or no mappings exist, so we're falling back to 404 |
||
170 | $oProcessorMap = new ErrorProcessorMap(NotFoundProcessor::class, '.*'); |
||
171 | $oProcessorMap->setTemplatePath(VSC_RES_PATH . 'templates'); |
||
172 | $oProcessorMap->setTemplate('404.php'); |
||
173 | } |
||
174 | |||
175 | 3 | $sPath = $oProcessorMap->getPath(); |
|
176 | try { |
||
177 | 3 | if (ClassMap::isValidMap($sPath) || (stristr(basename($sPath), '.') === false && !is_file($sPath))) { |
|
178 | |||
179 | try { |
||
180 | 2 | if (class_exists($sPath)) { |
|
181 | 2 | $this->oProcessor = new $sPath(); |
|
182 | } else { |
||
183 | 2 | $this->oProcessor = new NotFoundProcessor(); |
|
184 | } |
||
185 | } catch (\Exception $e) { |
||
186 | 2 | $this->oProcessor = new ErrorProcessor($e); |
|
187 | } |
||
188 | 1 | } elseif ($this->getSiteMap()->isValidStaticPath($sPath)) { |
|
189 | // static stuff |
||
190 | 1 | $this->oProcessor = new StaticFileProcessor(); |
|
191 | 1 | $this->oProcessor->setFilePath($sPath); |
|
192 | } /*else { |
||
193 | $this->oProcessor = new NotFoundProcessor(); |
||
194 | }*/ |
||
195 | |||
196 | 3 | if (ProcessorA::isValid($this->oProcessor)) { |
|
197 | 3 | if (!(ErrorProcessor::isValid($this->oProcessor) && MappingA::isValid($this->oProcessor->getMap()))) { |
|
198 | // @TODO: this should be a MappingA->merge() when the processor already has a map |
||
199 | 2 | $this->oProcessor->setMap($oProcessorMap); |
|
200 | } |
||
201 | |||
202 | // setting the variables defined in the processor into the tainted variables |
||
203 | /** @var RwHttpRequest $oRawRequest */ |
||
204 | 3 | $oRawRequest = $this->getRequest(); |
|
205 | 3 | if (RwHttpRequest::isValid($oRawRequest)) { |
|
206 | 3 | $oRawRequest->setTaintedVars($this->oProcessor->getLocalVars()); // FIXME!!! |
|
207 | } |
||
208 | } else { |
||
209 | // broken URL |
||
210 | 3 | throw new ExceptionResponseError('Broken URL', 400); |
|
211 | } |
||
212 | } catch (ExceptionResponseRedirect $e) { |
||
213 | // get the response |
||
214 | $oResponse = vsc::getEnv()->getHttpResponse(); |
||
215 | $oResponse->setLocation($e->getLocation()); |
||
216 | ob_end_flush(); |
||
217 | $oResponse->outputHeaders(); |
||
218 | } |
||
219 | } |
||
220 | |||
221 | 3 | return $this->oProcessor; |
|
222 | } |
||
223 | |||
224 | /** |
||
225 | * |
||
226 | * @param string $sIncPath |
||
227 | * @throws \Exception |
||
228 | * @throws ExceptionSitemap |
||
229 | * @return boolean |
||
230 | */ |
||
231 | 19 | public function loadSiteMap($sIncPath) { |
|
232 | try { |
||
233 | // hic sunt leones |
||
234 | /** @var ModuleMap $oMap */ |
||
235 | 19 | $oMap = $this->getSiteMap()->map('\A/', $sIncPath); |
|
236 | 19 | if (count($oMap->getControllerMaps()) == 0) { |
|
237 | 19 | $oMap->map('\A.*\Z', Html5Controller::class); |
|
238 | } |
||
239 | } catch (ExceptionSitemap $e) { |
||
240 | // there was a faulty controller in the sitemap |
||
241 | // this will probably result in a incomplete parsed sitemap tree |
||
242 | throw ($e); |
||
243 | } |
||
244 | 19 | return true; |
|
245 | } |
||
246 | |||
247 | public function getView() {} |
||
248 | |||
249 | 1 | public function getTemplatePath() { |
|
250 | 1 | $aMaps = $this->getSiteMap()->getMaps(); |
|
251 | 1 | $oProcessorMap = self::getCurrentMap($aMaps); |
|
252 | |||
253 | 1 | if (ClassMap::isValid($oProcessorMap)) { |
|
254 | 1 | $sPath = $oProcessorMap->getTemplatePath(); |
|
255 | } else { |
||
260 | } |
||
261 |