Skip to content

Commit c0765dd

Browse files
author
Oleksandr Dubovyk
committed
Merge remote-tracking branch 'local/MC-38810' into PRodubovyk20201222
2 parents d08f452 + 9544ad0 commit c0765dd

File tree

11 files changed

+140
-10
lines changed

11 files changed

+140
-10
lines changed

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

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,64 @@ public function testExport(): void
108108
$this->assertEquals(1, $occurrencesCount);
109109
}
110110

111+
/**
112+
* Verify successful export of the product with custom attributes containing json and markup
113+
*
114+
* @magentoDataFixture Magento/Catalog/_files/product_text_attribute.php
115+
* @magentoDataFixture Magento/Catalog/_files/second_product_simple.php
116+
* @magentoDbIsolation enabled
117+
* @dataProvider exportWithJsonAndMarkupTextAttributeDataProvider
118+
* @param string $attributeData
119+
* @param string $expectedResult
120+
* @return void
121+
*/
122+
public function testExportWithJsonAndMarkupTextAttribute(string $attributeData, string $expectedResult): void
123+
{
124+
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository */
125+
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
126+
$productRepository = $objectManager->get(\Magento\Catalog\Api\ProductRepositoryInterface::class);
127+
$product = $productRepository->get('simple2');
128+
129+
/** @var \Magento\Eav\Model\Config $eavConfig */
130+
$eavConfig = $objectManager->get(\Magento\Eav\Model\Config::class);
131+
$eavConfig->clear();
132+
$attribute = $eavConfig->getAttribute(\Magento\Catalog\Model\Product::ENTITY, 'text_attribute');
133+
$attribute->setDefaultValue($attributeData);
134+
/** @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface $productAttributeRepository */
135+
$productAttributeRepository = $objectManager->get(\Magento\Catalog\Api\ProductAttributeRepositoryInterface::class);
136+
$productAttributeRepository->save($attribute);
137+
$product->setCustomAttribute('text_attribute', $attribute->getDefaultValue());
138+
$productRepository->save($product);
139+
140+
$this->model->setWriter(
141+
$this->objectManager->create(
142+
\Magento\ImportExport\Model\Export\Adapter\Csv::class
143+
)
144+
);
145+
$exportData = $this->model->export();
146+
$this->assertStringContainsString('Simple Product2', $exportData);
147+
$this->assertStringContainsString($expectedResult, $exportData);
148+
}
149+
150+
/**
151+
* @return array
152+
*/
153+
public function exportWithJsonAndMarkupTextAttributeDataProvider(): array
154+
{
155+
return [
156+
'json' => [
157+
'{"type": "basic", "unit": "inch", "sign": "(\")", "size": "1.5\""}',
158+
'"text_attribute={""type"": ""basic"", ""unit"": ""inch"", ""sign"": ""(\"")"", ""size"": ""1.5\""""}"'
159+
],
160+
'markup' => [
161+
'<div data-content>Element type is basic, measured in inches ' .
162+
'(marked with sign (\")) with size 1.5\", mid-price range</div>',
163+
'"text_attribute=<div data-content>Element type is basic, measured in inches ' .
164+
'(marked with sign (\"")) with size 1.5\"", mid-price range</div>"'
165+
],
166+
];
167+
}
168+
111169
/**
112170
* @magentoDataFixture Magento/CatalogImportExport/_files/product_export_data_special_chars.php
113171
* @magentoDbIsolation enabled

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

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2344,6 +2344,67 @@ public function testProductWithWrappedAdditionalAttributes()
23442344
);
23452345
}
23462346

2347+
/**
2348+
* @magentoDataFixture Magento/Catalog/_files/product_text_attribute.php
2349+
* @magentoAppIsolation enabled
2350+
* @magentoDbIsolation enabled
2351+
* @dataProvider importWithJsonAndMarkupTextAttributeDataProvider
2352+
* @param string $productSku
2353+
* @param string $expectedResult
2354+
* @return void
2355+
*/
2356+
public function testImportWithJsonAndMarkupTextAttribute(string $productSku, string $expectedResult): void
2357+
{
2358+
// added by _files/product_import_with_json_and_markup_attributes.csv
2359+
$this->importedProducts = [
2360+
'SkuProductWithJson',
2361+
'SkuProductWithMarkup',
2362+
];
2363+
2364+
$importParameters =[
2365+
'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND,
2366+
'entity' => 'catalog_product',
2367+
\Magento\ImportExport\Model\Import::FIELDS_ENCLOSURE => 0
2368+
];
2369+
$filesystem = $this->objectManager->create(\Magento\Framework\Filesystem::class);
2370+
$directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT);
2371+
$source = $this->objectManager->create(
2372+
\Magento\ImportExport\Model\Import\Source\Csv::class,
2373+
[
2374+
'file' => __DIR__ . '/_files/products_to_import_with_json_and_markup_attributes.csv',
2375+
'directory' => $directory
2376+
]
2377+
);
2378+
$this->_model->setParameters($importParameters);
2379+
$this->_model->setSource($source);
2380+
$errors = $this->_model->validateData();
2381+
$this->assertTrue($errors->getErrorsCount() == 0);
2382+
$this->_model->importData();
2383+
$productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
2384+
\Magento\Catalog\Api\ProductRepositoryInterface::class
2385+
);
2386+
$product = $productRepository->get($productSku);
2387+
$this->assertEquals($expectedResult, $product->getData('text_attribute'));
2388+
}
2389+
2390+
/**
2391+
* @return array
2392+
*/
2393+
public function importWithJsonAndMarkupTextAttributeDataProvider(): array
2394+
{
2395+
return [
2396+
'import of attribute with json' => [
2397+
'SkuProductWithJson',
2398+
'{"type": "basic", "unit": "inch", "sign": "(\")", "size": "1.5\""}'
2399+
],
2400+
'import of attribute with markup' => [
2401+
'SkuProductWithMarkup',
2402+
'<div data-content>Element type is basic, measured in inches ' .
2403+
'(marked with sign (\")) with size 1.5\", mid-price range</div>'
2404+
],
2405+
];
2406+
}
2407+
23472408
/**
23482409
* Import and check data from file.
23492410
*
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
sku,product_type,name,price,attribute_set_code,categories,additional_attributes
2+
SkuProductWithJson,simple,"Product With Json Attribute",100,Default,"Default Category/Category 1","text_attribute={""type"": ""basic"", ""unit"": ""inch"", ""sign"": ""(\"")"", ""size"": ""1.5\""""}"
3+
SkuProductWithMarkup,simple,"Product With Markup Attribute",100,Default,"Default Category/Category 1","text_attribute=<div data-content>Element type is basic, measured in inches (marked with sign (\"")) with size 1.5\"", mid-price range</div>"

dev/tests/integration/testsuite/Magento/Setup/Console/Command/DependenciesShowFrameworkCommandTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@ public function testExecute()
7070
);
7171
$this->assertStringContainsString('"Dependencies for each module:",' . PHP_EOL, $fileContents);
7272
$this->assertStringContainsString(
73-
'"Magento\A",1' . PHP_EOL . '" -- Magento\Framework",2' . PHP_EOL,
73+
'Magento\A,1' . PHP_EOL . '" -- Magento\Framework",2' . PHP_EOL,
7474
$fileContents
7575
);
7676
$this->assertStringContainsString(
77-
'"Magento\B",1' . PHP_EOL . '" -- Magento\Framework",2' . PHP_EOL,
77+
'Magento\B,1' . PHP_EOL . '" -- Magento\Framework",2' . PHP_EOL,
7878
$fileContents
7979
);
8080
}

dev/tests/integration/testsuite/Magento/Setup/Module/Dependency/_files/expected/framework-dependencies.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
,3
33

44
"Dependencies for each module:",
5-
"Magento\FirstModule",3
5+
Magento\FirstModule,3
66
" -- Magento\LibFirst",1
77
" -- Magento\LibSecond",2
88
" -- Magento\Third",1

lib/internal/Magento/Framework/File/Csv.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ class Csv
3030
*/
3131
protected $_enclosure = '"';
3232

33+
/**
34+
* @var string
35+
*/
36+
private $escape = "\0";
37+
3338
/**
3439
* @var File
3540
*/
@@ -96,7 +101,7 @@ public function getData($file)
96101
}
97102

98103
$fh = fopen($file, 'r');
99-
while ($rowData = fgetcsv($fh, $this->_lineLength, $this->_delimiter, $this->_enclosure)) {
104+
while ($rowData = fgetcsv($fh, $this->_lineLength, $this->_delimiter, $this->_enclosure, $this->escape)) {
100105
$data[] = $rowData;
101106
}
102107
fclose($fh);

lib/internal/Magento/Framework/Filesystem/Driver/File.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ public function fileRead($resource, $length)
647647
* @return array|bool|null
648648
* @throws FileSystemException
649649
*/
650-
public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\')
650+
public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = "\0")
651651
{
652652
$result = @fgetcsv($resource, $length, $delimiter, $enclosure, $escape);
653653
if ($result === null) {
@@ -801,7 +801,10 @@ public function filePutCsv($resource, array $data, $delimiter = ',', $enclosure
801801
}
802802
}
803803

804-
$result = @fputcsv($resource, $data, $delimiter, $enclosure);
804+
// Escape symbol is needed to fix known issue in PHP broken fputcsv escaping functionality
805+
// where backslash followed by double quote breaks file consistency
806+
$escape = "\0";
807+
$result = @fputcsv($resource, $data, $delimiter, $enclosure, $escape);
805808
if (!$result) {
806809
throw new FileSystemException(
807810
new Phrase(

lib/internal/Magento/Framework/Filesystem/Driver/StatefulFile.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ public function fileRead($resource, $length)
642642
* @return array|bool|null
643643
* @throws FileSystemException
644644
*/
645-
public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\')
645+
public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = "\0")
646646
{
647647
$result = @fgetcsv($resource, $length, $delimiter, $enclosure, $escape);
648648
if ($result === null) {

lib/internal/Magento/Framework/Filesystem/DriverInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ public function fileRead($resource, $length);
276276
* @return array|bool|null
277277
* @throws FileSystemException
278278
*/
279-
public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\');
279+
public function fileGetCsv($resource, $length = 0, $delimiter = ',', $enclosure = '"', $escape = "\0");
280280

281281
/**
282282
* Returns position of read/write pointer

lib/internal/Magento/Framework/Filesystem/File/Read.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public function readLine($length, $ending = null)
124124
* @param string $escape [optional]
125125
* @return array|bool|null
126126
*/
127-
public function readCsv($length = 0, $delimiter = ',', $enclosure = '"', $escape = '\\')
127+
public function readCsv($length = 0, $delimiter = ',', $enclosure = '"', $escape = "\0")
128128
{
129129
return $this->driver->fileGetCsv($this->resource, $length, $delimiter, $enclosure, $escape);
130130
}

0 commit comments

Comments
 (0)