OnRequestHandler::hasMobileRedirect()   B
last analyzed

Complexity

Conditions 11
Paths 15

Size

Total Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 132

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 0
cts 11
cp 0
rs 7.3166
c 0
b 0
f 0
cc 11
nc 15
nop 0
crap 132

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * OnRequestHandler.php
4
 *
5
 * @copyright      More in license.md
6
 * @license        https://www.ipublikuj.eu
7
 * @author         Adam Kadlec <[email protected]>
8
 * @package        iPublikuj:MobileDetect!
9
 * @subpackage     Events
10
 * @since          1.0.0
11
 *
12
 * @date           22.04.14
13
 */
14
15
declare(strict_types = 1);
16
17
namespace IPub\MobileDetect\Events;
18
19
use Nette\Application;
20
use Nette\Application\Responses;
21
use Nette\Http;
22
23
use IPub\MobileDetect;
24
use IPub\MobileDetect\Helpers;
25
26
/**
27
 * On request event handler
28
 *
29
 * @package        iPublikuj:MobileDetect!
30
 * @subpackage     Events
31
 *
32
 * @author         Adam Kadlec <[email protected]>
33
 */
34 1
final class OnRequestHandler
35
{
36
	private const REDIRECT = 'redirect';
37
	private const NO_REDIRECT = 'noRedirect';
38
	private const REDIRECT_WITHOUT_PATH = 'redirectWithoutPath';
39
40
	private const MOBILE = 'mobile';
41
	private const TABLET = 'tablet';
42
	private const PHONE = 'phone';
43
44
	/**
45
	 * @var array
46
	 */
47
	public $redirectConf = [];
48
49
	/**
50
	 * @var bool
51
	 */
52
	public $isFullPath = true;
53
54
	/**
55
	 * @var Http\IRequest
56
	 */
57
	private $httpRequest;
58
59
	/**
60
	 * @var Http\IResponse
61
	 */
62
	private $httpResponse;
63
64
	/**
65
	 * @var Application\IRouter
66
	 */
67
	private $router;
68
69
	/**
70
	 * @var MobileDetect\MobileDetect
71
	 */
72
	private $mobileDetect;
73
74
	/**
75
	 * @var Helpers\DeviceView
76
	 */
77
	private $deviceView;
78
79
	/**
80
	 * @var OnResponseHandler
81
	 */
82
	private $onResponseHandler;
83
84
	/**
85
	 * @param Http\IRequest $httpRequest
86
	 * @param Http\IResponse $httpResponse
87
	 * @param Application\IRouter $router
88
	 * @param OnResponseHandler $onResponseHandler
89
	 * @param MobileDetect\MobileDetect $mobileDetect
90
	 * @param Helpers\DeviceView $deviceView
91
	 */
92
	public function __construct(
93
		Http\IRequest $httpRequest,
94
		Http\IResponse $httpResponse,
95
		Application\IRouter $router,
96
		OnResponseHandler $onResponseHandler,
97
		MobileDetect\MobileDetect $mobileDetect,
98
		Helpers\DeviceView $deviceView
99
	) {
100 1
		$this->httpRequest = $httpRequest;
101 1
		$this->httpResponse = $httpResponse;
102
103 1
		$this->router = $router;
104
105 1
		$this->onResponseHandler = $onResponseHandler;
106
107 1
		$this->mobileDetect = $mobileDetect;
108 1
		$this->deviceView = $deviceView;
109 1
	}
110
111
	/**
112
	 * @param Application\Application $application
113
	 *
114
	 * @return void
115
	 */
116
	public function __invoke(Application\Application $application) : void
117
	{
118
		// Redirect only normal request
119
		if ($this->httpRequest->isAjax()) {
120
			return;
121
		}
122
123
		// Sets the flag for the response handled by the GET switch param and the type of the view.
124
		if ($this->deviceView->hasSwitchParameter()) {
125
			if ($response = $this->getRedirectResponseBySwitchParam()) {
126
				$response->send($this->httpRequest, $this->httpResponse);
127
				exit();
128
			}
129
130
			return;
131
		}
132
133
		// If the device view is either the full view or not the mobile view
134
		if ($this->deviceView->isFullView() || $this->deviceView->isNotMobileView()) {
135
			return;
136
		}
137
138
		// Redirects to the phone version and set the 'phone' device view in a cookie.
139
		if ($this->hasPhoneRedirect()) {
140
			if ($response = $this->getDeviceRedirectResponse(self::PHONE)) {
141
				$response->send($this->httpRequest, $this->httpResponse);
142
				exit();
143
			}
144
145
			return;
146
		}
147
148
		// Redirects to the tablet version and set the 'tablet' device view in a cookie.
149
		if ($this->hasTabletRedirect()) {
150
			if ($response = $this->getDeviceRedirectResponse(self::TABLET)) {
151
				$response->send($this->httpRequest, $this->httpResponse);
152
				exit();
153
			}
154
155
			return;
156
		}
157
158
		// Redirects to the mobile version and set the 'mobile' device view in a cookie.
159
		if ($this->hasMobileRedirect()) {
160
			if ($response = $this->getDeviceRedirectResponse(self::MOBILE)) {
161
				$response->send($this->httpRequest, $this->httpResponse);
162
				exit();
163
			}
164
165
			return;
166
		}
167
168
		// No need to redirect
169
170
		// Sets the flag for the response handler
171
		$this->onResponseHandler->needModifyResponse();
172
173
		// Checking the need to modify the Response and set closure
174
		if ($this->needPhoneResponseModify()) {
175
			$this->deviceView->setPhoneView();
176
177
			return;
178
		}
179
180
		// Checking the need to modify the Response and set closure
181
		if ($this->needTabletResponseModify()) {
182
			$this->deviceView->setTabletView();
183
184
			return;
185
		}
186
187
		// Sets the closure modifier mobile Response
188
		if ($this->needMobileResponseModify()) {
189
			$this->deviceView->setMobileView();
190
191
			return;
192
		}
193
194
		// Sets the closure modifier not_mobile Response
195
		if ($this->needNotMobileResponseModify()) {
196
			$this->deviceView->setNotMobileView();
197
198
			return;
199
		}
200
	}
201
202
	/**
203
	 * Detects phone redirections
204
	 *
205
	 * @return bool
206
	 */
207
	private function hasPhoneRedirect() : bool
208
	{
209
		if (!$this->redirectConf['phone']['isEnabled']) {
210
			return false;
211
		}
212
213
		$isPhone = $this->mobileDetect->isPhone();
214
215
		if ($this->redirectConf['detectPhoneAsMobile'] === false) {
216
			$isPhoneHost = ($this->getCurrentHost() === $this->redirectConf['phone']['host']);
217
218
			if ($isPhone && !$isPhoneHost && ($this->getRoutingOption(self::PHONE) != self::NO_REDIRECT)) {
219
				return true;
220
			}
221
222
		} else {
223
			$isMobileHost = ($this->getCurrentHost() === $this->redirectConf['mobile']['host']);
224
225
			if ($isPhone && !$isMobileHost && ($this->getRoutingOption(self::PHONE) != self::NO_REDIRECT)) {
226
				return true;
227
			}
228
		}
229
230
		return false;
231
	}
232
233
	/**
234
	 * Detects tablet redirections
235
	 *
236
	 * @return bool
237
	 */
238
	private function hasTabletRedirect() : bool
239
	{
240
		if (!$this->redirectConf['tablet']['isEnabled']) {
241
			return false;
242
		}
243
244
		$isTablet = $this->mobileDetect->isTablet();
245
246
		if ($this->redirectConf['detectTabletAsMobile'] === false) {
247
			$isTabletHost = ($this->getCurrentHost() === $this->redirectConf['tablet']['host']);
248
249
			if ($isTablet && !$isTabletHost && ($this->getRoutingOption(self::TABLET) != self::NO_REDIRECT)) {
250
				return true;
251
			}
252
253
		} else {
254
			$isMobileHost = ($this->getCurrentHost() === $this->redirectConf['mobile']['host']);
255
256
			if ($isTablet && !$isMobileHost && ($this->getRoutingOption(self::TABLET) != self::NO_REDIRECT)) {
257
				return true;
258
			}
259
		}
260
261
		return false;
262
	}
263
264
	/**
265
	 * Detects mobile redirections
266
	 *
267
	 * @return bool
268
	 */
269
	private function hasMobileRedirect() : bool
270
	{
271
		if (!$this->redirectConf['mobile']['isEnabled']) {
272
			return false;
273
		}
274
275
		if ($this->redirectConf['detectPhoneAsMobile'] === false) {
276
			$isMobile = ($this->mobileDetect->isTablet() || ($this->mobileDetect->isMobile()) && !$this->mobileDetect->isPhone());
277
278
		} elseif ($this->redirectConf['detectTabletAsMobile'] === false) {
279
			$isMobile = ($this->mobileDetect->isPhone() || ($this->mobileDetect->isMobile()) && !$this->mobileDetect->isTablet());
280
281
		} else {
282
			$isMobile = $this->mobileDetect->isMobile();
283
		}
284
285
		$isMobileHost = ($this->getCurrentHost() === $this->redirectConf['mobile']['host']);
286
287
		if ($isMobile && !$isMobileHost && ($this->getRoutingOption(self::MOBILE) != self::NO_REDIRECT)) {
288
			return true;
289
		}
290
291
		return false;
292
	}
293
294
	/**
295
	 * If a modified Response for phone devices is needed
296
	 *
297
	 * @return bool
298
	 */
299
	private function needPhoneResponseModify() : bool
300
	{
301
		if (($this->deviceView->getViewType() === null || $this->deviceView->isPhoneView()) && $this->mobileDetect->isMobile() && !$this->mobileDetect->isTablet()) {
302
			$this->onResponseHandler->modifyResponseClosure = function (Helpers\DeviceView $deviceView) : Http\IResponse {
303
				return $deviceView->modifyPhoneResponse();
304
			};
305
306
			return true;
307
		}
308
309
		return false;
310
	}
311
312
	/**
313
	 * If a modified Response for tablet devices is needed
314
	 *
315
	 * @return bool
316
	 */
317
	private function needTabletResponseModify() : bool
318
	{
319
		if (($this->deviceView->getViewType() === null || $this->deviceView->isTabletView()) && $this->mobileDetect->isTablet()) {
320
			$this->onResponseHandler->modifyResponseClosure = function (Helpers\DeviceView $deviceView) : Http\IResponse {
321
				return $deviceView->modifyTabletResponse();
322
			};
323
324
			return true;
325
		}
326
327
		return false;
328
	}
329
330
	/**
331
	 * If a modified Response for mobile devices is needed
332
	 *
333
	 * @return bool
334
	 */
335
	private function needMobileResponseModify() : bool
336
	{
337
		if (($this->deviceView->getViewType() === null || $this->deviceView->isMobileView()) && $this->mobileDetect->isMobile()) {
338
			$this->onResponseHandler->modifyResponseClosure = function (Helpers\DeviceView $deviceView) : Http\IResponse {
339
				return $deviceView->modifyMobileResponse();
340
			};
341
342
			return true;
343
		}
344
345
		return false;
346
	}
347
348
	/**
349
	 * If a modified Response for non-mobile devices is needed
350
	 *
351
	 * @return bool
352
	 */
353
	private function needNotMobileResponseModify() : bool
354
	{
355
		if ($this->deviceView->getViewType() === null || $this->deviceView->isNotMobileView()) {
356
			$this->onResponseHandler->modifyResponseClosure = function (Helpers\DeviceView $deviceView) : Http\IResponse {
357
				return $deviceView->modifyNotMobileResponse();
358
			};
359
360
			return true;
361
		}
362
363
		return false;
364
	}
365
366
	/**
367
	 * Gets the RedirectResponse by switch param
368
	 *
369
	 * @return Responses\RedirectResponse
370
	 */
371
	private function getRedirectResponseBySwitchParam() : Responses\RedirectResponse
372
	{
373
		// Generate full url path
374
		if ($this->isFullPath === true) {
375
			// Get actual url
376
			$url = $this->httpRequest->getUrl();
377
378
			// Remove switch param
379
			$url->setQueryParameter($this->deviceView->getSwitchParameterName(), null);
380
381
			// Create full path url
382
			$redirectUrl = $this->getCurrentHost() . $url->getRelativeUrl();
383
384
			// Generate only domain path
385
		} else {
386
			$redirectUrl = $this->getCurrentHost();
387
		}
388
389
		return $this->deviceView->getRedirectResponseBySwitchParam($redirectUrl);
390
	}
391
392
	/**
393
	 * Gets the device RedirectResponse
394
	 *
395
	 * @param string $device
396
	 *
397
	 * @return Responses\RedirectResponse|NULL
398
	 */
399
	private function getDeviceRedirectResponse(string $device) : ?Responses\RedirectResponse
400
	{
401
		if ($host = $this->getRedirectUrl($device)) {
402
			return $this->deviceView->getMobileRedirectResponse(
403
				$host,
404
				$this->redirectConf[$device]['statusCode']
405
			);
406
		}
407
408
		return null;
409
	}
410
411
	/**
412
	 * Gets the redirect url
413
	 *
414
	 * @param string $platform
415
	 *
416
	 * @return string|NULL
417
	 */
418
	private function getRedirectUrl(string $platform) : ?string
419
	{
420
		if ($routingOption = $this->getRoutingOption($platform)) {
421
			switch ($routingOption) {
422
				case self::REDIRECT:
423
					return rtrim($this->redirectConf[$platform]['host'], '/') . '/' . ltrim($this->httpRequest->getUrl()->getRelativeUrl(), '/');
424
425
				case self::REDIRECT_WITHOUT_PATH:
426
					return $this->redirectConf[$platform]['host'];
427
			}
428
		}
429
430
		return null;
431
	}
432
433
	/**
434
	 * Gets named option from current route
435
	 *
436
	 * @param string $name
437
	 *
438
	 * @return string|NULL
439
	 */
440
	private function getRoutingOption(string $name) : ?string
441
	{
442
		$option = null;
443
444
		// Get actual route
445
		$request = $this->router->match($this->httpRequest);
446
447
		if ($request instanceof Application\Request) {
0 ignored issues
show
Bug introduced by
The class Nette\Application\Request does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
448
			$params = $request->getParameters();
449
			$option = isset($params[$name]) ? $params[$name] : null;
450
		}
451
452
		if (!$option) {
453
			$option = $this->redirectConf[$name]['action'];
454
		}
455
456
		if (in_array($option, [self::REDIRECT, self::REDIRECT_WITHOUT_PATH, self::NO_REDIRECT])) {
457
			return $option;
458
		}
459
460
		return null;
461
	}
462
463
	/**
464
	 * Gets the current host
465
	 *
466
	 * @return string
467
	 */
468
	private function getCurrentHost() : string
469
	{
470
		return $this->httpRequest->getUrl()->getHostUrl() . $this->httpRequest->getUrl()->getScriptPath();
471
	}
472
}
473