-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2416 from graphcommerce-org/feature/custom-attrib…
…ute-option Created a new field for products: `custom_attribute(attribute_code: "attribute_code")` to retrieve attribute option value labels.
- Loading branch information
Showing
13 changed files
with
258 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@graphcommerce/magento-graphql': minor | ||
--- | ||
|
||
Created a new field for products: `custom_attribute(attribute_code: "attribute_code")` to retrieve attribute option value labels. This field is only available in Magento 2.4.7 and up. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'@graphcommerce/magento-graphql': minor | ||
--- | ||
|
||
Added an `attribute`-field to `AttributeValueInterface` to be able to retrieve attribute metadata from the value of an attribute. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import fragments from '@graphcommerce/graphql/generated/fragments.json' | ||
import type { | ||
AttributeValueInterfaceResolvers, | ||
MeshContext, | ||
Resolvers, | ||
} from '@graphcommerce/graphql-mesh' | ||
import { customAttributeMetadataV2 } from './customAttributeMetadataV2' | ||
|
||
type AttributeValueResolver = Pick<AttributeValueInterfaceResolvers<MeshContext>, 'attribute'> | ||
|
||
const attributeValueResolver: AttributeValueResolver = { | ||
attribute: { | ||
selectionSet: `{ code }`, | ||
resolve: async (root, _, context) => | ||
root.attribute ?? | ||
(await customAttributeMetadataV2( | ||
{ attribute_code: root.code, entity_type: 'catalog_product' }, | ||
context, | ||
)), | ||
}, | ||
} | ||
|
||
type AttributeValueTypes = NonNullable< | ||
Awaited<ReturnType<AttributeValueInterfaceResolvers['__resolveType']>> | ||
> | ||
const attributeValueTypes = fragments.possibleTypes.AttributeValueInterface as AttributeValueTypes[] | ||
const resolvers: Resolvers = {} | ||
attributeValueTypes.forEach((attributeValueType) => { | ||
if (!resolvers[attributeValueType]) resolvers[attributeValueType] = attributeValueResolver | ||
}) | ||
export default resolvers |
68 changes: 68 additions & 0 deletions
68
packages/magento-graphql/mesh/customAttributeMetadataV2.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import type { MeshContext, CustomAttributeMetadataInterface } from '@graphcommerce/graphql-mesh' | ||
|
||
export type CustomAttributeInput = { attribute_code: string; entity_type: 'catalog_product' } | ||
|
||
export async function customAttributeMetadataV2( | ||
input: CustomAttributeInput, | ||
context: MeshContext, | ||
): Promise<CustomAttributeMetadataInterface | null> { | ||
const cacheKey = `customAttributeMetadata-${input.entity_type}-${input.attribute_code}` | ||
const cached = await context.cache.get(cacheKey) | ||
if (cached) return cached | ||
|
||
if (input.entity_type !== 'catalog_product') | ||
throw Error('Only catalog_product is supported at this moment') | ||
|
||
if ( | ||
!('customAttributeMetadataV2' in context.m2.Query) || | ||
typeof context.m2.Query.customAttributeMetadataV2 !== 'function' | ||
) | ||
throw Error('This field is only available in Magento 2.4.7 and up') | ||
|
||
const attribute = await context.m2.Query.customAttributeMetadataV2({ | ||
context, | ||
key: input, | ||
argsFromKeys: (attributes) => ({ attributes }), | ||
selectionSet: /* GraphQL */ ` | ||
{ | ||
items { | ||
__typename | ||
code | ||
label | ||
default_value | ||
entity_type | ||
frontend_class | ||
frontend_input | ||
is_required | ||
is_unique | ||
label | ||
... on CatalogAttributeMetadata { | ||
apply_to | ||
is_comparable | ||
is_filterable | ||
is_filterable_in_search | ||
is_html_allowed_on_front | ||
is_searchable | ||
is_used_for_price_rules | ||
is_used_for_promo_rules | ||
is_visible_in_advanced_search | ||
is_visible_on_front | ||
is_wysiwyg_enabled | ||
used_in_product_listing | ||
} | ||
options { | ||
label | ||
is_default | ||
value | ||
} | ||
} | ||
} | ||
`, | ||
valuesFromResults: (res, attributes) => | ||
attributes.map((attr) => res.items?.find((v) => v?.code === attr.attribute_code)), | ||
}) | ||
|
||
// Cache for 1 hour | ||
await context.cache.set(cacheKey, attribute, { ttl: 60 * 60 }) | ||
return attribute ?? null | ||
} |
47 changes: 47 additions & 0 deletions
47
packages/magento-graphql/mesh/customAttributeV2Resolver.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import fragments from '@graphcommerce/graphql/generated/fragments.json' | ||
import type { MeshContext, ProductInterfaceResolvers, Resolvers } from '@graphcommerce/graphql-mesh' | ||
import { Kind } from 'graphql' | ||
import { CustomAttributeInput, customAttributeMetadataV2 } from './customAttributeMetadataV2' | ||
|
||
type CustomAttributeV2Resolver = Pick<ProductInterfaceResolvers<MeshContext>, 'custom_attributeV2'> | ||
|
||
const customAttributeV2Resolver: CustomAttributeV2Resolver = { | ||
custom_attributeV2: { | ||
selectionSet: (fieldNode) => ({ | ||
kind: Kind.SELECTION_SET, | ||
selections: (fieldNode.arguments ?? []) | ||
.map((arg) => arg.value) | ||
.filter((value) => value.kind === Kind.STRING) | ||
.map((value) => ({ kind: Kind.FIELD, name: { kind: Kind.NAME, value: value.value } })), | ||
}), | ||
resolve: async (root, { attribute_code: code }, context) => { | ||
const value = String(root[code] ?? '') | ||
const input: CustomAttributeInput = { attribute_code: code, entity_type: 'catalog_product' } | ||
const attribute = await customAttributeMetadataV2(input, context) | ||
|
||
if (!attribute || !value) return null | ||
|
||
if ( | ||
attribute?.frontend_input && | ||
['SELECT', 'MULTISELECT'].includes(attribute.frontend_input) | ||
) { | ||
const values = attribute.frontend_input === 'SELECT' ? [value] : value.split(',') | ||
const selected_options = values.map((v) => { | ||
const found = attribute.options?.find((o) => o?.value === v || o?.label === v) | ||
if (!found) return null | ||
return { ...found, __typename: 'AttributeSelectedOption' } | ||
}) | ||
return { __typename: 'AttributeSelectedOptions', code, selected_options, attribute } | ||
} | ||
return { __typename: 'AttributeValue', code, value, attribute } | ||
}, | ||
}, | ||
} | ||
|
||
type ProductTypes = NonNullable<Awaited<ReturnType<ProductInterfaceResolvers['__resolveType']>>> | ||
const productInterfaceTypes = fragments.possibleTypes.ProductInterface as ProductTypes[] | ||
const resolvers: Resolvers = {} | ||
productInterfaceTypes.forEach((productType) => { | ||
if (!resolvers[productType]) resolvers[productType] = customAttributeV2Resolver | ||
}) | ||
export default resolvers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import type { meshConfig as meshConfigBase } from '@graphcommerce/graphql-mesh/meshConfig' | ||
import type { FunctionPlugin, PluginConfig } from '@graphcommerce/next-config' | ||
|
||
export const config: PluginConfig = { | ||
module: '@graphcommerce/graphql-mesh/meshConfig', | ||
type: 'function', | ||
} | ||
|
||
export const meshConfig: FunctionPlugin<typeof meshConfigBase> = ( | ||
prev, | ||
baseConfig, | ||
graphCommerceConfig, | ||
) => | ||
prev( | ||
{ | ||
...baseConfig, | ||
additionalResolvers: [ | ||
...(baseConfig.additionalResolvers ?? []), | ||
'@graphcommerce/magento-graphql/mesh/customAttributeV2Resolver.ts', | ||
'@graphcommerce/magento-graphql/mesh/attributeValueResolver.ts', | ||
], | ||
}, | ||
graphCommerceConfig, | ||
) |
7 changes: 7 additions & 0 deletions
7
packages/magento-graphql/schema-247/Query-customAttributeMetadataV2.graphqls
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
type Query { | ||
""" | ||
Retrieve EAV attributes metadata. | ||
""" | ||
customAttributeMetadataV2(attributes: [AttributeInput!]): AttributesMetadataOutput! | ||
@deprecated(reason: "Magento >= 2.4.7") | ||
} |
9 changes: 9 additions & 0 deletions
9
packages/magento-graphql/schema/AttributeValueInterface-attribute.graphqls
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
extend interface AttributeValueInterface { | ||
attribute: CustomAttributeMetadataInterface | ||
} | ||
extend type AttributeValue { | ||
attribute: CustomAttributeMetadataInterface | ||
} | ||
extend type AttributeSelectedOptions { | ||
attribute: CustomAttributeMetadataInterface | ||
} |
49 changes: 49 additions & 0 deletions
49
packages/magento-graphql/schema/ProductInterface-custom_attribute.graphqls
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
extend interface ProductInterface { | ||
""" | ||
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value. | ||
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query. | ||
""" | ||
custom_attributeV2(attribute_code: String!): AttributeValueInterface | ||
} | ||
extend type SimpleProduct { | ||
""" | ||
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value. | ||
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query. | ||
""" | ||
custom_attributeV2(attribute_code: String!): AttributeValueInterface | ||
} | ||
extend type ConfigurableProduct { | ||
""" | ||
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value. | ||
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query. | ||
""" | ||
custom_attributeV2(attribute_code: String!): AttributeValueInterface | ||
} | ||
extend type BundleProduct { | ||
""" | ||
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value. | ||
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query. | ||
""" | ||
custom_attributeV2(attribute_code: String!): AttributeValueInterface | ||
} | ||
extend type DownloadableProduct { | ||
""" | ||
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value. | ||
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query. | ||
""" | ||
custom_attributeV2(attribute_code: String!): AttributeValueInterface | ||
} | ||
extend type VirtualProduct { | ||
""" | ||
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value. | ||
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query. | ||
""" | ||
custom_attributeV2(attribute_code: String!): AttributeValueInterface | ||
} | ||
extend type GroupedProduct { | ||
""" | ||
This is the singular version of the custom_attributesV2 and allows selecting a single attribute option value. | ||
Available only after Magento 2.4.7 as it relies on the customAttributesV2 query. | ||
""" | ||
custom_attributeV2(attribute_code: String!): AttributeValueInterface | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters