Skip to content

Commit 1186eb7

Browse files
authored
LYNX-102: Catalog GraphQL CatalogAttributeMetadata implementation of CustomAttributeMetadataInterface
1 parent 3360dd7 commit 1186eb7

File tree

8 files changed

+425
-1
lines changed

8 files changed

+425
-1
lines changed
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
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\Catalog\Test\Fixture;
9+
10+
use Magento\Catalog\Model\Category\Attribute;
11+
use Magento\Eav\Api\AttributeRepositoryInterface;
12+
use Magento\Eav\Model\AttributeFactory;
13+
use Magento\Eav\Model\ResourceModel\Entity\Attribute as ResourceModelAttribute;
14+
use Magento\Framework\DataObject;
15+
use Magento\TestFramework\Fixture\Api\DataMerger;
16+
use Magento\TestFramework\Fixture\Data\ProcessorInterface;
17+
use Magento\TestFramework\Fixture\RevertibleDataFixtureInterface;
18+
19+
class CategoryAttribute implements RevertibleDataFixtureInterface
20+
{
21+
private const DEFAULT_DATA = [
22+
'is_wysiwyg_enabled' => false,
23+
'is_html_allowed_on_front' => true,
24+
'used_for_sort_by' => false,
25+
'is_filterable' => false,
26+
'is_filterable_in_search' => false,
27+
'is_used_in_grid' => true,
28+
'is_visible_in_grid' => true,
29+
'is_filterable_in_grid' => true,
30+
'position' => 0,
31+
'is_searchable' => '0',
32+
'is_visible_in_advanced_search' => '0',
33+
'is_comparable' => '0',
34+
'is_used_for_promo_rules' => '0',
35+
'is_visible_on_front' => '0',
36+
'used_in_product_listing' => '0',
37+
'is_visible' => true,
38+
'scope' => 'store',
39+
'attribute_code' => 'category_attribute%uniqid%',
40+
'frontend_input' => 'text',
41+
'entity_type_id' => '3',
42+
'is_required' => false,
43+
'is_user_defined' => true,
44+
'default_frontend_label' => 'Category Attribute%uniqid%',
45+
'backend_type' => 'varchar',
46+
'is_unique' => '0',
47+
'apply_to' => [],
48+
];
49+
50+
/**
51+
* @var DataMerger
52+
*/
53+
private DataMerger $dataMerger;
54+
55+
/**
56+
* @var ProcessorInterface
57+
*/
58+
private ProcessorInterface $processor;
59+
60+
/**
61+
* @var AttributeFactory
62+
*/
63+
private AttributeFactory $attributeFactory;
64+
65+
/**
66+
* @var ResourceModelAttribute
67+
*/
68+
private ResourceModelAttribute $resourceModelAttribute;
69+
70+
/**
71+
* @var AttributeRepositoryInterface
72+
*/
73+
private AttributeRepositoryInterface $attributeRepository;
74+
75+
/**
76+
* @param DataMerger $dataMerger
77+
* @param ProcessorInterface $processor
78+
* @param AttributeRepositoryInterface $attributeRepository
79+
* @param AttributeFactory $attributeFactory
80+
* @param ResourceModelAttribute $resourceModelAttribute
81+
*/
82+
public function __construct(
83+
DataMerger $dataMerger,
84+
ProcessorInterface $processor,
85+
AttributeRepositoryInterface $attributeRepository,
86+
AttributeFactory $attributeFactory,
87+
ResourceModelAttribute $resourceModelAttribute
88+
) {
89+
$this->dataMerger = $dataMerger;
90+
$this->processor = $processor;
91+
$this->attributeFactory = $attributeFactory;
92+
$this->resourceModelAttribute = $resourceModelAttribute;
93+
$this->attributeRepository = $attributeRepository;
94+
}
95+
96+
/**
97+
* @inheritdoc
98+
*/
99+
public function apply(array $data = []): ?DataObject
100+
{
101+
/** @var Attribute $attr */
102+
$attr = $this->attributeFactory->createAttribute(Attribute::class, self::DEFAULT_DATA);
103+
$mergedData = $this->processor->process($this, $this->dataMerger->merge(self::DEFAULT_DATA, $data));
104+
$attr->setData($mergedData);
105+
$this->resourceModelAttribute->save($attr);
106+
return $attr;
107+
}
108+
109+
/**
110+
* @inheritdoc
111+
*/
112+
public function revert(DataObject $data): void
113+
{
114+
$this->attributeRepository->deleteById($data['attribute_id']);
115+
}
116+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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\CatalogGraphQl\Model\Output;
9+
10+
use Magento\Catalog\Model\Entity\Attribute;
11+
use Magento\Eav\Api\Data\AttributeInterface;
12+
use Magento\EavGraphQl\Model\Output\GetAttributeDataInterface;
13+
use Magento\Framework\Exception\LocalizedException;
14+
use Magento\Framework\Exception\NoSuchEntityException;
15+
16+
/**
17+
* Format attributes metadata for GraphQL output
18+
*/
19+
class AttributeMetadata implements GetAttributeDataInterface
20+
{
21+
/**
22+
* @var string
23+
*/
24+
private string $entityType;
25+
26+
/**
27+
* @param string $entityType
28+
*/
29+
public function __construct(string $entityType)
30+
{
31+
$this->entityType = $entityType;
32+
}
33+
34+
/**
35+
* Retrieve formatted attribute data
36+
*
37+
* @param Attribute $attribute
38+
* @param string $entityType
39+
* @param int $storeId
40+
* @return array
41+
* @throws LocalizedException
42+
* @throws NoSuchEntityException
43+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
44+
*/
45+
public function execute(
46+
AttributeInterface $attribute,
47+
string $entityType,
48+
int $storeId
49+
): array {
50+
if ($entityType !== $this->entityType) {
51+
return [];
52+
}
53+
54+
$metadata = [
55+
'is_searchable' => $attribute->getIsSearchable() === "1",
56+
'is_filterable' => $attribute->getIsFilterable() === "1",
57+
'is_comparable' => $attribute->getIsComparable() === "1",
58+
'is_html_allowed_on_front' => $attribute->getIsHtmlAllowedOnFront() === "1",
59+
'is_used_for_price_rules' => $attribute->getIsUsedForPriceRules() === "1",
60+
'is_filterable_in_search' => $attribute->getIsFilterableInSearch() === "1",
61+
'used_in_product_listing' => $attribute->getUsedInProductListing() === "1",
62+
'is_wysiwyg_enabled' => $attribute->getIsWysiwygEnabled() === "1",
63+
'is_used_for_promo_rules' => $attribute->getIsUsedForPromoRules() === "1",
64+
'apply_to' => null,
65+
];
66+
67+
if (!empty($attribute->getApplyTo())) {
68+
$metadata['apply_to'] = array_map('strtoupper', $attribute->getApplyTo());
69+
}
70+
71+
return $metadata;
72+
}
73+
}

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@
211211
<type name="Magento\EavGraphQl\Model\TypeResolver\AttributeMetadata">
212212
<arguments>
213213
<argument name="entityTypes" xsi:type="array">
214-
<item name="PRODUCT" xsi:type="string">CatalogAttributeMetadata</item>
214+
<item name="CATALOG_PRODUCT" xsi:type="string">CatalogAttributeMetadata</item>
215+
<item name="CATALOG_CATEGORY" xsi:type="string">CatalogAttributeMetadata</item>
215216
</argument>
216217
</arguments>
217218
</type>
@@ -220,8 +221,27 @@
220221
<argument name="map" xsi:type="array">
221222
<item name="AttributeEntityTypeEnum" xsi:type="array">
222223
<item name="catalog_product" xsi:type="string">catalog_product</item>
224+
<item name="catalog_category" xsi:type="string">catalog_category</item>
223225
</item>
224226
</argument>
225227
</arguments>
226228
</type>
229+
<type name="Magento\EavGraphQl\Model\Output\GetAttributeDataComposite">
230+
<arguments>
231+
<argument name="providers" xsi:type="array">
232+
<item name="catalog_product" xsi:type="object">GetCatalogProductAttributesMetadata</item>
233+
<item name="catalog_category" xsi:type="object">GetCatalogCategoryAttributesMetadata</item>
234+
</argument>
235+
</arguments>
236+
</type>
237+
<virtualType name="GetCatalogProductAttributesMetadata" type="Magento\CatalogGraphQl\Model\Output\AttributeMetadata">
238+
<arguments>
239+
<argument name="entityType" xsi:type="string">catalog_product</argument>
240+
</arguments>
241+
</virtualType>
242+
<virtualType name="GetCatalogCategoryAttributesMetadata" type="Magento\CatalogGraphQl\Model\Output\AttributeMetadata">
243+
<arguments>
244+
<argument name="entityType" xsi:type="string">catalog_category</argument>
245+
</arguments>
246+
</virtualType>
227247
</config>

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,4 +535,28 @@ type VirtualWishlistItem implements WishlistItemInterface @doc(description: "Con
535535

536536
enum AttributeEntityTypeEnum {
537537
CATALOG_PRODUCT
538+
CATALOG_CATEGORY
539+
}
540+
541+
type CatalogAttributeMetadata implements CustomAttributeMetadataInterface @doc(description: "Catalog attribute metadata.") {
542+
is_filterable_in_search: Boolean! @doc(description: "Whether a product or category attribute can be filtered in search or not.")
543+
used_in_product_listing: Boolean! @doc(description: "Whether a product or category attribute is used in product listing or not.")
544+
is_searchable: Boolean! @doc(description: "Whether a product or category attribute can be searched or not.")
545+
is_filterable: Boolean! @doc(description: "Whether a product or category attribute can be filtered or not.")
546+
is_comparable: Boolean! @doc(description: "Whether a product or category attribute can be compared against another or not.")
547+
is_html_allowed_on_front: Boolean! @doc(description: "Whether a product or category attribute can use HTML on front or not.")
548+
is_used_for_price_rules: Boolean! @doc(description: "Whether a product or category attribute can be used for price rules or not.")
549+
is_wysiwyg_enabled: Boolean! @doc(description: "Whether a product or category attribute has WYSIWYG enabled or not.")
550+
is_used_for_promo_rules: Boolean! @doc(description: "Whether a product or category attribute is used for promo rules or not.")
551+
apply_to: [CatalogAttributeApplyToEnum] @doc(description: "To which catalog types an attribute can be applied.")
552+
}
553+
554+
enum CatalogAttributeApplyToEnum {
555+
SIMPLE
556+
VIRTUAL
557+
BUNDLE
558+
DOWNLOADABLE
559+
CONFIGURABLE
560+
GROUPED
561+
CATEGORY
538562
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public function execute(
7373
$entityType
7474
),
7575
'frontend_input' => $this->getFrontendInput($attribute),
76+
'frontend_class' => $attribute->getFrontendClass(),
7677
'is_required' => $attribute->getIsRequired(),
7778
'default_value' => $attribute->getDefaultValue(),
7879
'is_unique' => $attribute->getIsUnique(),

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ interface CustomAttributeMetadataInterface @typeResolver(class: "Magento\\EavGra
7676
label: String @doc(description: "The label assigned to the attribute.")
7777
entity_type: AttributeEntityTypeEnum! @doc(description: "The type of entity that defines the attribute.")
7878
frontend_input: AttributeFrontendInputEnum @doc(description: "The frontend input type of the attribute.")
79+
frontend_class: String @doc(description: "The frontend class of the attribute.")
7980
is_required: Boolean! @doc(description: "Whether the attribute value is required.")
8081
default_value: String @doc(description: "Default attribute value.")
8182
is_unique: Boolean! @doc(description: "Whether the attribute value must be unique.")

0 commit comments

Comments
 (0)