Skip to content

Commit fbf848f

Browse files
committed
MAGETWO-51951: SQL Error when cloning product with custom option with CatalogStaging enabled
1 parent 1aa5f73 commit fbf848f

File tree

3 files changed

+57
-8
lines changed

3 files changed

+57
-8
lines changed

app/code/Magento/Catalog/Model/Product/Copier.php

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
*/
88
namespace Magento\Catalog\Model\Product;
99

10+
use Magento\Catalog\Api\Data\ProductInterface;
11+
1012
class Copier
1113
{
1214
/**
@@ -24,6 +26,11 @@ class Copier
2426
*/
2527
protected $productFactory;
2628

29+
/**
30+
* @var \Magento\Framework\EntityManager\MetadataPool
31+
*/
32+
protected $metadataPool;
33+
2734
/**
2835
* @param CopyConstructorInterface $copyConstructor
2936
* @param \Magento\Catalog\Model\ProductFactory $productFactory
@@ -71,14 +78,18 @@ public function copy(\Magento\Catalog\Model\Product $product)
7178
} catch (\Magento\Framework\Exception\AlreadyExistsException $e) {
7279
}
7380
} while (!$isDuplicateSaved);
74-
7581
$this->getOptionRepository()->duplicate($product, $duplicate);
76-
$product->getResource()->duplicate($product->getEntityId(), $duplicate->getEntityId());
82+
$metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class);
83+
$product->getResource()->duplicate(
84+
$product->getData($metadata->getLinkField()),
85+
$duplicate->getData($metadata->getLinkField())
86+
);
7787
return $duplicate;
7888
}
7989

8090
/**
8191
* @return Option\Repository
92+
* @deprecated
8293
*/
8394
private function getOptionRepository()
8495
{
@@ -88,4 +99,17 @@ private function getOptionRepository()
8899
}
89100
return $this->optionRepository;
90101
}
102+
103+
/**
104+
* @return \Magento\Framework\EntityManager\MetadataPool
105+
* @deprecated
106+
*/
107+
private function getMetadataPool()
108+
{
109+
if (null === $this->metadataPool) {
110+
$this->metadataPool = \Magento\Framework\App\ObjectManager::getInstance()
111+
->get('Magento\Framework\EntityManager\MetadataPool');
112+
}
113+
return $this->metadataPool;
114+
}
91115
}

app/code/Magento/Catalog/Model/Product/Option/Repository.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,11 @@ public function duplicate(
113113
\Magento\Catalog\Api\Data\ProductInterface $product,
114114
\Magento\Catalog\Api\Data\ProductInterface $duplicate
115115
) {
116+
$metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class);
116117
return $this->optionResource->duplicate(
117118
$this->getOptionFactory()->create([]),
118-
$product->getId(),
119-
$duplicate->getId()
119+
$product->getData($metadata->getLinkField()),
120+
$duplicate->getData($metadata->getLinkField())
120121
);
121122
}
122123

@@ -189,6 +190,7 @@ protected function markRemovedValues($newValues, $originalValues)
189190

190191
/**
191192
* @return \Magento\Catalog\Model\Product\OptionFactory
193+
* @deprecated
192194
*/
193195
private function getOptionFactory()
194196
{
@@ -201,6 +203,7 @@ private function getOptionFactory()
201203

202204
/**
203205
* @return \Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory
206+
* @deprecated
204207
*/
205208
private function getCollectionFactory()
206209
{
@@ -213,6 +216,7 @@ private function getCollectionFactory()
213216

214217
/**
215218
* @return \Magento\Framework\EntityManager\MetadataPool
219+
* @deprecated
216220
*/
217221
private function getMetadataPool()
218222
{

app/code/Magento/Catalog/Test/Unit/Model/Product/CopierTest.php

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ class CopierTest extends \PHPUnit_Framework_TestCase
3434
*/
3535
protected $productMock;
3636

37+
/**
38+
* @var \PHPUnit_Framework_MockObject_MockObject
39+
*/
40+
protected $metadata;
41+
3742
protected function setUp()
3843
{
3944
$this->copyConstructorMock = $this->getMock('\Magento\Catalog\Model\Product\CopyConstructorInterface');
@@ -54,22 +59,33 @@ protected function setUp()
5459
$this->optionRepositoryMock;
5560
$this->productMock = $this->getMock('\Magento\Catalog\Model\Product', [], [], '', false);
5661
$this->productMock->expects($this->any())->method('getEntityId')->willReturn(1);
57-
$this->productMock->expects($this->any())->method('getData')->will($this->returnValue('product data'));
5862

63+
$this->metadata = $this->getMockBuilder('Magento\Framework\EntityManager\EntityMetadata')
64+
->disableOriginalConstructor()
65+
->getMock();
66+
$metadataPool = $this->getMockBuilder('Magento\Framework\EntityManager\MetadataPool')
67+
->disableOriginalConstructor()
68+
->getMock();
69+
$metadataPool->expects($this->any())->method('getMetadata')->willReturn($this->metadata);
5970
$this->_model = new Copier(
6071
$this->copyConstructorMock,
6172
$this->productFactoryMock
6273
);
6374

6475
$this->setProperties($this->_model, [
65-
'optionRepository' => $this->optionRepositoryMock
76+
'optionRepository' => $this->optionRepositoryMock,
77+
'metadataPool' => $metadataPool,
6678
]);
6779
}
6880

6981
public function testCopy()
7082
{
7183
$this->productMock->expects($this->atLeastOnce())->method('getWebsiteIds');
7284
$this->productMock->expects($this->atLeastOnce())->method('getCategoryIds');
85+
$this->productMock->expects($this->any())->method('getData')->willReturnMap([
86+
['', null, 'product data'],
87+
['linkField', null, '1'],
88+
]);
7389

7490
$resourceMock = $this->getMock('\Magento\Catalog\Model\ResourceModel\Product', [], [], '', false);
7591
$this->productMock->expects($this->once())->method('getResource')->will($this->returnValue($resourceMock));
@@ -79,6 +95,7 @@ public function testCopy()
7995
[
8096
'__wakeup',
8197
'setData',
98+
'getData',
8299
'setIsDuplicate',
83100
'setOriginalId',
84101
'setStatus',
@@ -121,8 +138,12 @@ public function testCopy()
121138
$duplicateMock->expects($this->once())->method('getUrlKey')->willReturn('urk-key-1');
122139
$duplicateMock->expects($this->once())->method('setUrlKey')->with('urk-key-2');
123140
$duplicateMock->expects($this->once())->method('save');
124-
$duplicateMock->expects($this->any())->method('getEntityId')->willReturn(2);
125-
$this->optionRepositoryMock->expects($this->once())
141+
142+
$this->metadata->expects($this->any())->method('getLinkField')->willReturn('linkField');
143+
144+
$duplicateMock->expects($this->any())->method('getData')->willReturnMap([
145+
['linkField', null, '2'],
146+
]); $this->optionRepositoryMock->expects($this->once())
126147
->method('duplicate')
127148
->with($this->productMock, $duplicateMock);
128149
$resourceMock->expects($this->once())->method('duplicate')->with(1, 2);

0 commit comments

Comments
 (0)