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.35%

Importance

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