Skip to content

Commit 25cf0c3

Browse files
author
Michail Slabko
committed
MAGETWO-46826: Multistore: Import product with Replace behaviour causes an error "URL key for specified store already exists."
1 parent e367c18 commit 25cf0c3

File tree

2 files changed

+1
-250
lines changed

2 files changed

+1
-250
lines changed

app/code/Magento/CatalogUrlRewrite/Observer/AfterImportDataObserver.php

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,6 @@ class AfterImportDataObserver implements ObserverInterface
6666
/** @var \Magento\Catalog\Model\ProductFactory $catalogProductFactory */
6767
protected $catalogProductFactory;
6868

69-
/** @var int */
70-
protected $urlKeyAttribute;
71-
7269
/** @var array */
7370
protected $acceptableCategories;
7471

@@ -78,9 +75,6 @@ class AfterImportDataObserver implements ObserverInterface
7875
/** @var array */
7976
protected $websitesToStoreIds;
8077

81-
/** @var array */
82-
protected $entityStoresToCheckOverridden = [];
83-
8478
/** @var array */
8579
protected $storesCache = [];
8680

@@ -100,10 +94,8 @@ class AfterImportDataObserver implements ObserverInterface
10094

10195
/**
10296
* @param \Magento\Catalog\Model\ProductFactory $catalogProductFactory
103-
* @param \Magento\Eav\Model\Config $eavConfig
10497
* @param \Magento\CatalogUrlRewrite\Model\ObjectRegistryFactory $objectRegistryFactory
10598
* @param \Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator $productUrlPathGenerator
106-
* @param \Magento\Framework\App\ResourceConnection $resource
10799
* @param \Magento\CatalogUrlRewrite\Service\V1\StoreViewService $storeViewService
108100
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
109101
* @param UrlPersistInterface $urlPersist
@@ -114,10 +106,8 @@ class AfterImportDataObserver implements ObserverInterface
114106
*/
115107
public function __construct(
116108
\Magento\Catalog\Model\ProductFactory $catalogProductFactory,
117-
\Magento\Eav\Model\Config $eavConfig,
118109
\Magento\CatalogUrlRewrite\Model\ObjectRegistryFactory $objectRegistryFactory,
119110
\Magento\CatalogUrlRewrite\Model\ProductUrlPathGenerator $productUrlPathGenerator,
120-
\Magento\Framework\App\ResourceConnection $resource,
121111
\Magento\CatalogUrlRewrite\Service\V1\StoreViewService $storeViewService,
122112
\Magento\Store\Model\StoreManagerInterface $storeManager,
123113
UrlPersistInterface $urlPersist,
@@ -131,16 +121,6 @@ public function __construct(
131121
$this->storeViewService = $storeViewService;
132122
$this->storeManager = $storeManager;
133123
$this->urlRewriteFactory = $urlRewriteFactory;
134-
$attribute = $eavConfig->getAttribute(Product::ENTITY, self::URL_KEY_ATTRIBUTE_CODE);
135-
if (!$attribute) {
136-
throw new \InvalidArgumentException(sprintf(
137-
'Cannot retrieve attribute for entity type "%s"',
138-
Product::ENTITY
139-
));
140-
}
141-
$this->connection = $resource->getConnection();
142-
$this->urlKeyAttributeId = $attribute->getId();
143-
$this->urlKeyAttributeBackendTable = $attribute->getBackendTable();
144124
$this->urlFinder = $urlFinder;
145125
}
146126

@@ -177,7 +157,7 @@ public function execute(Observer $observer)
177157
protected function _populateForUrlGeneration($rowData)
178158
{
179159
$newSku = $this->import->getNewSku($rowData[ImportProduct::COL_SKU]);
180-
if (empty($newSku) || !isset($newSku['entity_id'])) {
160+
if (empty($newSku) || !isset($newSku['entity_id']) || empty($rowData[self::URL_KEY_ATTRIBUTE_CODE])) {
181161
return null;
182162
}
183163
$rowData['entity_id'] = $newSku['entity_id'];
@@ -254,8 +234,6 @@ protected function populateGlobalProduct($product)
254234
$this->storesCache[$storeId] = true;
255235
if (!$this->isGlobalScope($storeId)) {
256236
$this->addProductToImport($product, $storeId);
257-
$this->entityStoresToCheckOverridden[] = $this->connection->quoteInto('(store_id = ?', $storeId)
258-
. $this->connection->quoteInto(' AND entity_id = ?)', $product->getId());
259237
}
260238
}
261239
}
@@ -269,8 +247,6 @@ protected function populateGlobalProduct($product)
269247
*/
270248
protected function generateUrls()
271249
{
272-
$this->cleanOverriddenUrlKey();
273-
274250
/**
275251
* @var $urls \Magento\UrlRewrite\Service\V1\Data\UrlRewrite[]
276252
*/
@@ -291,25 +267,6 @@ protected function generateUrls()
291267
return $result;
292268
}
293269

294-
/**
295-
* @return $this
296-
*/
297-
protected function cleanOverriddenUrlKey()
298-
{
299-
if (empty($this->entityStoresToCheckOverridden)) {
300-
return $this;
301-
}
302-
$select = $this->connection->select()
303-
->from($this->urlKeyAttributeBackendTable, ['store_id', 'entity_id'])
304-
->where('attribute_id = ?', $this->urlKeyAttributeId)
305-
->where(implode(' OR ', $this->entityStoresToCheckOverridden));
306-
$entityStoresToClean = $this->connection->fetchAll($select);
307-
foreach ($entityStoresToClean as $entityStore) {
308-
unset($this->products[$entityStore['entity_id']][$entityStore['store_id']]);
309-
}
310-
return $this;
311-
}
312-
313270
/**
314271
* Check is global scope
315272
*

app/code/Magento/CatalogUrlRewrite/Test/Unit/Observer/AfterImportDataObserverTest.php

Lines changed: 0 additions & 206 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,6 @@ class AfterImportDataObserverTest extends \PHPUnit_Framework_TestCase
7070
*/
7171
protected $storeManager;
7272

73-
/**
74-
* @var \Magento\Framework\DB\Adapter\AdapterInterface|\PHPUnit_Framework_MockObject_MockObject
75-
*/
76-
protected $connection;
77-
7873
/**
7974
* @var \Magento\CatalogUrlRewrite\Model\ObjectRegistryFactory|\PHPUnit_Framework_MockObject_MockObject
8075
*/
@@ -90,21 +85,6 @@ class AfterImportDataObserverTest extends \PHPUnit_Framework_TestCase
9085
*/
9186
protected $storeViewService;
9287

93-
/**
94-
* @var \Magento\Eav\Model\Config|\PHPUnit_Framework_MockObject_MockObject
95-
*/
96-
protected $eavConfig;
97-
98-
/**
99-
* @var \Magento\Framework\App\ResourceConnection|\PHPUnit_Framework_MockObject_MockObject
100-
*/
101-
protected $resource;
102-
103-
/**
104-
* @var \Magento\Framework\DB\Select|\PHPUnit_Framework_MockObject_MockObject
105-
*/
106-
protected $select;
107-
10888
/**
10989
* @var \Magento\UrlRewrite\Service\V1\Data\UrlRewriteFactory|\PHPUnit_Framework_MockObject_MockObject
11090
*/
@@ -214,66 +194,6 @@ public function setUp()
214194
->disableOriginalConstructor()
215195
->getMock();
216196

217-
$this->eavConfig = $this->getMock(
218-
'\Magento\Eav\Model\Config',
219-
[
220-
'getAttribute',
221-
],
222-
[],
223-
'',
224-
false
225-
);
226-
$attribute = $this->getMockBuilder('\Magento\Eav\Model\Entity\Attribute\AbstractAttribute')
227-
->setMethods([
228-
'getBackendTable',
229-
])
230-
->disableOriginalConstructor()
231-
->getMockForAbstractClass();
232-
$beTable = 'backend table';
233-
$attribute->expects($this->any())
234-
->method('getBackendTable')
235-
->willReturn($beTable);
236-
$this->eavConfig->expects($this->any())
237-
->method('getAttribute')
238-
->with(
239-
\Magento\Catalog\Model\Product::ENTITY,
240-
\Magento\CatalogUrlRewrite\Observer\AfterImportDataObserver::URL_KEY_ATTRIBUTE_CODE
241-
)
242-
->willReturn($attribute);
243-
244-
$this->resource = $this->getMock(
245-
'\Magento\Framework\App\ResourceConnection',
246-
[],
247-
[],
248-
'',
249-
false
250-
);
251-
$this->connection = $this->getMockBuilder('\Magento\Framework\DB\Adapter\AdapterInterface')
252-
->disableOriginalConstructor()
253-
->setMethods([
254-
'quoteInto',
255-
'select',
256-
'fetchAll',
257-
])
258-
->getMockForAbstractClass();
259-
$this->resource
260-
->expects($this->any())
261-
->method('getConnection')
262-
->willReturn($this->connection);
263-
$this->select = $this->getMock(
264-
'\Magento\Framework\DB\Select',
265-
[
266-
'from',
267-
'where',
268-
],
269-
[],
270-
'',
271-
false
272-
);
273-
$this->connection
274-
->expects($this->any())
275-
->method('select')
276-
->willReturn($this->select);
277197
$this->objectRegistryFactory = $this->getMock(
278198
'\Magento\CatalogUrlRewrite\Model\ObjectRegistryFactory',
279199
[],
@@ -364,10 +284,8 @@ public function setUp()
364284
'\Magento\CatalogUrlRewrite\Observer\AfterImportDataObserver',
365285
[
366286
'catalogProductFactory' => $this->catalogProductFactory,
367-
'eavConfig' => $this->eavConfig,
368287
'objectRegistryFactory' => $this->objectRegistryFactory,
369288
'productUrlPathGenerator' => $this->productUrlPathGenerator,
370-
'resource' => $this->resource,
371289
'storeViewService' => $this->storeViewService,
372290
'storeManager'=> $this->storeManager,
373291
'urlPersist' => $this->urlPersist,
@@ -471,7 +389,6 @@ public function testAfterImportData()
471389
$newSku[0]['entity_id'],
472390
$newSku[0]['entity_id'],
473391
$newSku[0]['entity_id'],
474-
$newSku[0]['entity_id'],
475392
$newSku[1]['entity_id'],
476393
$newSku[1]['entity_id'],
477394
$newSku[1]['entity_id']
@@ -501,33 +418,6 @@ public function testAfterImportData()
501418
->expects($this->exactly($productsCount))
502419
->method('create')
503420
->willReturn($product);
504-
$this->connection
505-
->expects($this->exactly(4))
506-
->method('quoteInto')
507-
->withConsecutive(
508-
[
509-
'(store_id = ?',
510-
$storeIds[0],
511-
],
512-
[
513-
' AND entity_id = ?)',
514-
$newSku[0]['entity_id'],
515-
],
516-
[
517-
'(store_id = ?',
518-
$storeIds[0],
519-
],
520-
[
521-
' AND entity_id = ?)',
522-
$newSku[1]['entity_id'],
523-
]
524-
);
525-
$this->connection
526-
->expects($this->once())
527-
->method('fetchAll')
528-
->willReturn([]);
529-
$this->select->expects($this->any())->method('from')->willReturnSelf();
530-
$this->select->expects($this->any())->method('where')->willReturnSelf();
531421

532422
$this->urlFinder->expects($this->any())->method('findAllByData')->willReturn([]);
533423

@@ -562,78 +452,6 @@ public function testAfterImportData()
562452
$this->import->execute($this->observer);
563453
}
564454

565-
/**
566-
* Cover cleanOverriddenUrlKey().
567-
*/
568-
public function testCleanOverriddenUrlKey()
569-
{
570-
$urlKeyAttributeBackendTable = 'table value';
571-
$urlKeyAttributeId = 'id value';
572-
$entityStoresToCheckOverridden = [1,2,3];
573-
$this->import->urlKeyAttributeBackendTable = $urlKeyAttributeBackendTable;
574-
$this->import->urlKeyAttributeId = $urlKeyAttributeId;
575-
$this->setPropertyValue($this->import, 'entityStoresToCheckOverridden', $entityStoresToCheckOverridden);
576-
$this->select
577-
->expects($this->once())
578-
->method('from')
579-
->with(
580-
$urlKeyAttributeBackendTable,
581-
['store_id', 'entity_id']
582-
)
583-
->will($this->returnSelf());
584-
$this->select
585-
->expects($this->exactly(2))
586-
->method('where')
587-
->withConsecutive(
588-
[
589-
'attribute_id = ?',
590-
$urlKeyAttributeId,
591-
],
592-
[
593-
implode(' OR ', $entityStoresToCheckOverridden)
594-
]
595-
)
596-
->will($this->returnSelf());
597-
598-
$entityIdVal = 'entity id value';
599-
$storeIdVal = 'store id value';
600-
$entityStore = [
601-
'entity_id' => $entityIdVal,
602-
'store_id' => $storeIdVal,
603-
];
604-
$entityStoresToClean = [$entityStore];
605-
$products = [
606-
$entityIdVal => [
607-
$storeIdVal => 'value',
608-
]
609-
];
610-
$this->setPropertyValue($this->import, 'products', $products);
611-
$this->connection
612-
->expects($this->once())
613-
->method('fetchAll')
614-
->willReturn($entityStoresToClean);
615-
616-
$actualResult = $this->invokeMethod($this->import, 'cleanOverriddenUrlKey');
617-
$this->assertEquals($this->import, $actualResult);
618-
}
619-
620-
/**
621-
* Cover cleanOverriddenUrlKey() method with empty entityStoresToCheckOverridden property.
622-
*/
623-
public function testCleanOverriddenUrlKeyEmptyEntityStoresToCheckOverridden()
624-
{
625-
$this->setPropertyValue($this->import, 'entityStoresToCheckOverridden', null);
626-
$this->select
627-
->expects($this->never())
628-
->method('from');
629-
$this->select
630-
->expects($this->never())
631-
->method('where');
632-
633-
$actualResult = $this->invokeMethod($this->import, 'cleanOverriddenUrlKey');
634-
$this->assertEquals($this->import, $actualResult);
635-
}
636-
637455
/**
638456
* Cover canonicalUrlRewriteGenerate().
639457
*/
@@ -848,30 +666,6 @@ protected function invokeMethod($object, $methodName, array $parameters = [])
848666
return $method->invokeArgs($object, $parameters);
849667
}
850668

851-
/**
852-
* Get mock of Import class instance with defined methods and called constructor.
853-
*/
854-
protected function getImportMock($methods = [])
855-
{
856-
return $this->getMock(
857-
'\Magento\CatalogUrlRewrite\Observer\AfterImportDataObserver',
858-
$methods,
859-
[
860-
$this->catalogProductFactory,
861-
$this->eavConfig,
862-
$this->objectRegistryFactory,
863-
$this->productUrlPathGenerator,
864-
$this->resource,
865-
$this->storeViewService,
866-
$this->storeManager,
867-
$this->urlPersist,
868-
$this->urlRewriteFactory,
869-
$this->urlFinder,
870-
],
871-
''
872-
);
873-
}
874-
875669
/**
876670
* @param mixed $storeId
877671
* @param mixed $productId

0 commit comments

Comments
 (0)