Complex classes like Turbolinks 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 Turbolinks, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
27 | class Turbolinks |
||
28 | { |
||
29 | /** |
||
30 | * Request header used for origin validation. |
||
31 | * |
||
32 | * @var string |
||
33 | */ |
||
34 | const ORIGIN_REQUEST_HEADER = 'Turbolinks-Referrer'; |
||
35 | |||
36 | /** |
||
37 | * Response header used for origin validation. |
||
38 | * |
||
39 | * @var string |
||
40 | */ |
||
41 | const ORIGIN_RESPONSE_HEADER = 'Location'; |
||
42 | |||
43 | /** |
||
44 | * Redirect header inserted in the response. |
||
45 | * |
||
46 | * @var string |
||
47 | */ |
||
48 | const REDIRECT_RESPONSE_HEADER = 'Turbolinks-Location'; |
||
49 | |||
50 | /** |
||
51 | * Session attribute name for the redirect location. |
||
52 | * |
||
53 | * @var string |
||
54 | */ |
||
55 | const LOCATION_SESSION_ATTR_NAME = 'helthe_turbolinks_location'; |
||
56 | |||
57 | /** |
||
58 | * @var array |
||
59 | */ |
||
60 | public static $turbolinksOptionsMap = array( |
||
61 | // Handles normal redirection with Turbolinks, if not set to `false`. |
||
62 | // Possible values: `null`, `'replace'`, `'advance'` or `false` |
||
63 | 'turbolinks' => 'X-Turbolinks', |
||
64 | ); |
||
65 | |||
66 | /** |
||
67 | * Modifies the HTTP headers and status code of the Response so that it can be |
||
68 | * properly handled by the Turbolinks javascript. |
||
69 | * |
||
70 | * @param Request $request |
||
71 | * @param Response $response |
||
72 | */ |
||
73 | public function decorateResponse(Request $request, Response $response) |
||
87 | |||
88 | /** |
||
89 | * @param Request $request |
||
90 | * @param Response $response |
||
91 | * @return \Symfony\Component\HttpFoundation\Response |
||
92 | */ |
||
93 | public function redirectTo($request, $response) |
||
110 | |||
111 | /** |
||
112 | * Checks if the request can handle a Turbolink redirect. You need to have a |
||
113 | * session and a XHR request header to handle a redirect. |
||
114 | * |
||
115 | * @param Request $request |
||
116 | * |
||
117 | * @return bool |
||
118 | */ |
||
119 | private function canHandleRedirect(Request $request) |
||
125 | |||
126 | /** |
||
127 | * Parse the given url into an origin array with the scheme, host and port. |
||
128 | * |
||
129 | * @param string $url |
||
130 | * |
||
131 | * @return array |
||
132 | */ |
||
133 | private function getUrlOrigin($url) |
||
141 | |||
142 | /** |
||
143 | * Checks if the request and the response have the same origin. |
||
144 | * |
||
145 | * @param Request $request |
||
146 | * @param Response $response |
||
147 | * |
||
148 | * @return bool |
||
149 | */ |
||
150 | private function haveSameOrigin(Request $request, Response $response) |
||
157 | |||
158 | /** |
||
159 | * Modifies the response status code. Checks for cross domain redirects and |
||
160 | * blocks them. |
||
161 | * |
||
162 | * @param Request $request |
||
163 | * @param Response $response |
||
164 | */ |
||
165 | private function modifyStatusCode(Request $request, Response $response) |
||
174 | |||
175 | /** |
||
176 | * @param ResponseHeaderBag $headers |
||
177 | * @return mixed |
||
178 | */ |
||
179 | private function extractTurbolinksOptions($headers) |
||
194 | |||
195 | private function visitLocationWithTurbolinks($location, $action) |
||
207 | |||
208 | /** |
||
209 | * @param Request $request |
||
210 | * @param Response $response |
||
211 | */ |
||
212 | private function storeTurbolinksLocationInSession(Request $request, Response $response) |
||
225 | |||
226 | /** |
||
227 | * @param Request $request |
||
228 | * @param Response $response |
||
229 | * @param string $body Content of the response |
||
230 | */ |
||
231 | private function performTurbolinksResponse(Request $request, Response $response, $body) |
||
238 | |||
239 | /** |
||
240 | * @param Request $request |
||
241 | * @param Response $response |
||
242 | */ |
||
243 | private function setTurbolinksLocationHeaderFromSession(Request $request, Response $response) |
||
255 | |||
256 | /** |
||
257 | * @param ResponseHeaderBag $headers |
||
258 | * |
||
259 | * @return array Turbolinks options |
||
260 | */ |
||
261 | public function extractTurbolinksHeaders($headers) |
||
282 | |||
283 | /** |
||
284 | * Return HTTP headers equivalent of the given Turbolinks options. |
||
285 | * E.G. `['turbolinks' => 'advance']` becomes `['X-Turbolinks' => 'advance']` |
||
286 | * |
||
287 | * @param array $options |
||
288 | * |
||
289 | * @return array |
||
290 | */ |
||
291 | public function convertTurbolinksOptions($options = array()) |
||
304 | } |
||
305 |
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.