Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like WebRequest 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 WebRequest, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class WebRequest |
||
24 | { |
||
25 | /** |
||
26 | * @var \Waca\Providers\GlobalState\IGlobalStateProvider Provides access to the global state. |
||
27 | */ |
||
28 | private static $globalStateProvider; |
||
29 | |||
30 | /** |
||
31 | * Returns a boolean value if the request was submitted with the HTTP POST method. |
||
32 | * @return bool |
||
33 | */ |
||
34 | 3 | public static function wasPosted() |
|
35 | { |
||
36 | 3 | return self::method() === 'POST'; |
|
37 | } |
||
38 | |||
39 | /** |
||
40 | * Gets the HTTP Method used |
||
41 | * @return string|null |
||
42 | */ |
||
43 | 3 | View Code Duplication | public static function method() |
|
|||
44 | { |
||
45 | 3 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
|
46 | |||
47 | 3 | if (isset($server['REQUEST_METHOD'])) { |
|
48 | 2 | return $server['REQUEST_METHOD']; |
|
49 | } |
||
50 | |||
51 | 1 | return null; |
|
52 | } |
||
53 | |||
54 | /** |
||
55 | * Gets a boolean value stating whether the request was served over HTTPS or not. |
||
56 | * @return bool |
||
57 | */ |
||
58 | 7 | public static function isHttps() |
|
59 | { |
||
60 | 7 | $server = &self::$globalStateProvider->getServerSuperGlobal(); |
|
61 | |||
62 | 7 | View Code Duplication | if (isset($server['HTTP_X_FORWARDED_PROTO'])) { |
63 | 3 | if ($server['HTTP_X_FORWARDED_PROTO'] === 'https') { |
|
64 | // Client <=> Proxy is encrypted |
||
65 | 2 | return true; |
|
66 | } |
||
67 | else { |
||
68 | // Proxy <=> Server link unknown, Client <=> Proxy is not encrypted. |
||
69 | 1 | return false; |
|
70 | } |
||
71 | } |
||
72 | |||
73 | 4 | View Code Duplication | if (isset($server['HTTPS'])) { |
74 | 3 | if ($server['HTTPS'] === 'off') { |
|
75 | // ISAPI on IIS breaks the spec. :( |
||
76 | 1 | return false; |
|
77 | } |
||
78 | |||
79 | 2 | if ($server['HTTPS'] !== '') { |
|
80 | // Set to a non-empty value |
||
81 | 2 | return true; |
|
82 | } |
||
83 | } |
||
84 | |||
85 | 1 | return false; |
|
86 | } |
||
87 | |||
88 | /** |
||
89 | * Gets the path info |
||
90 | * |
||
91 | * @return array Array of path info segments |
||
92 | */ |
||
93 | 13 | public static function pathInfo() |
|
106 | |||
107 | /** |
||
108 | * Gets the remote address of the web request |
||
109 | * @return null|string |
||
110 | */ |
||
111 | 2 | View Code Duplication | public static function remoteAddress() |
121 | |||
122 | /** |
||
123 | * Gets the XFF header contents for the web request |
||
124 | * @return null|string |
||
125 | */ |
||
126 | 2 | View Code Duplication | public static function forwardedAddress() |
136 | |||
137 | /** |
||
138 | * Sets the global state provider. |
||
139 | * |
||
140 | * Almost guaranteed this is not the method you want in production code. |
||
141 | * |
||
142 | * @param \Waca\Providers\GlobalState\IGlobalStateProvider $globalState |
||
143 | */ |
||
144 | 49 | public static function setGlobalStateProvider($globalState) |
|
148 | |||
149 | #region POST variables |
||
150 | |||
151 | /** |
||
152 | * @param string $key |
||
153 | * |
||
154 | * @return null|string |
||
155 | */ |
||
156 | 1 | View Code Duplication | public static function postString($key) |
169 | |||
170 | /** |
||
171 | * @param string $key |
||
172 | * |
||
173 | * @return null|string |
||
174 | */ |
||
175 | View Code Duplication | public static function postEmail($key) |
|
190 | |||
191 | /** |
||
192 | * @param string $key |
||
193 | * |
||
194 | * @return int|null |
||
195 | */ |
||
196 | 1 | View Code Duplication | public static function postInt($key) |
211 | |||
212 | /** |
||
213 | * @param string $key |
||
214 | * |
||
215 | * @return bool |
||
216 | */ |
||
217 | 1 | View Code Duplication | public static function postBoolean($key) |
235 | |||
236 | #endregion |
||
237 | |||
238 | #region GET variables |
||
239 | |||
240 | /** |
||
241 | * @param string $key |
||
242 | * |
||
243 | * @return bool |
||
244 | */ |
||
245 | 1 | View Code Duplication | public static function getBoolean($key) |
263 | |||
264 | /** |
||
265 | * @param string $key |
||
266 | * |
||
267 | * @return int|null |
||
268 | */ |
||
269 | 1 | View Code Duplication | public static function getInt($key) |
284 | |||
285 | /** |
||
286 | * @param string $key |
||
287 | * |
||
288 | * @return null|string |
||
289 | */ |
||
290 | 5 | View Code Duplication | public static function getString($key) |
303 | |||
304 | #endregion |
||
305 | |||
306 | /** |
||
307 | * Sets the logged-in user to the specified user. |
||
308 | * |
||
309 | * @param User $user |
||
310 | */ |
||
311 | 1 | public static function setLoggedInUser(User $user) |
|
312 | { |
||
313 | 1 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
|
314 | |||
315 | 1 | $session['userID'] = $user->getId(); |
|
316 | 1 | unset($session['partialLogin']); |
|
317 | 1 | } |
|
318 | |||
319 | /** |
||
320 | * Sets the post-login redirect |
||
321 | */ |
||
322 | 2 | public static function setPostLoginRedirect() |
|
327 | |||
328 | /** |
||
329 | * @return string|null |
||
330 | */ |
||
331 | 2 | View Code Duplication | public static function requestUri() |
341 | |||
342 | /** |
||
343 | * Clears the post-login redirect |
||
344 | * @return string |
||
345 | */ |
||
346 | 2 | public static function clearPostLoginRedirect() |
|
358 | |||
359 | /** |
||
360 | * @return string|null |
||
361 | */ |
||
362 | View Code Duplication | public static function serverName() |
|
372 | |||
373 | /** |
||
374 | * You probably only want to deal with this through SessionAlert. |
||
375 | * @return void |
||
376 | */ |
||
377 | public static function clearSessionAlertData() |
||
378 | { |
||
379 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
380 | if (array_key_exists('alerts', $session)) { |
||
381 | unset($session['alerts']); |
||
382 | } |
||
383 | } |
||
384 | |||
385 | /** |
||
386 | * You probably only want to deal with this through SessionAlert. |
||
387 | * |
||
388 | * @return string[] |
||
389 | */ |
||
390 | public static function getSessionAlertData() |
||
391 | { |
||
392 | $session = &self::$globalStateProvider->getSessionSuperGlobal(); |
||
393 | if (array_key_exists('alerts', $session)) { |
||
394 | return $session['alerts']; |
||
395 | } |
||
396 | |||
397 | return array(); |
||
398 | } |
||
399 | |||
400 | /** |
||
401 | * You probably only want to deal with this through SessionAlert. |
||
402 | * |
||
403 | * @param string[] $data |
||
404 | */ |
||
405 | public static function setSessionAlertData($data) |
||
410 | |||
411 | /** |
||
412 | * You probably only want to deal with this through TokenManager. |
||
413 | * |
||
414 | * @return string[] |
||
415 | */ |
||
416 | public static function getSessionTokenData() |
||
425 | |||
426 | /** |
||
427 | * You probably only want to deal with this through TokenManager. |
||
428 | * |
||
429 | * @param string[] $data |
||
430 | */ |
||
431 | public static function setSessionTokenData($data) |
||
436 | |||
437 | /** |
||
438 | * @param string $key |
||
439 | * |
||
440 | * @return mixed |
||
441 | */ |
||
442 | public static function getSessionContext($key) |
||
456 | |||
457 | /** |
||
458 | * @param string $key |
||
459 | * @param mixed $data |
||
460 | */ |
||
461 | public static function setSessionContext($key, $data) |
||
471 | |||
472 | /** |
||
473 | * @return int|null |
||
474 | */ |
||
475 | public static function getSessionUserId() |
||
481 | |||
482 | /** |
||
483 | * @param User $user |
||
484 | */ |
||
485 | public static function setPartialLogin(User $user) |
||
490 | |||
491 | /** |
||
492 | * @return int|null |
||
493 | */ |
||
494 | public static function getPartialLogin() |
||
500 | |||
501 | /** |
||
502 | * @return null|string |
||
503 | */ |
||
504 | View Code Duplication | public static function userAgent() |
|
514 | |||
515 | /** |
||
516 | * @return null|string |
||
517 | */ |
||
518 | View Code Duplication | public static function scriptName() |
|
528 | |||
529 | /** |
||
530 | * @return null|string |
||
531 | */ |
||
532 | View Code Duplication | public static function origin() |
|
542 | } |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.