Router   C
last analyzed

Complexity

Total Complexity 55

Size/Duplication

Total Lines 455
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 25

Test Coverage

Coverage 96.4%

Importance

Changes 0
Metric Value
wmc 55
lcom 1
cbo 25
dl 0
loc 455
ccs 134
cts 139
cp 0.964
rs 6
c 0
b 0
f 0

21 Methods

Rating   Name   Duplication   Size   Complexity  
B routeHeader() 0 42 7
C routeContent() 0 72 17
A _tokenGuard() 0 4 2
A _authGuard() 0 4 2
A _aliasValidator() 0 5 2
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
	public function routeHeader() : bool
33 3
	{
34
		Module\Hook::trigger('routeHeader');
35 3
36
		/* handle break */
37
38
		if ($this->_registry->get('routerBreak'))
39 3
		{
40
			Header::responseCode(202);
41 1
		}
42
43
		/* handle guard */
44
45
		if ($this->_tokenGuard())
46 3
		{
47
			Header::responseCode(403);
48 1
		}
49
		if ($this->_authGuard())
50 3
		{
51
			Header::responseCode(403);
52
		}
53
54
		/* handle validator */
55
56
		if ($this->_aliasValidator())
57 3
		{
58
			Header::responseCode(202);
59
		}
60
		else if (!$this->_contentValidator())
61 3
		{
62
			Header::responseCode(404);
63
		}
64
65
		/* handle post */
66
67
		if ($this->_request->getPost('Redaxscript\View\SearchForm'))
68 3
		{
69
			return $this->_redirectSearch();
70 1
		}
71
72
		return (bool)$this->_registry->get('routerBreak');
73 2
	}
74
75
	/**
76
	 * route the content
77
	 *
78
	 * @since 3.3.0
79
	 *
80
	 * @return string|null
81
	 */
82
83
	public function routeContent() : ?string
84 17
	{
85
		Module\Hook::trigger('routeContent');
86 17
		$firstParameter = $this->getFirst();
87 17
		$fileInstall = $this->_registry->get('file') === 'install.php' && $this->_config->get('env') !== 'production';
88 17
89
		/* handle guard */
90
91
		if ($this->_tokenGuard())
92 17
		{
93
			return $this->_errorToken();
94 1
		}
95
		if ($this->_authGuard())
96 16
		{
97
			return $this->_errorAccess();
98
		}
99
100
		/* handle post */
101
102
		if ($this->_request->getPost('Redaxscript\View\CommentForm'))
103 16
		{
104
			return $this->_processComment();
105 1
		}
106
		if ($this->_request->getPost('Redaxscript\View\LoginForm'))
107 15
		{
108
			return $this->_processLogin();
109 1
		}
110
		if ($this->_request->getPost('Redaxscript\View\ResetForm'))
111 14
		{
112
			return $this->_processReset();
113 1
		}
114
		if ($this->_request->getPost('Redaxscript\View\RecoverForm'))
115 13
		{
116
			return $this->_processRecover();
117 1
		}
118
		if ($this->_request->getPost('Redaxscript\View\RegisterForm'))
119 12
		{
120
			return $this->_processRegister();
121 1
		}
122
		if ($fileInstall && $this->_request->getPost('Redaxscript\View\InstallForm'))
123 11
		{
124
			return $this->_processInstall();
125 1
		}
126
127
		/* handle route */
128
129
		if ($firstParameter === 'search')
130 10
		{
131
			return $this->_processSearch();
132 1
		}
133
		if ($firstParameter === 'login')
134 9
		{
135
			return $this->_renderLogin();
136 4
		}
137
		if ($firstParameter === 'logout')
138 5
		{
139
			return $this->_processLogout();
140 1
		}
141
		if ($firstParameter === 'register')
142 4
		{
143
			return $this->_renderRegister();
144 2
		}
145
		if ($fileInstall)
146 2
		{
147
			return $this->_renderInstall();
148 1
		}
149
		if ($this->_registry->get('routerBreak'))
150 1
		{
151
			return '<!-- routerBreak -->';
152
		}
153
		return null;
154 1
	}
155
156
	/**
157
	 * token guard
158
	 *
159
	 * @since 3.3.0
160
	 *
161
	 * @return bool
162
	 */
163
164
	protected function _tokenGuard() : bool
165 20
	{
166
		return $this->_request->get('post') && $this->_request->getPost('token') !== $this->_registry->get('token');
167 20
	}
168
169
	/**
170
	 * auth guard
171
	 *
172
	 * @since 3.3.0
173
	 *
174
	 * @return bool
175
	 */
176
177
	protected function _authGuard() : bool
178 19
	{
179
		return $this->_registry->get('token') !== $this->_registry->get('loggedIn') && $this->_registry->get('firstParameter') === 'admin';
180 19
	}
181
182
	/**
183
	 * alias validator
184
	 *
185
	 * @since 4.0.0
186
	 *
187
	 * @return bool
188
	 */
189
190
	protected function _aliasValidator() : bool
191 3
	{
192
		$aliasValidator = new Validator\Alias();
193 3
		return $aliasValidator->validate($this->_registry->get('firstParameter'), 'system') && $this->_registry->get('fullRoute') !== 'admin';
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...
194 3
	}
195
196
	/**
197
	 * content validator
198
	 *
199
	 * @since 4.0.0
200
	 *
201
	 * @return bool
202
	 */
203
204
	protected function _contentValidator() : bool
205 3
	{
206
		return $this->_registry->get('lastId') > 0;
207 3
	}
208 3
209 3
	/**
210 3
	 * redirect the search
211 3
	 *
212
	 * @since 3.3.0
213
	 *
214
	 * @return bool
215
	 */
216
217
	protected function _redirectSearch() : bool
218
	{
219
		$aliasFilter = new Filter\Alias();
220
		$root = $this->_registry->get('root');
221
		$parameterRoute = $this->_registry->get('parameterRoute');
222 1
223
		/* handle post */
224 1
225 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...
226 1
		$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...
227
		$tableString = $table ? '/' . $table : null;
228
229
		/* redirect */
230 1
231 1
		return Header::doRedirect($root . '/' . $parameterRoute . 'search' . $tableString . '/' . $search);
232 1
	}
233
234
	/**
235
	 * process the search
236 1
	 *
237
	 * @since 3.3.0
238
	 *
239
	 * @return string
240
	 */
241
242
	protected function _processSearch() : string
243
	{
244
		$searchController = new Controller\Search($this->_registry, $this->_request, $this->_language, $this->_config);
245
		return $searchController->process();
246
	}
247 1
248
	/**
249 1
	 * process the comment
250 1
	 *
251
	 * @since 3.3.0
252
	 *
253
	 * @return string
254
	 */
255
256
	protected function _processComment() : string
257
	{
258
		$commentController = new Controller\Comment($this->_registry, $this->_request, $this->_language, $this->_config);
259
		return $commentController->process();
260
	}
261 1
262
	/**
263 1
	 * process the login
264 1
	 *
265
	 * @since 3.3.0
266
	 *
267
	 * @return string
268
	 */
269
270
	protected function _processLogin() : string
271
	{
272
		$loginController = new Controller\Login($this->_registry, $this->_request, $this->_language, $this->_config);
273
		return $loginController->process();
274
	}
275 1
276
	/**
277 1
	 * process the reset
278 1
	 *
279
	 * @since 3.3.0
280
	 *
281
	 * @return string
282
	 */
283
284
	protected function _processReset() : string
285
	{
286
		$resetController = new Controller\Reset($this->_registry, $this->_request, $this->_language, $this->_config);
287
		return $resetController->process();
288
	}
289 1
290
	/**
291 1
	 * process the recover
292 1
	 *
293
	 * @since 3.3.0
294
	 *
295
	 * @return string
296
	 */
297
298
	protected function _processRecover() : string
299
	{
300
		$recoverController = new Controller\Recover($this->_registry, $this->_request, $this->_language, $this->_config);
301
		return $recoverController->process();
302
	}
303 1
304
	/**
305 1
	 * process the register
306 1
	 *
307
	 * @since 3.3.0
308
	 *
309
	 * @return string
310
	 */
311
312
	protected function _processRegister() : string
313
	{
314
		$registerController = new Controller\Register($this->_registry, $this->_request, $this->_language, $this->_config);
315
		return $registerController->process();
316
	}
317 1
318
	/**
319 1
	 * process the logout
320 1
	 *
321
	 * @since 3.3.0
322
	 *
323
	 * @return string
324
	 */
325
326
	protected function _processLogout() : string
327
	{
328
		$logoutController = new Controller\Logout($this->_registry, $this->_request, $this->_language, $this->_config);
329
		return $logoutController->process();
330
	}
331 1
332
	/**
333 1
	 * process the install
334 1
	 *
335
	 * @since 3.3.0
336
	 *
337
	 * @return string
338
	 */
339
340
	protected function _processInstall() : string
341
	{
342
		$this->_request->setSession('installArray',
343
		[
344
			'dbType' => $this->_request->getPost('db-type'),
345 1
			'dbHost' => $this->_request->getPost('db-host'),
346
			'dbName' => $this->_request->getPost('db-name'),
347 1
			'dbUser' => $this->_request->getPost('db-user'),
348
			'dbPassword' => $this->_request->getPost('db-password'),
349 1
			'dbPrefix' => $this->_request->getPost('db-prefix'),
350 1
			'adminName' => $this->_request->getPost('admin-name'),
351 1
			'adminUser' => $this->_request->getPost('admin-user'),
352 1
			'adminPassword' => $this->_request->getPost('admin-password'),
353 1
			'adminEmail' => $this->_request->getPost('admin-email')
354 1
		]);
355 1
		$installController = new Controller\Install($this->_registry, $this->_request, $this->_language, $this->_config);
356 1
		return $installController->process();
357 1
	}
358 1
359
	/**
360 1
	 * render the login
361 1
	 *
362
	 * @since 3.3.0
363
	 *
364
	 * @return string
365
	 */
366
367
	protected function _renderLogin() : string
368
	{
369
		$secondParameter = $this->getSecond();
370
		$thirdParameter = $this->getThird();
371
		$thirdSubParameter = $this->getThirdSub();
372 4
		$settingModel = new Model\Setting();
373
374 4
		/* handle login */
375 4
376 4
		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...
377 4
		{
378
			if ($secondParameter === 'recover')
379
			{
380
				$recoverForm = new View\RecoverForm($this->_registry, $this->_language);
381 4
				return $recoverForm->render();
382
			}
383 2
			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...
384
			{
385 1
				$resetForm = new View\ResetForm($this->_registry, $this->_language);
386 1
				return $resetForm->render();
387
			}
388 1
		}
389
		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...
390 1
		{
391 1
			$loginForm = new View\LoginForm($this->_registry, $this->_language);
392
			return $loginForm->render();
393
		}
394 2
		return $this->_errorAccess();
395
	}
396 1
397 1
	/**
398
	 * render the register
399 1
	 *
400
	 * @since 3.3.0
401
	 *
402
	 * @return string
403
	 */
404
405
	protected function _renderRegister() : string
406
	{
407
		$settingModel = new Model\Setting();
408
		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...
409
		{
410 2
			$registerForm = new View\RegisterForm($this->_registry, $this->_language);
411
			return $registerForm->render();
412 2
		}
413 2
		return $this->_errorAccess();
414
	}
415 1
416 1
	/**
417
	 * render the install
418 1
	 *
419
	 * @since 3.3.0
420
	 *
421
	 * @return string
422
	 */
423
424
	protected function _renderInstall() : string
425
	{
426
		$installArray = $this->_request->getSession('installArray');
427
		$systemStatus = new View\SystemStatus($this->_registry, $this->_language);
428
		$installForm = new View\InstallForm($this->_registry, $this->_language);
429 1
		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...
430
	}
431 1
432 1
	/**
433 1
	 * messenger factory
434 1
	 *
435
	 * @since 4.0.0
436
	 *
437
	 * @return View\Helper\Messenger
438
	 */
439
440
	protected function _messengerFactory() : View\Helper\Messenger
441
	{
442
		return new View\Helper\Messenger($this->_registry);
443
	}
444
445 3
	/**
446
	 * show the token error
447 3
	 *
448
	 * @since 3.3.0
449
	 *
450
	 * @return string
451
	 */
452
453
	protected function _errorToken() : string
454
	{
455
		$messenger = $this->_messengerFactory();
456
		return $messenger
457
			->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...
458 1
			->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...
459
	}
460 1
461
	/**
462 1
	 * show the access error
463 1
	 *
464
	 * @since 3.3.0
465
	 *
466
	 * @return string
467
	 */
468
469
	protected function _errorAccess() : string
470
	{
471
		$messenger = $this->_messengerFactory();
472
		return $messenger
473
			->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...
474 2
			->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...
475
	}
476
}
477