From 12cb7fc32036641eba87e74479c41709879649e2 Mon Sep 17 00:00:00 2001 From: magento-engcom-team Date: Wed, 1 Nov 2017 11:48:03 +0200 Subject: [PATCH 01/11] 8255: Export Products action doesn't consider hide_for_product_page value. --- .../Model/Export/Product.php | 68 +++++-- .../Model/Import/Product.php | 181 +++++++++++++----- .../Model/Export/ProductTest.php | 35 ++++ .../Model/Import/ProductTest.php | 22 ++- .../Import/_files/import_media_two_stores.csv | 3 + .../_files/product_export_with_images.php | 47 +++++ 6 files changed, 287 insertions(+), 69 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_two_stores.csv create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images.php diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index 8ff71faaacd98..c5618ef482ef7 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -532,11 +532,12 @@ protected function getMediaGallery(array $productIds) ] )->joinLeft( ['mgv' => $this->_resourceModel->getTableName('catalog_product_entity_media_gallery_value')], - '(mg.value_id = mgv.value_id AND mgv.store_id = 0)', + '(mg.value_id = mgv.value_id)', [ 'mgv.label', 'mgv.position', - 'mgv.disabled' + 'mgv.disabled', + 'mgv.store_id' ] )->where( "mgvte.{$this->getProductEntityLinkField()} IN (?)", @@ -552,6 +553,7 @@ protected function getMediaGallery(array $productIds) '_media_label' => $mediaRow['label'], '_media_position' => $mediaRow['position'], '_media_is_disabled' => $mediaRow['disabled'], + '_media_store_id' => $mediaRow['store_id'], ]; } @@ -903,7 +905,7 @@ protected function getExportData() $dataRow = array_merge($dataRow, $stockItemRows[$productId]); } $this->appendMultirowData($dataRow, $multirawData); - if ($dataRow) { + if ($dataRow && !$this->skipRow($dataRow)) { $exportData[] = $dataRow; } } @@ -931,8 +933,8 @@ protected function loadCollection(): array foreach ($collection as $itemId => $item) { $data[$itemId][$storeId] = $item; } + $collection->clear(); } - $collection->clear(); return $data; } @@ -1024,12 +1026,10 @@ protected function collectRawData() unset($data[$itemId][$storeId][self::COL_ADDITIONAL_ATTRIBUTES]); } - if (!empty($data[$itemId][$storeId]) || $this->hasMultiselectData($item, $storeId)) { - $attrSetId = $item->getAttributeSetId(); - $data[$itemId][$storeId][self::COL_STORE] = $storeCode; - $data[$itemId][$storeId][self::COL_ATTR_SET] = $this->_attrSetIdToName[$attrSetId]; - $data[$itemId][$storeId][self::COL_TYPE] = $item->getTypeId(); - } + $attrSetId = $item->getAttributeSetId(); + $data[$itemId][$storeId][self::COL_STORE] = $storeCode; + $data[$itemId][$storeId][self::COL_ATTR_SET] = $this->_attrSetIdToName[$attrSetId]; + $data[$itemId][$storeId][self::COL_TYPE] = $item->getTypeId(); $data[$itemId][$storeId][self::COL_SKU] = htmlspecialchars_decode($item->getSku()); $data[$itemId][$storeId]['store_id'] = $storeId; $data[$itemId][$storeId]['product_id'] = $itemId; @@ -1162,7 +1162,7 @@ protected function isValidAttributeValue($code, $value) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - private function appendMultirowData(&$dataRow, &$multiRawData) + private function appendMultirowData(&$dataRow, $multiRawData) { $productId = $dataRow['product_id']; $productLinkId = $dataRow['product_link_id']; @@ -1191,11 +1191,13 @@ private function appendMultirowData(&$dataRow, &$multiRawData) $additionalImageLabels = []; $additionalImageIsDisabled = []; foreach ($multiRawData['mediaGalery'][$productLinkId] as $mediaItem) { - $additionalImages[] = $mediaItem['_media_image']; - $additionalImageLabels[] = $mediaItem['_media_label']; + if ((int)$mediaItem['_media_store_id'] === Store::DEFAULT_STORE_ID) { + $additionalImages[] = $mediaItem['_media_image']; + $additionalImageLabels[] = $mediaItem['_media_label']; - if ($mediaItem['_media_is_disabled'] == true) { - $additionalImageIsDisabled[] = $mediaItem['_media_image']; + if ($mediaItem['_media_is_disabled'] == true) { + $additionalImageIsDisabled[] = $mediaItem['_media_image']; + } } } $dataRow['additional_images'] = @@ -1229,6 +1231,21 @@ private function appendMultirowData(&$dataRow, &$multiRawData) } } $dataRow = $this->rowCustomizer->addData($dataRow, $productId); + } else { + $additionalImageIsDisabled = []; + if (!empty($multiRawData['mediaGalery'][$productLinkId])) { + foreach ($multiRawData['mediaGalery'][$productLinkId] as $mediaItem) { + if ((int)$mediaItem['_media_store_id'] === $storeId) { + if ($mediaItem['_media_is_disabled'] == true) { + $additionalImageIsDisabled[] = $mediaItem['_media_image']; + } + } + } + } + if ($additionalImageIsDisabled) { + $dataRow['hide_from_product_page'] = + implode(Import::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalImageIsDisabled); + } } if (!empty($this->collectedMultiselectsData[$storeId][$productId])) { @@ -1494,4 +1511,25 @@ protected function getProductEntityLinkField() } return $this->productEntityLinkField; } + + /** + * Check if row has valuable information to export. + * + * @param array $dataRow + * @return bool + */ + private function skipRow(array $dataRow) + { + $baseInfo = [ + self::COL_STORE, + self::COL_ATTR_SET, + self::COL_TYPE, + self::COL_SKU, + 'store_id', + 'product_id', + 'product_link_id', + ]; + + return empty(array_diff(array_keys($dataRow), $baseInfo)); + } } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index a0f1e25cf6512..36c0524bfae08 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -8,7 +8,6 @@ use Magento\Catalog\Model\Product\Visibility; use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface as ValidatorInterface; use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\App\ObjectManager; use Magento\Framework\Model\ResourceModel\Db\ObjectRelationProcessor; use Magento\Framework\Model\ResourceModel\Db\TransactionManagerInterface; use Magento\Framework\Stdlib\DateTime; @@ -1694,10 +1693,25 @@ protected function _saveProducts() // 5. Media gallery phase $disabledImages = []; list($rowImages, $rowLabels) = $this->getImagesFromRow($rowData); + $storeId = !empty($rowData[self::COL_STORE]) + ? $this->getStoreIdByCode($rowData[self::COL_STORE]) + : Store::DEFAULT_STORE_ID; if (isset($rowData['_media_is_disabled'])) { $disabledImages = array_flip( explode($this->getMultipleValueSeparator(), $rowData['_media_is_disabled']) ); + foreach ($disabledImages as $disabledImage => $position) { + $uploadedFile = $this->uploadMediaFiles($disabledImage, true); + $uploadedFile = $uploadedFile ?: $this->getSystemFile($disabledImage); + $mediaGallery[$storeId][$rowSku][$uploadedFile] = [ + 'attribute_id' => $this->getMediaGalleryAttributeId(), + 'label' => $rowLabels[self::COL_MEDIA_IMAGE][$position] ?? '', + 'position' => $position, + 'disabled' => 1, + 'value' => $disabledImage, + 'store_id' => $storeId, + ]; + } } $rowData[self::COL_MEDIA_IMAGE] = []; @@ -1730,7 +1744,7 @@ protected function _saveProducts() $rowData[$column] = $uploadedFile; } - if ($uploadedFile && !isset($mediaGallery[$rowSku][$uploadedFile])) { + if ($uploadedFile && !isset($mediaGallery[$storeId][$rowSku][$uploadedFile])) { if (isset($existingImages[$rowSku][$uploadedFile])) { if (isset($rowLabels[$column][$columnImageKey]) && $rowLabels[$column][$columnImageKey] != $existingImages[$rowSku][$uploadedFile]['label'] @@ -1744,7 +1758,7 @@ protected function _saveProducts() if ($column == self::COL_MEDIA_IMAGE) { $rowData[$column][] = $uploadedFile; } - $mediaGallery[$rowSku][$uploadedFile] = [ + $mediaGallery[$storeId][$rowSku][$uploadedFile] = [ 'attribute_id' => $this->getMediaGalleryAttributeId(), 'label' => isset($rowLabels[$column][$columnImageKey]) ? $rowLabels[$column][$columnImageKey] : '', 'position' => ++$position, @@ -1756,6 +1770,10 @@ protected function _saveProducts() } } + //Add images to restore "hide from product page" value for specified store and product. + if (empty($mediaGallery[$storeId][$rowSku])) { + $mediaGallery[$storeId][$rowSku]['all'] = ['restore' => true]; + } // 6. Attributes phase $rowStore = (self::SCOPE_STORE == $rowScope) ? $this->storeResolver->getStoreCodeToId($rowData[self::COL_STORE]) @@ -2075,66 +2093,64 @@ protected function _saveMediaGallery(array $mediaGalleryData) return $this; } $this->initMediaGalleryResources(); - $productIds = []; $imageNames = []; $multiInsertData = []; $valueToProductId = []; - foreach ($mediaGalleryData as $productSku => $mediaGalleryRows) { - $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; - $productIds[] = $productId; - $insertedGalleryImgs = []; - foreach ($mediaGalleryRows as $insertValue) { - if (!in_array($insertValue['value'], $insertedGalleryImgs)) { - $valueArr = [ - 'attribute_id' => $insertValue['attribute_id'], - 'value' => $insertValue['value'], - ]; - $valueToProductId[$insertValue['value']][] = $productId; - $imageNames[] = $insertValue['value']; - $multiInsertData[] = $valueArr; - $insertedGalleryImgs[] = $insertValue['value']; + $mediaGalleryData = $this->restoreDisableImage($mediaGalleryData); + foreach (array_keys($mediaGalleryData) as $storeId) { + foreach ($mediaGalleryData[$storeId] as $productSku => $mediaGalleryRows) { + $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; + + $insertedGalleryImgs = []; + foreach ($mediaGalleryRows as $insertValue) { + if (!in_array($insertValue['value'], $insertedGalleryImgs)) { + $valueArr = [ + 'attribute_id' => $insertValue['attribute_id'], + 'value' => $insertValue['value'], + ]; + $valueToProductId[$insertValue['value']][] = $productId; + $imageNames[] = $insertValue['value']; + $multiInsertData[] = $valueArr; + $insertedGalleryImgs[] = $insertValue['value']; + } } } } - $oldMediaValues = $this->_connection->fetchAssoc( - $this->_connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value']) - ->where('value IN (?)', $imageNames) - ); - $this->_connection->insertOnDuplicate($this->mediaGalleryTableName, $multiInsertData, []); - $multiInsertData = []; + $multiInsertData = $this->filterImageInsertData($multiInsertData, $imageNames); + if ($multiInsertData) { + $this->_connection->insertOnDuplicate($this->mediaGalleryTableName, $multiInsertData); + } $newMediaSelect = $this->_connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value']) ->where('value IN (?)', $imageNames); - if (array_keys($oldMediaValues)) { - $newMediaSelect->where('value_id NOT IN (?)', array_keys($oldMediaValues)); - } - $dataForSkinnyTable = []; + $multiInsertData = []; $newMediaValues = $this->_connection->fetchAssoc($newMediaSelect); - foreach ($mediaGalleryData as $productSku => $mediaGalleryRows) { - foreach ($mediaGalleryRows as $insertValue) { - foreach ($newMediaValues as $value_id => $values) { - if ($values['value'] == $insertValue['value']) { - $insertValue['value_id'] = $value_id; - $insertValue[$this->getProductEntityLinkField()] - = array_shift($valueToProductId[$values['value']]); - unset($newMediaValues[$value_id]); - break; + foreach (array_keys($mediaGalleryData) as $storeId) { + foreach ($mediaGalleryData[$storeId] as $productSku => $mediaGalleryRows) { + foreach ($mediaGalleryRows as $insertValue) { + foreach ($newMediaValues as $value_id => $values) { + if ($values['value'] == $insertValue['value']) { + $insertValue['value_id'] = $value_id; + $insertValue[$this->getProductEntityLinkField()] + = array_shift($valueToProductId[$values['value']]); + break; + } + } + if (isset($insertValue['value_id'])) { + $valueArr = [ + 'value_id' => $insertValue['value_id'], + 'store_id' => $storeId, + $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], + 'label' => $insertValue['label'], + 'position' => $insertValue['position'], + 'disabled' => $insertValue['disabled'], + ]; + $multiInsertData[] = $valueArr; + $dataForSkinnyTable[] = [ + 'value_id' => $insertValue['value_id'], + $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], + ]; } - } - if (isset($insertValue['value_id'])) { - $valueArr = [ - 'value_id' => $insertValue['value_id'], - 'store_id' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, - $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], - 'label' => $insertValue['label'], - 'position' => $insertValue['position'], - 'disabled' => $insertValue['disabled'], - ]; - $multiInsertData[] = $valueArr; - $dataForSkinnyTable[] = [ - 'value_id' => $insertValue['value_id'], - $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], - ]; } } } @@ -2155,6 +2171,7 @@ protected function _saveMediaGallery(array $mediaGalleryData) $this->_connection->quoteInto('value_id IN (?)', $newMediaValues) ); } + return $this; } @@ -2976,4 +2993,64 @@ private function getExistingSku($sku) { return $this->_oldSku[strtolower($sku)]; } + + /** + * Set product images 'disable' = 0 for specified store. + * + * @param array $mediaGalleryData + * @return array + */ + private function restoreDisableImage(array $mediaGalleryData) + { + $restoreData = []; + foreach (array_keys($mediaGalleryData) as $storeId) { + foreach ($mediaGalleryData[$storeId] as $productSku => $mediaGalleryRows) { + $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; + $restoreData[] = sprintf( + 'store_id = %s and %s = %s', + $storeId, + $this->getProductEntityLinkField(), + $productId + ); + if (isset($mediaGalleryRows['all']['restore'])) { + unset($mediaGalleryData[$storeId][$productSku]); + } + } + } + + $this->_connection->update( + $this->mediaGalleryValueTableName, + ['disabled' => 0], + new \Zend_Db_Expr(implode(' or ', $restoreData)) + ); + + return $mediaGalleryData; + } + + /** + * Remove existed images from insert data. + * + * @param array $multiInsertData + * @param array $imageNames + * @return array + */ + private function filterImageInsertData(array $multiInsertData, array $imageNames) + { + //Remove image duplicates for stores. + $multiInsertData = array_map("unserialize", array_unique(array_map("serialize", $multiInsertData))); + $oldMediaValues = $this->_connection->fetchAssoc( + $this->_connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value', 'attribute_id']) + ->where('value IN (?)', $imageNames) + ); + foreach ($multiInsertData as $key => $data) { + foreach ($oldMediaValues as $mediaValue) { + if ($data['value'] == $mediaValue['value'] && $data['attribute_id'] == $mediaValue['attribute_id']) { + unset($multiInsertData[$key]); + break; + } + } + } + + return $multiInsertData; + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php index 085d6fac0e00b..269572ebcc27c 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php @@ -9,6 +9,8 @@ * @magentoDataFixtureBeforeTransaction Magento/Catalog/_files/enable_reindex_schedule.php * @magentoAppIsolation enabled * @magentoDbIsolation enabled + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class ProductTest extends \PHPUnit\Framework\TestCase { @@ -288,4 +290,37 @@ public function testCategoryIdsFilter() $this->assertNotContains('Simple Product Two', $exportData); $this->assertNotContains('Simple Product Not Visible On Storefront', $exportData); } + + /** + * Test 'hide from product page' export for non-default store. + * + * @magentoDataFixture Magento/CatalogImportExport/_files/product_export_with_images.php + */ + public function testExportWithMedia() + { + /** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */ + $productRepository = $this->objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); + $product = $productRepository->get('simple', 1); + $mediaGallery = $product->getData('media_gallery'); + $image = array_shift($mediaGallery['images']); + $expected = [ + 'hide_from_product_page' => 'hide_from_product_page', + '' => '', + $image['file'] => $image['file'], + ]; + $this->model->setWriter( + $this->objectManager->create( + \Magento\ImportExport\Model\Export\Adapter\Csv::class + ) + ); + $exportData = $this->model->export(); + /** @var $varDirectory \Magento\Framework\Filesystem\Directory\WriteInterface */ + $varDirectory = $this->objectManager->get(\Magento\Framework\Filesystem::class) + ->getDirectoryWrite(\Magento\Framework\App\Filesystem\DirectoryList::VAR_DIR); + $varDirectory->writeFile('test_product_with_image.csv', $exportData); + /** @var \Magento\Framework\File\Csv $csv */ + $csv = $this->objectManager->get(\Magento\Framework\File\Csv::class); + $data = $csv->getDataPairs($varDirectory->getAbsolutePath('test_product_with_image.csv'), 76, 76); + self::assertSame($expected, $data); + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index 0f9cb373e59ed..fc2a2de24f4ac 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -22,11 +22,10 @@ use Magento\Framework\App\Bootstrap; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\ObjectManager; -use Magento\Framework\Registry; use Magento\Framework\Filesystem; +use Magento\Framework\Registry; use Magento\ImportExport\Model\Import; use Magento\Store\Model\Store; -use Magento\UrlRewrite\Model\UrlRewrite; /** * Class ProductTest @@ -1919,4 +1918,23 @@ public function testImportWithDifferentSkuCase() ); } } + + /** + * Test that product import with images for non-default store works properly. + * + * @magentoDataIsolation enabled + * @magentoDataFixture mediaImportImageFixture + * @magentoAppIsolation enabled + */ + public function testImportImageForNonDefaultStore() + { + $this->importDataForMediaTest('import_media_two_stores.csv'); + $product = $this->getProductBySku('simple_with_images'); + $mediaGallery = $product->getData('media_gallery'); + foreach ($mediaGallery['images'] as $image) { + $image['file'] === 'magento_image.jpg' + ? self::assertSame('1', $image['disabled']) + : self::assertSame('0', $image['disabled']); + } + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_two_stores.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_two_stores.csv new file mode 100644 index 0000000000000..59f8df69f555e --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_media_two_stores.csv @@ -0,0 +1,3 @@ +sku,store_view_code,attribute_set_code,product_type,categories,product_websites,name,description,short_description,weight,product_online,tax_class_name,visibility,price,special_price,special_price_from_date,special_price_to_date,url_key,meta_title,meta_keywords,meta_description,base_image,base_image_label,small_image,small_image_label,thumbnail_image,thumbnail_image_label,swatch_image,swatch_image_label,created_at,updated_at,new_from_date,new_to_date,display_product_options_in,map_price,msrp_price,map_enabled,gift_message_available,custom_design,custom_design_from,custom_design_to,custom_layout_update,page_layout,product_options_container,msrp_display_actual_price_type,country_of_manufacture,additional_attributes,qty,out_of_stock_qty,use_config_min_qty,is_qty_decimal,allow_backorders,use_config_backorders,min_cart_qty,use_config_min_sale_qty,max_cart_qty,use_config_max_sale_qty,is_in_stock,notify_on_stock_below,use_config_notify_stock_qty,manage_stock,use_config_manage_stock,use_config_qty_increments,qty_increments,use_config_enable_qty_inc,enable_qty_increments,is_decimal_divided,website_id,related_skus,related_position,crosssell_skus,crosssell_position,upsell_skus,upsell_position,additional_images,additional_image_labels,hide_from_product_page,custom_options,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,bundle_shipment_type,configurable_variations,configurable_variation_labels,associated_skus +simple_with_images,,Default,simple,Default Category,base,Simple Product,Description with html tag,Short description,1,1,0,"Catalog, Search",10,,,,simple-product,meta title,meta keyword,meta description,magento_image.jpg,,magento_image.jpg,,magento_image.jpg,,,,"11/1/17, 1:41 AM","11/1/17, 1:41 AM",,,Block after Info Column,,,,,,,,,,,,,,100,0,1,0,0,1,1,1,0,1,1,,1,0,1,1,0,1,0,0,0,,,,,,,magento_image.jpg,Image Alt Text,,"name=Test Select,type=drop_down,required=1,price=3.0000,price_type=fixed,sku=3-1-select,file_extension=,image_size_x=,image_size_y=,option_title=Option 1|name=Test Select,type=drop_down,required=1,price=3.0000,price_type=fixed,sku=3-2-select,file_extension=,image_size_x=,image_size_y=,option_title=Option 2|name=Test Field,type=field,required=1,price=1.0000,price_type=fixed,sku=1-text,max_characters=100,file_extension=,image_size_x=,image_size_y=|name=Test Radio,type=radio,required=1,price=3.0000,price_type=fixed,sku=4-1-radio,file_extension=,image_size_x=,image_size_y=,option_title=Option 1|name=Test Radio,type=radio,required=1,price=3.0000,price_type=fixed,sku=4-2-radio,file_extension=,image_size_x=,image_size_y=,option_title=Option 2|name=Test Date and Time,type=date_time,required=1,price=2.0000,price_type=fixed,sku=2-date,file_extension=,image_size_x=,image_size_y=",,,,,,,,, +simple_with_images,default,Default,simple,,,,,,,,,,,,,,,,,,,Image Alt Text,,Image Alt Text,,Image Alt Text,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,magento_image.jpg,,,,,,,,,, diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images.php new file mode 100644 index 0000000000000..1c9dbbb5553f8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images.php @@ -0,0 +1,47 @@ +create(\Magento\Catalog\Api\ProductRepositoryInterface::class); +$product = $productRepository->get('simple'); +$product->setStoreId(0) + ->setImage('/m/a/magento_image.jpg') + ->setSmallImage('/m/a/magento_image.jpg') + ->setThumbnail('/m/a/magento_image.jpg') + ->setData( + 'media_gallery', + [ + 'images' => [ + [ + 'file' => '/m/a/magento_image.jpg', + 'position' => 1, + 'label' => 'Image Alt Text', + 'disabled' => 0, + 'media_type' => 'image', + ], + ], + ] + )->save(); +$image = array_shift($product->getData('media_gallery')['images']); +$product->setStoreId(1)->setData( + 'media_gallery', + [ + 'images' => [ + [ + 'file' => $image['file'], + 'value_id' => $image['value_id'], + 'position' => 1, + 'label' => 'Image Alt Text', + 'disabled' => 1, + 'media_type' => 'image', + ], + ], + ] +)->save(); From b7703ac414d52093790eb1df1012f7b9492ad56f Mon Sep 17 00:00:00 2001 From: magento-engcom-team Date: Wed, 1 Nov 2017 16:28:23 +0200 Subject: [PATCH 02/11] 8255: Export Products action doesn't consider hide_for_product_page value. --- .../Magento/CatalogImportExport/Model/Import/Product.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 14fd7f58b7c65..bdf7062e2467d 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -5,18 +5,19 @@ */ namespace Magento\CatalogImportExport\Model\Import; +use Magento\Catalog\Model\Config as CatalogConfig; use Magento\Catalog\Model\Product\Visibility; use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface as ValidatorInterface; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Filesystem; use Magento\Framework\Model\ResourceModel\Db\ObjectRelationProcessor; use Magento\Framework\Model\ResourceModel\Db\TransactionManagerInterface; use Magento\Framework\Stdlib\DateTime; -use Magento\Framework\Filesystem; use Magento\ImportExport\Model\Import; use Magento\ImportExport\Model\Import\Entity\AbstractEntity; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingError; use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; -use Magento\Catalog\Model\Config as CatalogConfig; +use Magento\Store\Model\Store; /** * Import entity product model From 426183c1c771c4897f2fa16b4d9c083090e0ccd3 Mon Sep 17 00:00:00 2001 From: magento-engcom-team Date: Thu, 2 Nov 2017 10:53:33 +0200 Subject: [PATCH 03/11] 8255: Export Products action doesn't consider hide_for_product_page value. --- .../Magento/CatalogImportExport/Model/Import/ProductTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index fd9f24f980cdc..3d4dd7c9cf8b9 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -34,6 +34,7 @@ * @magentoDbIsolation enabled * @magentoDataFixtureBeforeTransaction Magento/Catalog/_files/enable_reindex_schedule.php * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) */ class ProductTest extends \Magento\TestFramework\Indexer\TestCase { From 64ddd51bb43a4bc1b3501672a6b2f3cbac34dc0e Mon Sep 17 00:00:00 2001 From: magento-engcom-team Date: Tue, 14 Nov 2017 10:30:01 +0200 Subject: [PATCH 04/11] 8255: Export Products action doesn't consider hide_for_product_page value. --- .../Model/Export/Product.php | 1 + .../Model/Import/Product.php | 235 +--------- .../Import/Product/MediaGalleryProcessor.php | 407 ++++++++++++++++++ .../Model/Export/ProductTest.php | 13 +- 4 files changed, 431 insertions(+), 225 deletions(-) create mode 100644 app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index c5618ef482ef7..4174fbefd90ef 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -1104,6 +1104,7 @@ protected function collectMultirawData() * @param \Magento\Catalog\Model\Product $item * @param int $storeId * @return bool + * @deprecated */ protected function hasMultiselectData($item, $storeId) { diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 477493cdbd06f..80ef6305e5b71 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -7,6 +7,7 @@ use Magento\Catalog\Model\Config as CatalogConfig; use Magento\Catalog\Model\Product\Visibility; +use Magento\CatalogImportExport\Model\Import\Product\MediaGalleryProcessor; use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface as ValidatorInterface; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Filesystem; @@ -698,6 +699,13 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity */ private $catalogConfig; + /** + * Provide ability to process and save images during import. + * + * @var MediaGalleryProcessor + */ + private $mediaProcessor; + /** * @param \Magento\Framework\Json\Helper\Data $jsonHelper * @param \Magento\ImportExport\Helper\Data $importExportData @@ -737,6 +745,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity * @param array $data * @param array $dateAttrCodes * @param CatalogConfig $catalogConfig + * @param MediaGalleryProcessor $mediaProcessor * @throws \Magento\Framework\Exception\LocalizedException * * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -780,7 +789,8 @@ public function __construct( \Magento\Catalog\Model\Product\Url $productUrl, array $data = [], array $dateAttrCodes = [], - CatalogConfig $catalogConfig = null + CatalogConfig $catalogConfig = null, + MediaGalleryProcessor $mediaProcessor = null ) { $this->_eventManager = $eventManager; $this->stockRegistry = $stockRegistry; @@ -813,7 +823,8 @@ public function __construct( $this->dateAttrCodes = array_merge($this->dateAttrCodes, $dateAttrCodes); $this->catalogConfig = $catalogConfig ?: \Magento\Framework\App\ObjectManager::getInstance() ->get(CatalogConfig::class); - + $this->mediaProcessor = $mediaProcessor ?: \Magento\Framework\App\ObjectManager::getInstance() + ->get(MediaGalleryProcessor::class); parent::__construct( $jsonHelper, $importExportData, @@ -1447,6 +1458,7 @@ private function getNewSkuFieldsForSelect() * Init media gallery resources * @return void * @since 100.0.4 + * @deprecated */ protected function initMediaGalleryResources() { @@ -1470,48 +1482,7 @@ protected function initMediaGalleryResources() */ protected function getExistingImages($bunch) { - $result = []; - if ($this->getErrorAggregator()->hasToBeTerminated()) { - return $result; - } - - $this->initMediaGalleryResources(); - $productSKUs = array_map('strval', array_column($bunch, self::COL_SKU)); - $select = $this->_connection->select()->from( - ['mg' => $this->mediaGalleryTableName], - ['value' => 'mg.value'] - )->joinInner( - ['mgvte' => $this->mediaGalleryEntityToValueTableName], - '(mg.value_id = mgvte.value_id)', - [ - $this->getProductEntityLinkField() => 'mgvte.' . $this->getProductEntityLinkField(), - 'value_id' => 'mgvte.value_id' - ] - )->joinLeft( - ['mgv' => $this->mediaGalleryValueTableName], - sprintf( - '(mg.value_id = mgv.value_id AND mgv.%s = mgvte.%s AND mgv.store_id = %d)', - $this->getProductEntityLinkField(), - $this->getProductEntityLinkField(), - \Magento\Store\Model\Store::DEFAULT_STORE_ID - ), - [ - 'label' => 'mgv.label' - ] - )->joinInner( - ['pe' => $this->productEntityTableName], - "(mgvte.{$this->getProductEntityLinkField()} = pe.{$this->getProductEntityLinkField()})", - ['sku' => 'pe.sku'] - )->where( - 'pe.sku IN (?)', - $productSKUs - ); - - foreach ($this->_connection->fetchAll($select) as $image) { - $result[$image['sku']][$image['value']] = $image; - } - - return $result; + return $this->mediaProcessor->getExistingImages($bunch); } /** @@ -2082,93 +2053,13 @@ private function getSystemFile($fileName) * * @param array $mediaGalleryData * @return $this - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _saveMediaGallery(array $mediaGalleryData) { if (empty($mediaGalleryData)) { return $this; } - $this->initMediaGalleryResources(); - $imageNames = []; - $multiInsertData = []; - $valueToProductId = []; - $mediaGalleryData = $this->restoreDisableImage($mediaGalleryData); - foreach (array_keys($mediaGalleryData) as $storeId) { - foreach ($mediaGalleryData[$storeId] as $productSku => $mediaGalleryRows) { - $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; - - $insertedGalleryImgs = []; - foreach ($mediaGalleryRows as $insertValue) { - if (!in_array($insertValue['value'], $insertedGalleryImgs)) { - $valueArr = [ - 'attribute_id' => $insertValue['attribute_id'], - 'value' => $insertValue['value'], - ]; - $valueToProductId[$insertValue['value']][] = $productId; - $imageNames[] = $insertValue['value']; - $multiInsertData[] = $valueArr; - $insertedGalleryImgs[] = $insertValue['value']; - } - } - } - } - $multiInsertData = $this->filterImageInsertData($multiInsertData, $imageNames); - if ($multiInsertData) { - $this->_connection->insertOnDuplicate($this->mediaGalleryTableName, $multiInsertData); - } - $newMediaSelect = $this->_connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value']) - ->where('value IN (?)', $imageNames); - $dataForSkinnyTable = []; - $multiInsertData = []; - $newMediaValues = $this->_connection->fetchAssoc($newMediaSelect); - foreach (array_keys($mediaGalleryData) as $storeId) { - foreach ($mediaGalleryData[$storeId] as $productSku => $mediaGalleryRows) { - foreach ($mediaGalleryRows as $insertValue) { - foreach ($newMediaValues as $value_id => $values) { - if ($values['value'] == $insertValue['value']) { - $insertValue['value_id'] = $value_id; - $insertValue[$this->getProductEntityLinkField()] - = array_shift($valueToProductId[$values['value']]); - break; - } - } - if (isset($insertValue['value_id'])) { - $valueArr = [ - 'value_id' => $insertValue['value_id'], - 'store_id' => $storeId, - $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], - 'label' => $insertValue['label'], - 'position' => $insertValue['position'], - 'disabled' => $insertValue['disabled'], - ]; - $multiInsertData[] = $valueArr; - $dataForSkinnyTable[] = [ - 'value_id' => $insertValue['value_id'], - $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], - ]; - } - } - } - } - try { - $this->_connection->insertOnDuplicate( - $this->mediaGalleryValueTableName, - $multiInsertData, - ['value_id', 'store_id', $this->getProductEntityLinkField(), 'label', 'position', 'disabled'] - ); - $this->_connection->insertOnDuplicate( - $this->mediaGalleryEntityToValueTableName, - $dataForSkinnyTable, - ['value_id'] - ); - } catch (\Exception $e) { - $this->_connection->delete( - $this->mediaGalleryTableName, - $this->_connection->quoteInto('value_id IN (?)', $newMediaValues) - ); - } + $this->mediaProcessor->saveMediaGallery($mediaGalleryData); return $this; } @@ -2920,39 +2811,7 @@ private function updateMediaGalleryLabels(array $labels) if (empty($labels)) { return; } - - $insertData = []; - foreach ($labels as $label) { - $imageData = $label['imageData']; - - if ($imageData['label'] === null) { - $insertData[] = [ - 'label' => $label['label'], - $this->getProductEntityLinkField() => $imageData[$this->getProductEntityLinkField()], - 'value_id' => $imageData['value_id'], - 'store_id' => \Magento\Store\Model\Store::DEFAULT_STORE_ID - ]; - } else { - $this->_connection->update( - $this->mediaGalleryValueTableName, - [ - 'label' => $label['label'] - ], - [ - $this->getProductEntityLinkField() . ' = ?' => $imageData[$this->getProductEntityLinkField()], - 'value_id = ?' => $imageData['value_id'], - 'store_id = ?' => \Magento\Store\Model\Store::DEFAULT_STORE_ID - ] - ); - } - } - - if (!empty($insertData)) { - $this->_connection->insertMultiple( - $this->mediaGalleryValueTableName, - $insertData - ); - } + $this->mediaProcessor->updateMediaGalleryLabels($labels); } /** @@ -2991,64 +2850,4 @@ private function getExistingSku($sku) { return $this->_oldSku[strtolower($sku)]; } - - /** - * Set product images 'disable' = 0 for specified store. - * - * @param array $mediaGalleryData - * @return array - */ - private function restoreDisableImage(array $mediaGalleryData) - { - $restoreData = []; - foreach (array_keys($mediaGalleryData) as $storeId) { - foreach ($mediaGalleryData[$storeId] as $productSku => $mediaGalleryRows) { - $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; - $restoreData[] = sprintf( - 'store_id = %s and %s = %s', - $storeId, - $this->getProductEntityLinkField(), - $productId - ); - if (isset($mediaGalleryRows['all']['restore'])) { - unset($mediaGalleryData[$storeId][$productSku]); - } - } - } - - $this->_connection->update( - $this->mediaGalleryValueTableName, - ['disabled' => 0], - new \Zend_Db_Expr(implode(' or ', $restoreData)) - ); - - return $mediaGalleryData; - } - - /** - * Remove existed images from insert data. - * - * @param array $multiInsertData - * @param array $imageNames - * @return array - */ - private function filterImageInsertData(array $multiInsertData, array $imageNames) - { - //Remove image duplicates for stores. - $multiInsertData = array_map("unserialize", array_unique(array_map("serialize", $multiInsertData))); - $oldMediaValues = $this->_connection->fetchAssoc( - $this->_connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value', 'attribute_id']) - ->where('value IN (?)', $imageNames) - ); - foreach ($multiInsertData as $key => $data) { - foreach ($oldMediaValues as $mediaValue) { - if ($data['value'] == $mediaValue['value'] && $data['attribute_id'] == $mediaValue['attribute_id']) { - unset($multiInsertData[$key]); - break; - } - } - } - - return $multiInsertData; - } } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php new file mode 100644 index 0000000000000..bced070ae5609 --- /dev/null +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php @@ -0,0 +1,407 @@ +skuProcessor = $skuProcessor; + $this->metadataPool = $metadataPool; + $this->connection = $resourceConnection->getConnection(); + $this->resourceFactory = $resourceModelFactory; + $this->errorAggregator = $errorAggregator; + } + + /** + * Save product media gallery. + * + * @param $mediaGalleryData + * @return void + */ + public function saveMediaGallery(array $mediaGalleryData) + { + $this->initMediaGalleryResources(); + $imageNames = []; + $multiInsertData = []; + $valueToProductId = []; + $mediaGalleryData = $this->restoreDisableImage($mediaGalleryData); + foreach (array_keys($mediaGalleryData) as $storeId) { + foreach ($mediaGalleryData[$storeId] as $productSku => $mediaGalleryRows) { + $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; + + $insertedGalleryImgs = []; + foreach ($mediaGalleryRows as $insertValue) { + if (!in_array($insertValue['value'], $insertedGalleryImgs)) { + $valueArr = [ + 'attribute_id' => $insertValue['attribute_id'], + 'value' => $insertValue['value'], + ]; + $valueToProductId[$insertValue['value']][] = $productId; + $imageNames[] = $insertValue['value']; + $multiInsertData[] = $valueArr; + $insertedGalleryImgs[] = $insertValue['value']; + } + } + } + } + $multiInsertData = $this->filterImageInsertData($multiInsertData, $imageNames); + if ($multiInsertData) { + $this->connection->insertOnDuplicate($this->mediaGalleryTableName, $multiInsertData); + } + $newMediaSelect = $this->connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value']) + ->where('value IN (?)', $imageNames); + + $newMediaValues = $this->connection->fetchAssoc($newMediaSelect); + list($multiInsertData, $dataForSkinnyTable) = $this->prepareInsertData( + $mediaGalleryData, + $newMediaValues, + $valueToProductId + ); + try { + $this->connection->insertOnDuplicate( + $this->mediaGalleryValueTableName, + $multiInsertData, + ['value_id', 'store_id', $this->getProductEntityLinkField(), 'label', 'position', 'disabled'] + ); + $this->connection->insertOnDuplicate( + $this->mediaGalleryEntityToValueTableName, + $dataForSkinnyTable, + ['value_id'] + ); + } catch (\Exception $e) { + $this->connection->delete( + $this->mediaGalleryTableName, + $this->connection->quoteInto('value_id IN (?)', $newMediaValues) + ); + } + } + + /** + * Update media gallery labels. + * + * @param array $labels + * @return void + */ + public function updateMediaGalleryLabels(array $labels) + { + $insertData = []; + foreach ($labels as $label) { + $imageData = $label['imageData']; + + if ($imageData['label'] === null) { + $insertData[] = [ + 'label' => $label['label'], + $this->getProductEntityLinkField() => $imageData[$this->getProductEntityLinkField()], + 'value_id' => $imageData['value_id'], + 'store_id' => Store::DEFAULT_STORE_ID, + ]; + } else { + $this->connection->update( + $this->mediaGalleryValueTableName, + [ + 'label' => $label['label'], + ], + [ + $this->getProductEntityLinkField() . ' = ?' => $imageData[$this->getProductEntityLinkField()], + 'value_id = ?' => $imageData['value_id'], + 'store_id = ?' => Store::DEFAULT_STORE_ID, + ] + ); + } + } + + if (!empty($insertData)) { + $this->connection->insertMultiple( + $this->mediaGalleryValueTableName, + $insertData + ); + } + } + + /** + * Get existing images for current bunch. + * + * @param array $bunch + * @return array + */ + public function getExistingImages(array $bunch) + { + $result = []; + if ($this->errorAggregator->hasToBeTerminated()) { + return $result; + } + $this->initMediaGalleryResources(); + $productSKUs = array_map( + 'strval', + array_column($bunch, Product::COL_SKU) + ); + $select = $this->connection->select()->from( + ['mg' => $this->mediaGalleryTableName], + ['value' => 'mg.value'] + )->joinInner( + ['mgvte' => $this->mediaGalleryEntityToValueTableName], + '(mg.value_id = mgvte.value_id)', + [ + $this->getProductEntityLinkField() => 'mgvte.' . $this->getProductEntityLinkField(), + 'value_id' => 'mgvte.value_id', + ] + )->joinLeft( + ['mgv' => $this->mediaGalleryValueTableName], + sprintf( + '(mg.value_id = mgv.value_id AND mgv.%s = mgvte.%s AND mgv.store_id = %d)', + $this->getProductEntityLinkField(), + $this->getProductEntityLinkField(), + Store::DEFAULT_STORE_ID + ), + [ + 'label' => 'mgv.label', + ] + )->joinInner( + ['pe' => $this->productEntityTableName], + "(mgvte.{$this->getProductEntityLinkField()} = pe.{$this->getProductEntityLinkField()})", + ['sku' => 'pe.sku'] + )->where( + 'pe.sku IN (?)', + $productSKUs + ); + + foreach ($this->connection->fetchAll($select) as $image) { + $result[$image['sku']][$image['value']] = $image; + } + + return $result; + } + + /** + * Init media gallery resources. + * + * @return void + */ + private function initMediaGalleryResources() + { + if (null == $this->mediaGalleryTableName) { + $this->productEntityTableName = $this->getResource()->getTable('catalog_product_entity'); + $this->mediaGalleryTableName = $this->getResource()->getTable('catalog_product_entity_media_gallery'); + $this->mediaGalleryValueTableName = $this->getResource()->getTable( + 'catalog_product_entity_media_gallery_value' + ); + $this->mediaGalleryEntityToValueTableName = $this->getResource()->getTable( + 'catalog_product_entity_media_gallery_value_to_entity' + ); + } + } + + /** + * Remove existed images from insert data. + * + * @param array $multiInsertData + * @param array $imageNames + * @return array + */ + private function filterImageInsertData(array $multiInsertData, array $imageNames) + { + $oldMediaValues = $this->connection->fetchAssoc( + $this->connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value', 'attribute_id']) + ->where('value IN (?)', $imageNames) + ); + foreach ($multiInsertData as $key => $data) { + foreach ($oldMediaValues as $mediaValue) { + if ($data['value'] === $mediaValue['value'] && $data['attribute_id'] === $mediaValue['attribute_id']) { + unset($multiInsertData[$key]); + } + } + } + + return $multiInsertData; + } + + /** + * Set product images 'disable' = 0 for specified store. + * + * @param array $mediaGalleryData + * @return array + */ + private function restoreDisableImage(array $mediaGalleryData) + { + $restoreData = []; + foreach (array_keys($mediaGalleryData) as $storeId) { + foreach ($mediaGalleryData[$storeId] as $productSku => $mediaGalleryRows) { + $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; + $restoreData[] = sprintf( + 'store_id = %s and %s = %s', + $storeId, + $this->getProductEntityLinkField(), + $productId + ); + if (isset($mediaGalleryRows['all']['restore'])) { + unset($mediaGalleryData[$storeId][$productSku]); + } + } + } + + $this->connection->update( + $this->mediaGalleryValueTableName, + ['disabled' => 0], + new \Zend_Db_Expr(implode(' or ', $restoreData)) + ); + + return $mediaGalleryData; + } + + /** + * Get product entity link field. + * + * @return string + */ + private function getProductEntityLinkField() + { + if (!$this->productEntityLinkField) { + $this->productEntityLinkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); + } + + return $this->productEntityLinkField; + } + + /** + * @return \Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceModel + */ + private function getResource() + { + if (!$this->resourceModel) { + $this->resourceModel = $this->resourceFactory->create(); + } + + return $this->resourceModel; + } + + /** + * @param array $mediaGalleryData + * @param array $newMediaValues + * @param array $valueToProductId + * @return array + */ + private function prepareInsertData(array $mediaGalleryData, array $newMediaValues, array $valueToProductId) + { + $dataForSkinnyTable = []; + $multiInsertData = []; + foreach (array_keys($mediaGalleryData) as $storeId) { + foreach ($mediaGalleryData[$storeId] as $mediaGalleryRows) { + foreach ($mediaGalleryRows as $insertValue) { + foreach ($newMediaValues as $value_id => $values) { + if ($values['value'] == $insertValue['value']) { + $insertValue['value_id'] = $value_id; + $insertValue[$this->getProductEntityLinkField()] + = array_shift($valueToProductId[$values['value']]); + break; + } + } + if (isset($insertValue['value_id'])) { + $valueArr = [ + 'value_id' => $insertValue['value_id'], + 'store_id' => $storeId, + $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], + 'label' => $insertValue['label'], + 'position' => $insertValue['position'], + 'disabled' => $insertValue['disabled'], + ]; + $multiInsertData[] = $valueArr; + $dataForSkinnyTable[] = [ + 'value_id' => $insertValue['value_id'], + $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], + ]; + } + } + } + } + + return [$multiInsertData, $dataForSkinnyTable]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php index 269572ebcc27c..66dc304388a94 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php @@ -303,11 +303,6 @@ public function testExportWithMedia() $product = $productRepository->get('simple', 1); $mediaGallery = $product->getData('media_gallery'); $image = array_shift($mediaGallery['images']); - $expected = [ - 'hide_from_product_page' => 'hide_from_product_page', - '' => '', - $image['file'] => $image['file'], - ]; $this->model->setWriter( $this->objectManager->create( \Magento\ImportExport\Model\Export\Adapter\Csv::class @@ -320,7 +315,11 @@ public function testExportWithMedia() $varDirectory->writeFile('test_product_with_image.csv', $exportData); /** @var \Magento\Framework\File\Csv $csv */ $csv = $this->objectManager->get(\Magento\Framework\File\Csv::class); - $data = $csv->getDataPairs($varDirectory->getAbsolutePath('test_product_with_image.csv'), 76, 76); - self::assertSame($expected, $data); + $data = $csv->getData($varDirectory->getAbsolutePath('test_product_with_image.csv')); + foreach ($data[0] as $columnNumber => $columnName) { + if ($columnName === 'hide_from_product_page') { + self::assertSame($image['file'], $data[2][$columnNumber]); + } + } } } From 2a1b0418485c59a0711e88f6674137f97fa672de Mon Sep 17 00:00:00 2001 From: magento-engcom-team Date: Tue, 14 Nov 2017 11:44:17 +0200 Subject: [PATCH 05/11] 8255: Export Products action doesn't consider hide_for_product_page value. --- .../_files/product_export_with_images.php | 10 +++++----- .../_files/product_export_with_images_rollback.php | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images_rollback.php diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images.php index 1c9dbbb5553f8..da456767257e1 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images.php @@ -30,18 +30,18 @@ ] )->save(); $image = array_shift($product->getData('media_gallery')['images']); -$product->setStoreId(1)->setData( +$product = $productRepository->get('simple', false, 1, true); +$product->setData( 'media_gallery', [ 'images' => [ [ - 'file' => $image['file'], 'value_id' => $image['value_id'], - 'position' => 1, - 'label' => 'Image Alt Text', + 'file' => $image['file'], 'disabled' => 1, 'media_type' => 'image', ], ], ] -)->save(); +); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images_rollback.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images_rollback.php new file mode 100644 index 0000000000000..d7a52465ead4a --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_with_images_rollback.php @@ -0,0 +1,8 @@ + Date: Thu, 23 Nov 2017 17:06:31 +0200 Subject: [PATCH 06/11] 8255: Export Products action doesn't consider hide_for_product_page value. --- .../Import/Product/MediaGalleryProcessor.php | 164 ++++++++---------- 1 file changed, 73 insertions(+), 91 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php index bced070ae5609..55d908f2190dd 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php @@ -109,42 +109,73 @@ public function __construct( public function saveMediaGallery(array $mediaGalleryData) { $this->initMediaGalleryResources(); + $mediaGalleryDataGlobal = $this->processMediaGallery($mediaGalleryData); $imageNames = []; $multiInsertData = []; $valueToProductId = []; - $mediaGalleryData = $this->restoreDisableImage($mediaGalleryData); - foreach (array_keys($mediaGalleryData) as $storeId) { - foreach ($mediaGalleryData[$storeId] as $productSku => $mediaGalleryRows) { - $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; - - $insertedGalleryImgs = []; - foreach ($mediaGalleryRows as $insertValue) { - if (!in_array($insertValue['value'], $insertedGalleryImgs)) { - $valueArr = [ - 'attribute_id' => $insertValue['attribute_id'], - 'value' => $insertValue['value'], - ]; - $valueToProductId[$insertValue['value']][] = $productId; - $imageNames[] = $insertValue['value']; - $multiInsertData[] = $valueArr; - $insertedGalleryImgs[] = $insertValue['value']; - } + foreach ($mediaGalleryDataGlobal as $productSku => $mediaGalleryRows) { + $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; + $insertedGalleryImgs = []; + foreach ($mediaGalleryRows as $insertValue) { + if (!in_array($insertValue['value'], $insertedGalleryImgs)) { + $valueArr = [ + 'attribute_id' => $insertValue['attribute_id'], + 'value' => $insertValue['value'], + ]; + $valueToProductId[$insertValue['value']][] = $productId; + $imageNames[] = $insertValue['value']; + $multiInsertData[] = $valueArr; + $insertedGalleryImgs[] = $insertValue['value']; } } } - $multiInsertData = $this->filterImageInsertData($multiInsertData, $imageNames); - if ($multiInsertData) { + $oldMediaValues = $this->connection->fetchAssoc( + $this->connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value']) + ->where('value IN (?)', $imageNames) + ); + if (!empty($multiInsertData)) { $this->connection->insertOnDuplicate($this->mediaGalleryTableName, $multiInsertData); } + $multiInsertData = []; $newMediaSelect = $this->connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value']) ->where('value IN (?)', $imageNames); + if (array_keys($oldMediaValues)) { + $newMediaSelect->where('value_id NOT IN (?)', array_keys($oldMediaValues)); + } + $dataForSkinnyTable = []; $newMediaValues = $this->connection->fetchAssoc($newMediaSelect); - list($multiInsertData, $dataForSkinnyTable) = $this->prepareInsertData( - $mediaGalleryData, - $newMediaValues, - $valueToProductId - ); + $this->restoreDisableImage($mediaGalleryData); + foreach ($mediaGalleryData as $storeId => $mediaGalleryDataPerStore) { + foreach ($mediaGalleryDataPerStore as $productSku => $mediaGalleryRows) { + foreach ($mediaGalleryRows as $insertValue) { + foreach ($newMediaValues as $value_id => $values) { + if ($values['value'] == $insertValue['value']) { + $insertValue['value_id'] = $value_id; + $insertValue[$this->getProductEntityLinkField()] + = array_shift($valueToProductId[$values['value']]); + unset($newMediaValues[$value_id]); + break; + } + } + if (isset($insertValue['value_id'])) { + $valueArr = [ + 'value_id' => $insertValue['value_id'], + 'store_id' => $storeId, + $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], + 'label' => $insertValue['label'], + 'position' => $insertValue['position'], + 'disabled' => $insertValue['disabled'], + ]; + $multiInsertData[] = $valueArr; + $dataForSkinnyTable[] = [ + 'value_id' => $insertValue['value_id'], + $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], + ]; + } + } + } + } try { $this->connection->insertOnDuplicate( $this->mediaGalleryValueTableName, @@ -279,30 +310,6 @@ private function initMediaGalleryResources() } } - /** - * Remove existed images from insert data. - * - * @param array $multiInsertData - * @param array $imageNames - * @return array - */ - private function filterImageInsertData(array $multiInsertData, array $imageNames) - { - $oldMediaValues = $this->connection->fetchAssoc( - $this->connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value', 'attribute_id']) - ->where('value IN (?)', $imageNames) - ); - foreach ($multiInsertData as $key => $data) { - foreach ($oldMediaValues as $mediaValue) { - if ($data['value'] === $mediaValue['value'] && $data['attribute_id'] === $mediaValue['attribute_id']) { - unset($multiInsertData[$key]); - } - } - } - - return $multiInsertData; - } - /** * Set product images 'disable' = 0 for specified store. * @@ -336,6 +343,24 @@ private function restoreDisableImage(array $mediaGalleryData) return $mediaGalleryData; } + /** + * Remove store specific information for inserting images. + * + * @param array $mediaGalleryData + * @return array + */ + private function processMediaGallery(array $mediaGalleryData) + { + $mediaGalleryDataGlobal = array_merge(...$mediaGalleryData); + foreach ($mediaGalleryDataGlobal as $sku => $row) { + if (isset($mediaGalleryDataGlobal[$sku]['all']['restore'])) { + unset($mediaGalleryDataGlobal[$sku]); + } + } + + return $mediaGalleryDataGlobal; + } + /** * Get product entity link field. * @@ -361,47 +386,4 @@ private function getResource() return $this->resourceModel; } - - /** - * @param array $mediaGalleryData - * @param array $newMediaValues - * @param array $valueToProductId - * @return array - */ - private function prepareInsertData(array $mediaGalleryData, array $newMediaValues, array $valueToProductId) - { - $dataForSkinnyTable = []; - $multiInsertData = []; - foreach (array_keys($mediaGalleryData) as $storeId) { - foreach ($mediaGalleryData[$storeId] as $mediaGalleryRows) { - foreach ($mediaGalleryRows as $insertValue) { - foreach ($newMediaValues as $value_id => $values) { - if ($values['value'] == $insertValue['value']) { - $insertValue['value_id'] = $value_id; - $insertValue[$this->getProductEntityLinkField()] - = array_shift($valueToProductId[$values['value']]); - break; - } - } - if (isset($insertValue['value_id'])) { - $valueArr = [ - 'value_id' => $insertValue['value_id'], - 'store_id' => $storeId, - $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], - 'label' => $insertValue['label'], - 'position' => $insertValue['position'], - 'disabled' => $insertValue['disabled'], - ]; - $multiInsertData[] = $valueArr; - $dataForSkinnyTable[] = [ - 'value_id' => $insertValue['value_id'], - $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], - ]; - } - } - } - } - - return [$multiInsertData, $dataForSkinnyTable]; - } } From 51fa4bc17c9a31e30e01fa3ae8fabe2c4b3583fd Mon Sep 17 00:00:00 2001 From: magento-engcom-team Date: Thu, 23 Nov 2017 18:37:51 +0200 Subject: [PATCH 07/11] 8255: Export Products action doesn't consider hide_for_product_page value. --- .../Import/Product/MediaGalleryProcessor.php | 66 +++++++------------ 1 file changed, 23 insertions(+), 43 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php index 55d908f2190dd..857f8f99d212e 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php @@ -109,7 +109,8 @@ public function __construct( public function saveMediaGallery(array $mediaGalleryData) { $this->initMediaGalleryResources(); - $mediaGalleryDataGlobal = $this->processMediaGallery($mediaGalleryData); + $mediaGalleryData = $this->restoreDisableImage($mediaGalleryData); + $mediaGalleryDataGlobal = array_merge(...$mediaGalleryData); $imageNames = []; $multiInsertData = []; $valueToProductId = []; @@ -136,25 +137,22 @@ public function saveMediaGallery(array $mediaGalleryData) if (!empty($multiInsertData)) { $this->connection->insertOnDuplicate($this->mediaGalleryTableName, $multiInsertData); } - $multiInsertData = []; $newMediaSelect = $this->connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value']) ->where('value IN (?)', $imageNames); if (array_keys($oldMediaValues)) { $newMediaSelect->where('value_id NOT IN (?)', array_keys($oldMediaValues)); } - - $dataForSkinnyTable = []; $newMediaValues = $this->connection->fetchAssoc($newMediaSelect); - $this->restoreDisableImage($mediaGalleryData); foreach ($mediaGalleryData as $storeId => $mediaGalleryDataPerStore) { + $dataForSkinnyTable = []; + $multiInsertData = []; foreach ($mediaGalleryDataPerStore as $productSku => $mediaGalleryRows) { foreach ($mediaGalleryRows as $insertValue) { foreach ($newMediaValues as $value_id => $values) { if ($values['value'] == $insertValue['value']) { $insertValue['value_id'] = $value_id; - $insertValue[$this->getProductEntityLinkField()] - = array_shift($valueToProductId[$values['value']]); - unset($newMediaValues[$value_id]); + $ids = array_values($valueToProductId[$values['value']]); + $insertValue[$this->getProductEntityLinkField()] = array_shift($ids); break; } } @@ -175,23 +173,23 @@ public function saveMediaGallery(array $mediaGalleryData) } } } - } - try { - $this->connection->insertOnDuplicate( - $this->mediaGalleryValueTableName, - $multiInsertData, - ['value_id', 'store_id', $this->getProductEntityLinkField(), 'label', 'position', 'disabled'] - ); - $this->connection->insertOnDuplicate( - $this->mediaGalleryEntityToValueTableName, - $dataForSkinnyTable, - ['value_id'] - ); - } catch (\Exception $e) { - $this->connection->delete( - $this->mediaGalleryTableName, - $this->connection->quoteInto('value_id IN (?)', $newMediaValues) - ); + try { + $this->connection->insertOnDuplicate( + $this->mediaGalleryValueTableName, + $multiInsertData, + ['value_id', 'store_id', $this->getProductEntityLinkField(), 'label', 'position', 'disabled'] + ); + $this->connection->insertOnDuplicate( + $this->mediaGalleryEntityToValueTableName, + $dataForSkinnyTable, + ['value_id'] + ); + } catch (\Exception $e) { + $this->connection->delete( + $this->mediaGalleryTableName, + $this->connection->quoteInto('value_id IN (?)', $newMediaValues) + ); + } } } @@ -343,24 +341,6 @@ private function restoreDisableImage(array $mediaGalleryData) return $mediaGalleryData; } - /** - * Remove store specific information for inserting images. - * - * @param array $mediaGalleryData - * @return array - */ - private function processMediaGallery(array $mediaGalleryData) - { - $mediaGalleryDataGlobal = array_merge(...$mediaGalleryData); - foreach ($mediaGalleryDataGlobal as $sku => $row) { - if (isset($mediaGalleryDataGlobal[$sku]['all']['restore'])) { - unset($mediaGalleryDataGlobal[$sku]); - } - } - - return $mediaGalleryDataGlobal; - } - /** * Get product entity link field. * From 5dc5acdbae841d04118408fb6d73b85f33529e60 Mon Sep 17 00:00:00 2001 From: magento-engcom-team Date: Fri, 24 Nov 2017 16:03:06 +0200 Subject: [PATCH 08/11] 8255: Export Products action doesn't consider hide_for_product_page value. --- .../Import/Product/MediaGalleryProcessor.php | 117 ++++++++++-------- 1 file changed, 68 insertions(+), 49 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php index 857f8f99d212e..045f0942021bc 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php @@ -109,7 +109,7 @@ public function __construct( public function saveMediaGallery(array $mediaGalleryData) { $this->initMediaGalleryResources(); - $mediaGalleryData = $this->restoreDisableImage($mediaGalleryData); + $mediaGalleryData = $this->restoreDisabledImage($mediaGalleryData); $mediaGalleryDataGlobal = array_merge(...$mediaGalleryData); $imageNames = []; $multiInsertData = []; @@ -143,53 +143,8 @@ public function saveMediaGallery(array $mediaGalleryData) $newMediaSelect->where('value_id NOT IN (?)', array_keys($oldMediaValues)); } $newMediaValues = $this->connection->fetchAssoc($newMediaSelect); - foreach ($mediaGalleryData as $storeId => $mediaGalleryDataPerStore) { - $dataForSkinnyTable = []; - $multiInsertData = []; - foreach ($mediaGalleryDataPerStore as $productSku => $mediaGalleryRows) { - foreach ($mediaGalleryRows as $insertValue) { - foreach ($newMediaValues as $value_id => $values) { - if ($values['value'] == $insertValue['value']) { - $insertValue['value_id'] = $value_id; - $ids = array_values($valueToProductId[$values['value']]); - $insertValue[$this->getProductEntityLinkField()] = array_shift($ids); - break; - } - } - if (isset($insertValue['value_id'])) { - $valueArr = [ - 'value_id' => $insertValue['value_id'], - 'store_id' => $storeId, - $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], - 'label' => $insertValue['label'], - 'position' => $insertValue['position'], - 'disabled' => $insertValue['disabled'], - ]; - $multiInsertData[] = $valueArr; - $dataForSkinnyTable[] = [ - 'value_id' => $insertValue['value_id'], - $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], - ]; - } - } - } - try { - $this->connection->insertOnDuplicate( - $this->mediaGalleryValueTableName, - $multiInsertData, - ['value_id', 'store_id', $this->getProductEntityLinkField(), 'label', 'position', 'disabled'] - ); - $this->connection->insertOnDuplicate( - $this->mediaGalleryEntityToValueTableName, - $dataForSkinnyTable, - ['value_id'] - ); - } catch (\Exception $e) { - $this->connection->delete( - $this->mediaGalleryTableName, - $this->connection->quoteInto('value_id IN (?)', $newMediaValues) - ); - } + foreach ($mediaGalleryData as $storeId => $storeMediaGalleryData) { + $this->processMediaPerStore((int)$storeId, $storeMediaGalleryData, $newMediaValues, $valueToProductId); } } @@ -314,7 +269,7 @@ private function initMediaGalleryResources() * @param array $mediaGalleryData * @return array */ - private function restoreDisableImage(array $mediaGalleryData) + private function restoreDisabledImage(array $mediaGalleryData) { $restoreData = []; foreach (array_keys($mediaGalleryData) as $storeId) { @@ -341,6 +296,70 @@ private function restoreDisableImage(array $mediaGalleryData) return $mediaGalleryData; } + /** + * Save media gallery data per store. + * + * @param $storeId + * @param array $mediaGalleryData + * @param array $newMediaValues + * @param array $valueToProductId + * @return void + */ + private function processMediaPerStore( + int $storeId, + array $mediaGalleryData, + array $newMediaValues, + array $valueToProductId + ) { + $multiInsertData = []; + $dataForSkinnyTable = []; + foreach ($mediaGalleryData as $mediaGalleryRows) { + foreach ($mediaGalleryRows as $insertValue) { + foreach ($newMediaValues as $value_id => $values) { + if ($values['value'] == $insertValue['value']) { + $insertValue['value_id'] = $value_id; + $insertValue[$this->getProductEntityLinkField()] + = array_shift($valueToProductId[$values['value']]); + unset($newMediaValues[$value_id]); + break; + } + } + if (isset($insertValue['value_id'])) { + $valueArr = [ + 'value_id' => $insertValue['value_id'], + 'store_id' => $storeId, + $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], + 'label' => $insertValue['label'], + 'position' => $insertValue['position'], + 'disabled' => $insertValue['disabled'], + ]; + $multiInsertData[] = $valueArr; + $dataForSkinnyTable[] = [ + 'value_id' => $insertValue['value_id'], + $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], + ]; + } + } + } + try { + $this->connection->insertOnDuplicate( + $this->mediaGalleryValueTableName, + $multiInsertData, + ['value_id', 'store_id', $this->getProductEntityLinkField(), 'label', 'position', 'disabled'] + ); + $this->connection->insertOnDuplicate( + $this->mediaGalleryEntityToValueTableName, + $dataForSkinnyTable, + ['value_id'] + ); + } catch (\Exception $e) { + $this->connection->delete( + $this->mediaGalleryTableName, + $this->connection->quoteInto('value_id IN (?)', $newMediaValues) + ); + } + } + /** * Get product entity link field. * From 8aa3da1ec3cd5204e0857f43e46abef824d4d13d Mon Sep 17 00:00:00 2001 From: magento-engcom-team Date: Mon, 27 Nov 2017 18:14:39 +0200 Subject: [PATCH 09/11] 8255: Export Products action doesn't consider hide_for_product_page value. --- .../Model/Export/Product.php | 33 +++++-------------- .../_files/product_simple_multistore.php | 6 ++-- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index 4174fbefd90ef..45530ed6d7bae 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -905,7 +905,7 @@ protected function getExportData() $dataRow = array_merge($dataRow, $stockItemRows[$productId]); } $this->appendMultirowData($dataRow, $multirawData); - if ($dataRow && !$this->skipRow($dataRow)) { + if ($dataRow) { $exportData[] = $dataRow; } } @@ -1169,14 +1169,17 @@ private function appendMultirowData(&$dataRow, $multiRawData) $productLinkId = $dataRow['product_link_id']; $storeId = $dataRow['store_id']; $sku = $dataRow[self::COL_SKU]; + $type = $dataRow[self::COL_TYPE]; + $attributeSet = $dataRow[self::COL_ATTR_SET]; unset($dataRow['product_id']); unset($dataRow['product_link_id']); unset($dataRow['store_id']); unset($dataRow[self::COL_SKU]); - + unset($dataRow[self::COL_STORE]); + unset($dataRow[self::COL_ATTR_SET]); + unset($dataRow[self::COL_TYPE]); if (Store::DEFAULT_STORE_ID == $storeId) { - unset($dataRow[self::COL_STORE]); $this->updateDataWithCategoryColumns($dataRow, $multiRawData['rowCategories'], $productId); if (!empty($multiRawData['rowWebsites'][$productId])) { $websiteCodes = []; @@ -1274,6 +1277,9 @@ private function appendMultirowData(&$dataRow, $multiRawData) $dataRow[self::COL_STORE] = $this->_storeIdToCode[$storeId]; } $dataRow[self::COL_SKU] = $sku; + $dataRow[self::COL_ATTR_SET] = $attributeSet; + $dataRow[self::COL_TYPE] = $type; + return $dataRow; } @@ -1512,25 +1518,4 @@ protected function getProductEntityLinkField() } return $this->productEntityLinkField; } - - /** - * Check if row has valuable information to export. - * - * @param array $dataRow - * @return bool - */ - private function skipRow(array $dataRow) - { - $baseInfo = [ - self::COL_STORE, - self::COL_ATTR_SET, - self::COL_TYPE, - self::COL_SKU, - 'store_id', - 'product_id', - 'product_link_id', - ]; - - return empty(array_diff(array_keys($dataRow), $baseInfo)); - } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_multistore.php b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_multistore.php index 7829797c54e6c..4d4eb7fd8cdd7 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_multistore.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/_files/product_simple_multistore.php @@ -19,7 +19,8 @@ 1 )->setAttributeSetId( 4 -)->setStoreId( +)->setCustomAttribute( + 'tax_class_id', 1 )->setWebsiteIds( [1] @@ -42,8 +43,7 @@ )->save(); $product = $objectManager->create(\Magento\Catalog\Model\Product::class); -$product->setStoreId(1) - ->load(1) +$product->load(1) ->setStoreId($store->getId()) ->setName('StoreTitle') ->save(); From a22d2233be0773e0297bd49e97db05068161d964 Mon Sep 17 00:00:00 2001 From: magento-engcom-team Date: Tue, 28 Nov 2017 16:07:25 +0200 Subject: [PATCH 10/11] 8255: Export Products action doesn't consider hide_for_product_page value. --- .../Model/Import/Product/MediaGalleryProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php index 045f0942021bc..d45881b88c630 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php @@ -110,7 +110,7 @@ public function saveMediaGallery(array $mediaGalleryData) { $this->initMediaGalleryResources(); $mediaGalleryData = $this->restoreDisabledImage($mediaGalleryData); - $mediaGalleryDataGlobal = array_merge(...$mediaGalleryData); + $mediaGalleryDataGlobal = array_replace_recursive(...$mediaGalleryData); $imageNames = []; $multiInsertData = []; $valueToProductId = []; From e46c8fdd6a28f422bf4e008924af21dbfd3ffffb Mon Sep 17 00:00:00 2001 From: magento-engcom-team Date: Wed, 29 Nov 2017 17:27:09 +0200 Subject: [PATCH 11/11] 8255: Export Products action doesn't consider hide_for_product_page value. --- .../Model/Import/Product.php | 19 ++-------- .../Import/Product/MediaGalleryProcessor.php | 38 +------------------ .../Model/Import/ProductTest.php | 2 +- 3 files changed, 6 insertions(+), 53 deletions(-) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product.php b/app/code/Magento/CatalogImportExport/Model/Import/Product.php index 43d39b92978cd..9dbeaeaba6938 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product.php @@ -1670,17 +1670,10 @@ protected function _saveProducts() $disabledImages = array_flip( explode($this->getMultipleValueSeparator(), $rowData['_media_is_disabled']) ); - foreach ($disabledImages as $disabledImage => $position) { - $uploadedFile = $this->uploadMediaFiles($disabledImage, true); - $uploadedFile = $uploadedFile ?: $this->getSystemFile($disabledImage); - $mediaGallery[$storeId][$rowSku][$uploadedFile] = [ - 'attribute_id' => $this->getMediaGalleryAttributeId(), - 'label' => $rowLabels[self::COL_MEDIA_IMAGE][$position] ?? '', - 'position' => $position, - 'disabled' => 1, - 'value' => $disabledImage, - 'store_id' => $storeId, - ]; + if (empty($rowImages)) { + foreach (array_keys($disabledImages) as $disabledImage) { + $rowImages[self::COL_MEDIA_IMAGE][] = $disabledImage; + } } } $rowData[self::COL_MEDIA_IMAGE] = []; @@ -1740,10 +1733,6 @@ protected function _saveProducts() } } - //Add images to restore "hide from product page" value for specified store and product. - if (empty($mediaGallery[$storeId][$rowSku])) { - $mediaGallery[$storeId][$rowSku]['all'] = ['restore' => true]; - } // 6. Attributes phase $rowStore = (self::SCOPE_STORE == $rowScope) ? $this->storeResolver->getStoreCodeToId($rowData[self::COL_STORE]) diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php index d45881b88c630..ec7c6a1172996 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/MediaGalleryProcessor.php @@ -109,7 +109,6 @@ public function __construct( public function saveMediaGallery(array $mediaGalleryData) { $this->initMediaGalleryResources(); - $mediaGalleryData = $this->restoreDisabledImage($mediaGalleryData); $mediaGalleryDataGlobal = array_replace_recursive(...$mediaGalleryData); $imageNames = []; $multiInsertData = []; @@ -134,9 +133,7 @@ public function saveMediaGallery(array $mediaGalleryData) $this->connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value']) ->where('value IN (?)', $imageNames) ); - if (!empty($multiInsertData)) { - $this->connection->insertOnDuplicate($this->mediaGalleryTableName, $multiInsertData); - } + $this->connection->insertOnDuplicate($this->mediaGalleryTableName, $multiInsertData); $newMediaSelect = $this->connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value']) ->where('value IN (?)', $imageNames); if (array_keys($oldMediaValues)) { @@ -263,39 +260,6 @@ private function initMediaGalleryResources() } } - /** - * Set product images 'disable' = 0 for specified store. - * - * @param array $mediaGalleryData - * @return array - */ - private function restoreDisabledImage(array $mediaGalleryData) - { - $restoreData = []; - foreach (array_keys($mediaGalleryData) as $storeId) { - foreach ($mediaGalleryData[$storeId] as $productSku => $mediaGalleryRows) { - $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; - $restoreData[] = sprintf( - 'store_id = %s and %s = %s', - $storeId, - $this->getProductEntityLinkField(), - $productId - ); - if (isset($mediaGalleryRows['all']['restore'])) { - unset($mediaGalleryData[$storeId][$productSku]); - } - } - } - - $this->connection->update( - $this->mediaGalleryValueTableName, - ['disabled' => 0], - new \Zend_Db_Expr(implode(' or ', $restoreData)) - ); - - return $mediaGalleryData; - } - /** * Save media gallery data per store. * diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php index 3d4dd7c9cf8b9..6c673ad4712a1 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/ProductTest.php @@ -1983,7 +1983,7 @@ public function testImportImageForNonDefaultStore() $product = $this->getProductBySku('simple_with_images'); $mediaGallery = $product->getData('media_gallery'); foreach ($mediaGallery['images'] as $image) { - $image['file'] === 'magento_image.jpg' + $image['file'] === '/m/a/magento_image.jpg' ? self::assertSame('1', $image['disabled']) : self::assertSame('0', $image['disabled']); }