Skip to content

Commit bc48e9f

Browse files
authored
LYNX-132: Attribute options UIDs
1 parent bd29788 commit bc48e9f

File tree

8 files changed

+396
-34
lines changed

8 files changed

+396
-34
lines changed

app/code/Magento/CustomerGraphQl/etc/graphql/di.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,14 @@
6262
</argument>
6363
</arguments>
6464
</type>
65+
<type name="Magento\Framework\GraphQl\Schema\Type\Enum\DefaultDataMapper">
66+
<arguments>
67+
<argument name="map" xsi:type="array">
68+
<item name="AttributeEntityTypeEnum" xsi:type="array">
69+
<item name="customer" xsi:type="string">customer</item>
70+
<item name="customer_address" xsi:type="string">customer_address</item>
71+
</item>
72+
</argument>
73+
</arguments>
74+
</type>
6575
</config>
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
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\Test\Fixture;
9+
10+
use Magento\Eav\Api\AttributeRepositoryInterface;
11+
use Magento\Framework\DataObject;
12+
use Magento\Framework\Exception\InvalidArgumentException;
13+
use Magento\TestFramework\Fixture\Api\DataMerger;
14+
use Magento\TestFramework\Fixture\Api\ServiceFactory;
15+
use Magento\TestFramework\Fixture\RevertibleDataFixtureInterface;
16+
use Magento\TestFramework\Fixture\Data\ProcessorInterface;
17+
18+
class Attribute implements RevertibleDataFixtureInterface
19+
{
20+
private const DEFAULT_DATA = [
21+
'entity_type_id' => null,
22+
'attribute_id' => null,
23+
'attribute_code' => 'attribute%uniqid%',
24+
'default_frontend_label' => 'Attribute%uniqid%',
25+
'frontend_labels' => [],
26+
'frontend_input' => 'text',
27+
'backend_type' => 'varchar',
28+
'is_required' => false,
29+
'is_user_defined' => true,
30+
'note' => null,
31+
'backend_model' => null,
32+
'source_model' => null,
33+
'default_value' => null,
34+
'is_unique' => '0',
35+
'frontend_class' => null
36+
];
37+
38+
/**
39+
* @var ServiceFactory
40+
*/
41+
private ServiceFactory $serviceFactory;
42+
43+
/**
44+
* @var DataMerger
45+
*/
46+
private DataMerger $dataMerger;
47+
48+
/**
49+
* @var ProcessorInterface
50+
*/
51+
private ProcessorInterface $processor;
52+
53+
/**
54+
* @var AttributeRepositoryInterface
55+
*/
56+
private AttributeRepositoryInterface $attributeRepository;
57+
58+
/**
59+
* @param ServiceFactory $serviceFactory
60+
* @param DataMerger $dataMerger
61+
* @param ProcessorInterface $processor
62+
* @param AttributeRepositoryInterface $attributeRepository
63+
*/
64+
public function __construct(
65+
ServiceFactory $serviceFactory,
66+
DataMerger $dataMerger,
67+
ProcessorInterface $processor,
68+
AttributeRepositoryInterface $attributeRepository
69+
) {
70+
$this->serviceFactory = $serviceFactory;
71+
$this->dataMerger = $dataMerger;
72+
$this->processor = $processor;
73+
$this->attributeRepository = $attributeRepository;
74+
}
75+
76+
/**
77+
* @inheritdoc
78+
*/
79+
public function apply(array $data = []): ?DataObject
80+
{
81+
if (empty($data['entity_type_id'])) {
82+
throw new InvalidArgumentException(
83+
__(
84+
'"%field" value is required to create an attribute',
85+
[
86+
'field' => 'entity_type_id'
87+
]
88+
)
89+
);
90+
}
91+
92+
$mergedData = $this->processor->process($this, $this->dataMerger->merge(self::DEFAULT_DATA, $data));
93+
94+
$this->serviceFactory->create(AttributeRepositoryInterface::class, 'save')->execute(
95+
[
96+
'attribute' => $mergedData
97+
]
98+
);
99+
100+
return $this->attributeRepository->get($mergedData['entity_type_id'], $mergedData['attribute_code']);
101+
}
102+
103+
/**
104+
* @inheritdoc
105+
*/
106+
public function revert(DataObject $data): void
107+
{
108+
$this->attributeRepository->deleteById($data['attribute_id']);
109+
}
110+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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\Test\Fixture;
9+
10+
use Magento\Eav\Api\AttributeOptionManagementInterface;
11+
use Magento\Eav\Api\AttributeRepositoryInterface;
12+
use Magento\Framework\DataObject;
13+
use Magento\Framework\Exception\InvalidArgumentException;
14+
use Magento\TestFramework\Fixture\Api\DataMerger;
15+
use Magento\TestFramework\Fixture\Api\ServiceFactory;
16+
use Magento\TestFramework\Fixture\DataFixtureInterface;
17+
use Magento\TestFramework\Fixture\Data\ProcessorInterface;
18+
19+
class AttributeOption implements DataFixtureInterface
20+
{
21+
private const DEFAULT_DATA = [
22+
'entity_type' => null,
23+
'attribute_code' => null,
24+
'label' => 'Option Label %uniqid%',
25+
'sort_order' => null,
26+
'store_labels' => '',
27+
'is_default' => ''
28+
];
29+
30+
/**
31+
* @var ServiceFactory
32+
*/
33+
private ServiceFactory $serviceFactory;
34+
35+
/**
36+
* @var DataMerger
37+
*/
38+
private DataMerger $dataMerger;
39+
40+
/**
41+
* @var ProcessorInterface
42+
*/
43+
private ProcessorInterface $processor;
44+
45+
/**
46+
* @var AttributeRepositoryInterface
47+
*/
48+
private AttributeRepositoryInterface $attributeRepository;
49+
50+
/**
51+
* @param ServiceFactory $serviceFactory
52+
* @param DataMerger $dataMerger
53+
* @param ProcessorInterface $processor
54+
* @param AttributeRepositoryInterface $attributeRepository
55+
*/
56+
public function __construct(
57+
ServiceFactory $serviceFactory,
58+
DataMerger $dataMerger,
59+
ProcessorInterface $processor,
60+
AttributeRepositoryInterface $attributeRepository
61+
) {
62+
$this->serviceFactory = $serviceFactory;
63+
$this->dataMerger = $dataMerger;
64+
$this->processor = $processor;
65+
$this->attributeRepository = $attributeRepository;
66+
}
67+
68+
/**
69+
* @inheritdoc
70+
*/
71+
public function apply(array $data = []): ?DataObject
72+
{
73+
if (empty($data['entity_type'])) {
74+
throw new InvalidArgumentException(
75+
__(
76+
'"%field" value is required to create an attribute option',
77+
[
78+
'field' => 'entity_type_id'
79+
]
80+
)
81+
);
82+
}
83+
84+
if (empty($data['attribute_code'])) {
85+
throw new InvalidArgumentException(
86+
__(
87+
'"%field" value is required to create an attribute option',
88+
[
89+
'field' => 'attribute_code'
90+
]
91+
)
92+
);
93+
}
94+
95+
$mergedData = array_filter(
96+
$this->processor->process($this, $this->dataMerger->merge(self::DEFAULT_DATA, $data))
97+
);
98+
99+
$entityType = $mergedData['entity_type'];
100+
$attributeCode = $mergedData['attribute_code'];
101+
unset($mergedData['entity_type'], $mergedData['attribute_code']);
102+
103+
$this->serviceFactory->create(AttributeOptionManagementInterface::class, 'add')->execute(
104+
[
105+
'entityType' => $entityType,
106+
'attributeCode' => $attributeCode,
107+
'option' => $mergedData
108+
]
109+
);
110+
111+
$attribute = $this->attributeRepository->get($entityType, $attributeCode);
112+
113+
foreach ($attribute->getOptions() as $option) {
114+
if ($option->getLabel() === $mergedData['label']) {
115+
return $option;
116+
}
117+
}
118+
119+
return null;
120+
}
121+
}

app/code/Magento/EavGraphQl/Model/Output/GetAttributeData.php

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,20 @@ private function getOptions(AttributeInterface $attribute): array
9292
if (!$attribute->getOptions()) {
9393
return [];
9494
}
95-
return array_map(
96-
function (AttributeOptionInterface $option) {
97-
return [
98-
'uid' => $this->uid->encode($option->getValue()), // TODO retrieve option id
99-
'label' => $option->getLabel(),
100-
'value' => $option->getValue(), // TODO test option labels and values for different stores
101-
'sort_order' => $option->getSortOrder(),
102-
];
103-
},
104-
$attribute->getOptions()
95+
return array_filter(
96+
array_map(
97+
function (AttributeOptionInterface $option) {
98+
if (empty(trim($option->getValue())) && empty(trim($option->getLabel()))) {
99+
return null;
100+
}
101+
return [
102+
'uid' => $this->uid->encode($option->getValue()),
103+
'label' => $option->getLabel(),
104+
'value' => $option->getValue()
105+
];
106+
},
107+
$attribute->getOptions()
108+
)
105109
);
106110
}
107111
}

app/code/Magento/EavGraphQl/Model/TypeResolver/AttributeOption.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ public function __construct(array $typeResolvers = [])
3434
*/
3535
public function resolveType(array $data): string
3636
{
37-
if (!isset($this->typeResolvers[$data['entity_type']])) {
38-
return self::TYPE;
39-
}
40-
return $this->typeResolvers[$data['entity_type']]->resolveType($data);
37+
return self::TYPE;
4138
}
4239
}

app/code/Magento/EavGraphQl/etc/schema.graphqls

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,9 @@ interface AttributeMetadataInterface @typeResolver(class: "Magento\\EavGraphQl\\
7777
}
7878

7979
interface AttributeOptionInterface @typeResolver(class: "Magento\\EavGraphQl\\Model\\TypeResolver\\AttributeOption") {
80-
uid: ID @doc(description: "The unique ID of an attribute option.")
81-
label: String @doc(description: "The label assigned to the attribute option.")
82-
value: String @doc(description: "The attribute option value.")
83-
sort_order: Int @doc(description: "Sort order of the option.")
80+
uid: ID! @doc(description: "The unique ID of an attribute option.")
81+
label: String! @doc(description: "The label assigned to the attribute option.")
82+
value: String! @doc(description: "The attribute option value.")
8483
}
8584

8685
type AttributeOptionMetadata implements AttributeOptionInterface @doc(description: "Base EAV implementation of AttributeOptionInterface.") {

0 commit comments

Comments
 (0)