Completed
Push — master ( a2fb8e...063c96 )
by Henry
24:41
created

Router   C

Complexity

Total Complexity 55

Size/Duplication

Total Lines 462
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 26

Test Coverage

Coverage 94.03%

Importance

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