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) { |
|
|
|
|
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
|
|
|
|
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 thecomposer.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
orrequire-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 you have not tested against this specific condition, such errors might go unnoticed.