Skip to content

Commit bdaefcd

Browse files
author
Spandana Chittimala
committed
Merge branch 'MC-18815' of https://github.com/magento-mpi/magento2ce into PR-16-08-2019
2 parents 5bc04c6 + a8bb138 commit bdaefcd

File tree

5 files changed

+123
-6
lines changed

5 files changed

+123
-6
lines changed

app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,42 @@ private function initMediaGalleryResources()
284284
}
285285
}
286286

287+
/**
288+
* Get the last media position for each product from the given list
289+
*
290+
* @param int $storeId
291+
* @param array $productIds
292+
* @return array
293+
*/
294+
private function getLastMediaPositionPerProduct(int $storeId, array $productIds): array
295+
{
296+
$result = [];
297+
if ($productIds) {
298+
$productKeyName = $this->getProductEntityLinkField();
299+
// this result could be achieved by using GROUP BY. But there is no index on position column, therefore
300+
// it can be slower than the implementation below
301+
$positions = $this->connection->fetchAll(
302+
$this->connection
303+
->select()
304+
->from($this->mediaGalleryValueTableName, [$productKeyName, 'position'])
305+
->where("$productKeyName IN (?)", $productIds)
306+
->where('value_id is not null')
307+
->where('store_id = ?', $storeId)
308+
);
309+
// Make sure the result contains all product ids even if the product has no media files
310+
$result = array_fill_keys($productIds, 0);
311+
// Find the largest position for each product
312+
foreach ($positions as $record) {
313+
$productId = $record[$productKeyName];
314+
$result[$productId] = $result[$productId] < $record['position']
315+
? $record['position']
316+
: $result[$productId];
317+
}
318+
}
319+
320+
return $result;
321+
}
322+
287323
/**
288324
* Save media gallery data per store.
289325
*
@@ -301,24 +337,30 @@ private function processMediaPerStore(
301337
) {
302338
$multiInsertData = [];
303339
$dataForSkinnyTable = [];
340+
$lastMediaPositionPerProduct = $this->getLastMediaPositionPerProduct(
341+
$storeId,
342+
array_unique(array_merge(...array_values($valueToProductId)))
343+
);
344+
304345
foreach ($mediaGalleryData as $mediaGalleryRows) {
305346
foreach ($mediaGalleryRows as $insertValue) {
306-
foreach ($newMediaValues as $value_id => $values) {
347+
foreach ($newMediaValues as $valueId => $values) {
307348
if ($values['value'] == $insertValue['value']) {
308-
$insertValue['value_id'] = $value_id;
349+
$insertValue['value_id'] = $valueId;
309350
$insertValue[$this->getProductEntityLinkField()]
310351
= array_shift($valueToProductId[$values['value']]);
311-
unset($newMediaValues[$value_id]);
352+
unset($newMediaValues[$valueId]);
312353
break;
313354
}
314355
}
315356
if (isset($insertValue['value_id'])) {
357+
$productId = $insertValue[$this->getProductEntityLinkField()];
316358
$valueArr = [
317359
'value_id' => $insertValue['value_id'],
318360
'store_id' => $storeId,
319-
$this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()],
361+
$this->getProductEntityLinkField() => $productId,
320362
'label' => $insertValue['label'],
321-
'position' => $insertValue['position'],
363+
'position' => $lastMediaPositionPerProduct[$productId] + $insertValue['position'],
322364
'disabled' => $insertValue['disabled'],
323365
];
324366
$multiInsertData[] = $valueArr;

dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,7 @@ function ($input) {
626626
explode(',', $optionData)
627627
)
628628
);
629+
// phpcs:ignore Magento2.Performance.ForeachArrayMerge.ForeachArrayMerge
629630
$option = array_merge(...$option);
630631

631632
if (!empty($option['type']) && !empty($option['name'])) {
@@ -692,12 +693,14 @@ protected function mergeWithExistingData(
692693
}
693694
} else {
694695
$existingOptionId = array_search($optionKey, $expectedOptions);
696+
// phpcs:ignore Magento2.Performance.ForeachArrayMerge.ForeachArrayMerge
695697
$expectedData[$existingOptionId] = array_merge(
696698
$this->getOptionData($option),
697699
$expectedData[$existingOptionId]
698700
);
699701
if ($optionValues) {
700702
foreach ($optionValues as $optionKey => $optionValue) {
703+
// phpcs:ignore Magento2.Performance.ForeachArrayMerge.ForeachArrayMerge
701704
$expectedValues[$existingOptionId][$optionKey] = array_merge(
702705
$optionValue,
703706
$expectedValues[$existingOptionId][$optionKey]
@@ -842,6 +845,58 @@ public function testSaveMediaImage()
842845
$this->assertEquals('Additional Image Label Two', $additionalImageTwoItem->getLabel());
843846
}
844847

848+
/**
849+
* Test that new images should be added after the existing ones.
850+
*
851+
* @magentoDataFixture mediaImportImageFixture
852+
* @magentoAppIsolation enabled
853+
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
854+
*/
855+
public function testNewImagesShouldBeAddedAfterExistingOnes()
856+
{
857+
$this->importDataForMediaTest('import_media.csv');
858+
859+
$product = $this->getProductBySku('simple_new');
860+
861+
$items = array_values($product->getMediaGalleryImages()->getItems());
862+
863+
$images = [
864+
['file' => '/m/a/magento_image.jpg', 'label' => 'Image Label'],
865+
['file' => '/m/a/magento_small_image.jpg', 'label' => 'Small Image Label'],
866+
['file' => '/m/a/magento_thumbnail.jpg', 'label' => 'Thumbnail Label'],
867+
['file' => '/m/a/magento_additional_image_one.jpg', 'label' => 'Additional Image Label One'],
868+
['file' => '/m/a/magento_additional_image_two.jpg', 'label' => 'Additional Image Label Two'],
869+
];
870+
871+
$this->assertCount(5, $items);
872+
$this->assertEquals(
873+
$images,
874+
array_map(
875+
function (\Magento\Framework\DataObject $item) {
876+
return $item->toArray(['file', 'label']);
877+
},
878+
$items
879+
)
880+
);
881+
882+
$this->importDataForMediaTest('import_media_additional_images.csv');
883+
$product->cleanModelCache();
884+
$product = $this->getProductBySku('simple_new');
885+
$items = array_values($product->getMediaGalleryImages()->getItems());
886+
$images[] = ['file' => '/m/a/magento_additional_image_three.jpg', 'label' => ''];
887+
$images[] = ['file' => '/m/a/magento_additional_image_four.jpg', 'label' => ''];
888+
$this->assertCount(7, $items);
889+
$this->assertEquals(
890+
$images,
891+
array_map(
892+
function (\Magento\Framework\DataObject $item) {
893+
return $item->toArray(['file', 'label']);
894+
},
895+
$items
896+
)
897+
);
898+
}
899+
845900
/**
846901
* Test that errors occurred during importing images are logged.
847902
*
@@ -892,6 +947,14 @@ public static function mediaImportImageFixture()
892947
'source' => __DIR__ . '/_files/magento_additional_image_two.jpg',
893948
'dest' => $dirPath . '/magento_additional_image_two.jpg',
894949
],
950+
[
951+
'source' => __DIR__ . '/_files/magento_additional_image_three.jpg',
952+
'dest' => $dirPath . '/magento_additional_image_three.jpg',
953+
],
954+
[
955+
'source' => __DIR__ . '/_files/magento_additional_image_four.jpg',
956+
'dest' => $dirPath . '/magento_additional_image_four.jpg',
957+
],
895958
];
896959

897960
foreach ($items as $item) {
@@ -2023,7 +2086,17 @@ private function importDataForMediaTest(string $fileName, int $expectedErrors =
20232086
$this->assertTrue($errors->getErrorsCount() == 0);
20242087

20252088
$this->_model->importData();
2026-
$this->assertTrue($this->_model->getErrorAggregator()->getErrorsCount() == $expectedErrors);
2089+
$this->assertEquals(
2090+
$expectedErrors,
2091+
$this->_model->getErrorAggregator()->getErrorsCount(),
2092+
array_reduce(
2093+
$this->_model->getErrorAggregator()->getAllErrors(),
2094+
function ($output, $error) {
2095+
return "$output\n{$error->getErrorMessage()}";
2096+
},
2097+
''
2098+
)
2099+
);
20272100
}
20282101

20292102
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
sku,additional_images
2+
simple_new,"magento_additional_image_three.jpg,magento_additional_image_four.jpg"

0 commit comments

Comments
 (0)