Skip to content

Commit a8033fd

Browse files
authored
Merge branch 'magento-commerce:2.4-develop' into B2B-1875
2 parents 1e4370a + 7fb0c37 commit a8033fd

File tree

34 files changed

+690
-190
lines changed

34 files changed

+690
-190
lines changed

app/code/Magento/Customer/Api/SessionCleanerInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
interface SessionCleanerInterface
1414
{
1515
/**
16-
* Destroy all active customer sessions related to given customer except current session.
16+
* Destroy all active customer sessions related to given customer id, including current session.
1717
*
1818
* @param int $customerId
1919
* @return void

app/code/Magento/Customer/Controller/Account/EditPost.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Copyright © Magento, Inc. All rights reserved.
55
* See COPYING.txt for license details.
66
*/
7+
declare(strict_types=1);
78

89
namespace Magento\Customer\Controller\Account;
910

@@ -226,7 +227,7 @@ public function execute()
226227

227228
try {
228229
// whether a customer enabled change email option
229-
$this->processChangeEmailRequest($currentCustomerDataObject);
230+
$isEmailChanged = $this->processChangeEmailRequest($currentCustomerDataObject);
230231

231232
// whether a customer enabled change password option
232233
$isPasswordChanged = $this->changeCustomerPassword($currentCustomerDataObject->getEmail());
@@ -242,8 +243,8 @@ public function execute()
242243
);
243244
$this->dispatchSuccessEvent($customerCandidateDataObject);
244245
$this->messageManager->addSuccessMessage(__('You saved the account information.'));
245-
// logout from current session if password changed.
246-
if ($isPasswordChanged) {
246+
// logout from current session if password or email changed.
247+
if ($isPasswordChanged || $isEmailChanged) {
247248
$this->session->logout();
248249
$this->session->start();
249250
return $resultRedirect->setPath('customer/account/login');
@@ -364,7 +365,7 @@ protected function changeCustomerPassword($email)
364365
* Process change email request
365366
*
366367
* @param CustomerInterface $currentCustomerDataObject
367-
* @return void
368+
* @return bool
368369
* @throws InvalidEmailOrPasswordException
369370
* @throws UserLockedException
370371
*/
@@ -377,13 +378,15 @@ private function processChangeEmailRequest(CustomerInterface $currentCustomerDat
377378
$currentCustomerDataObject->getId(),
378379
$this->getRequest()->getPost('current_password')
379380
);
380-
$this->sessionCleaner->clearFor($currentCustomerDataObject->getId());
381+
$this->sessionCleaner->clearFor((int) $currentCustomerDataObject->getId());
382+
return true;
381383
} catch (InvalidEmailOrPasswordException $e) {
382384
throw new InvalidEmailOrPasswordException(
383385
__("The password doesn't match this account. Verify the password and try again.")
384386
);
385387
}
386388
}
389+
return false;
387390
}
388391

389392
/**

app/code/Magento/Customer/Model/ResourceModel/Customer.php

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Customer\Model\ResourceModel;
89

910
use Magento\Customer\Model\AccountConfirmation;
1011
use Magento\Customer\Model\Customer\NotificationStorage;
1112
use Magento\Framework\App\ObjectManager;
12-
use Magento\Framework\Validator\Exception as ValidatorException;
1313
use Magento\Framework\Exception\AlreadyExistsException;
14+
use Magento\Framework\Validator\Exception as ValidatorException;
1415

1516
/**
1617
* Customer entity resource model
@@ -403,4 +404,45 @@ public function changeResetPasswordLinkToken(\Magento\Customer\Model\Customer $c
403404
}
404405
return $this;
405406
}
407+
408+
/**
409+
* Gets the session cut off timestamp string for provided customer id.
410+
*
411+
* @param int $customerId
412+
* @return int|null
413+
*/
414+
public function findSessionCutOff(int $customerId): ?int
415+
{
416+
$connection = $this->getConnection();
417+
$select = $connection->select()->from(
418+
['customer_table' => $this->getTable('customer_entity')],
419+
['session_cutoff' => 'customer_table.session_cutoff']
420+
)->where(
421+
'entity_id =?',
422+
$customerId
423+
)->limit(
424+
1
425+
);
426+
$lookup = $connection->fetchRow($select);
427+
if (empty($lookup) || $lookup['session_cutoff'] == null) {
428+
return null;
429+
}
430+
return strtotime($lookup['session_cutoff']);
431+
}
432+
433+
/**
434+
* Update session cutoff column value for customer
435+
*
436+
* @param int $customerId
437+
* @param int $timestamp
438+
* @return void
439+
*/
440+
public function updateSessionCutOff(int $customerId, int $timestamp): void
441+
{
442+
$this->getConnection()->update(
443+
$this->getTable('customer_entity'),
444+
['session_cutoff' => $this->dateTime->formatDate($timestamp)],
445+
$this->getConnection()->quoteInto('entity_id = ?', $customerId)
446+
);
447+
}
406448
}

app/code/Magento/Customer/Model/ResourceModel/Visitor.php

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
67

78
namespace Magento\Customer\Model\ResourceModel;
89

@@ -59,7 +60,6 @@ protected function _prepareDataForSave(\Magento\Framework\Model\AbstractModel $v
5960
{
6061
return [
6162
'customer_id' => $visitor->getCustomerId(),
62-
'session_id' => $visitor->getSessionId(),
6363
'last_visit_at' => $visitor->getLastVisitAt()
6464
];
6565
}
@@ -95,4 +95,45 @@ public function clean(\Magento\Customer\Model\Visitor $object)
9595

9696
return $this;
9797
}
98+
99+
/**
100+
* Gets created at value for the visitor id.
101+
*
102+
* @param int $visitorId
103+
* @return int|null
104+
*/
105+
public function fetchCreatedAt(int $visitorId): ?int
106+
{
107+
$connection = $this->getConnection();
108+
$select = $connection->select()->from(
109+
['visitor_table' => $this->getTable('customer_visitor')],
110+
['created_at' => 'visitor_table.created_at']
111+
)->where(
112+
'visitor_table.visitor_id = ?',
113+
(string) $visitorId
114+
)->limit(
115+
1
116+
);
117+
$lookup = $connection->fetchRow($select);
118+
if (empty($lookup) || $lookup['created_at'] == null) {
119+
return null;
120+
}
121+
return strtotime($lookup['created_at']);
122+
}
123+
124+
/**
125+
* Update visitor session created at column value
126+
*
127+
* @param int $visitorId
128+
* @param int $timestamp
129+
* @return void
130+
*/
131+
public function updateCreatedAt(int $visitorId, int $timestamp): void
132+
{
133+
$this->getConnection()->update(
134+
$this->getTable('customer_visitor'),
135+
['created_at' => $this->dateTime->formatDate($timestamp)],
136+
$this->getConnection()->quoteInto('visitor_id = ?', $visitorId)
137+
);
138+
}
98139
}

app/code/Magento/Customer/Model/Session.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Customer\Model;
79

810
use Magento\Customer\Api\CustomerRepositoryInterface;
@@ -11,6 +13,7 @@
1113
use Magento\Customer\Model\Config\Share;
1214
use Magento\Customer\Model\ResourceModel\Customer as ResourceCustomer;
1315
use Magento\Framework\App\ObjectManager;
16+
use Magento\Framework\Session\Generic;
1417

1518
/**
1619
* Customer session model
@@ -70,7 +73,7 @@ class Session extends \Magento\Framework\Session\SessionManager
7073
protected $_configShare;
7174

7275
/**
73-
* @var \Magento\Framework\Session\Generic
76+
* @var Generic
7477
*/
7578
protected $_session;
7679

@@ -132,7 +135,7 @@ class Session extends \Magento\Framework\Session\SessionManager
132135
* @param ResourceCustomer $customerResource
133136
* @param CustomerFactory $customerFactory
134137
* @param \Magento\Framework\UrlFactory $urlFactory
135-
* @param \Magento\Framework\Session\Generic $session
138+
* @param Generic $session
136139
* @param \Magento\Framework\Event\ManagerInterface $eventManager
137140
* @param \Magento\Framework\App\Http\Context $httpContext
138141
* @param CustomerRepositoryInterface $customerRepository
@@ -158,7 +161,7 @@ public function __construct(
158161
ResourceCustomer $customerResource,
159162
CustomerFactory $customerFactory,
160163
\Magento\Framework\UrlFactory $urlFactory,
161-
\Magento\Framework\Session\Generic $session,
164+
Generic $session,
162165
\Magento\Framework\Event\ManagerInterface $eventManager,
163166
\Magento\Framework\App\Http\Context $httpContext,
164167
CustomerRepositoryInterface $customerRepository,
@@ -176,6 +179,10 @@ public function __construct(
176179
$this->customerRepository = $customerRepository;
177180
$this->_eventManager = $eventManager;
178181
$this->_httpContext = $httpContext;
182+
$this->groupManagement = $groupManagement;
183+
$this->response = $response;
184+
$this->accountConfirmation = $accountConfirmation ?: ObjectManager::getInstance()
185+
->get(AccountConfirmation::class);
179186
parent::__construct(
180187
$request,
181188
$sidResolver,
@@ -187,10 +194,6 @@ public function __construct(
187194
$cookieMetadataFactory,
188195
$appState
189196
);
190-
$this->groupManagement = $groupManagement;
191-
$this->response = $response;
192-
$this->accountConfirmation = $accountConfirmation ?: ObjectManager::getInstance()
193-
->get(AccountConfirmation::class);
194197
$this->_eventManager->dispatch('customer_session_init', ['customer_session' => $this]);
195198
}
196199

@@ -510,6 +513,7 @@ public function logout()
510513
*
511514
* @param bool|null $loginUrl
512515
* @return bool
516+
* @throws \Magento\Framework\Exception\SessionException
513517
*/
514518
public function authenticate($loginUrl = null)
515519
{

app/code/Magento/Customer/Model/Session/SessionCleaner.php

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
namespace Magento\Customer\Model\Session;
99

1010
use Magento\Customer\Api\SessionCleanerInterface;
11+
use Magento\Customer\Model\ResourceModel\Customer as CustomerResourceModel;
12+
use Magento\Customer\Model\ResourceModel\Visitor as VisitorResourceModel;
1113
use Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory as VisitorCollectionFactory;
1214
use Magento\Framework\App\Config\ScopeConfigInterface;
15+
use Magento\Framework\App\ObjectManager;
1316
use Magento\Framework\Intl\DateTimeFactory;
14-
use Magento\Framework\Session\Config;
1517
use Magento\Framework\Session\SaveHandlerInterface;
1618
use Magento\Framework\Session\SessionManagerInterface;
17-
use Magento\Framework\Stdlib\DateTime;
18-
use Magento\Store\Model\ScopeInterface;
1919

2020
/**
2121
* Deletes all session data which relates to customer, including current session data.
@@ -50,46 +50,57 @@ class SessionCleaner implements SessionCleanerInterface
5050
private $saveHandler;
5151

5252
/**
53-
* @inheritdoc
53+
* @var CustomerResourceModel
54+
*/
55+
private $customerResourceModel;
56+
57+
/**
58+
* @var VisitorResourceModel
59+
*/
60+
private $visitorResourceModel;
61+
62+
/**
63+
* @param ScopeConfigInterface $scopeConfig
64+
* @param DateTimeFactory $dateTimeFactory
65+
* @param VisitorCollectionFactory $visitorCollectionFactory
66+
* @param SessionManagerInterface $sessionManager
67+
* @param SaveHandlerInterface $saveHandler
68+
* @param CustomerResourceModel|null $customerResourceModel
69+
* @param VisitorResourceModel|null $visitorResourceModel
5470
*/
5571
public function __construct(
5672
ScopeConfigInterface $scopeConfig,
5773
DateTimeFactory $dateTimeFactory,
5874
VisitorCollectionFactory $visitorCollectionFactory,
5975
SessionManagerInterface $sessionManager,
60-
SaveHandlerInterface $saveHandler
76+
SaveHandlerInterface $saveHandler,
77+
CustomerResourceModel $customerResourceModel = null,
78+
VisitorResourceModel $visitorResourceModel = null
6179
) {
6280
$this->scopeConfig = $scopeConfig;
6381
$this->dateTimeFactory = $dateTimeFactory;
6482
$this->visitorCollectionFactory = $visitorCollectionFactory;
6583
$this->sessionManager = $sessionManager;
6684
$this->saveHandler = $saveHandler;
85+
$this->customerResourceModel = $customerResourceModel
86+
?: ObjectManager::getInstance()->get(CustomerResourceModel::class);
87+
88+
$this->visitorResourceModel = $visitorResourceModel
89+
?: ObjectManager::getInstance()->get(VisitorResourceModel::class);
6790
}
6891

6992
/**
7093
* @inheritdoc
7194
*/
7295
public function clearFor(int $customerId): void
7396
{
74-
$sessionLifetime = $this->scopeConfig->getValue(
75-
Config::XML_PATH_COOKIE_LIFETIME,
76-
ScopeInterface::SCOPE_STORE
77-
);
7897
$dateTime = $this->dateTimeFactory->create();
79-
$activeSessionsTime = $dateTime->setTimestamp($dateTime->getTimestamp() - $sessionLifetime)
80-
->format(DateTime::DATETIME_PHP_FORMAT);
81-
/** @var \Magento\Customer\Model\ResourceModel\Visitor\Collection $visitorCollection */
82-
$visitorCollection = $this->visitorCollectionFactory->create();
83-
$visitorCollection->addFieldToFilter('customer_id', $customerId);
84-
$visitorCollection->addFieldToFilter('last_visit_at', ['from' => $activeSessionsTime]);
85-
$visitorCollection->addFieldToFilter('session_id', ['neq' => $this->sessionManager->getSessionId()]);
86-
87-
/** @var \Magento\Customer\Model\Visitor $visitor */
88-
foreach ($visitorCollection->getItems() as $visitor) {
89-
$sessionId = $visitor->getSessionId();
90-
$this->sessionManager->start();
91-
$this->saveHandler->destroy($sessionId);
92-
$this->sessionManager->writeClose();
98+
$timestamp = $dateTime->getTimestamp();
99+
$this->customerResourceModel->updateSessionCutOff($customerId, $timestamp);
100+
if ($this->sessionManager->getVisitorData() !== null) {
101+
$visitorId = $this->sessionManager->getVisitorData()['visitor_id'];
102+
$this->visitorResourceModel->updateCreatedAt((int) $visitorId, $timestamp + 1);
93103
}
94104
}
95105
}
106+

0 commit comments

Comments
 (0)