Skip to content

Commit 6b3eb27

Browse files
author
cspruiell
committed
MAGETWO-58742: [Backport] After upgrading from 2.0.7 to 2.1, editing a category gives a 500 error - for 2.1.3
- Merge remote-tracking branch 'origin/MAGETWO-58742-category_500_error_2.1.3' into okapis-2.1.3-pr
2 parents f449e93 + a0e1872 commit 6b3eb27

File tree

8 files changed

+122
-32
lines changed

8 files changed

+122
-32
lines changed

app/code/Magento/BundleImportExport/Model/Export/RowCustomizer.php

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,7 @@ private function getShipmentTypeValue($type)
331331
protected function cleanNotBundleAdditionalAttributes($dataRow)
332332
{
333333
if (!empty($dataRow['additional_attributes'])) {
334-
$additionalAttributes = explode(
335-
ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR,
336-
$dataRow['additional_attributes']
337-
);
334+
$additionalAttributes = $this->parseAdditionalAttributes($dataRow['additional_attributes']);
338335
$dataRow['additional_attributes'] = $this->getNotBundleAttributes($additionalAttributes);
339336
}
340337

@@ -349,17 +346,37 @@ protected function cleanNotBundleAdditionalAttributes($dataRow)
349346
*/
350347
protected function getNotBundleAttributes($additionalAttributes)
351348
{
352-
$cleanedAdditionalAttributes = '';
353-
foreach ($additionalAttributes as $attribute) {
354-
list($attributeCode, $attributeValue) = explode(ImportProductModel::PAIR_NAME_VALUE_SEPARATOR, $attribute);
355-
if (!in_array('bundle_' . $attributeCode, $this->getBundleColumns())) {
356-
$cleanedAdditionalAttributes .= $attributeCode
357-
. ImportProductModel::PAIR_NAME_VALUE_SEPARATOR
358-
. $attributeValue
359-
. ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR;
349+
$filteredAttributes = [];
350+
foreach ($additionalAttributes as $code => $value) {
351+
if (!in_array('bundle_' . $code, $this->getBundleColumns())) {
352+
$filteredAttributes[] = $code . ImportProductModel::PAIR_NAME_VALUE_SEPARATOR . $value;
360353
}
361354
}
355+
return implode(ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $filteredAttributes);
356+
}
362357

363-
return rtrim($cleanedAdditionalAttributes, ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR);
358+
/**
359+
* Retrieves additional attributes as array code=>value
360+
*
361+
* @param string $additionalAttributes
362+
* @return array
363+
*/
364+
private function parseAdditionalAttributes($additionalAttributes)
365+
{
366+
$attributeNameValuePairs = explode(ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR, $additionalAttributes);
367+
$preparedAttributes = [];
368+
$code = '';
369+
foreach ($attributeNameValuePairs as $attributeData) {
370+
if (strpos($attributeData, ImportProductModel::PAIR_NAME_VALUE_SEPARATOR) === false) {
371+
if (!$code) {
372+
continue;
373+
}
374+
$preparedAttributes[$code] .= ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR . $attributeData;
375+
continue;
376+
}
377+
list($code, $value) = explode(ImportProductModel::PAIR_NAME_VALUE_SEPARATOR, $attributeData, 2);
378+
$preparedAttributes[$code] = $value;
379+
}
380+
return $preparedAttributes;
364381
}
365382
}

app/code/Magento/BundleImportExport/Test/Unit/Model/Export/Product/RowCustomizerTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,15 +178,16 @@ public function testAddHeaderColumns()
178178
public function testAddData()
179179
{
180180
$preparedData = $this->rowCustomizerMock->prepareData($this->productResourceCollection, [1]);
181-
$attributes = 'attribute=1,sku_type=1,price_type=1,price_view=1,weight_type=1,values=values,shipment_type=1';
181+
$attributes = 'attribute=1,sku_type=1,attribute2="Text",price_type=1,price_view=1,weight_type=1,'
182+
. 'values=values,shipment_type=1,attribute3=One,Two,Three';
182183
$dataRow = [
183184
'sku' => 'sku1',
184185
'additional_attributes' => $attributes
185186
];
186187
$preparedRow = $preparedData->addData($dataRow, 1);
187188
$expected = [
188189
'sku' => 'sku1',
189-
'additional_attributes' => 'attribute=1',
190+
'additional_attributes' => 'attribute=1,attribute2="Text",attribute3=One,Two,Three',
190191
'bundle_price_type' => 'fixed',
191192
'bundle_shipment_type' => 'separately',
192193
'bundle_sku_type' => 'fixed',

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

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2388,19 +2388,7 @@ private function _parseAdditionalAttributes($rowData)
23882388
if (empty($rowData['additional_attributes'])) {
23892389
return $rowData;
23902390
}
2391-
2392-
$attributeNameValuePairs = explode($this->getMultipleValueSeparator(), $rowData['additional_attributes']);
2393-
foreach ($attributeNameValuePairs as $attributeNameValuePair) {
2394-
$separatorPosition = strpos($attributeNameValuePair, self::PAIR_NAME_VALUE_SEPARATOR);
2395-
if ($separatorPosition !== false) {
2396-
$key = substr($attributeNameValuePair, 0, $separatorPosition);
2397-
$value = substr(
2398-
$attributeNameValuePair,
2399-
$separatorPosition + strlen(self::PAIR_NAME_VALUE_SEPARATOR)
2400-
);
2401-
$rowData[$key] = $value === false ? '' : $value;
2402-
}
2403-
}
2391+
$rowData = array_merge($rowData, $this->parseAdditionalAttributes($rowData['additional_attributes']));
24042392
return $rowData;
24052393
}
24062394

@@ -2587,4 +2575,29 @@ private function getProductIdentifierField()
25872575
}
25882576
return $this->productEntityIdentifierField;
25892577
}
2578+
2579+
/**
2580+
* Retrieves additional attributes as array code=>value
2581+
*
2582+
* @param string $additionalAttributes
2583+
* @return array
2584+
*/
2585+
private function parseAdditionalAttributes($additionalAttributes)
2586+
{
2587+
$attributeNameValuePairs = explode($this->getMultipleValueSeparator(), $additionalAttributes);
2588+
$preparedAttributes = [];
2589+
$code = '';
2590+
foreach ($attributeNameValuePairs as $attributeData) {
2591+
if (strpos($attributeData, self::PAIR_NAME_VALUE_SEPARATOR) === false) {
2592+
if (!$code) {
2593+
continue;
2594+
}
2595+
$preparedAttributes[$code] .= $this->getMultipleValueSeparator() . $attributeData;
2596+
continue;
2597+
}
2598+
list($code, $value) = explode(self::PAIR_NAME_VALUE_SEPARATOR, $attributeData, 2);
2599+
$preparedAttributes[$code] = $value;
2600+
}
2601+
return $preparedAttributes;
2602+
}
25902603
}

app/code/Magento/Eav/Model/ResourceModel/ReadHandler.php

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Magento\Framework\Model\Entity\ScopeInterface;
1414
use Magento\Framework\EntityManager\Operation\AttributeInterface;
1515
use Magento\Eav\Model\Entity\AttributeCache;
16+
use Psr\Log\LoggerInterface;
1617

1718
/**
1819
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -49,6 +50,11 @@ class ReadHandler implements AttributeInterface
4950
*/
5051
protected $scopeResolver;
5152

53+
/**
54+
* @var LoggerInterface
55+
*/
56+
private $logger;
57+
5258
/**
5359
* ReadHandler constructor.
5460
*
@@ -58,21 +64,24 @@ class ReadHandler implements AttributeInterface
5864
* @param AppResource $appResource
5965
* @param ScopeResolver $scopeResolver
6066
* @param AttributeCache $attributeCache
67+
* @param LoggerInterface $logger
6168
*/
6269
public function __construct(
6370
AttributeRepository $attributeRepository,
6471
MetadataPool $metadataPool,
6572
SearchCriteriaBuilder $searchCriteriaBuilder,
6673
AppResource $appResource,
6774
ScopeResolver $scopeResolver,
68-
AttributeCache $attributeCache
75+
AttributeCache $attributeCache,
76+
LoggerInterface $logger
6977
) {
7078
$this->attributeRepository = $attributeRepository;
7179
$this->metadataPool = $metadataPool;
7280
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
7381
$this->appResource = $appResource;
7482
$this->scopeResolver = $scopeResolver;
7583
$this->attributeCache = $attributeCache;
84+
$this->logger = $logger;
7685
}
7786

7887
/**
@@ -82,7 +91,6 @@ public function __construct(
8291
*/
8392
protected function getAttributes($entityType)
8493
{
85-
8694
$attributes = $this->attributeCache->getAttributes($entityType);
8795
if ($attributes) {
8896
return $attributes;
@@ -163,7 +171,14 @@ public function execute($entityType, $entityData, $arguments = [])
163171
\Magento\Framework\DB\Select::SQL_UNION_ALL
164172
);
165173
foreach ($connection->fetchAll($unionSelect) as $attributeValue) {
166-
$entityData[$attributesMap[$attributeValue['attribute_id']]] = $attributeValue['value'];
174+
if (isset($attributesMap[$attributeValue['attribute_id']])) {
175+
$entityData[$attributesMap[$attributeValue['attribute_id']]] = $attributeValue['value'];
176+
} else {
177+
$this->logger->warning(
178+
"Attempt to load value of nonexistent EAV attribute '{$attributeValue['attribute_id']}'
179+
for entity type '$entityType'."
180+
);
181+
}
167182
}
168183
}
169184
return $entityData;

dev/tests/integration/testsuite/Magento/BundleImportExport/Model/Export/RowCustomizerTest.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ protected function setUp()
3333
*/
3434
public function testPrepareData()
3535
{
36+
$parsedAdditonalAttributes = 'text_attribute=!@#$%^&*()_+1234567890-=|\\:;"\'<,>.?/'
37+
. ',text_attribute2=,';
38+
$allAdditionalAttributes = $parsedAdditonalAttributes . ',weight_type=0,price_type=1';
3639
/** @var \Magento\Catalog\Model\ResourceModel\Product\Collection $collection */
3740
$collection = $this->objectManager->get('Magento\Catalog\Model\ResourceModel\Product\Collection');
3841
$select = $collection->getConnection()->select()
@@ -42,7 +45,7 @@ public function testPrepareData()
4245
$select = (string)$collection->getSelect();
4346
$this->model->prepareData($collection, array_values($ids));
4447
$this->assertEquals($select, (string)$collection->getSelect());
45-
$result = $this->model->addData([], $ids['bundle-product']);
48+
$result = $this->model->addData(['additional_attributes' => $allAdditionalAttributes], $ids['bundle-product']);
4649
$this->assertArrayHasKey('bundle_price_type', $result);
4750
$this->assertArrayHasKey('bundle_shipment_type', $result);
4851
$this->assertArrayHasKey('bundle_sku_type', $result);
@@ -51,5 +54,6 @@ public function testPrepareData()
5154
$this->assertArrayHasKey('bundle_values', $result);
5255
$this->assertContains('sku=simple,', $result['bundle_values']);
5356
$this->assertEquals([], $this->model->addData([], $ids['simple']));
57+
$this->assertEquals($parsedAdditonalAttributes, $result['additional_attributes']);
5458
}
5559
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
$installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
7+
->create(\Magento\Catalog\Setup\CategorySetup::class);
8+
/** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */
9+
$attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
10+
->create(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class);
11+
$attribute->setData(
12+
[
13+
'attribute_code' => 'text_attribute',
14+
'entity_type_id' => $installer->getEntityTypeId('catalog_product'),
15+
'is_global' => 1,
16+
'is_user_defined' => 1,
17+
'frontend_input' => 'textarea',
18+
'is_unique' => 0,
19+
'is_required' => 0,
20+
'is_searchable' => 0,
21+
'is_visible_in_advanced_search' => 0,
22+
'is_comparable' => 0,
23+
'is_filterable' => 0,
24+
'is_filterable_in_search' => 0,
25+
'is_used_for_promo_rules' => 0,
26+
'is_html_allowed_on_front' => 1,
27+
'is_visible_on_front' => 0,
28+
'used_in_product_listing' => 0,
29+
'used_for_sort_by' => 0,
30+
'frontend_label' => ['Text Attribute'],
31+
'backend_type' => 'text',
32+
]
33+
);
34+
$attribute->save();
35+
/* Assign attribute to attribute set */
36+
$installer->addAttributeToGroup('catalog_product', 'Default', 'General', $attribute->getId());

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public function testExport()
8383
$this->assertContains('Option 4 ""!@#$%^&*', $exportData);
8484
$this->assertContains('test_option_code_2', $exportData);
8585
$this->assertContains('max_characters=10', $exportData);
86+
$this->assertContains('text_attribute=!@#$%^&*()_+1234567890-=|\\:;""\'<,>.?/', $exportData);
8687
}
8788

8889
/**

dev/tests/integration/testsuite/Magento/CatalogImportExport/_files/product_export_data.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
require dirname(dirname(__DIR__)) . '/Catalog/_files/category.php';
1010
require dirname(dirname(__DIR__)) . '/Store/_files/second_store.php';
1111
require dirname(dirname(__DIR__)) . '/Catalog/_files/products_with_multiselect_attribute.php';
12+
require dirname(dirname(__DIR__)) . '/Catalog/_files/text_attribute.php';
1213

1314
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
1415

@@ -52,6 +53,8 @@
5253
'simple'
5354
)->setPrice(
5455
10
56+
)->addData(
57+
['text_attribute' => '!@#$%^&*()_+1234567890-=|\\:;"\'<,>.?/']
5558
)->setTierPrice(
5659
[0 => ['website_id' => 0, 'cust_group' => 0, 'price_qty' => 3, 'price' => 8]]
5760
)->setVisibility(

0 commit comments

Comments
 (0)