Session.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Customer\Model;
  7. use Magento\Customer\Api\CustomerRepositoryInterface;
  8. use Magento\Customer\Api\Data\CustomerInterface as CustomerData;
  9. use Magento\Customer\Api\GroupManagementInterface;
  10. use Magento\Customer\Model\Config\Share;
  11. use Magento\Customer\Model\ResourceModel\Customer as ResourceCustomer;
  12. /**
  13. * Customer session model
  14. *
  15. * @api
  16. * @method string getNoReferer()
  17. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  18. * @since 100.0.2
  19. */
  20. class Session extends \Magento\Framework\Session\SessionManager
  21. {
  22. /**
  23. * Customer object
  24. *
  25. * @var CustomerData
  26. */
  27. protected $_customer;
  28. /**
  29. * @var ResourceCustomer
  30. */
  31. protected $_customerResource;
  32. /**
  33. * Customer model
  34. *
  35. * @var Customer
  36. */
  37. protected $_customerModel;
  38. /**
  39. * Flag with customer id validations result
  40. *
  41. * @var bool|null
  42. */
  43. protected $_isCustomerIdChecked = null;
  44. /**
  45. * Customer URL
  46. *
  47. * @var \Magento\Customer\Model\Url
  48. */
  49. protected $_customerUrl;
  50. /**
  51. * Core url
  52. *
  53. * @var \Magento\Framework\Url\Helper\Data|null
  54. */
  55. protected $_coreUrl = null;
  56. /**
  57. * @var Share
  58. */
  59. protected $_configShare;
  60. /**
  61. * @var \Magento\Framework\Session\Generic
  62. */
  63. protected $_session;
  64. /**
  65. * @var CustomerRepositoryInterface
  66. */
  67. protected $customerRepository;
  68. /**
  69. * @var CustomerFactory
  70. */
  71. protected $_customerFactory;
  72. /**
  73. * @var \Magento\Framework\UrlFactory
  74. */
  75. protected $_urlFactory;
  76. /**
  77. * @var \Magento\Framework\Event\ManagerInterface
  78. */
  79. protected $_eventManager;
  80. /**
  81. * @var \Magento\Framework\App\Http\Context
  82. */
  83. protected $_httpContext;
  84. /**
  85. * @var GroupManagementInterface
  86. */
  87. protected $groupManagement;
  88. /**
  89. * @var \Magento\Framework\App\Response\Http
  90. */
  91. protected $response;
  92. /**
  93. * @param \Magento\Framework\App\Request\Http $request
  94. * @param \Magento\Framework\Session\SidResolverInterface $sidResolver
  95. * @param \Magento\Framework\Session\Config\ConfigInterface $sessionConfig
  96. * @param \Magento\Framework\Session\SaveHandlerInterface $saveHandler
  97. * @param \Magento\Framework\Session\ValidatorInterface $validator
  98. * @param \Magento\Framework\Session\StorageInterface $storage
  99. * @param \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager
  100. * @param \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory
  101. * @param \Magento\Framework\App\State $appState
  102. * @param Share $configShare
  103. * @param \Magento\Framework\Url\Helper\Data $coreUrl
  104. * @param \Magento\Customer\Model\Url $customerUrl
  105. * @param ResourceCustomer $customerResource
  106. * @param CustomerFactory $customerFactory
  107. * @param \Magento\Framework\UrlFactory $urlFactory
  108. * @param \Magento\Framework\Session\Generic $session
  109. * @param \Magento\Framework\Event\ManagerInterface $eventManager
  110. * @param \Magento\Framework\App\Http\Context $httpContext
  111. * @param CustomerRepositoryInterface $customerRepository
  112. * @param GroupManagementInterface $groupManagement
  113. * @param \Magento\Framework\App\Response\Http $response
  114. * @throws \Magento\Framework\Exception\SessionException
  115. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  116. */
  117. public function __construct(
  118. \Magento\Framework\App\Request\Http $request,
  119. \Magento\Framework\Session\SidResolverInterface $sidResolver,
  120. \Magento\Framework\Session\Config\ConfigInterface $sessionConfig,
  121. \Magento\Framework\Session\SaveHandlerInterface $saveHandler,
  122. \Magento\Framework\Session\ValidatorInterface $validator,
  123. \Magento\Framework\Session\StorageInterface $storage,
  124. \Magento\Framework\Stdlib\CookieManagerInterface $cookieManager,
  125. \Magento\Framework\Stdlib\Cookie\CookieMetadataFactory $cookieMetadataFactory,
  126. \Magento\Framework\App\State $appState,
  127. Config\Share $configShare,
  128. \Magento\Framework\Url\Helper\Data $coreUrl,
  129. \Magento\Customer\Model\Url $customerUrl,
  130. ResourceCustomer $customerResource,
  131. CustomerFactory $customerFactory,
  132. \Magento\Framework\UrlFactory $urlFactory,
  133. \Magento\Framework\Session\Generic $session,
  134. \Magento\Framework\Event\ManagerInterface $eventManager,
  135. \Magento\Framework\App\Http\Context $httpContext,
  136. CustomerRepositoryInterface $customerRepository,
  137. GroupManagementInterface $groupManagement,
  138. \Magento\Framework\App\Response\Http $response
  139. ) {
  140. $this->_coreUrl = $coreUrl;
  141. $this->_customerUrl = $customerUrl;
  142. $this->_configShare = $configShare;
  143. $this->_customerResource = $customerResource;
  144. $this->_customerFactory = $customerFactory;
  145. $this->_urlFactory = $urlFactory;
  146. $this->_session = $session;
  147. $this->customerRepository = $customerRepository;
  148. $this->_eventManager = $eventManager;
  149. $this->_httpContext = $httpContext;
  150. parent::__construct(
  151. $request,
  152. $sidResolver,
  153. $sessionConfig,
  154. $saveHandler,
  155. $validator,
  156. $storage,
  157. $cookieManager,
  158. $cookieMetadataFactory,
  159. $appState
  160. );
  161. $this->groupManagement = $groupManagement;
  162. $this->response = $response;
  163. $this->_eventManager->dispatch('customer_session_init', ['customer_session' => $this]);
  164. }
  165. /**
  166. * Retrieve customer sharing configuration model
  167. *
  168. * @return Share
  169. */
  170. public function getCustomerConfigShare()
  171. {
  172. return $this->_configShare;
  173. }
  174. /**
  175. * Set customer object and setting customer id in session
  176. *
  177. * @param CustomerData $customer
  178. * @return $this
  179. */
  180. public function setCustomerData(CustomerData $customer)
  181. {
  182. $this->_customer = $customer;
  183. if ($customer === null) {
  184. $this->setCustomerId(null);
  185. } else {
  186. $this->_httpContext->setValue(
  187. Context::CONTEXT_GROUP,
  188. $customer->getGroupId(),
  189. \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID
  190. );
  191. $this->setCustomerId($customer->getId());
  192. }
  193. return $this;
  194. }
  195. /**
  196. * Retrieve customer model object
  197. *
  198. * @return CustomerData
  199. */
  200. public function getCustomerData()
  201. {
  202. if (!$this->_customer instanceof CustomerData && $this->getCustomerId()) {
  203. $this->_customer = $this->customerRepository->getById($this->getCustomerId());
  204. }
  205. return $this->_customer;
  206. }
  207. /**
  208. * Returns Customer data object with the customer information
  209. *
  210. * @return CustomerData
  211. */
  212. public function getCustomerDataObject()
  213. {
  214. /* TODO refactor this after all usages of the setCustomer is refactored */
  215. return $this->getCustomer()->getDataModel();
  216. }
  217. /**
  218. * Set Customer data object with the customer information
  219. *
  220. * @param CustomerData $customerData
  221. * @return $this
  222. */
  223. public function setCustomerDataObject(CustomerData $customerData)
  224. {
  225. $this->setId($customerData->getId());
  226. $this->getCustomer()->updateData($customerData);
  227. return $this;
  228. }
  229. /**
  230. * Set customer model and the customer id in session
  231. *
  232. * @param Customer $customerModel
  233. * @return $this
  234. * use setCustomerId() instead
  235. */
  236. public function setCustomer(Customer $customerModel)
  237. {
  238. $this->_customerModel = $customerModel;
  239. $this->_httpContext->setValue(
  240. Context::CONTEXT_GROUP,
  241. $customerModel->getGroupId(),
  242. \Magento\Customer\Model\Group::NOT_LOGGED_IN_ID
  243. );
  244. $this->setCustomerId($customerModel->getId());
  245. if (!$customerModel->isConfirmationRequired() && $customerModel->getConfirmation()) {
  246. $customerModel->setConfirmation(null)->save();
  247. }
  248. /**
  249. * The next line is a workaround.
  250. * It is used to distinguish users that are logged in from user data set via methods similar to setCustomerId()
  251. */
  252. $this->unsIsCustomerEmulated();
  253. return $this;
  254. }
  255. /**
  256. * Retrieve customer model object
  257. *
  258. * @return Customer
  259. * use getCustomerId() instead
  260. */
  261. public function getCustomer()
  262. {
  263. if ($this->_customerModel === null) {
  264. $this->_customerModel = $this->_customerFactory->create()->load($this->getCustomerId());
  265. }
  266. return $this->_customerModel;
  267. }
  268. /**
  269. * Set customer id
  270. *
  271. * @param int|null $id
  272. * @return $this
  273. */
  274. public function setCustomerId($id)
  275. {
  276. $this->storage->setData('customer_id', $id);
  277. return $this;
  278. }
  279. /**
  280. * Retrieve customer id from current session
  281. *
  282. * @api
  283. * @return int|null
  284. */
  285. public function getCustomerId()
  286. {
  287. if ($this->storage->getData('customer_id')) {
  288. return $this->storage->getData('customer_id');
  289. }
  290. return null;
  291. }
  292. /**
  293. * Retrieve customer id from current session
  294. *
  295. * @return int|null
  296. */
  297. public function getId()
  298. {
  299. return $this->getCustomerId();
  300. }
  301. /**
  302. * Set customer id
  303. *
  304. * @param int|null $customerId
  305. * @return $this
  306. */
  307. public function setId($customerId)
  308. {
  309. return $this->setCustomerId($customerId);
  310. }
  311. /**
  312. * Set customer group id
  313. *
  314. * @param int|null $id
  315. * @return $this
  316. */
  317. public function setCustomerGroupId($id)
  318. {
  319. $this->storage->setData('customer_group_id', $id);
  320. return $this;
  321. }
  322. /**
  323. * Get customer group id
  324. * If customer is not logged in system, 'not logged in' group id will be returned
  325. *
  326. * @return int
  327. */
  328. public function getCustomerGroupId()
  329. {
  330. if ($this->storage->getData('customer_group_id')) {
  331. return $this->storage->getData('customer_group_id');
  332. }
  333. if ($this->getCustomerData()) {
  334. $customerGroupId = $this->getCustomerData()->getGroupId();
  335. $this->setCustomerGroupId($customerGroupId);
  336. return $customerGroupId;
  337. }
  338. return Group::NOT_LOGGED_IN_ID;
  339. }
  340. /**
  341. * Checking customer login status
  342. *
  343. * @api
  344. * @return bool
  345. */
  346. public function isLoggedIn()
  347. {
  348. return (bool)$this->getCustomerId()
  349. && $this->checkCustomerId($this->getId())
  350. && !$this->getIsCustomerEmulated();
  351. }
  352. /**
  353. * Check exists customer (light check)
  354. *
  355. * @param int $customerId
  356. * @return bool
  357. */
  358. public function checkCustomerId($customerId)
  359. {
  360. if ($this->_isCustomerIdChecked === $customerId) {
  361. return true;
  362. }
  363. try {
  364. $this->customerRepository->getById($customerId);
  365. $this->_isCustomerIdChecked = $customerId;
  366. return true;
  367. } catch (\Exception $e) {
  368. return false;
  369. }
  370. }
  371. /**
  372. * @param Customer $customer
  373. * @return $this
  374. */
  375. public function setCustomerAsLoggedIn($customer)
  376. {
  377. $this->setCustomer($customer);
  378. $this->_eventManager->dispatch('customer_login', ['customer' => $customer]);
  379. $this->_eventManager->dispatch('customer_data_object_login', ['customer' => $this->getCustomerDataObject()]);
  380. $this->regenerateId();
  381. return $this;
  382. }
  383. /**
  384. * @param CustomerData $customer
  385. * @return $this
  386. */
  387. public function setCustomerDataAsLoggedIn($customer)
  388. {
  389. $this->_httpContext->setValue(Context::CONTEXT_AUTH, true, false);
  390. $this->setCustomerData($customer);
  391. $customerModel = $this->_customerFactory->create()->updateData($customer);
  392. $this->setCustomer($customerModel);
  393. $this->_eventManager->dispatch('customer_login', ['customer' => $customerModel]);
  394. $this->_eventManager->dispatch('customer_data_object_login', ['customer' => $customer]);
  395. return $this;
  396. }
  397. /**
  398. * Authorization customer by identifier
  399. *
  400. * @api
  401. * @param int $customerId
  402. * @return bool
  403. */
  404. public function loginById($customerId)
  405. {
  406. try {
  407. $customer = $this->customerRepository->getById($customerId);
  408. $this->setCustomerDataAsLoggedIn($customer);
  409. return true;
  410. } catch (\Exception $e) {
  411. return false;
  412. }
  413. }
  414. /**
  415. * Logout customer
  416. *
  417. * @api
  418. * @return $this
  419. */
  420. public function logout()
  421. {
  422. if ($this->isLoggedIn()) {
  423. $this->_eventManager->dispatch('customer_logout', ['customer' => $this->getCustomer()]);
  424. $this->_logout();
  425. }
  426. $this->_httpContext->unsValue(Context::CONTEXT_AUTH);
  427. return $this;
  428. }
  429. /**
  430. * Authenticate controller action by login customer
  431. *
  432. * @param bool|null $loginUrl
  433. * @return bool
  434. */
  435. public function authenticate($loginUrl = null)
  436. {
  437. if ($this->isLoggedIn()) {
  438. return true;
  439. }
  440. $this->setBeforeAuthUrl($this->_createUrl()->getUrl('*/*/*', ['_current' => true]));
  441. if (isset($loginUrl)) {
  442. $this->response->setRedirect($loginUrl);
  443. } else {
  444. $arguments = $this->_customerUrl->getLoginUrlParams();
  445. if ($this->_createUrl()->getUseSession()) {
  446. $arguments += [
  447. '_query' => [
  448. $this->sidResolver->getSessionIdQueryParam($this->_session) => $this->_session->getSessionId(),
  449. ]
  450. ];
  451. }
  452. $this->response->setRedirect(
  453. $this->_createUrl()->getUrl(\Magento\Customer\Model\Url::ROUTE_ACCOUNT_LOGIN, $arguments)
  454. );
  455. }
  456. return false;
  457. }
  458. /**
  459. * Set auth url
  460. *
  461. * @param string $key
  462. * @param string $url
  463. * @return $this
  464. */
  465. protected function _setAuthUrl($key, $url)
  466. {
  467. $url = $this->_coreUrl->removeRequestParam($url, $this->sidResolver->getSessionIdQueryParam($this));
  468. // Add correct session ID to URL if needed
  469. $url = $this->_createUrl()->getRebuiltUrl($url);
  470. return $this->storage->setData($key, $url);
  471. }
  472. /**
  473. * Logout without dispatching event
  474. *
  475. * @return $this
  476. */
  477. protected function _logout()
  478. {
  479. $this->_customer = null;
  480. $this->_customerModel = null;
  481. $this->setCustomerId(null);
  482. $this->setCustomerGroupId($this->groupManagement->getNotLoggedInGroup()->getId());
  483. $this->destroy(['clear_storage' => false]);
  484. return $this;
  485. }
  486. /**
  487. * Set Before auth url
  488. *
  489. * @param string $url
  490. * @return $this
  491. */
  492. public function setBeforeAuthUrl($url)
  493. {
  494. return $this->_setAuthUrl('before_auth_url', $url);
  495. }
  496. /**
  497. * Set After auth url
  498. *
  499. * @param string $url
  500. * @return $this
  501. */
  502. public function setAfterAuthUrl($url)
  503. {
  504. return $this->_setAuthUrl('after_auth_url', $url);
  505. }
  506. /**
  507. * Reset core session hosts after resetting session ID
  508. *
  509. * @return $this
  510. */
  511. public function regenerateId()
  512. {
  513. parent::regenerateId();
  514. $this->_cleanHosts();
  515. return $this;
  516. }
  517. /**
  518. * @return \Magento\Framework\UrlInterface
  519. */
  520. protected function _createUrl()
  521. {
  522. return $this->_urlFactory->create();
  523. }
  524. }