Completed
Branch newinternal (cd27a7)
by Simon
03:47
created

WebRequest   C

Complexity

Total Complexity 71

Size/Duplication

Total Lines 517
Duplicated Lines 40.23 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 58%

Importance

Changes 14
Bugs 1 Features 0
Metric Value
wmc 71
c 14
b 1
f 0
lcom 1
cbo 2
dl 208
loc 517
ccs 105
cts 181
cp 0.58
rs 5.5904

32 Methods

Rating   Name   Duplication   Size   Complexity  
A method() 10 10 2
A setGlobalStateProvider() 0 4 1
A setPostLoginRedirect() 0 5 1
A clearPostLoginRedirect() 0 12 2
A getSessionAlertData() 0 9 2
A setSessionAlertData() 0 5 1
A getSessionTokenData() 0 9 2
A setSessionTokenData() 0 5 1
A wasPosted() 0 4 1
B isHttps() 21 29 6
A pathInfo() 0 13 2
A remoteAddress() 10 10 2
A forwardedAddress() 10 10 2
A postString() 13 13 3
A postEmail() 15 15 3
A postInt() 15 15 3
A postBoolean() 18 18 4
A getBoolean() 18 18 4
A getInt() 15 15 3
A getString() 13 13 3
A setLoggedInUser() 0 7 1
A clearSessionAlertData() 0 7 2
A requestUri() 10 10 2
A serverName() 10 10 2
A getSessionContext() 0 13 3
A setSessionContext() 0 9 2
A getSessionUserId() 0 6 2
A setPartialLogin() 0 5 1
A getPartialLogin() 0 6 2
A userAgent() 10 10 2
A scriptName() 10 10 2
A origin() 10 10 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

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 Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

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
2
/******************************************************************************
3
 * Wikipedia Account Creation Assistance tool                                 *
4
 *                                                                            *
5
 * All code in this file is released into the public domain by the ACC        *
6
 * Development Team. Please see team.json for a list of contributors.         *
7
 ******************************************************************************/
8
9
namespace Waca;
10
11
use Waca\DataObjects\User;
12
use Waca\Providers\Interfaces\IGlobalStateProvider;
13
14
/**
15
 * Holds helper functions regarding the current request.
16
 *
17
 * This is the only place where it is allowed to use super-globals, but even then access MUST be pushed through the
18
 * global state provider to allow for unit tests. It's strongly recommended to do sanitising of data here, especially
19
 * if extra logic is required to get a deterministic value, like isHttps().
20
 *
21
 * @package Waca
22
 */
23
class WebRequest
24
{
25
	/**
26
	 * @var 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()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
63 3
			if ($server['HTTP_X_FORWARDED_PROTO'] === 'https') {
0 ignored issues
show
Coding Style introduced by
The if-else statement can be simplified to return $server['HTTP_X_F...ED_PROTO'] === 'https';.
Loading history...
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'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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()
94
	{
95 13
		$server = &self::$globalStateProvider->getServerSuperGlobal();
96 13
		if (!isset($server['PATH_INFO'])) {
97 1
			return array();
98
		}
99
100 12
		$exploded = explode('/', $server['PATH_INFO']);
101
102
		// filter out empty values, and reindex from zero. Notably, the first element is always zero, since it starts
103
		// with a /
104 12
		return array_values(array_filter($exploded));
105
	}
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()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
112
	{
113 2
		$server = &self::$globalStateProvider->getServerSuperGlobal();
114
115 2
		if (isset($server['REMOTE_ADDR'])) {
116 1
			return $server['REMOTE_ADDR'];
117
		}
118
119 1
		return null;
120
	}
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()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
127
	{
128 2
		$server = &self::$globalStateProvider->getServerSuperGlobal();
129
130 2
		if (isset($server['HTTP_X_FORWARDED_FOR'])) {
131 1
			return $server['HTTP_X_FORWARDED_FOR'];
132
		}
133
134 1
		return null;
135
	}
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 IGlobalStateProvider $globalState
143
	 */
144 45
	public static function setGlobalStateProvider($globalState)
145
	{
146 45
		self::$globalStateProvider = $globalState;
147 45
	}
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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
157
	{
158 1
		$post = &self::$globalStateProvider->getPostSuperGlobal();
159 1
		if (!array_key_exists($key, $post)) {
160
			return null;
161
		}
162
163 1
		if ($post[$key] === "") {
164 1
			return null;
165
		}
166
167 1
		return (string)$post[$key];
168
	}
169
170
	/**
171
	 * @param string $key
172
	 *
173
	 * @return null|string
174
	 */
175 View Code Duplication
	public static function postEmail($key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
176
	{
177
		$post = &self::$globalStateProvider->getPostSuperGlobal();
178
		if (!array_key_exists($key, $post)) {
179
			return null;
180
		}
181
182
		$filteredValue = filter_var($post[$key], FILTER_SANITIZE_EMAIL);
183
184
		if ($filteredValue === false) {
185
			return null;
186
		}
187
188
		return (string)$filteredValue;
189
	}
190
191
	/**
192
	 * @param string $key
193
	 *
194
	 * @return int|null
195
	 */
196 1 View Code Duplication
	public static function postInt($key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
197
	{
198 1
		$post = &self::$globalStateProvider->getPostSuperGlobal();
199 1
		if (!array_key_exists($key, $post)) {
200 1
			return null;
201
		}
202
203 1
		$filteredValue = filter_var($post[$key], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
204
205 1
		if ($filteredValue === null) {
206 1
			return null;
207
		}
208
209 1
		return (int)$filteredValue;
210
	}
211
212
	/**
213
	 * @param string $key
214
	 *
215
	 * @return bool
216
	 */
217 1 View Code Duplication
	public static function postBoolean($key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
218
	{
219 1
		$get = &self::$globalStateProvider->getPostSuperGlobal();
220 1
		if (!array_key_exists($key, $get)) {
221 1
			return false;
222
		}
223
224
		// presence of parameter only
225 1
		if ($get[$key] === "") {
226 1
			return true;
227
		}
228
229 1
		if (in_array($get[$key], array(false, 'no', 'off', 0, 'false'), true)) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !in_array($get[$k...f', 0, 'false'), true);.
Loading history...
230 1
			return false;
231
		}
232
233 1
		return true;
234
	}
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)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
246
	{
247 1
		$get = &self::$globalStateProvider->getGetSuperGlobal();
248 1
		if (!array_key_exists($key, $get)) {
249 1
			return false;
250
		}
251
252
		// presence of parameter only
253 1
		if ($get[$key] === "") {
254 1
			return true;
255
		}
256
257 1
		if (in_array($get[$key], array(false, 'no', 'off', 0, 'false'), true)) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return !in_array($get[$k...f', 0, 'false'), true);.
Loading history...
258 1
			return false;
259
		}
260
261 1
		return true;
262
	}
263
264
	/**
265
	 * @param string $key
266
	 *
267
	 * @return int|null
268
	 */
269 1 View Code Duplication
	public static function getInt($key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
270
	{
271 1
		$get = &self::$globalStateProvider->getGetSuperGlobal();
272 1
		if (!array_key_exists($key, $get)) {
273 1
			return null;
274
		}
275
276 1
		$filteredValue = filter_var($get[$key], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
277
278 1
		if ($filteredValue === null) {
279 1
			return null;
280
		}
281
282 1
		return (int)$filteredValue;
283
	}
284
285
	/**
286
	 * @param string $key
287
	 *
288
	 * @return null|string
289
	 */
290 1 View Code Duplication
	public static function getString($key)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
291
	{
292 1
		$get = &self::$globalStateProvider->getGetSuperGlobal();
293 1
		if (!array_key_exists($key, $get)) {
294
			return null;
295
		}
296
297 1
		if ($get[$key] === "") {
298 1
			return null;
299
		}
300
301 1
		return (string)$get[$key];
302
	}
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()
323
	{
324 2
		$session = &self::$globalStateProvider->getSessionSuperGlobal();
325 2
		$session['returnTo'] = self::requestUri();
326 2
	}
327
328
	/**
329
	 * @return string|null
330
	 */
331 2 View Code Duplication
	public static function requestUri()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
332
	{
333 2
		$server = &self::$globalStateProvider->getServerSuperGlobal();
334
335 2
		if (isset($server['REQUEST_URI'])) {
336 1
			return $server['REQUEST_URI'];
337
		}
338
339 1
		return null;
340
	}
341
342
	/**
343
	 * Clears the post-login redirect
344
	 * @return string
345
	 */
346 2
	public static function clearPostLoginRedirect()
347
	{
348 2
		$session = &self::$globalStateProvider->getSessionSuperGlobal();
349 2
		if (array_key_exists('returnTo', $session)) {
350 1
			$path = $session['returnTo'];
351 1
			unset($session['returnTo']);
352
353 1
			return $path;
354
		}
355
356 1
		return null;
357
	}
358
359
	/**
360
	 * @return string|null
361
	 */
362 View Code Duplication
	public static function serverName()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
363
	{
364
		$server = &self::$globalStateProvider->getServerSuperGlobal();
365
366
		if (isset($server['SERVER_NAME'])) {
367
			return $server['SERVER_NAME'];
368
		}
369
370
		return null;
371
	}
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)
406
	{
407
		$session = &self::$globalStateProvider->getSessionSuperGlobal();
408
		$session['alerts'] = $data;
409
	}
410
411
	/**
412
	 * You probably only want to deal with this through TokenManager.
413
	 *
414
	 * @return string[]
415
	 */
416
	public static function getSessionTokenData()
417
	{
418
		$session = &self::$globalStateProvider->getSessionSuperGlobal();
419
		if (array_key_exists('tokens', $session)) {
420
			return $session['tokens'];
421
		}
422
423
		return array();
424
	}
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)
432
	{
433
		$session = &self::$globalStateProvider->getSessionSuperGlobal();
434
		$session['tokens'] = $data;
435
	}
436
437
	/**
438
	 * @param string $key
439
	 * @return mixed
440
	 */
441
	public static function getSessionContext($key){
442
		$session = &self::$globalStateProvider->getSessionSuperGlobal();
443
444
		if(!isset($session['context'])) {
445
			$session['context'] = array();
446
		}
447
448
		if(!isset($session['context'][$key])){
449
			return null;
450
		}
451
452
		return $session['context'][$key];
453
	}
454
455
	/**
456
	 * @param string $key
457
	 * @param mixed  $data
458
	 */
459
	public static function setSessionContext($key, $data){
460
		$session = &self::$globalStateProvider->getSessionSuperGlobal();
461
462
		if(!isset($session['context'])){
463
			$session['context'] = array();
464
		}
465
466
		$session['context'][$key] = $data;
467
	}
468
469
	/**
470
	 * @return int|null
471
	 */
472
	public static function getSessionUserId()
473
	{
474
		$session = &self::$globalStateProvider->getSessionSuperGlobal();
475
476
		return isset($session['userID']) ? (int)$session['userID'] : null;
477
	}
478
479
	/**
480
	 * @param User $user
481
	 */
482
	public static function setPartialLogin(User $user)
483
	{
484
		$session = &self::$globalStateProvider->getSessionSuperGlobal();
485
		$session['partialLogin'] = $user->getId();
486
	}
487
488
	/**
489
	 * @return int|null
490
	 */
491
	public static function getPartialLogin()
492
	{
493
		$session = &self::$globalStateProvider->getSessionSuperGlobal();
494
495
		return isset($session['partialLogin']) ? (int)$session['partialLogin'] : null;
496
	}
497
498
	/**
499
	 * @return null|string
500
	 */
501 View Code Duplication
	public static function userAgent()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
502
	{
503
		$server = &self::$globalStateProvider->getServerSuperGlobal();
504
505
		if (isset($server['HTTP_USER_AGENT'])) {
506
			return $server['HTTP_USER_AGENT'];
507
		}
508
509
		return null;
510
	}
511
512
	/**
513
	 * @return null|string
514
	 */
515 View Code Duplication
	public static function scriptName()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
516
	{
517
		$server = &self::$globalStateProvider->getServerSuperGlobal();
518
519
		if (isset($server['SCRIPT_NAME'])) {
520
			return $server['SCRIPT_NAME'];
521
		}
522
523
		return null;
524
	}
525
526
	/**
527
	 * @return null|string
528
	 */
529 View Code Duplication
	public static function origin()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
530
	{
531
		$server = &self::$globalStateProvider->getServerSuperGlobal();
532
533
		if (isset($server['HTTP_ORIGIN'])) {
534
			return $server['HTTP_ORIGIN'];
535
		}
536
537
		return null;
538
	}
539
}