Skip to content

Commit 35ba942

Browse files
author
Prabhu Ram
committed
PWA-1720: Expose storefront properties of Catalog attributes
- Added implementation
1 parent d4f3adf commit 35ba942

File tree

7 files changed

+103
-26
lines changed

7 files changed

+103
-26
lines changed

app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/AttributeOptionProvider.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ public function getOptions(array $optionIds, ?int $storeId, array $attributeCode
6363
'attribute_id' => 'a.attribute_id',
6464
'attribute_code' => 'a.attribute_code',
6565
'attribute_label' => 'a.frontend_label',
66+
'position' => 'attribute_configuration.position'
6667
]
6768
)
6869
->joinLeft(
@@ -72,6 +73,11 @@ public function getOptions(array $optionIds, ?int $storeId, array $attributeCode
7273
'attribute_store_label' => 'attribute_label.value',
7374
]
7475
)
76+
->joinLeft(
77+
['attribute_configuration' => $this->resourceConnection->getTableName('catalog_eav_attribute')],
78+
'a.attribute_id = attribute_configuration.attribute_id',
79+
[]
80+
)
7581
->joinLeft(
7682
['options' => $this->resourceConnection->getTableName('eav_attribute_option')],
7783
'a.attribute_id = options.attribute_id',
@@ -131,6 +137,7 @@ private function formatResult(Select $select): array
131137
'attribute_code' => $option['attribute_code'],
132138
'attribute_label' => $option['attribute_store_label']
133139
? $option['attribute_store_label'] : $option['attribute_label'],
140+
'position' => $option['position'],
134141
'options' => [],
135142
];
136143
}

app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/Builder/Attribute.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,11 @@ public function build(AggregationInterface $aggregation, ?int $storeId): array
8383
$result[$bucketName] = $this->layerFormatter->buildLayer(
8484
$attribute['attribute_label'] ?? $bucketName,
8585
\count($bucket->getValues()),
86-
$attribute['attribute_code'] ?? $bucketName
86+
$attribute['attribute_code'] ?? $bucketName,
87+
$attribute['position']
8788
);
8889

89-
$options = $this->getSortedOptions($bucket,$attribute['options'] ?: []);
90+
$options = $this->getSortedOptions($bucket, $attribute['options'] ?: []);
9091
foreach ($options as $option) {
9192
$result[$bucketName]['options'][] = $this->layerFormatter->buildItem(
9293
$option['label'],

app/code/Magento/CatalogGraphQl/DataProvider/Product/LayeredNavigation/Formatter/LayerFormatter.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@ class LayerFormatter
1818
* @param string $layerName
1919
* @param string $itemsCount
2020
* @param string $requestName
21+
* @param int $position
2122
* @return array
2223
*/
23-
public function buildLayer($layerName, $itemsCount, $requestName): array
24+
public function buildLayer($layerName, $itemsCount, $requestName, $position = null): array
2425
{
2526
return [
2627
'label' => $layerName,
2728
'count' => $itemsCount,
28-
'attribute_code' => $requestName
29+
'attribute_code' => $requestName,
30+
'position' => isset($position) ? (int)$position : null
2931
];
3032
}
3133

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ type Aggregation @doc(description: "A bucket that contains information for each
474474
label: String @doc(description: "The aggregation display name.")
475475
attribute_code: String! @doc(description: "Attribute code of the aggregation group.")
476476
options: [AggregationOption] @doc(description: "Array of options for the aggregation.")
477+
position: Int @doc(description: "The position of attribute in layered navigation block.")
477478
}
478479

479480
interface AggregationOptionInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\\AggregationOptionTypeResolverComposite") {

app/code/Magento/EavGraphQl/Model/Resolver/CustomAttributeMetadata.php

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99

1010
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
1111
use Magento\EavGraphQl\Model\Resolver\Query\Type;
12-
use Magento\EavGraphQl\Model\Resolver\Query\FrontendType;
12+
use Magento\EavGraphQl\Model\Resolver\Query\Attribute;
1313
use Magento\Framework\Exception\InputException;
1414
use Magento\Framework\Exception\LocalizedException;
1515
use Magento\Framework\GraphQl\Config\Element\Field;
1616
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
1717
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
1818
use Magento\Framework\GraphQl\Query\ResolverInterface;
19+
use Magento\Eav\Api\Data\AttributeInterface;
1920

2021
/**
2122
* Resolve data for custom attribute metadata requests
@@ -28,18 +29,18 @@ class CustomAttributeMetadata implements ResolverInterface
2829
private $type;
2930

3031
/**
31-
* @var FrontendType
32+
* @var Attribute
3233
*/
33-
private $frontendType;
34+
private $attribute;
3435

3536
/**
3637
* @param Type $type
37-
* @param FrontendType $frontendType
38+
* @param Attribute $attribute
3839
*/
39-
public function __construct(Type $type, FrontendType $frontendType)
40+
public function __construct(Type $type, Attribute $attribute)
4041
{
4142
$this->type = $type;
42-
$this->frontendType = $frontendType;
43+
$this->attribute = $attribute;
4344
}
4445

4546
/**
@@ -54,27 +55,27 @@ public function resolve(
5455
) {
5556
$attributes['items'] = null;
5657
$attributeInputs = $args['attributes'];
57-
foreach ($attributeInputs as $attribute) {
58-
if (!isset($attribute['attribute_code']) || !isset($attribute['entity_type'])) {
59-
$attributes['items'][] = $this->createInputException($attribute);
60-
continue;
61-
}
58+
$this->validateInputFields($attributeInputs);
59+
foreach ($attributeInputs as $attributeInput) {
6260
try {
63-
$frontendType = $this->frontendType->getType($attribute['attribute_code'], $attribute['entity_type']);
64-
$type = $this->type->getType($attribute['attribute_code'], $attribute['entity_type']);
61+
$attribute = $this->attribute->getAttribute(
62+
$attributeInput['attribute_code'],
63+
$attributeInput['entity_type']
64+
);
65+
$type = $this->type->getType($attributeInput['attribute_code'], $attributeInput['entity_type']);
6566
} catch (InputException $exception) {
6667
$attributes['items'][] = new GraphQlNoSuchEntityException(
6768
__(
6869
'Attribute code %1 of entity type %2 not configured to have a type.',
69-
[$attribute['attribute_code'], $attribute['entity_type']]
70+
[$attributeInput['attribute_code'], $attributeInput['entity_type']]
7071
)
7172
);
7273
continue;
7374
} catch (LocalizedException $exception) {
7475
$attributes['items'][] = new GraphQlInputException(
7576
__(
7677
'Invalid entity_type specified: %1',
77-
[$attribute['entity_type']]
78+
[$attributeInput['entity_type']]
7879
)
7980
);
8081
continue;
@@ -85,16 +86,64 @@ public function resolve(
8586
}
8687

8788
$attributes['items'][] = [
88-
'attribute_code' => $attribute['attribute_code'],
89-
'entity_type' => $attribute['entity_type'],
89+
'attribute_code' => $attributeInput['attribute_code'],
90+
'entity_type' => $attributeInput['entity_type'],
9091
'attribute_type' => ucfirst($type),
91-
'input_type' => $frontendType
92+
'input_type' => isset($attribute) ? $attribute->getFrontendInput() : null,
93+
'storefront_properties' => isset($attribute) ?$this->getStorefrontProperties($attribute) : null
9294
];
9395
}
9496

9597
return $attributes;
9698
}
9799

100+
/**
101+
* Format storefront properties
102+
*
103+
* @param AttributeInterface $attribute
104+
* @return array
105+
*/
106+
private function getStorefrontProperties(AttributeInterface $attribute)
107+
{
108+
return [
109+
'use_in_search' => $attribute->getIsSearchable(),
110+
'position'=> $attribute->getPosition(),
111+
'visible_on_catalog_storefront'=> $attribute->getIsVisibleOnFront(),
112+
'use_in_search_results_layered_navigation' => $attribute->getIsFilterableInSearch(),
113+
'used_in_product_listing'=> $attribute->getUsedInProductListing(),
114+
'use_in_layered_navigation'=>
115+
$this->getLayeredNavigationPropertiesEnum()[$attribute->getisFilterable()] ?? null
116+
];
117+
}
118+
119+
/**
120+
* Return enum for resolving use in layered navigation
121+
*
122+
* @return string[]
123+
*/
124+
private function getLayeredNavigationPropertiesEnum() {
125+
return [
126+
0 => 'NO',
127+
1 => 'FILTERABLE_WITH_RESULTS',
128+
2 => 'FILTERABLE_NO_RESULT'
129+
];
130+
}
131+
132+
/**
133+
* Validate input
134+
*
135+
* @param array $attributeInputs
136+
*/
137+
private function validateInputFields(array $attributeInputs)
138+
{
139+
foreach ($attributeInputs as $attribute) {
140+
if (!isset($attribute['attribute_code']) || !isset($attribute['entity_type'])) {
141+
$attributes['items'][] = $this->createInputException($attribute);
142+
continue;
143+
}
144+
}
145+
}
146+
98147
/**
99148
* Create GraphQL input exception for an invalid attribute input
100149
*

app/code/Magento/EavGraphQl/Model/Resolver/Query/FrontendType.php renamed to app/code/Magento/EavGraphQl/Model/Resolver/Query/Attribute.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
namespace Magento\EavGraphQl\Model\Resolver\Query;
99

1010
use Magento\Eav\Api\AttributeRepositoryInterface;
11+
use Magento\Eav\Api\Data\AttributeInterface;
1112
use Magento\Framework\Exception\NoSuchEntityException;
1213
use Magento\Framework\Webapi\ServiceTypeToEntityTypeMap;
1314

1415
/**
1516
* Get frontend input type for EAV attribute
1617
*/
17-
class FrontendType
18+
class Attribute
1819
{
1920
/**
2021
* @var AttributeRepositoryInterface
@@ -43,9 +44,9 @@ public function __construct(
4344
*
4445
* @param string $attributeCode
4546
* @param string $entityType
46-
* @return null|string
47+
* @return null | AttributeInterface
4748
*/
48-
public function getType(string $attributeCode, string $entityType): ?string
49+
public function getAttribute(string $attributeCode, string $entityType): ?AttributeInterface
4950
{
5051
$mappedEntityType = $this->serviceTypeMap->getEntityType($entityType);
5152
if ($mappedEntityType) {
@@ -56,6 +57,6 @@ public function getType(string $attributeCode, string $entityType): ?string
5657
} catch (NoSuchEntityException $e) {
5758
return null;
5859
}
59-
return $attribute->getFrontendInput();
60+
return $attribute;
6061
}
6162
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,22 @@ type Attribute @doc(description: "Attribute contains the attribute_type of the s
1515
attribute_type: String @doc(description: "The data type of the attribute")
1616
input_type: String @doc(description: "The frontend input type of the attribute")
1717
attribute_options: [AttributeOption] @resolver(class: "Magento\\EavGraphQl\\Model\\Resolver\\AttributeOptions") @doc(description: "Attribute options list.")
18+
storefront_properties: StorefrontProperties
19+
}
20+
21+
type StorefrontProperties {
22+
used_in_product_listing: Boolean
23+
use_in_search: Boolean
24+
position: Int
25+
visible_on_catalog_storefront: Boolean
26+
use_in_layered_navigation: UseInLayeredNavigationOptions
27+
use_in_search_results_layered_navigation: Boolean
28+
}
29+
30+
enum UseInLayeredNavigationOptions {
31+
NO
32+
FILTERABLE_WITH_RESULTS
33+
FILTERABLE_NO_RESULT
1834
}
1935

2036
type AttributeOption @doc(description: "Attribute option.") {

0 commit comments

Comments
 (0)