Router   C
last analyzed

Complexity

Total Complexity 54

Size/Duplication

Total Lines 457
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 25

Test Coverage

Coverage 96.35%

Importance

Changes 0
Metric Value
wmc 54
lcom 1
cbo 25
dl 0
loc 457
ccs 132
cts 137
cp 0.9635
rs 6.4799
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
B routeHeader() 0 41 7
C routeContent() 0 75 17
A _tokenGuard() 0 4 2
A _authGuard() 0 4 2
A _aliasValidator() 0 5 1
A _contentValidator() 0 4 1
A _redirectSearch() 0 16 2
A _processSearch() 0 5 1
A _processComment() 0 5 1
A _processLogin() 0 5 1
A _processReset() 0 5 1
A _processRecover() 0 5 1
A _processRegister() 0 5 1
A _processLogout() 0 5 1
A _processInstall() 0 18 1
B _renderLogin() 0 29 7
A _renderRegister() 0 10 2
A _renderInstall() 0 7 2
A _messengerFactory() 0 4 1
A _errorToken() 0 7 1
A _errorAccess() 0 7 1

How to fix   Complexity   

Complex Class

Complex classes like Router 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 Router, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace Redaxscript\Router;
3
4
use Redaxscript\Controller;
5
use Redaxscript\Filter;
6
use Redaxscript\Header;
7
use Redaxscript\Model;
8
use Redaxscript\Module;
9
use Redaxscript\Validator;
10
use Redaxscript\View;
11
12
/**
13
 * parent class to provide the router
14
 *
15
 * @since 3.3.0
16
 *
17
 * @package Redaxscript
18
 * @category Router
19
 * @author Henry Ruhs
20
 */
21
22
class Router extends RouterAbstract
23
{
24
	/**
25
	 * route the header
26
	 *
27
	 * @since 3.3.0
28
	 *
29
	 * @return bool
30
	 */
31
32 3
	public function routeHeader() : bool
33
	{
34 3
		Module\Hook::trigger('routeHeader');
35
36
		/* handle break */
37
38 3
		if ($this->_registry->get('routerBreak'))
39
		{
40 1
			Header::responseCode(202);
41
		}
42
43
		/* handle guard */
44
45 3
		if ($this->_tokenGuard())
46
		{
47 1
			Header::responseCode(403);
48
		}
49 3
		if ($this->_authGuard())
50
		{
51
			Header::responseCode(403);
52
		}
53
54
		/* handle validator */
55
56 3
		if ($this->_aliasValidator())
57
		{
58
			Header::responseCode(202);
59
		}
60 3
		else if (!$this->_contentValidator())
61
		{
62
			Header::responseCode(404);
63
		}
64
65
		/* handle post */
66
67 3
		if ($this->_request->getPost('Redaxscript\View\SearchForm'))
68
		{
69 1
			return $this->_redirectSearch();
70
		}
71
		return (bool)$this->_registry->get('routerBreak');
72 2
	}
73
74
	/**
75
	 * route the content
76
	 *
77
	 * @since 3.3.0
78
	 *
79
	 * @return string|null
80
	 */
81
82
	public function routeContent() : ?string
83 17
	{
84
		Module\Hook::trigger('routeContent');
85 17
		$firstParameter = $this->getFirst();
86 17
		$fileInstall = $this->_registry->get('file') === 'install.php' && $this->_config->get('env') !== 'production';
87 17
88
		/* handle break */
89
90
		if ($this->_registry->get('routerBreak'))
91 17
		{
92
			return '<!-- routerBreak -->';
93 1
		}
94
95 16
		/* handle guard */
96
97
		if ($this->_tokenGuard())
98
		{
99
			return $this->_errorToken();
100
		}
101
		if ($this->_authGuard())
102 16
		{
103
			return $this->_errorAccess();
104 1
		}
105
106 15
		/* handle post */
107
108 1
		if ($this->_request->getPost('Redaxscript\View\CommentForm'))
109
		{
110 14
			return $this->_processComment();
111
		}
112 1
		if ($this->_request->getPost('Redaxscript\View\LoginForm'))
113
		{
114 13
			return $this->_processLogin();
115
		}
116 1
		if ($this->_request->getPost('Redaxscript\View\ResetForm'))
117
		{
118 12
			return $this->_processReset();
119
		}
120 1
		if ($this->_request->getPost('Redaxscript\View\RecoverForm'))
121
		{
122 11
			return $this->_processRecover();
123
		}
124 1
		if ($this->_request->getPost('Redaxscript\View\RegisterForm'))
125
		{
126
			return $this->_processRegister();
127
		}
128
		if ($fileInstall && $this->_request->getPost('Redaxscript\View\InstallForm'))
129 10
		{
130
			return $this->_processInstall();
131 1
		}
132
133 9
		/* handle route */
134
135 4
		if ($firstParameter === 'search')
136
		{
137 5
			return $this->_processSearch();
138
		}
139 1
		if ($firstParameter === 'login')
140
		{
141 4
			return $this->_renderLogin();
142
		}
143 2
		if ($firstParameter === 'logout')
144
		{
145 2
			return $this->_processLogout();
146
		}
147 1
		if ($firstParameter === 'register')
148
		{
149 1
			return $this->_renderRegister();
150
		}
151
		if ($fileInstall)
152
		{
153 1
			return $this->_renderInstall();
154
		}
155
		return null;
156
	}
157
158
	/**
159
	 * token guard
160
	 *
161
	 * @since 3.3.0
162
	 *
163
	 * @return bool
164 20
	 */
165
166 20
	protected function _tokenGuard() : bool
167
	{
168
		return $this->_request->get('post') && $this->_request->getPost('token') !== $this->_registry->get('token');
169
	}
170
171
	/**
172
	 * auth guard
173
	 *
174
	 * @since 3.3.0
175
	 *
176
	 * @return bool
177 19
	 */
178
179 19
	protected function _authGuard() : bool
180
	{
181
		return $this->_registry->get('token') !== $this->_registry->get('loggedIn') && $this->_registry->get('firstParameter') === 'admin';
182
	}
183
184
	/**
185
	 * alias validator
186
	 *
187
	 * @since 4.0.0
188
	 *
189
	 * @return bool
190 3
	 */
191
192 3
	protected function _aliasValidator() : bool
193 3
	{
194
		$aliasValidator = new Validator\Alias();
195
		return !$aliasValidator->validate($this->_registry->get('firstParameter'), 'system');
0 ignored issues
show
Bug introduced by redaxmedia
It seems like $this->_registry->get('firstParameter') targeting Redaxscript\Registry::get() can also be of type array; however, Redaxscript\Validator\Alias::validate() does only seem to accept null|string, maybe add an additional type check?

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.

Loading history...
196
	}
197
198
	/**
199
	 * content validator
200
	 *
201
	 * @since 4.0.0
202
	 *
203
	 * @return bool
204 3
	 */
205
206 3
	protected function _contentValidator() : bool
207
	{
208
		return $this->_registry->get('lastId') > 0;
209
	}
210
211
	/**
212
	 * redirect the search
213
	 *
214
	 * @since 3.3.0
215
	 *
216
	 * @return bool
217 1
	 */
218
219 1
	protected function _redirectSearch() : bool
220 1
	{
221 1
		$aliasFilter = new Filter\Alias();
222
		$root = $this->_registry->get('root');
223
		$parameterRoute = $this->_registry->get('parameterRoute');
224
225 1
		/* handle post */
226 1
227 1
		$table = $aliasFilter->sanitize($this->_request->getPost('table'));
0 ignored issues
show
Bug introduced by redaxmedia
It seems like $this->_request->getPost('table') targeting Redaxscript\Request::getPost() can also be of type array; however, Redaxscript\Filter\Alias::sanitize() does only seem to accept null|string, maybe add an additional type check?

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.

Loading history...
228
		$search = $aliasFilter->sanitize($this->_request->getPost('search'));
0 ignored issues
show
Bug introduced by redaxmedia
It seems like $this->_request->getPost('search') targeting Redaxscript\Request::getPost() can also be of type array; however, Redaxscript\Filter\Alias::sanitize() does only seem to accept null|string, maybe add an additional type check?

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.

Loading history...
229
		$tableString = $table ? '/' . $table : null;
230
231 1
		/* redirect */
232
233
		return Header::doRedirect($root . '/' . $parameterRoute . 'search' . $tableString . '/' . $search);
234
	}
235
236
	/**
237
	 * process the search
238
	 *
239
	 * @since 3.3.0
240
	 *
241
	 * @return string
242 1
	 */
243
244 1
	protected function _processSearch() : string
245 1
	{
246
		$searchController = new Controller\Search($this->_registry, $this->_request, $this->_language, $this->_config);
247
		return $searchController->process();
248
	}
249
250
	/**
251
	 * process the comment
252
	 *
253
	 * @since 3.3.0
254
	 *
255
	 * @return string
256 1
	 */
257
258 1
	protected function _processComment() : string
259 1
	{
260
		$commentController = new Controller\Comment($this->_registry, $this->_request, $this->_language, $this->_config);
261
		return $commentController->process();
262
	}
263
264
	/**
265
	 * process the login
266
	 *
267
	 * @since 3.3.0
268
	 *
269
	 * @return string
270 1
	 */
271
272 1
	protected function _processLogin() : string
273 1
	{
274
		$loginController = new Controller\Login($this->_registry, $this->_request, $this->_language, $this->_config);
275
		return $loginController->process();
276
	}
277
278
	/**
279
	 * process the reset
280
	 *
281
	 * @since 3.3.0
282
	 *
283
	 * @return string
284 1
	 */
285
286 1
	protected function _processReset() : string
287 1
	{
288
		$resetController = new Controller\Reset($this->_registry, $this->_request, $this->_language, $this->_config);
289
		return $resetController->process();
290
	}
291
292
	/**
293
	 * process the recover
294
	 *
295
	 * @since 3.3.0
296
	 *
297
	 * @return string
298 1
	 */
299
300 1
	protected function _processRecover() : string
301 1
	{
302
		$recoverController = new Controller\Recover($this->_registry, $this->_request, $this->_language, $this->_config);
303
		return $recoverController->process();
304
	}
305
306
	/**
307
	 * process the register
308
	 *
309
	 * @since 3.3.0
310
	 *
311
	 * @return string
312 1
	 */
313
314 1
	protected function _processRegister() : string
315 1
	{
316
		$registerController = new Controller\Register($this->_registry, $this->_request, $this->_language, $this->_config);
317
		return $registerController->process();
318
	}
319
320
	/**
321
	 * process the logout
322
	 *
323
	 * @since 3.3.0
324
	 *
325
	 * @return string
326 1
	 */
327
328 1
	protected function _processLogout() : string
329 1
	{
330
		$logoutController = new Controller\Logout($this->_registry, $this->_request, $this->_language, $this->_config);
331
		return $logoutController->process();
332
	}
333
334
	/**
335
	 * process the install
336
	 *
337
	 * @since 3.3.0
338
	 *
339
	 * @return string
340 1
	 */
341
342 1
	protected function _processInstall() : string
343
	{
344 1
		$this->_request->setSession('installArray',
345 1
		[
346 1
			'dbType' => $this->_request->getPost('db-type'),
347 1
			'dbHost' => $this->_request->getPost('db-host'),
348 1
			'dbName' => $this->_request->getPost('db-name'),
349 1
			'dbUser' => $this->_request->getPost('db-user'),
350 1
			'dbPassword' => $this->_request->getPost('db-password'),
351 1
			'dbPrefix' => $this->_request->getPost('db-prefix'),
352 1
			'adminName' => $this->_request->getPost('admin-name'),
353 1
			'adminUser' => $this->_request->getPost('admin-user'),
354
			'adminPassword' => $this->_request->getPost('admin-password'),
355 1
			'adminEmail' => $this->_request->getPost('admin-email')
356 1
		]);
357
		$installController = new Controller\Install($this->_registry, $this->_request, $this->_language, $this->_config);
358
		return $installController->process();
359
	}
360
361
	/**
362
	 * render the login
363
	 *
364
	 * @since 3.3.0
365
	 *
366
	 * @return string
367 4
	 */
368
369 4
	protected function _renderLogin() : string
370 4
	{
371 4
		$secondParameter = $this->getSecond();
372 4
		$thirdParameter = $this->getThird();
373
		$thirdSubParameter = $this->getThirdSub();
374
		$settingModel = new Model\Setting();
375
376 4
		/* handle login */
377
378 2
		if ($settingModel->get('recovery'))
0 ignored issues
show
Bug Best Practice introduced by redaxmedia
The expression $settingModel->get('recovery') of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
379
		{
380 1
			if ($secondParameter === 'recover')
381 1
			{
382
				$recoverForm = new View\RecoverForm($this->_registry, $this->_language);
383 1
				return $recoverForm->render();
384
			}
385 1
			if ($secondParameter === 'reset' && $thirdParameter && $thirdSubParameter)
0 ignored issues
show
Bug Best Practice introduced by redaxmedia
The expression $thirdParameter of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by redaxmedia
The expression $thirdSubParameter of type integer|null is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
386 1
			{
387
				$resetForm = new View\ResetForm($this->_registry, $this->_language);
388
				return $resetForm->render();
389 2
			}
390
		}
391 1
		if (!$secondParameter)
0 ignored issues
show
Bug Best Practice introduced by redaxmedia
The expression $secondParameter of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
392 1
		{
393
			$loginForm = new View\LoginForm($this->_registry, $this->_language);
394 1
			return $loginForm->render();
395
		}
396
		return $this->_errorAccess();
397
	}
398
399
	/**
400
	 * render the register
401
	 *
402
	 * @since 3.3.0
403
	 *
404
	 * @return string
405 2
	 */
406
407 2
	protected function _renderRegister() : string
408 2
	{
409
		$settingModel = new Model\Setting();
410 1
		if ($settingModel->get('registration'))
0 ignored issues
show
Bug Best Practice introduced by redaxmedia
The expression $settingModel->get('registration') of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
411 1
		{
412
			$registerForm = new View\RegisterForm($this->_registry, $this->_language);
413 1
			return $registerForm->render();
414
		}
415
		return $this->_errorAccess();
416
	}
417
418
	/**
419
	 * render the install
420
	 *
421
	 * @since 3.3.0
422
	 *
423
	 * @return string
424 1
	 */
425
426 1
	protected function _renderInstall() : string
427 1
	{
428 1
		$installArray = $this->_request->getSession('installArray');
429 1
		$systemStatus = new View\SystemStatus($this->_registry, $this->_language);
430
		$installForm = new View\InstallForm($this->_registry, $this->_language);
431
		return $systemStatus->render() . $installForm->render($installArray ? : []);
0 ignored issues
show
Bug introduced by redaxmedia
It seems like $installArray ?: array() can also be of type string; however, Redaxscript\View\InstallForm::render() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
432
	}
433
434
	/**
435
	 * messenger factory
436
	 *
437
	 * @since 4.0.0
438
	 *
439
	 * @return View\Helper\Messenger
440 3
	 */
441
442 3
	protected function _messengerFactory() : View\Helper\Messenger
443
	{
444
		return new View\Helper\Messenger($this->_registry);
445
	}
446
447
	/**
448
	 * show the token error
449
	 *
450
	 * @since 3.3.0
451
	 *
452
	 * @return string
453 1
	 */
454
455 1
	protected function _errorToken() : string
456
	{
457 1
		$messenger = $this->_messengerFactory();
458 1
		return $messenger
459
			->setUrl($this->_language->get('home'), $this->_registry->get('root'))
0 ignored issues
show
Bug introduced by redaxmedia
It seems like $this->_language->get('home') targeting Redaxscript\Language::get() can also be of type array; however, Redaxscript\View\Helper\Messenger::setUrl() does only seem to accept null|string, maybe add an additional type check?

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.

Loading history...
Bug introduced by redaxmedia
It seems like $this->_registry->get('root') targeting Redaxscript\Registry::get() can also be of type array; however, Redaxscript\View\Helper\Messenger::setUrl() does only seem to accept null|string, maybe add an additional type check?

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.

Loading history...
460
			->error($this->_language->get('token_incorrect'), $this->_language->get('error_occurred'));
0 ignored issues
show
Bug introduced by redaxmedia
It seems like $this->_language->get('error_occurred') targeting Redaxscript\Language::get() can also be of type array; however, Redaxscript\View\Helper\Messenger::error() does only seem to accept null|string, maybe add an additional type check?

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.

Loading history...
461
	}
462
463
	/**
464
	 * show the access error
465
	 *
466
	 * @since 3.3.0
467
	 *
468
	 * @return string
469 2
	 */
470
471 2
	protected function _errorAccess() : string
472
	{
473 2
		$messenger = $this->_messengerFactory();
474 2
		return $messenger
475
			->setUrl($this->_language->get('home'), $this->_registry->get('root'))
0 ignored issues
show
Bug introduced by redaxmedia
It seems like $this->_language->get('home') targeting Redaxscript\Language::get() can also be of type array; however, Redaxscript\View\Helper\Messenger::setUrl() does only seem to accept null|string, maybe add an additional type check?

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.

Loading history...
Bug introduced by redaxmedia
It seems like $this->_registry->get('root') targeting Redaxscript\Registry::get() can also be of type array; however, Redaxscript\View\Helper\Messenger::setUrl() does only seem to accept null|string, maybe add an additional type check?

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.

Loading history...
476
			->error($this->_language->get('access_no'), $this->_language->get('error_occurred'));
0 ignored issues
show
Bug introduced by redaxmedia
It seems like $this->_language->get('error_occurred') targeting Redaxscript\Language::get() can also be of type array; however, Redaxscript\View\Helper\Messenger::error() does only seem to accept null|string, maybe add an additional type check?

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.

Loading history...
477
	}
478
}
479