Skip to content

Commit 18e240e

Browse files
MAGETWO-85301: 10797: catalogProductTierPriceManagementV1 DELETE and POST operation wipes out media gallery selections when used on store code "all". #977
2 parents 832bb38 + abf901b commit 18e240e

File tree

3 files changed

+90
-31
lines changed

3 files changed

+90
-31
lines changed

app/code/Magento/Catalog/Model/ProductRepository.php

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ private function processLinks(\Magento\Catalog\Api\Data\ProductInterface $produc
493493
* @return $this
494494
* @throws InputException
495495
* @throws StateException
496+
* @throws LocalizedException
496497
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
497498
*/
498499
protected function processMediaGallery(ProductInterface $product, $mediaGalleryEntries)
@@ -502,16 +503,16 @@ protected function processMediaGallery(ProductInterface $product, $mediaGalleryE
502503
$entriesById = [];
503504
if (!empty($existingMediaGallery)) {
504505
foreach ($mediaGalleryEntries as $entry) {
505-
if (isset($entry['value_id'])) {
506-
$entriesById[$entry['value_id']] = $entry;
506+
if (isset($entry['id'])) {
507+
$entriesById[$entry['id']] = $entry;
507508
} else {
508509
$newEntries[] = $entry;
509510
}
510511
}
511512
foreach ($existingMediaGallery as $key => &$existingEntry) {
512513
if (isset($entriesById[$existingEntry['value_id']])) {
513514
$updatedEntry = $entriesById[$existingEntry['value_id']];
514-
if ($updatedEntry['file'] === null) {
515+
if (array_key_exists('file', $updatedEntry) && $updatedEntry['file'] === null) {
515516
unset($updatedEntry['file']);
516517
}
517518
$existingMediaGallery[$key] = array_merge($existingEntry, $updatedEntry);
@@ -520,6 +521,7 @@ protected function processMediaGallery(ProductInterface $product, $mediaGalleryE
520521
$existingEntry['removed'] = true;
521522
}
522523
}
524+
unset($existingEntry);
523525
$product->setData('media_gallery', ["images" => $existingMediaGallery]);
524526
} else {
525527
$newEntries = $mediaGalleryEntries;
@@ -534,26 +536,8 @@ protected function processMediaGallery(ProductInterface $product, $mediaGalleryE
534536
}
535537
}
536538
}
539+
$this->processEntries($product, $newEntries, $entriesById);
537540

538-
foreach ($newEntries as $newEntry) {
539-
if (!isset($newEntry['content'])) {
540-
throw new InputException(__('The image content is not valid.'));
541-
}
542-
/** @var ImageContentInterface $contentDataObject */
543-
$contentDataObject = $this->contentFactory->create()
544-
->setName($newEntry['content']['data'][ImageContentInterface::NAME])
545-
->setBase64EncodedData($newEntry['content']['data'][ImageContentInterface::BASE64_ENCODED_DATA])
546-
->setType($newEntry['content']['data'][ImageContentInterface::TYPE]);
547-
$newEntry['content'] = $contentDataObject;
548-
$this->processNewMediaGalleryEntry($product, $newEntry);
549-
550-
$finalGallery = $product->getData('media_gallery');
551-
$newEntryId = key(array_diff_key($product->getData('media_gallery')['images'], $entriesById));
552-
$newEntry = array_replace_recursive($newEntry, $finalGallery['images'][$newEntryId]);
553-
$entriesById[$newEntryId] = $newEntry;
554-
$finalGallery['images'][$newEntryId] = $newEntry;
555-
$product->setData('media_gallery', $finalGallery);
556-
}
557541
return $this;
558542
}
559543

@@ -592,8 +576,8 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO
592576
$product = $this->initializeProductData($productDataArray, empty($existingProduct));
593577

594578
$this->processLinks($product, $productLinks);
595-
if (isset($productDataArray['media_gallery'])) {
596-
$this->processMediaGallery($product, $productDataArray['media_gallery']['images']);
579+
if (isset($productDataArray['media_gallery_entries'])) {
580+
$this->processMediaGallery($product, $productDataArray['media_gallery_entries']);
597581
}
598582

599583
if (!$product->getOptionsReadonly()) {
@@ -791,4 +775,60 @@ private function getCollectionProcessor()
791775
}
792776
return $this->collectionProcessor;
793777
}
778+
779+
/**
780+
* Convert extension attribute for product media gallery.
781+
*
782+
* @param array $newEntry
783+
* @param array $extensionAttributes
784+
* @return void
785+
*/
786+
private function processExtensionAttributes(array &$newEntry, array $extensionAttributes)
787+
{
788+
foreach ($extensionAttributes as $code => $value) {
789+
if (is_array($value)) {
790+
$this->processExtensionAttributes($newEntry, $value);
791+
} else {
792+
$newEntry[$code] = $value;
793+
}
794+
}
795+
unset($newEntry['extension_attributes']);
796+
}
797+
798+
/**
799+
* Convert entries into product media gallery data and set to product.
800+
*
801+
* @param ProductInterface $product
802+
* @param array $newEntries
803+
* @param array $entriesById
804+
* @throws InputException
805+
* @throws LocalizedException
806+
* @throws StateException
807+
* @return void
808+
*/
809+
private function processEntries(ProductInterface $product, array $newEntries, array $entriesById)
810+
{
811+
foreach ($newEntries as $newEntry) {
812+
if (!isset($newEntry['content'])) {
813+
throw new InputException(__('The image content is not valid.'));
814+
}
815+
/** @var ImageContentInterface $contentDataObject */
816+
$contentDataObject = $this->contentFactory->create()
817+
->setName($newEntry['content'][ImageContentInterface::NAME])
818+
->setBase64EncodedData($newEntry['content'][ImageContentInterface::BASE64_ENCODED_DATA])
819+
->setType($newEntry['content'][ImageContentInterface::TYPE]);
820+
$newEntry['content'] = $contentDataObject;
821+
$this->processNewMediaGalleryEntry($product, $newEntry);
822+
823+
$finalGallery = $product->getData('media_gallery');
824+
$newEntryId = key(array_diff_key($product->getData('media_gallery')['images'], $entriesById));
825+
if (isset($newEntry['extension_attributes'])) {
826+
$this->processExtensionAttributes($newEntry, $newEntry['extension_attributes']);
827+
}
828+
$newEntry = array_replace_recursive($newEntry, $finalGallery['images'][$newEntryId]);
829+
$entriesById[$newEntryId] = $newEntry;
830+
$finalGallery['images'][$newEntryId] = $newEntry;
831+
$product->setData('media_gallery', $finalGallery);
832+
}
833+
}
794834
}

app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
namespace Magento\Catalog\Test\Unit\Model;
1111

12-
use Magento\Catalog\Api\Data\ProductAttributeInterface;
1312
use Magento\Framework\Api\Data\ImageContentInterface;
1413
use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface;
1514
use Magento\Framework\DB\Adapter\ConnectionException;
@@ -1178,7 +1177,21 @@ public function testSaveExistingWithNewMediaGalleryEntries()
11781177

11791178
$this->setupProductMocksForSave();
11801179
//media gallery data
1181-
$this->productData['media_gallery'] = $newEntriesData;
1180+
$this->productData['media_gallery_entries'] = [
1181+
[
1182+
'id' => null,
1183+
'label' => "label_text",
1184+
'position' => 10,
1185+
'disabled' => false,
1186+
'types' => ['image', 'small_image'],
1187+
'content' => [
1188+
ImageContentInterface::NAME => 'filename',
1189+
ImageContentInterface::TYPE => 'image/jpeg',
1190+
ImageContentInterface::BASE64_ENCODED_DATA => 'encoded_content',
1191+
],
1192+
'media_type' => 'media_type',
1193+
]
1194+
];
11821195
$this->extensibleDataObjectConverterMock
11831196
->expects($this->once())
11841197
->method('toNestedArray')
@@ -1288,7 +1301,7 @@ public function testSaveExistingWithMediaGalleryEntries()
12881301
//update one entry, delete one entry
12891302
$newEntries = [
12901303
[
1291-
'value_id' => 5,
1304+
'id' => 5,
12921305
"label" => "new_label_text",
12931306
'file' => 'filename1',
12941307
'position' => 10,
@@ -1316,7 +1329,7 @@ public function testSaveExistingWithMediaGalleryEntries()
13161329
$expectedResult = [
13171330
[
13181331
'value_id' => 5,
1319-
'value_id' => 5,
1332+
'id' => 5,
13201333
"label" => "new_label_text",
13211334
'file' => 'filename1',
13221335
'position' => 10,
@@ -1332,7 +1345,7 @@ public function testSaveExistingWithMediaGalleryEntries()
13321345

13331346
$this->setupProductMocksForSave();
13341347
//media gallery data
1335-
$this->productData['media_gallery']['images'] = $newEntries;
1348+
$this->productData['media_gallery_entries'] = $newEntries;
13361349
$this->extensibleDataObjectConverterMock
13371350
->expects($this->once())
13381351
->method('toNestedArray')

dev/tests/api-functional/testsuite/Magento/Catalog/Api/ProductTierPriceManagementTest.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,17 @@ public function getListDataProvider()
6060
/**
6161
* @param string|int $customerGroupId
6262
* @param int $qty
63-
* @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
63+
* @magentoApiDataFixture Magento/Catalog/_files/product_with_image.php
6464
* @dataProvider deleteDataProvider
6565
*/
6666
public function testDelete($customerGroupId, $qty)
6767
{
6868
$productSku = 'simple';
69+
$objectManager = \Magento\TestFramework\ObjectManager::getInstance();
70+
$productBefore = $objectManager->get(ProductRepositoryInterface::class)->get($productSku, false, null, true);
6971
$serviceInfo = [
7072
'rest' => [
71-
'resourcePath' => self::RESOURCE_PATH
73+
'resourcePath' => self::RESOURCE_PATH
7274
. $productSku . "/group-prices/" . $customerGroupId . "/tiers/" . $qty,
7375
'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_DELETE,
7476
],
@@ -80,6 +82,10 @@ public function testDelete($customerGroupId, $qty)
8082
];
8183
$requestData = ['sku' => $productSku, 'customerGroupId' => $customerGroupId, 'qty' => $qty];
8284
$this->assertTrue($this->_webApiCall($serviceInfo, $requestData));
85+
$productAfter = $objectManager->get(ProductRepositoryInterface::class)->get($productSku, false, null, true);
86+
$this->assertSame($productBefore->getImage(), $productAfter->getImage());
87+
$this->assertSame($productBefore->getSmallImage(), $productAfter->getSmallImage());
88+
$this->assertSame($productBefore->getThumbnail(), $productAfter->getThumbnail());
8389
}
8490

8591
public function deleteDataProvider()

0 commit comments

Comments
 (0)