vendor/tattali/mobile-detect-bundle/src/Helper/DeviceView.php line 106

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the MobileDetectBundle.
  4. *
  5. * (c) Nikolay Ivlev <nikolay.kotovsky@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. declare(strict_types=1);
  11. namespace MobileDetectBundle\Helper;
  12. use Symfony\Component\HttpFoundation\Cookie;
  13. use Symfony\Component\HttpFoundation\Request;
  14. use Symfony\Component\HttpFoundation\RequestStack;
  15. use Symfony\Component\HttpFoundation\Response;
  16. /**
  17. * @author suncat2000 <nikolay.kotovsky@gmail.com>
  18. */
  19. class DeviceView
  20. {
  21. public const VIEW_MOBILE = 'mobile';
  22. public const VIEW_TABLET = 'tablet';
  23. public const VIEW_FULL = 'full';
  24. public const VIEW_NOT_MOBILE = 'not_mobile';
  25. public const COOKIE_KEY_DEFAULT = 'device_view';
  26. public const COOKIE_PATH_DEFAULT = '/';
  27. public const COOKIE_DOMAIN_DEFAULT = '';
  28. public const COOKIE_SECURE_DEFAULT = false;
  29. public const COOKIE_HTTP_ONLY_DEFAULT = true;
  30. public const COOKIE_RAW_DEFAULT = false;
  31. public const COOKIE_SAMESITE_DEFAULT = Cookie::SAMESITE_LAX;
  32. public const COOKIE_EXPIRE_DATETIME_MODIFIER_DEFAULT = '1 month';
  33. public const SWITCH_PARAM_DEFAULT = 'device_view';
  34. /**
  35. * @var Request
  36. */
  37. protected $request;
  38. /**
  39. * @var string
  40. */
  41. protected $requestedViewType;
  42. /**
  43. * @var string
  44. */
  45. protected $viewType;
  46. /**
  47. * @var string
  48. */
  49. protected $cookieKey = self::COOKIE_KEY_DEFAULT;
  50. /**
  51. * @var string
  52. */
  53. protected $cookiePath = self::COOKIE_PATH_DEFAULT;
  54. /**
  55. * @var string
  56. */
  57. protected $cookieDomain = self::COOKIE_DOMAIN_DEFAULT;
  58. /**
  59. * @var bool
  60. */
  61. protected $cookieSecure = self::COOKIE_SECURE_DEFAULT;
  62. /**
  63. * @var bool
  64. */
  65. protected $cookieHttpOnly = self::COOKIE_HTTP_ONLY_DEFAULT;
  66. /**
  67. * @var bool
  68. */
  69. protected $cookieRaw = self::COOKIE_RAW_DEFAULT;
  70. /**
  71. * @var string|null
  72. */
  73. protected $cookieSameSite = self::COOKIE_SAMESITE_DEFAULT;
  74. /**
  75. * @var string
  76. */
  77. protected $cookieExpireDatetimeModifier = self::COOKIE_EXPIRE_DATETIME_MODIFIER_DEFAULT;
  78. /**
  79. * @var string
  80. */
  81. protected $switchParam = self::SWITCH_PARAM_DEFAULT;
  82. /**
  83. * @var array
  84. */
  85. protected $redirectConfig = [];
  86. public function __construct(RequestStack $requestStack = null)
  87. {
  88. $methodName = method_exists(RequestStack::class, 'getMainRequest') ? 'getMainRequest' : 'getMasterRequest';
  89. if (!$requestStack || !$this->request = $requestStack->{$methodName}()) {
  90. $this->viewType = self::VIEW_NOT_MOBILE;
  91. return;
  92. }
  93. if ($this->request->query->has($this->switchParam)) {
  94. $this->viewType = $this->request->query->get($this->switchParam);
  95. } elseif ($this->request->cookies->has($this->cookieKey)) {
  96. $this->viewType = $this->request->cookies->get($this->cookieKey);
  97. }
  98. $this->requestedViewType = $this->viewType;
  99. }
  100. /**
  101. * Gets the view type for a device.
  102. */
  103. public function getViewType(): ?string
  104. {
  105. return $this->viewType;
  106. }
  107. /**
  108. * Gets the view type that has explicitly been requested either by switch param, or by cookie.
  109. *
  110. * @return string the requested view type or null if no view type has been explicitly requested
  111. */
  112. public function getRequestedViewType(): ?string
  113. {
  114. return $this->requestedViewType;
  115. }
  116. /**
  117. * Is the device in full view.
  118. */
  119. public function isFullView(): bool
  120. {
  121. return self::VIEW_FULL === $this->viewType;
  122. }
  123. public function isTabletView(): bool
  124. {
  125. return self::VIEW_TABLET === $this->viewType;
  126. }
  127. public function isMobileView(): bool
  128. {
  129. return self::VIEW_MOBILE === $this->viewType;
  130. }
  131. /**
  132. * Is not the device a mobile view type (PC, Mac, etc.).
  133. */
  134. public function isNotMobileView(): bool
  135. {
  136. return self::VIEW_NOT_MOBILE === $this->viewType;
  137. }
  138. /**
  139. * Has the Request the switch param in the query string (GET header).
  140. */
  141. public function hasSwitchParam(): bool
  142. {
  143. return $this->request && $this->request->query->has($this->switchParam);
  144. }
  145. public function setView(string $view): void
  146. {
  147. $this->viewType = $view;
  148. }
  149. /**
  150. * Sets the full (desktop) view type.
  151. */
  152. public function setFullView(): void
  153. {
  154. $this->viewType = self::VIEW_FULL;
  155. }
  156. public function setTabletView(): void
  157. {
  158. $this->viewType = self::VIEW_TABLET;
  159. }
  160. public function setMobileView(): void
  161. {
  162. $this->viewType = self::VIEW_MOBILE;
  163. }
  164. public function setNotMobileView(): void
  165. {
  166. $this->viewType = self::VIEW_NOT_MOBILE;
  167. }
  168. public function getRedirectConfig(): array
  169. {
  170. return $this->redirectConfig;
  171. }
  172. public function setRedirectConfig(array $redirectConfig): void
  173. {
  174. $this->redirectConfig = $redirectConfig;
  175. }
  176. public function getRedirectResponseBySwitchParam(string $redirectUrl): RedirectResponseWithCookie
  177. {
  178. switch ($this->getSwitchParamValue()) {
  179. case self::VIEW_MOBILE:
  180. $viewType = self::VIEW_MOBILE;
  181. break;
  182. case self::VIEW_TABLET:
  183. $viewType = self::VIEW_TABLET;
  184. if (isset($this->getRedirectConfig()['detect_tablet_as_mobile']) && true === $this->getRedirectConfig()['detect_tablet_as_mobile']) {
  185. $viewType = self::VIEW_MOBILE;
  186. }
  187. break;
  188. default:
  189. $viewType = self::VIEW_FULL;
  190. }
  191. return new RedirectResponseWithCookie(
  192. $redirectUrl,
  193. $this->getStatusCode($viewType),
  194. $this->createCookie($viewType)
  195. );
  196. }
  197. /**
  198. * Gets the switch param value from the query string (GET header).
  199. */
  200. public function getSwitchParamValue(): ?string
  201. {
  202. if (!$this->request) {
  203. return null;
  204. }
  205. return $this->request->query->get($this->switchParam, self::VIEW_FULL);
  206. }
  207. public function getCookieExpireDatetimeModifier(): string
  208. {
  209. return $this->cookieExpireDatetimeModifier;
  210. }
  211. public function setCookieExpireDatetimeModifier(string $cookieExpireDatetimeModifier): void
  212. {
  213. $this->cookieExpireDatetimeModifier = $cookieExpireDatetimeModifier;
  214. }
  215. public function getCookieKey(): string
  216. {
  217. return $this->cookieKey;
  218. }
  219. public function setCookieKey(string $cookieKey): void
  220. {
  221. $this->cookieKey = $cookieKey;
  222. }
  223. public function getCookiePath(): string
  224. {
  225. return $this->cookiePath;
  226. }
  227. public function setCookiePath(string $cookiePath): void
  228. {
  229. $this->cookiePath = $cookiePath;
  230. }
  231. public function getCookieDomain(): string
  232. {
  233. return $this->cookieDomain;
  234. }
  235. public function setCookieDomain(string $cookieDomain): void
  236. {
  237. $this->cookieDomain = $cookieDomain;
  238. }
  239. public function isCookieSecure(): bool
  240. {
  241. return $this->cookieSecure;
  242. }
  243. public function setCookieSecure(bool $cookieSecure): void
  244. {
  245. $this->cookieSecure = $cookieSecure;
  246. }
  247. public function isCookieHttpOnly(): bool
  248. {
  249. return $this->cookieHttpOnly;
  250. }
  251. public function setCookieHttpOnly(bool $cookieHttpOnly): void
  252. {
  253. $this->cookieHttpOnly = $cookieHttpOnly;
  254. }
  255. public function isCookieRaw(): bool
  256. {
  257. return $this->cookieRaw;
  258. }
  259. public function setCookieRaw(bool $cookieRaw = false): void
  260. {
  261. $this->cookieRaw = $cookieRaw;
  262. }
  263. public function getCookieSameSite(): ?string
  264. {
  265. return $this->cookieSameSite;
  266. }
  267. public function setCookieSameSite(?string $cookieSameSite = Cookie::SAMESITE_LAX): void
  268. {
  269. $this->cookieSameSite = $cookieSameSite;
  270. }
  271. /**
  272. * Modifies the Response for the specified device view.
  273. *
  274. * @param string $view the device view for which the response should be modified
  275. */
  276. public function modifyResponse(string $view, Response $response): Response
  277. {
  278. $response->headers->setCookie($this->createCookie($view));
  279. return $response;
  280. }
  281. /**
  282. * Gets the RedirectResponse for the specified device view.
  283. *
  284. * @param string $view The device view for which we want the RedirectResponse
  285. * @param string $host Uri host
  286. * @param int $statusCode Status code
  287. */
  288. public function getRedirectResponse(string $view, string $host, int $statusCode): RedirectResponseWithCookie
  289. {
  290. return new RedirectResponseWithCookie($host, $statusCode, $this->createCookie($view));
  291. }
  292. public function getSwitchParam(): string
  293. {
  294. return $this->switchParam;
  295. }
  296. public function setSwitchParam(string $switchParam): void
  297. {
  298. $this->switchParam = $switchParam;
  299. }
  300. protected function getStatusCode(string $view): int
  301. {
  302. if (isset($this->getRedirectConfig()[$view]['status_code'])) {
  303. return $this->getRedirectConfig()[$view]['status_code'];
  304. }
  305. return Response::HTTP_FOUND;
  306. }
  307. /**
  308. * Create the Cookie object.
  309. */
  310. protected function createCookie(string $value): Cookie
  311. {
  312. try {
  313. $expire = new \DateTime($this->getCookieExpireDatetimeModifier());
  314. } catch (\Exception $e) {
  315. $expire = new \DateTime(self::COOKIE_EXPIRE_DATETIME_MODIFIER_DEFAULT);
  316. }
  317. return Cookie::create(
  318. $this->getCookieKey(),
  319. $value,
  320. $expire,
  321. $this->getCookiePath(),
  322. $this->getCookieDomain(),
  323. $this->isCookieSecure(),
  324. $this->isCookieHttpOnly(),
  325. $this->isCookieRaw(),
  326. $this->getCookieSameSite()
  327. );
  328. }
  329. }