diff --git a/app/code/Magento/CatalogImportExport/Model/Export/Product.php b/app/code/Magento/CatalogImportExport/Model/Export/Product.php index 6f9dda090914a..97a0e6aaebf4f 100644 --- a/app/code/Magento/CatalogImportExport/Model/Export/Product.php +++ b/app/code/Magento/CatalogImportExport/Model/Export/Product.php @@ -5,6 +5,7 @@ */ namespace Magento\CatalogImportExport\Model\Export; +use Magento\CatalogImportExport\Model\Import\Product\CategoryProcessor; use Magento\ImportExport\Model\Import; use \Magento\Store\Model\Store; use \Magento\CatalogImportExport\Model\Import\Product as ImportProduct; @@ -438,11 +439,12 @@ protected function initCategories() if ($pathSize > 1) { $path = []; for ($i = 1; $i < $pathSize; $i++) { - $path[] = $collection->getItemById($structure[$i])->getName(); + $name = $collection->getItemById($structure[$i])->getName(); + $path[] = $this->quoteCategoryDelimiter($name); } $this->_rootCategories[$category->getId()] = array_shift($path); if ($pathSize > 2) { - $this->_categories[$category->getId()] = implode('/', $path); + $this->_categories[$category->getId()] = implode(CategoryProcessor::DELIMITER_CATEGORY, $path); } } } @@ -1470,4 +1472,19 @@ protected function getProductEntityLinkField() } return $this->productEntityLinkField; } + + /** + * Quoting category delimiter character in string. + * + * @param string $string + * @return string + */ + private function quoteCategoryDelimiter($string) + { + return str_replace( + CategoryProcessor::DELIMITER_CATEGORY, + '\\' . CategoryProcessor::DELIMITER_CATEGORY, + $string + ); + } } diff --git a/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php b/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php index 81c83c38bb546..788623d822e31 100644 --- a/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php +++ b/app/code/Magento/CatalogImportExport/Model/Import/Product/CategoryProcessor.php @@ -84,7 +84,8 @@ protected function initCategories() if ($pathSize > 1) { $path = []; for ($i = 1; $i < $pathSize; $i++) { - $path[] = $collection->getItemById((int)$structure[$i])->getName(); + $name = $collection->getItemById((int)$structure[$i])->getName(); + $path[] = $this->quoteDelimiter($name); } /** @var string $index */ $index = $this->standardizeString( @@ -114,7 +115,7 @@ protected function createCategory($name, $parentId) } $category->setPath($parentCategory->getPath()); $category->setParentId($parentId); - $category->setName($name); + $category->setName($this->unquoteDelimiter($name)); $category->setIsActive(true); $category->setIncludeInMenu(true); $category->setAttributeSetId($category->getDefaultAttributeSetId()); @@ -137,7 +138,7 @@ protected function upsertCategory($categoryPath) $index = $this->standardizeString($categoryPath); if (!isset($this->categories[$index])) { - $pathParts = explode(self::DELIMITER_CATEGORY, $categoryPath); + $pathParts = preg_split('~(?create(\Magento\Catalog\Model\Category::class); +$category->isObjectNew(true); +$category->setId( + 3331 +)->setCreatedAt( + '2017-06-23 09:50:07' +)->setName( + 'Category with slash/ symbol' +)->setParentId( + 2 +)->setPath( + '1/2/3331' +)->setLevel( + 2 +)->setAvailableSortBy( + ['position', 'name'] +)->setDefaultSortBy( + 'name' +)->setIsActive( + true +)->setPosition( + 1 +)->save(); 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..6cdca3e6e46af 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Export/ProductTest.php @@ -104,6 +104,7 @@ public function testExportSpecialChars() ); $exportData = $this->model->export(); $this->assertContains('simple ""1""', $exportData); + $this->assertContains('Category with slash\/ symbol', $exportData); } /** diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv index c0deb9b289fd3..4885522f5a363 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_custom_separator.csv @@ -1,2 +1,2 @@ sku,product_type,store_view_code,name,price,attribute_set_code,categories,product_websites -simple1,simple,,"simple 2",25,Default,"Default Category/Category 1|Default Category/Category 2",base +simple1,simple,,"simple 2",25,Default,"Default Category/Category 1|Default Category/Category\/ 2",base diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_default_separator.csv b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_default_separator.csv index 9bf687dec4632..80ed257f25078 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_default_separator.csv +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/Model/Import/_files/import_new_categories_default_separator.csv @@ -1,2 +1,2 @@ sku,product_type,store_view_code,name,price,attribute_set_code,categories,product_websites,url_key -simple1,simple,,"simple 1",25,Default,"Default Category/Category 1,Default Category/Category 2",base,simple1-ds +simple1,simple,,"simple 1",25,Default,"Default Category/Category 1,Default Category/Category\/ 2",base,simple1-ds diff --git a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_special_chars.php b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_special_chars.php index 06a686d9d7830..8c7e0ab151410 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_special_chars.php +++ b/dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data_special_chars.php @@ -5,6 +5,8 @@ */ /** Create category */ require dirname(dirname(__DIR__)) . '/Catalog/_files/category.php'; +/** Create category with special chars */ +require dirname(dirname(__DIR__)) . '/Catalog/_files/catalog_category_with_slash.php'; /** Create fixture store */ require dirname(dirname(__DIR__)) . '/Store/_files/second_store.php'; /** Create product with multiselect attribute and values */ @@ -28,10 +30,8 @@ ->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH) ->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) ->setWebsiteIds([1]) - ->setCateroryIds([]) ->setStockData(['qty' => 100, 'is_in_stock' => 1]) ->setCanSaveCustomOptions(true) - ->setCategoryIds([333]) - ->setUpSellLinkData([$product->getId() => ['position' => 1]]); + ->setCategoryIds([333, 3331]); $productModel->setOptions([])->save();