Skip to content

Commit 548cb7b

Browse files
committed
MAGETWO-63590: [Backport] - [Github] Imported configurable products with multiple super attributes do not retain super attribute ordering #6079 - for 2.0
1 parent 20e1a7c commit 548cb7b

File tree

4 files changed

+343
-0
lines changed

4 files changed

+343
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\ConfigurableImportExport\Model\Import\Product\Type;
7+
8+
use Magento\Catalog\Api\ProductRepositoryInterface;
9+
use Magento\Framework\App\Filesystem\DirectoryList;
10+
use Magento\ImportExport\Model\Import;
11+
12+
/**
13+
* @magentoAppArea adminhtml
14+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
15+
*/
16+
class ConfigurableTest extends \PHPUnit_Framework_TestCase
17+
{
18+
/**
19+
* Configurable product test Name
20+
*/
21+
const TEST_PRODUCT_NAME = 'Configurable 1';
22+
23+
/**
24+
* Configurable product test Type
25+
*/
26+
const TEST_PRODUCT_TYPE = 'configurable';
27+
28+
/**
29+
* @var \Magento\CatalogImportExport\Model\Import\Product
30+
*/
31+
protected $model;
32+
33+
/**
34+
* Configurable product options SKU list
35+
*
36+
* @var array
37+
*/
38+
protected $optionSkuList = ['Configurable 1-Option 2-Option 1'];
39+
40+
/**
41+
* @var \Magento\Framework\ObjectManagerInterface
42+
*/
43+
protected $objectManager;
44+
45+
46+
47+
protected function setUp()
48+
{
49+
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
50+
\Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType::$commonAttributesCache = [];
51+
$this->model = $this->objectManager->create(\Magento\CatalogImportExport\Model\Import\Product::class);
52+
}
53+
54+
/**
55+
* @magentoDataFixture Magento/ConfigurableImportExport/Model/Import/_files/configurable_attributes.php
56+
* @magentoAppArea adminhtml
57+
*/
58+
public function testConfigurableWithAttributesSortingImport()
59+
{
60+
// import data from CSV file
61+
$pathToFile = __DIR__ . '/../../_files/import_configurable_with_attributes_sorting.csv';
62+
$filesystem = $this->objectManager->create(
63+
\Magento\Framework\Filesystem::class
64+
);
65+
66+
$directory = $filesystem->getDirectoryWrite(DirectoryList::ROOT);
67+
$source = $this->objectManager->create(
68+
\Magento\ImportExport\Model\Import\Source\Csv::class,
69+
[
70+
'file' => $pathToFile,
71+
'directory' => $directory
72+
]
73+
);
74+
$errors = $this->model->setSource(
75+
$source
76+
)->setParameters(
77+
[
78+
'behavior' => \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND,
79+
'entity' => 'catalog_product'
80+
]
81+
)->validateData();
82+
83+
$this->assertTrue($errors->getErrorsCount() == 0);
84+
$this->model->importData();
85+
86+
/** @var \Magento\Catalog\Model\ResourceModel\Product $resource */
87+
$resource = $this->objectManager->get(\Magento\Catalog\Model\ResourceModel\Product::class);
88+
$productId = $resource->getIdBySku(self::TEST_PRODUCT_NAME);
89+
$this->assertTrue(is_numeric($productId));
90+
/** @var \Magento\Catalog\Model\Product $product */
91+
$product = $this->objectManager->get(ProductRepositoryInterface::class)->getById($productId);
92+
$configurableProductOptions = $product->getExtensionAttributes()->getConfigurableProductOptions();
93+
94+
$this->assertFalse($product->isObjectNew());
95+
$this->assertEquals(self::TEST_PRODUCT_NAME, $product->getName());
96+
$this->assertEquals(self::TEST_PRODUCT_TYPE, $product->getTypeId());
97+
98+
$optionCollection = $product->getTypeInstance()->getConfigurableOptions($product);
99+
foreach ($optionCollection as $option) {
100+
$this->assertContains($option[0]['sku'], $this->optionSkuList);
101+
}
102+
103+
$optionIdList = $resource->getProductsIdsBySkus($this->optionSkuList);
104+
foreach ($optionIdList as $optionId) {
105+
$this->assertArrayHasKey($optionId, $product->getExtensionAttributes()->getConfigurableProductLinks());
106+
}
107+
108+
$this->assertEquals(2, count($optionCollection));
109+
110+
$attributesPositionExpectation = [
111+
'test_attribute_2' => 0,
112+
'test_attribute_1' => 1,
113+
];
114+
115+
/** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute $configurableProductOption */
116+
foreach ($configurableProductOptions as $configurableProductOption){
117+
$productAttribute = $configurableProductOption->getProductAttribute();
118+
$productAttributeCode = $productAttribute->getAttributeCode();
119+
$productAttributeData = $productAttribute->getData();
120+
$productAttributeDataExpectation = self::getProductAttributesDataExpectation()[$productAttributeCode];
121+
122+
$productOptionData = $configurableProductOption->getData();
123+
$productOptionLabel = $productOptionData['label'];
124+
$productOptionsDataExpectation = self::getProductOptionsDataExpectation()[$productOptionLabel];
125+
126+
if (isset($attributesPositionExpectation[$productAttributeCode])) {
127+
$expectedPosition = $attributesPositionExpectation[$productAttributeCode];
128+
$this->assertEquals($expectedPosition, $configurableProductOption->getPosition());
129+
}
130+
131+
$this->assertArrayHasKey('product_super_attribute_id', $productOptionData);
132+
$this->assertArrayHasKey('product_id', $productOptionData);
133+
$this->assertArrayHasKey('attribute_id', $productOptionData);
134+
$this->assertArrayHasKey('position', $productOptionData);
135+
$this->assertArrayHasKey('extension_attributes', $productOptionData);
136+
$this->assertArrayHasKey('product_attribute', $productOptionData);
137+
$this->assertArrayHasKey('attribute_id', $productAttributeData);
138+
$this->assertArrayHasKey('entity_type_id', $productAttributeData);
139+
$this->assertArrayHasKey('attribute_code', $productAttributeData);
140+
$this->assertArrayHasKey('frontend_label', $productAttributeData);
141+
$this->assertArrayHasKey('label', $productOptionData);
142+
$this->assertArrayHasKey('use_default', $productOptionData);
143+
$this->assertArrayHasKey('options', $productOptionData);
144+
145+
$this->assertEquals(
146+
$productAttributeDataExpectation['attribute_code'],
147+
$productAttributeData['attribute_code']
148+
);
149+
$this->assertEquals(
150+
$product->getData('entity_id'),
151+
$productOptionData['product_id']);
152+
$this->assertEquals(
153+
$productAttributeDataExpectation['frontend_label'],
154+
$productAttributeData['frontend_label']
155+
);
156+
$this->assertEquals(
157+
$productOptionsDataExpectation['label'],
158+
$productOptionData['label']
159+
);
160+
$this->assertEquals(
161+
$productOptionsDataExpectation['options']['label'],
162+
$productOptionData['options'][0]['label']
163+
);
164+
$this->assertEquals(
165+
$productOptionsDataExpectation['options']['default_label'],
166+
$productOptionData['options'][0]['default_label']
167+
);
168+
$this->assertEquals(
169+
$productOptionsDataExpectation['options']['store_label'],
170+
$productOptionData['options'][0]['store_label']
171+
);
172+
$this->assertArrayHasKey('values', $productOptionData);
173+
$valuesData = $productOptionData['values'];
174+
$this->assertEquals(1, count($valuesData));
175+
}
176+
}
177+
178+
/**
179+
* @return array
180+
*/
181+
private function getProductOptionsDataExpectation()
182+
{
183+
return [
184+
'Test attribute 1' => [
185+
'label' => 'Test attribute 1',
186+
'options' => [
187+
'label' => 'Option 1',
188+
'default_label' => 'Option 1',
189+
'store_label' => 'Option 1'
190+
]
191+
],
192+
193+
194+
'Test attribute 2' => [
195+
'label' => 'Test attribute 2',
196+
'options' => [
197+
'label' => 'Option 2',
198+
'default_label' => 'Option 2',
199+
'store_label' => 'Option 2'
200+
]
201+
]
202+
];
203+
}
204+
205+
/**
206+
* @return array
207+
*/
208+
private function getProductAttributesDataExpectation()
209+
{
210+
return [
211+
'test_attribute_1' => [
212+
'attribute_code' => 'test_attribute_1',
213+
'frontend_label' => 'Test attribute 1'
214+
],
215+
'test_attribute_2' => [
216+
'attribute_code' => 'test_attribute_2',
217+
'frontend_label' => 'Test attribute 2'
218+
]
219+
];
220+
}
221+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
/** @var \Magento\Eav\Model\Config $eavConfig */
8+
$eavConfig = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Eav\Model\Config');
9+
/** @var $installer \Magento\Catalog\Setup\CategorySetup */
10+
$installer = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create('Magento\Catalog\Setup\CategorySetup');
11+
12+
/** @var $attributes array */
13+
$attributes = [
14+
[
15+
'code' => 'test_attribute_1',
16+
'label' => 'Test attribute 1'
17+
], [
18+
'code' => 'test_attribute_2',
19+
'label' => 'Test attribute 2'
20+
]
21+
];
22+
23+
foreach ($attributes as $item) {
24+
$code = $item['code'];
25+
$label = $item['label'];
26+
$attribute = $eavConfig->getAttribute('catalog_product', $code);
27+
if ($attribute instanceof \Magento\Eav\Model\Entity\Attribute\AbstractAttribute
28+
&& $attribute->getId()
29+
) {
30+
$attribute->delete();
31+
}
32+
33+
$eavConfig->clear();
34+
35+
/* Create attribute */
36+
/** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */
37+
$attribute = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
38+
'Magento\Catalog\Model\ResourceModel\Eav\Attribute'
39+
);
40+
41+
$attribute->setData(
42+
[
43+
'attribute_code' => $code,
44+
'entity_type_id' => 4,
45+
'is_global' => 1,
46+
'is_user_defined' => 1,
47+
'frontend_input' => 'select',
48+
'is_unique' => 0,
49+
'is_required' => 0,
50+
'is_searchable' => 0,
51+
'is_visible_in_advanced_search' => 0,
52+
'is_comparable' => 0,
53+
'is_filterable' => 0,
54+
'is_filterable_in_search' => 0,
55+
'is_used_for_promo_rules' => 0,
56+
'is_html_allowed_on_front' => 1,
57+
'is_visible_on_front' => 0,
58+
'used_in_product_listing' => 0,
59+
'used_for_sort_by' => 0,
60+
'frontend_label' => [$label],
61+
'backend_type' => 'int',
62+
'option' => [
63+
'value' => ['option_0' => ['Option 1'], 'option_1' => ['Option 2']],
64+
'order' => ['option_0' => 1, 'option_1' => 2],
65+
],
66+
]
67+
);
68+
69+
$attribute->save();
70+
71+
/* Assign attribute to attribute set */
72+
$installer->addAttributeToGroup('catalog_product', 'Default', 'General', $attribute->getId());
73+
74+
}
75+
76+
/** @var \Magento\Eav\Model\Config $eavConfig */
77+
$eavConfig = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Eav\Model\Config');
78+
$eavConfig->clear();
79+
80+
81+
82+
83+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
/** @var \Magento\Framework\Registry $registry */
8+
$registry = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Framework\Registry');
9+
10+
$registry->unregister('isSecureArea');
11+
$registry->register('isSecureArea', true);
12+
13+
$eavConfig = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get('Magento\Eav\Model\Config');
14+
/** @var $attributes array */
15+
$attributes = [
16+
[
17+
'code' => 'test_attribute_1',
18+
'label' => 'Test attribute 1'
19+
], [
20+
'code' => 'test_attribute_2',
21+
'label' => 'Test attribute 2'
22+
]
23+
];
24+
25+
foreach ($attributes as $attribute) {
26+
$attribute = $eavConfig->getAttribute('catalog_product', $attribute['code']);
27+
if ($attribute instanceof \Magento\Eav\Model\Entity\Attribute\AbstractAttribute
28+
&& $attribute->getId()
29+
) {
30+
$attribute->delete();
31+
}
32+
}
33+
$eavConfig->clear();
34+
35+
$registry->unregister('isSecureArea');
36+
$registry->register('isSecureArea', false);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
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,deferred_stock_update,use_config_deferred_stock_update,related_skus,crosssell_skus,upsell_skus,additional_images,additional_image_labels,hide_from_product_page,bundle_price_type,bundle_sku_type,bundle_price_view,bundle_weight_type,bundle_values,configurable_variations,configurable_variation_labels,associated_skus
2+
Configurable 1-Option 2-Option 1,,Default,simple,Default Category/Test category,base,Configurable 1-Option 2-Option 1,,,1,1,Taxable Goods,Not Visible Individually,100,,,,configurable-1-option-2-option-1,Configurable 1,Configurable 1,Configurable 1 ,,,,,,,,,"5/3/17, 3:39 AM","5/3/17, 3:39 AM",,,Block after Info Column,,,,,,,,,,,,,"test_attribute_1=Option 1,test_attribute_2=Option 2",10,0,1,0,0,1,1,1,0,1,1,,1,1,1,1,0,1,0,0,1,0,1,,,,,,,,,,,,,,
3+
Configurable 1,,Default,configurable,Default Category/Test category,base,Configurable 1,,,1,1,Taxable Goods,"Catalog, Search",,,,,configurable-1,Configurable 1,Configurable 1,Configurable 1 ,,,,,,,,,"5/3/17, 3:39 AM","5/3/17, 3:39 AM",,,Block after Info Column,,,,,,,,,,,,,,0,0,1,0,0,1,1,1,0,1,1,,1,1,1,1,0,1,0,0,1,0,1,,,,,,,,,,,,"sku=Configurable 1-Option 2-Option 1,test_attribute_2=Option 2,test_attribute_1=Option 1",,

0 commit comments

Comments
 (0)