Skip to content

Commit 54e25b9

Browse files
committed
ACP2E-2737: Duplicate customers being created with same email address using import
1 parent 7e0fc6b commit 54e25b9

File tree

4 files changed

+77
-7
lines changed

4 files changed

+77
-7
lines changed

app/code/Magento/CustomerImportExport/Model/Import/AbstractCustomer.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
namespace Magento\CustomerImportExport\Model\Import;
88

9+
use Magento\Customer\Model\Config\Share;
10+
use Magento\Framework\App\ObjectManager;
911
use Magento\Framework\Validator\EmailAddress;
1012
use Magento\Framework\Validator\ValidateException;
1113
use Magento\Framework\Validator\ValidatorChain;
@@ -87,6 +89,11 @@ abstract class AbstractCustomer extends \Magento\ImportExport\Model\Import\Entit
8789
*/
8890
protected $masterAttributeCode = '_email';
8991

92+
/**
93+
* @var Share
94+
*/
95+
private $configShare;
96+
9097
/**
9198
* @param \Magento\Framework\Stdlib\StringUtils $string
9299
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
@@ -99,6 +106,7 @@ abstract class AbstractCustomer extends \Magento\ImportExport\Model\Import\Entit
99106
* @param \Magento\Eav\Model\Config $eavConfig
100107
* @param \Magento\CustomerImportExport\Model\ResourceModel\Import\Customer\StorageFactory $storageFactory
101108
* @param array $data
109+
* @param Share|null $configShare
102110
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
103111
*/
104112
public function __construct(
@@ -112,7 +120,8 @@ public function __construct(
112120
\Magento\ImportExport\Model\Export\Factory $collectionFactory,
113121
\Magento\Eav\Model\Config $eavConfig,
114122
\Magento\CustomerImportExport\Model\ResourceModel\Import\Customer\StorageFactory $storageFactory,
115-
array $data = []
123+
array $data = [],
124+
?Share $configShare = null
116125
) {
117126
$this->_storageFactory = $storageFactory;
118127
parent::__construct(
@@ -127,7 +136,7 @@ public function __construct(
127136
$eavConfig,
128137
$data
129138
);
130-
139+
$this->configShare = $configShare ?? ObjectManager::getInstance()->get(Share::class);
131140
$this->addMessageTemplate(self::ERROR_WEBSITE_IS_EMPTY, __('Please specify a website.'));
132141
$this->addMessageTemplate(
133142
self::ERROR_EMAIL_IS_EMPTY,
@@ -174,6 +183,11 @@ protected function _initCustomers(array $data)
174183
protected function _getCustomerId($email, $websiteCode)
175184
{
176185
$email = strtolower(trim($email));
186+
187+
if ($this->configShare->isGlobalScope()) {
188+
return $this->_customerStorage->getCustomerIdByEmail($email);
189+
}
190+
177191
if (isset($this->_websiteCodeToId[$websiteCode])) {
178192
$websiteId = $this->_websiteCodeToId[$websiteCode];
179193
return $this->_customerStorage->getCustomerId($email, $websiteId);

app/code/Magento/CustomerImportExport/Model/Import/Address.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace Magento\CustomerImportExport\Model\Import;
88

9+
use Magento\Customer\Model\Config\Share;
910
use Magento\Customer\Model\ResourceModel\Address\Attribute\Source\CountryWithWebsites as CountryWithWebsitesSource;
1011
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
1112
use Magento\Framework\App\ObjectManager;
@@ -252,6 +253,11 @@ class Address extends AbstractCustomer
252253
*/
253254
private $indexerProcessor;
254255

256+
/**
257+
* @var Share
258+
*/
259+
private $configShare;
260+
255261
/**
256262
* @param \Magento\Framework\Stdlib\StringUtils $string
257263
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
@@ -272,7 +278,8 @@ class Address extends AbstractCustomer
272278
* @param array $data
273279
* @param CountryWithWebsitesSource|null $countryWithWebsites
274280
* @param AddressStorage|null $addressStorage
275-
* @param Processor $indexerProcessor
281+
* @param Processor|null $indexerProcessor
282+
* @param Share|null $configShare
276283
*
277284
* @SuppressWarnings(PHPMD.NPathComplexity)
278285
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
@@ -297,7 +304,8 @@ public function __construct(
297304
array $data = [],
298305
?CountryWithWebsitesSource $countryWithWebsites = null,
299306
?AddressStorage $addressStorage = null,
300-
?Processor $indexerProcessor = null
307+
?Processor $indexerProcessor = null,
308+
?Share $configShare = null
301309
) {
302310
$this->_customerFactory = $customerFactory;
303311
$this->_addressFactory = $addressFactory;
@@ -325,7 +333,8 @@ public function __construct(
325333
$collectionFactory,
326334
$eavConfig,
327335
$storageFactory,
328-
$data
336+
$data,
337+
$configShare
329338
);
330339

331340
$this->_entityTable = isset(
@@ -351,6 +360,7 @@ public function __construct(
351360
$this->indexerProcessor = $indexerProcessor
352361
?: ObjectManager::getInstance()->get(Processor::class);
353362

363+
$this->configShare = $configShare ?? ObjectManager::getInstance()->get(Share::class);
354364
$this->_initAttributes();
355365
$this->_initCountryRegions();
356366
}

app/code/Magento/CustomerImportExport/Model/ResourceModel/Import/Customer/Storage.php

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\CustomerImportExport\Model\ResourceModel\Import\Customer;
77

8+
use Magento\Customer\Api\CustomerRepositoryInterface;
89
use Magento\Customer\Model\ResourceModel\Customer\Collection as CustomerCollection;
910
use Magento\Customer\Model\ResourceModel\Customer\CollectionFactory as CustomerCollectionFactory;
1011
use Magento\Framework\DataObject;
@@ -29,6 +30,11 @@ class Storage
2930
*/
3031
protected $_customerIds = [];
3132

33+
/**
34+
* @var array
35+
*/
36+
private $customerIdsByEmail = [];
37+
3238
/**
3339
* Number of items to fetch from db in one query
3440
*
@@ -60,19 +66,27 @@ class Storage
6066
*/
6167
private $customerStoreIds = [];
6268

69+
/**
70+
* @var CustomerRepositoryInterface
71+
*/
72+
private $customerRepository;
73+
6374
/**
6475
* @param CustomerCollectionFactory $collectionFactory
76+
* @param CustomerRepositoryInterface $customerRepository
6577
* @param array $data
6678
*/
6779
public function __construct(
6880
CustomerCollectionFactory $collectionFactory,
81+
CustomerRepositoryInterface $customerRepository,
6982
array $data = []
7083
) {
7184
$this->_customerCollection = isset(
7285
$data['customer_collection']
7386
) ? $data['customer_collection'] : $collectionFactory->create();
7487
$this->_pageSize = isset($data['page_size']) ? (int) $data['page_size'] : 0;
7588
$this->customerCollectionFactory = $collectionFactory;
89+
$this->customerRepository = $customerRepository;
7690
}
7791

7892
/**
@@ -130,7 +144,8 @@ public function addCustomerByArray(array $customer): Storage
130144
/**
131145
* Add customer to array
132146
*
133-
* @deprecated 100.3.0 @see addCustomerByArray
147+
* @deprecated 100.3.0
148+
* @see addCustomerByArray
134149
* @param DataObject $customer
135150
* @return $this
136151
*/
@@ -164,6 +179,25 @@ public function getCustomerId(string $email, int $websiteId)
164179
return false;
165180
}
166181

182+
/**
183+
* Find customer ID by email.
184+
*
185+
* @param string $email
186+
* @return bool|int
187+
*/
188+
public function getCustomerIdByEmail(string $email)
189+
{
190+
if (!isset($this->customerIdsByEmail[$email])) {
191+
try {
192+
$this->customerIdsByEmail[$email] = $this->customerRepository->get($email)->getId();
193+
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
194+
$this->customerIdsByEmail[$email] = false;
195+
}
196+
}
197+
198+
return $this->customerIdsByEmail[$email];
199+
}
200+
167201
/**
168202
* Get previously loaded customer id.
169203
*

app/code/Magento/CustomerImportExport/Test/Unit/Model/Import/AddressTest.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use Magento\Customer\Model\Address\Validator\Postcode;
1111
use Magento\Customer\Model\AddressFactory;
12+
use Magento\Customer\Model\Config\Share;
1213
use Magento\Customer\Model\CustomerFactory;
1314
use Magento\Customer\Model\Indexer\Processor;
1415
use Magento\Customer\Model\ResourceModel\Address\Attribute as AddressAttribute;
@@ -149,6 +150,11 @@ class AddressTest extends TestCase
149150
*/
150151
private $countryWithWebsites;
151152

153+
/**
154+
* @var Share|MockObject
155+
*/
156+
private $configShare;
157+
152158
/**
153159
* Init entity adapter model
154160
*/
@@ -171,6 +177,7 @@ protected function setUp(): void
171177

172178
->method('getAllOptions')
173179
->willReturn([]);
180+
$this->configShare = $this->createMock(Share::class);
174181
$this->_model = $this->_getModelMock();
175182
$this->errorAggregator = $this->createPartialMock(
176183
ProcessingErrorAggregator::class,
@@ -387,7 +394,8 @@ protected function _getModelMock()
387394
$this->_getModelDependencies(),
388395
$this->countryWithWebsites,
389396
$this->createMock(\Magento\CustomerImportExport\Model\ResourceModel\Import\Address\Storage::class),
390-
$this->createMock(Processor::class)
397+
$this->createMock(Processor::class),
398+
$this->configShare
391399
);
392400

393401
$property = new \ReflectionProperty($modelMock, '_availableBehaviors');
@@ -446,6 +454,10 @@ public function testValidateRowForUpdate(array $rowData, array $errors, $isValid
446454
{
447455
$this->_model->setParameters(['behavior' => Import::BEHAVIOR_ADD_UPDATE]);
448456

457+
$this->configShare->expects($this->once())
458+
->method('isGlobalScope')
459+
->willReturn(false);
460+
449461
if ($isValid) {
450462
$this->assertTrue($this->_model->validateRow($rowData, 0));
451463
} else {

0 commit comments

Comments
 (0)