Session.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Persistent\Model;
  7. /**
  8. * Persistent Session Model
  9. *
  10. * @api
  11. * @method int getCustomerId()
  12. * @method Session setCustomerId()
  13. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  14. * @since 100.0.2
  15. */
  16. class Session extends \Magento\Framework\Model\AbstractModel
  17. {
  18. /**
  19. * Persistent cookie key length
  20. */
  21. const KEY_LENGTH = 50;
  22. /**
  23. * Persistent cookie name
  24. */
  25. const COOKIE_NAME = 'persistent_shopping_cart';
  26. /**
  27. * Fields which model does not save into `info` db field
  28. *
  29. * @var string[]
  30. */
  31. protected $_unserializableFields = [
  32. 'persistent_id',
  33. 'key',
  34. 'customer_id',
  35. 'website_id',
  36. 'info',
  37. 'updated_at',
  38. ];
  39. /**
  40. * If model loads expired sessions
  41. *
  42. * @var bool
  43. */
  44. protected $_loadExpired = false;
  45. /**
  46. * Persistent data
  47. *
  48. * @var \Magento\Persistent\Helper\Data
  49. */
  50. protected $_persistentData;
  51. /**
  52. * Json Helper
  53. *
  54. * @var \Magento\Framework\Json\Helper\Data
  55. */
  56. protected $jsonHelper;
  57. /**
  58. * @var \Magento\Framework\App\Config\ScopeConfigInterface
  59. */
  60. protected $_coreConfig;
  61. /**
  62. * Store manager
  63. *
  64. * @var \Magento\Store\Model\StoreManagerInterface
  65. */
  66. protected $_storeManager;
  67. /**
  68. * Cookie manager
  69. *
  70. * @var \Magento\Framework\Stdlib\CookieManagerInterface
  71. */
  72. protected $_cookieManager;
  73. /**
  74. * Cookie metadata factory
  75. *
  76. * @var \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory
  77. */
  78. protected $_cookieMetadataFactory;
  79. /**
  80. * @var \Magento\Framework\Math\Random
  81. */
  82. protected $mathRandom;
  83. /**
  84. * @var \Magento\Framework\Session\Config\ConfigInterface
  85. */
  86. protected $sessionConfig;
  87. /**
  88. * Request
  89. *
  90. * @var \Magento\Framework\App\Request\Http
  91. */
  92. private $request;
  93. /**
  94. * Constructor
  95. *
  96. * @param \Magento\Framework\Model\Context $context
  97. * @param \Magento\Framework\Registry $registry
  98. * @param \Magento\Framework\App\Config\ScopeConfigInterface $coreConfig
  99. * @param \Magento\Framework\Json\Helper\Data $jsonHelper
  100. * @param \Magento\Persistent\Helper\Data $persistentData
  101. * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager
  102. * @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory
  103. * @param \Magento\Store\Model\StoreManagerInterface $storeManager
  104. * @param \Magento\Framework\Math\Random $mathRandom
  105. * @param \Magento\Framework\Session\Config\ConfigInterface $sessionConfig
  106. * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
  107. * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
  108. * @param array $data
  109. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  110. */
  111. public function __construct(
  112. \Magento\Framework\Model\Context $context,
  113. \Magento\Framework\Registry $registry,
  114. \Magento\Framework\App\Config\ScopeConfigInterface $coreConfig,
  115. \Magento\Framework\Json\Helper\Data $jsonHelper,
  116. \Magento\Persistent\Helper\Data $persistentData,
  117. \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager,
  118. \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory,
  119. \Magento\Store\Model\StoreManagerInterface $storeManager,
  120. \Magento\Framework\Math\Random $mathRandom,
  121. \Magento\Framework\Session\Config\ConfigInterface $sessionConfig,
  122. \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
  123. \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
  124. array $data = []
  125. ) {
  126. $this->jsonHelper = $jsonHelper;
  127. $this->_persistentData = $persistentData;
  128. $this->_coreConfig = $coreConfig;
  129. $this->_cookieManager = $cookieManager;
  130. $this->_cookieMetadataFactory = $cookieMetadataFactory;
  131. $this->_storeManager = $storeManager;
  132. $this->sessionConfig = $sessionConfig;
  133. $this->mathRandom = $mathRandom;
  134. parent::__construct($context, $registry, $resource, $resourceCollection, $data);
  135. }
  136. /**
  137. * Define resource model
  138. *
  139. * @return void
  140. * @codeCoverageIgnore
  141. */
  142. protected function _construct()
  143. {
  144. $this->_init(\Magento\Persistent\Model\ResourceModel\Session::class);
  145. }
  146. /**
  147. * Set if load expired persistent session
  148. *
  149. * @param bool $loadExpired
  150. * @return $this
  151. * @codeCoverageIgnore
  152. */
  153. public function setLoadExpired($loadExpired = true)
  154. {
  155. $this->_loadExpired = $loadExpired;
  156. return $this;
  157. }
  158. /**
  159. * Get if model loads expired sessions
  160. *
  161. * @return bool
  162. * @SuppressWarnings(PHPMD.BooleanGetMethodName)
  163. */
  164. public function getLoadExpired()
  165. {
  166. return $this->_loadExpired;
  167. }
  168. /**
  169. * Get date-time before which persistent session is expired
  170. *
  171. * @param int|string|\Magento\Store\Model\Store $store
  172. * @return string
  173. * @codeCoverageIgnore
  174. */
  175. public function getExpiredBefore($store = null)
  176. {
  177. return gmdate('Y-m-d H:i:s', time() - $this->_persistentData->getLifeTime($store));
  178. }
  179. /**
  180. * Serialize info for Resource Model to save
  181. *
  182. * For new model check and set available cookie key
  183. *
  184. * @return $this
  185. */
  186. public function beforeSave()
  187. {
  188. parent::beforeSave();
  189. // Setting info
  190. $info = [];
  191. foreach ($this->getData() as $index => $value) {
  192. if (!in_array($index, $this->_unserializableFields)) {
  193. $info[$index] = $value;
  194. }
  195. }
  196. $this->setInfo($this->jsonHelper->jsonEncode($info));
  197. if ($this->isObjectNew()) {
  198. $this->setWebsiteId($this->_storeManager->getStore()->getWebsiteId());
  199. // Setting cookie key
  200. do {
  201. $this->setKey($this->mathRandom->getRandomString(self::KEY_LENGTH));
  202. } while (!$this->getResource()->isKeyAllowed($this->getKey()));
  203. }
  204. return $this;
  205. }
  206. /**
  207. * Set model data from info field
  208. *
  209. * @return $this
  210. */
  211. protected function _afterLoad()
  212. {
  213. parent::_afterLoad();
  214. $info = null;
  215. if ($this->getInfo()) {
  216. $info = $this->jsonHelper->jsonDecode($this->getInfo());
  217. }
  218. if (is_array($info)) {
  219. foreach ($info as $key => $value) {
  220. $this->setData($key, $value);
  221. }
  222. }
  223. return $this;
  224. }
  225. /**
  226. * Get persistent session by cookie key
  227. *
  228. * @param string $key
  229. * @return $this
  230. */
  231. public function loadByCookieKey($key = null)
  232. {
  233. if (null === $key) {
  234. $key = $this->_cookieManager->getCookie(self::COOKIE_NAME);
  235. }
  236. if ($key) {
  237. $this->load($key, 'key');
  238. }
  239. return $this;
  240. }
  241. /**
  242. * Load session model by specified customer id
  243. *
  244. * @param int $id
  245. * @return $this
  246. * @codeCoverageIgnore
  247. */
  248. public function loadByCustomerId($id)
  249. {
  250. return $this->load($id, 'customer_id');
  251. }
  252. /**
  253. * Delete customer persistent session by customer id
  254. *
  255. * @param int $customerId
  256. * @param bool $clearCookie
  257. * @return $this
  258. */
  259. public function deleteByCustomerId($customerId, $clearCookie = true)
  260. {
  261. if ($clearCookie) {
  262. $this->removePersistentCookie();
  263. }
  264. $this->getResource()->deleteByCustomerId($customerId);
  265. return $this;
  266. }
  267. /**
  268. * Remove persistent cookie
  269. *
  270. * @return $this
  271. * @api
  272. */
  273. public function removePersistentCookie()
  274. {
  275. $cookieMetadata = $this->_cookieMetadataFactory->createSensitiveCookieMetadata()
  276. ->setPath($this->sessionConfig->getCookiePath());
  277. $this->_cookieManager->deleteCookie(self::COOKIE_NAME, $cookieMetadata);
  278. return $this;
  279. }
  280. /**
  281. * Set persistent cookie
  282. *
  283. * @param int $duration Time in seconds.
  284. * @param string $path
  285. * @return $this
  286. * @api
  287. */
  288. public function setPersistentCookie($duration, $path)
  289. {
  290. $value = $this->getKey();
  291. $this->setCookie($value, $duration, $path);
  292. return $this;
  293. }
  294. /**
  295. * Postpone cookie expiration time if cookie value defined
  296. *
  297. * @param int $duration Time in seconds.
  298. * @param string $path
  299. * @return $this
  300. */
  301. public function renewPersistentCookie($duration, $path)
  302. {
  303. if ($duration === null) {
  304. return $this;
  305. }
  306. $value = $this->_cookieManager->getCookie(self::COOKIE_NAME);
  307. if (null !== $value) {
  308. $this->setCookie($value, $duration, $path);
  309. }
  310. return $this;
  311. }
  312. /**
  313. * Delete expired persistent sessions for the website
  314. *
  315. * @param null|int $websiteId
  316. * @return $this
  317. */
  318. public function deleteExpired($websiteId = null)
  319. {
  320. if ($websiteId === null) {
  321. $websiteId = $this->_storeManager->getStore()->getWebsiteId();
  322. }
  323. $lifetime = $this->_coreConfig->getValue(
  324. \Magento\Persistent\Helper\Data::XML_PATH_LIFE_TIME,
  325. 'website',
  326. (int)$websiteId
  327. );
  328. if ($lifetime) {
  329. $this->getResource()->deleteExpired($websiteId, gmdate('Y-m-d H:i:s', time() - $lifetime));
  330. }
  331. return $this;
  332. }
  333. /**
  334. * Delete 'persistent' cookie
  335. *
  336. * @return $this
  337. * @codeCoverageIgnore
  338. */
  339. public function afterDeleteCommit()
  340. {
  341. $this->removePersistentCookie();
  342. return parent::afterDeleteCommit();
  343. }
  344. /**
  345. * Set persistent shopping cart cookie.
  346. *
  347. * @param string $value
  348. * @param int $duration
  349. * @param string $path
  350. * @return void
  351. */
  352. private function setCookie($value, $duration, $path)
  353. {
  354. $publicCookieMetadata = $this->_cookieMetadataFactory->createPublicCookieMetadata()
  355. ->setDuration($duration)
  356. ->setPath($path)
  357. ->setSecure($this->getRequest()->isSecure())
  358. ->setHttpOnly(true);
  359. $this->_cookieManager->setPublicCookie(
  360. self::COOKIE_NAME,
  361. $value,
  362. $publicCookieMetadata
  363. );
  364. }
  365. /**
  366. * Get request object
  367. *
  368. * @return \Magento\Framework\App\Request\Http
  369. * @deprecated 100.1.0
  370. */
  371. private function getRequest()
  372. {
  373. if ($this->request == null) {
  374. $this->request = \Magento\Framework\App\ObjectManager::getInstance()
  375. ->get(\Magento\Framework\App\Request\Http::class);
  376. }
  377. return $this->request;
  378. }
  379. /**
  380. * Set `updated_at` to be always changed
  381. *
  382. * @return $this
  383. * @since 100.1.0
  384. */
  385. public function save()
  386. {
  387. $this->setUpdatedAt(gmdate('Y-m-d H:i:s'));
  388. return parent::save();
  389. }
  390. }