Skip to content

Commit 1e3b190

Browse files
MC-21001: Add/move/delete attribute for attribute sets
1 parent 65763df commit 1e3b190

File tree

1 file changed

+286
-0
lines changed
  • dev/tests/integration/testsuite/Magento/Eav/Model/Entity/Attribute

1 file changed

+286
-0
lines changed
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Eav\Model\Entity\Attribute;
9+
10+
use Magento\Catalog\Model\Product;
11+
use Magento\Catalog\Model\Product\Attribute\Group;
12+
use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory;
13+
use Magento\Eav\Api\AttributeGroupRepositoryInterface;
14+
use Magento\Eav\Api\AttributeSetRepositoryInterface;
15+
use Magento\Eav\Api\Data\AttributeGroupInterface;
16+
use Magento\Eav\Model\Config;
17+
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Set as AttributeSetResource;
18+
use Magento\Framework\Api\SearchCriteriaBuilder;
19+
use Magento\Framework\ObjectManagerInterface;
20+
use Magento\TestFramework\Helper\Bootstrap;
21+
22+
/**
23+
* Provides tests for attribute set model saving.
24+
*/
25+
class SaveTest extends \PHPUnit\Framework\TestCase
26+
{
27+
/**
28+
* @var ObjectManagerInterface
29+
*/
30+
private $objectManager;
31+
32+
/**
33+
* @var AttributeSetRepositoryInterface
34+
*/
35+
private $setRepository;
36+
37+
/**
38+
* @var AttributeGroupRepositoryInterface
39+
*/
40+
private $groupRepository;
41+
42+
/**
43+
* @var Config
44+
*/
45+
private $config;
46+
47+
/**
48+
* @var SearchCriteriaBuilder
49+
*/
50+
private $criteriaBuilder;
51+
52+
/**
53+
* @var AttributeSetResource
54+
*/
55+
private $attributeSetResource;
56+
57+
/**
58+
* @var CollectionFactory
59+
*/
60+
private $attributeCollectionFactory;
61+
62+
/**
63+
* @var int
64+
*/
65+
private $defaultSetId;
66+
67+
/**
68+
* @inheritdoc
69+
*/
70+
protected function setUp()
71+
{
72+
parent::setUp();
73+
$this->objectManager = Bootstrap::getObjectManager();
74+
$this->setRepository = $this->objectManager->get(AttributeSetRepositoryInterface::class);
75+
$this->groupRepository = Bootstrap::getObjectManager()->create(AttributeGroupRepositoryInterface::class);
76+
$this->config = $this->objectManager->get(Config::class);
77+
$this->defaultSetId = (int)$this->config->getEntityType(Product::ENTITY)->getDefaultAttributeSetId();
78+
$this->criteriaBuilder = Bootstrap::getObjectManager()->create(SearchCriteriaBuilder::class);
79+
$this->attributeSetResource = $this->objectManager->get(AttributeSetResource::class);
80+
$this->attributeCollectionFactory = $this->objectManager->get(CollectionFactory ::class);
81+
}
82+
83+
/**
84+
* @magentoDataFixture Magento/Eav/_files/attribute_with_options.php
85+
* @dataProvider addAttributeToSetDataProvider
86+
* @magentoDbIsolation enabled
87+
* @param string $groupName
88+
* @param string $attributeCode
89+
* @return void
90+
*/
91+
public function testSaveWithGroupsAndAttributes(string $groupName, string $attributeCode): void
92+
{
93+
$set = $this->setRepository->get($this->defaultSetId);
94+
$groupId = $this->getAttributeGroup($groupName)
95+
? $this->getAttributeGroup($groupName)->getAttributeGroupId()
96+
: 'ynode-1';
97+
$attributeId = (int)$this->config->getAttribute(Product::ENTITY, $attributeCode)->getAttributeId();
98+
$additional = [
99+
'attributes' => [
100+
[$attributeId, $groupId, 1],
101+
],
102+
'groups' => [
103+
[$groupId, $groupName, 1],
104+
],
105+
];
106+
$set->organizeData($this->getAttributeSetData($additional));
107+
$this->attributeSetResource->save($set);
108+
$groupId = $this->getAttributeGroup($groupName)->getAttributeGroupId();
109+
$this->config->clear();
110+
$setInfo = $this->attributeSetResource->getSetInfo([$attributeId], $this->defaultSetId);
111+
$expectedInfo = [
112+
$attributeId => [$this->defaultSetId => ['group_id' => $groupId, 'group_sort' => '1', 'sort' => '1']],
113+
];
114+
$this->assertEquals($expectedInfo, $setInfo);
115+
}
116+
117+
/**
118+
* @return array
119+
*/
120+
public function addAttributeToSetDataProvider(): array
121+
{
122+
return [
123+
'add_to_existing_group' => [
124+
'group_name' => 'Content',
125+
'attribute_code' => 'zzz',
126+
],
127+
'add_to_new_group' => [
128+
'group_name' => 'Test',
129+
'attribute_code' => 'zzz',
130+
],
131+
'move_to_existing_group' => [
132+
'group_name' => 'Images',
133+
'attribute_code' => 'description',
134+
],
135+
'move_to_new_group' => [
136+
'group_name' => 'Test',
137+
'attribute_code' => 'description',
138+
],
139+
];
140+
}
141+
142+
/**
143+
* @magentoDbIsolation enabled
144+
* @return void
145+
*/
146+
public function testSaveWithChangedGroupSorting(): void
147+
{
148+
$set = $this->setRepository->get($this->defaultSetId);
149+
$contentGroupId = $this->getAttributeGroup('Content')->getAttributeGroupId();
150+
$imagesGroupId = $this->getAttributeGroup('Images')->getAttributeGroupId();
151+
$additional = [
152+
'groups' => [
153+
[$contentGroupId, 'Content', 2],
154+
[$imagesGroupId, 'Images', 1]
155+
]
156+
];
157+
$set->organizeData($this->getAttributeSetData($additional));
158+
$this->attributeSetResource->save($set);
159+
$contentGroupSort = $this->getAttributeGroup('Content')->getSortOrder();
160+
$imagesGroupSort = $this->getAttributeGroup('Images')->getSortOrder();
161+
$this->assertEquals(2, $contentGroupSort);
162+
$this->assertEquals(1, $imagesGroupSort);
163+
}
164+
165+
/**
166+
* @magentoDbIsolation enabled
167+
* @return void
168+
*/
169+
public function testSaveWithRemovedGroup(): void
170+
{
171+
$set = $this->setRepository->get($this->defaultSetId);
172+
$designGroupId = $this->getAttributeGroup('Design')->getAttributeGroupId();
173+
$additional = [
174+
'removeGroups' => [$designGroupId],
175+
];
176+
$set->organizeData($this->getAttributeSetData($additional));
177+
$this->attributeSetResource->save($set);
178+
$this->assertNull(
179+
$this->getAttributeGroup('Design'),
180+
'Group Design wan\'t deleted.'
181+
);
182+
$unusedSetAttributes = $this->getUnusedSetAttributes((int)$set->getAttributeSetId());
183+
$designAttributeCodes = ['page_layout', 'options_container', 'custom_layout_update'];
184+
$this->assertNotEmpty(
185+
array_intersect($designAttributeCodes, $unusedSetAttributes),
186+
'Attributes from Design group still assigned to attribute set.'
187+
);
188+
}
189+
190+
/**
191+
* @magentoDbIsolation enabled
192+
* @return void
193+
*/
194+
public function testSaveWithRemovedAttribute(): void
195+
{
196+
$set = $this->setRepository->get($this->defaultSetId);
197+
$attributeId = (int)$this->config->getAttribute(Product::ENTITY, 'meta_description')
198+
->getAttributeId();
199+
$additional = [
200+
'not_attributes' => [$this->getEntityAttributeId($this->defaultSetId, $attributeId)],
201+
];
202+
$set->organizeData($this->getAttributeSetData($additional));
203+
$this->attributeSetResource->save($set);
204+
$this->config->clear();
205+
$setInfo = $this->attributeSetResource->getSetInfo([$attributeId], $this->defaultSetId);
206+
$this->assertEmpty($setInfo[$attributeId]);
207+
$unusedSetAttributes = $this->getUnusedSetAttributes((int)$set->getAttributeSetId());
208+
$this->assertNotEmpty(
209+
array_intersect(['meta_description'], $unusedSetAttributes),
210+
'Attribute still assigned to attribute set.'
211+
);
212+
}
213+
214+
/**
215+
* Returns attribute set data for saving.
216+
*
217+
* @param array $additional
218+
* @return array
219+
*/
220+
private function getAttributeSetData(array $additional): array
221+
{
222+
$data = [
223+
'attributes' => [],
224+
'groups' => [],
225+
'not_attributes' => [],
226+
'removeGroups' => [],
227+
'attribute_set_name' => 'Default',
228+
];
229+
230+
return array_merge($data, $additional);
231+
}
232+
233+
/**
234+
* Returns attribute group by name.
235+
*
236+
* @param string $groupName
237+
* @return AttributeGroupInterface|Group|null
238+
*/
239+
private function getAttributeGroup(string $groupName): ?AttributeGroupInterface
240+
{
241+
$searchCriteria = $this->criteriaBuilder->addFilter('attribute_group_name', $groupName)
242+
->addFilter('attribute_set_id', $this->defaultSetId)
243+
->create();
244+
$result = $this->groupRepository->getList($searchCriteria)->getItems();
245+
246+
return !empty($result) ? reset($result) : null;
247+
}
248+
249+
/**
250+
* Returns list of unused attributes in attribute set.
251+
*
252+
* @param int $setId
253+
* @return array
254+
*/
255+
private function getUnusedSetAttributes(int $setId): array
256+
{
257+
$result = [];
258+
$attributesIds = $this->attributeCollectionFactory->create()
259+
->setAttributeSetFilter($setId)
260+
->getAllIds();
261+
$collection = $this->attributeCollectionFactory->create()
262+
->setAttributesExcludeFilter($attributesIds)
263+
->addVisibleFilter();
264+
/** @var AbstractAttribute $attribute */
265+
foreach ($collection as $attribute) {
266+
$result[] = $attribute->getAttributeCode();
267+
}
268+
269+
return $result;
270+
}
271+
272+
/**
273+
* @param int|null $setId
274+
* @param int $attributeId
275+
* @return int
276+
*/
277+
private function getEntityAttributeId(?int $setId, int $attributeId): int
278+
{
279+
$select = $this->attributeSetResource->getConnection()->select()
280+
->from('eav_entity_attribute', ['entity_attribute_id'])
281+
->where('attribute_set_id = ?', $setId)
282+
->where('attribute_id = ?', $attributeId);
283+
284+
return (int)$this->attributeSetResource->getConnection()->fetchOne($select);
285+
}
286+
}

0 commit comments

Comments
 (0)