Skip to content

Commit

Permalink
LYNX-103: Customer GraphQL CustomerAttributeMetadata implementation o…
Browse files Browse the repository at this point in the history
…f AttributeMetadataInterface (#98)
  • Loading branch information
loginesta authored Apr 25, 2023
1 parent e27f246 commit 65fd385
Show file tree
Hide file tree
Showing 13 changed files with 443 additions and 43 deletions.
3 changes: 3 additions & 0 deletions app/code/Magento/Customer/Test/Fixture/CustomerAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class CustomerAttribute implements RevertibleDataFixtureInterface
'sort_order' => null,
'attribute_set_id' => null,
'attribute_group_id' => null,
'input_filter' => null,
'multiline_count' => 0,
'validate_rules' => null
];

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CustomerGraphQl\Model\Output;

use Magento\Customer\Api\MetadataInterface;
use Magento\Customer\Model\Data\ValidationRule;
use Magento\Eav\Api\Data\AttributeInterface;
use Magento\EavGraphQl\Model\Output\GetAttributeDataInterface;
use Magento\EavGraphQl\Model\Uid as AttributeUid;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Query\EnumLookup;
use Magento\Framework\GraphQl\Query\Uid;

/**
* Format attributes metadata for GraphQL output
*/
class CustomerAttributeMetadata implements GetAttributeDataInterface
{
/**
* @var AttributeUid
*/
private AttributeUid $attributeUid;

/**
* @var Uid
*/
private Uid $uid;

/**
* @var EnumLookup
*/
private EnumLookup $enumLookup;

/**
* @var MetadataInterface
*/
private MetadataInterface $metadata;

/**
* @var string
*/
private string $entityType;

/**
* @param AttributeUid $attributeUid
* @param Uid $uid
* @param EnumLookup $enumLookup
* @param MetadataInterface $metadata
* @param string $entityType
*/
public function __construct(
AttributeUid $attributeUid,
Uid $uid,
EnumLookup $enumLookup,
MetadataInterface $metadata,
string $entityType
) {
$this->attributeUid = $attributeUid;
$this->uid = $uid;
$this->enumLookup = $enumLookup;
$this->metadata = $metadata;
$this->entityType = $entityType;
}

/**
* Retrieve formatted attribute data
*
* @param AttributeInterface $attribute
* @param string $entityType
* @param int $storeId
* @return array
* @throws LocalizedException
* @throws NoSuchEntityException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function execute(
AttributeInterface $attribute,
string $entityType,
int $storeId
): array {
if ($entityType !== $this->entityType) {
return [];
}

$attributeMetadata = $this->metadata->getAttributeMetadata($attribute->getAttributeCode());
$data = [];

$validationRules = array_map(function (ValidationRule $validationRule) {
return [
'name' => $this->enumLookup->getEnumValueFromField(
'ValidationRuleEnum',
strtoupper($validationRule->getName())
),
'value' => $validationRule->getValue()
];
}, $attributeMetadata->getValidationRules());

if ($attributeMetadata->isVisible()) {
$data = [
'input_filter' =>
empty($attributeMetadata->getInputFilter())
? 'NONE'
: $this->enumLookup->getEnumValueFromField(
'InputFilterEnum',
strtoupper($attributeMetadata->getInputFilter())
),
'multiline_count' => $attributeMetadata->getMultilineCount(),
'sort_order' => $attributeMetadata->getSortOrder(),
'validate_rules' => $validationRules,
'attributeMetadata' => $attributeMetadata
];
}

return $data;
}
}
46 changes: 46 additions & 0 deletions app/code/Magento/CustomerGraphQl/etc/graphql/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,34 @@
</argument>
</arguments>
</type>
<type name="Magento\EavGraphQl\Model\TypeResolver\AttributeMetadata">
<arguments>
<argument name="entityTypes" xsi:type="array">
<item name="CUSTOMER" xsi:type="string">CustomerAttributeMetadata</item>
<item name="CUSTOMER_ADDRESS" xsi:type="string">CustomerAttributeMetadata</item>
</argument>
</arguments>
</type>
<type name="Magento\EavGraphQl\Model\Output\GetAttributeDataComposite">
<arguments>
<argument name="providers" xsi:type="array">
<item name="customer" xsi:type="object">GetCustomerAttributesMetadata</item>
<item name="customer_address" xsi:type="object">GetCustomerAddressAttributesMetadata</item>
</argument>
</arguments>
</type>
<virtualType name="GetCustomerAttributesMetadata" type="Magento\CustomerGraphQl\Model\Output\CustomerAttributeMetadata">
<arguments>
<argument name="metadata" xsi:type="object">Magento\Customer\Model\Metadata\CustomerMetadata</argument>
<argument name="entityType" xsi:type="string">customer</argument>
</arguments>
</virtualType>
<virtualType name="GetCustomerAddressAttributesMetadata" type="Magento\CustomerGraphQl\Model\Output\CustomerAttributeMetadata">
<arguments>
<argument name="metadata" xsi:type="object">Magento\Customer\Model\Metadata\AddressMetadata</argument>
<argument name="entityType" xsi:type="string">customer_address</argument>
</arguments>
</virtualType>
<!-- Validate input customer data -->
<type name="Magento\CustomerGraphQl\Model\Customer\ValidateCustomerData">
<arguments>
Expand Down Expand Up @@ -69,6 +97,24 @@
<item name="customer" xsi:type="string">customer</item>
<item name="customer_address" xsi:type="string">customer_address</item>
</item>
<item name="InputFilterEnum" xsi:type="array">
<item name="none" xsi:type="string">NONE</item>
<item name="date" xsi:type="string">DATE</item>
<item name="trim" xsi:type="string">TRIM</item>
<item name="striptags" xsi:type="string">STRIPTAGS</item>
<item name="escapehtml" xsi:type="string">ESCAPEHTML</item>
</item>
<item name="ValidationRuleEnum" xsi:type="array">
<item name="date_range_max" xsi:type="string">DATE_RANGE_MAX</item>
<item name="date_range_min" xsi:type="string">DATE_RANGE_MIN</item>
<item name="file_extensions" xsi:type="string">FILE_EXTENSIONS</item>
<item name="input_validation" xsi:type="string">INPUT_VALIDATION</item>
<item name="max_text_length" xsi:type="string">MAX_TEXT_LENGTH</item>
<item name="min_text_length" xsi:type="string">MIN_TEXT_LENGTH</item>
<item name="max_file_size" xsi:type="string">MAX_FILE_SIZE</item>
<item name="max_image_height" xsi:type="string">MAX_IMAGE_HEGHT</item>
<item name="max_image_width" xsi:type="string">MAX_IMAGE_WIDTH</item>
</item>
</argument>
</arguments>
</type>
Expand Down
32 changes: 32 additions & 0 deletions app/code/Magento/CustomerGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -431,3 +431,35 @@ enum AttributeEntityTypeEnum {
CUSTOMER
CUSTOMER_ADDRESS
}

type CustomerAttributeMetadata implements AttributeMetadataInterface @doc(description: "Customer attribute metadata.") {
input_filter: InputFilterEnum @doc(description: "The template used for the input of the attribute (e.g., 'date').")
multiline_count: Int @doc(description: "The number of lines of the attribute value.")
sort_order: Int @doc(description: "The position of the attribute in the form.")
validate_rules: [ValidationRule] @doc(description: "The validation rules of the attribute value.")
}

enum InputFilterEnum @doc(description: "List of templates/filters applied to customer attribute input.") {
NONE @doc(description: "There are no templates or filters to be applied.")
DATE @doc(description: "Forces attribute input to follow the date format.")
TRIM @doc(description: "Strip whitespace (or other characters) from the beginning and end of the input.")
STRIPTAGS @doc(description: "Strip HTML Tags.")
ESCAPEHTML @doc(description: "Escape HTML Entities.")
}

type ValidationRule @doc(description: "Defines a customer attribute validation rule.") {
name: ValidationRuleEnum @doc(description: "Validation rule name applied to a customer attribute.")
value: String @doc(description: "Validation rule value.")
}

enum ValidationRuleEnum @doc(description: "List of validation rule names applied to a customer attribute.") {
DATE_RANGE_MAX
DATE_RANGE_MIN
FILE_EXTENSIONS
INPUT_VALIDATION
MAX_TEXT_LENGTH
MIN_TEXT_LENGTH
MAX_FILE_SIZE
MAX_IMAGE_HEIGHT
MAX_IMAGE_WIDTH
}
1 change: 0 additions & 1 deletion app/code/Magento/EavGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ type AttributesFormOutput @doc(description: "Metadata of EAV attributes associat
errors: [AttributeMetadataError!]! @doc(description: "Errors of retrieving certain attributes metadata.")
}


interface AttributeValueInterface @typeResolver(class: "Magento\\EavGraphQl\\Model\\TypeResolver\\AttributeValue") {
uid: ID! @doc(description: "The unique ID of an attribute value.")
code: String! @doc(description: "The attribute code.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
namespace Magento\GraphQl\Customer\Attribute;

use Magento\Customer\Api\CustomerMetadataInterface;
use Magento\Eav\Api\Data\AttributeInterface;
use Magento\Eav\Test\Fixture\Attribute;
use Magento\Customer\Api\Data\AttributeMetadataInterface;
use Magento\Customer\Test\Fixture\CustomerAttribute;
use Magento\EavGraphQl\Model\Uid;
use Magento\TestFramework\Fixture\DataFixture;
use Magento\TestFramework\Fixture\DataFixtureStorageManager;
Expand Down Expand Up @@ -49,7 +49,7 @@ class BooleanTest extends GraphQlAbstract

#[
DataFixture(
Attribute::class,
CustomerAttribute::class,
[
'entity_type_id' => CustomerMetadataInterface::ATTRIBUTE_SET_ID_CUSTOMER,
'frontend_input' => 'boolean',
Expand All @@ -60,7 +60,7 @@ class BooleanTest extends GraphQlAbstract
]
public function testMetadata(): void
{
/** @var AttributeInterface $attribute */
/** @var AttributeMetadataInterface $attribute */
$attribute = DataFixtureStorageManager::getStorage()->get('attribute');

$uid = Bootstrap::getObjectManager()->get(Uid::class)->encode(
Expand All @@ -77,7 +77,7 @@ public function testMetadata(): void
[
'uid' => $uid,
'code' => $attribute->getAttributeCode(),
'label' => $attribute->getDefaultFrontendLabel(),
'label' => $attribute->getFrontendLabel(),
'entity_type' => 'CUSTOMER',
'frontend_input' => 'BOOLEAN',
'is_required' => false,
Expand All @@ -95,7 +95,6 @@ public function testMetadata(): void
'value' => '0'
]
]

]
],
'errors' => []
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\GraphQl\Customer\Attribute;

use Magento\Customer\Api\AddressMetadataInterface;
use Magento\Customer\Api\Data\AttributeMetadataInterface;
use Magento\Customer\Test\Fixture\CustomerAttribute;
use Magento\EavGraphQl\Model\Uid;
use Magento\TestFramework\Fixture\DataFixture;
use Magento\TestFramework\Fixture\DataFixtureStorageManager;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\TestCase\GraphQlAbstract;

/**
* Test catalog EAV attributes metadata retrieval via GraphQL API
*/
class CustomerAddressAttributesTest extends GraphQlAbstract
{
private const QUERY = <<<QRY
{
attributesMetadata(attributes: [{attribute_code: "%s", entity_type: "%s"}]) {
items {
uid
code
label
entity_type
frontend_input
is_required
default_value
is_unique
... on CustomerAttributeMetadata {
input_filter
validate_rules {
name
value
}
}
}
errors {
type
message
}
}
}
QRY;

#[
DataFixture(
CustomerAttribute::class,
[
'entity_type_id' => AddressMetadataInterface::ATTRIBUTE_SET_ID_ADDRESS,
'frontend_input' => 'date',
'default_value' => '2023-03-22 00:00:00',
'input_filter' => 'DATE',
'validate_rules' =>
'{"DATE_RANGE_MIN":"1679443200","DATE_RANGE_MAX":"1679875200","INPUT_VALIDATION":"DATE"}'
],
'attribute'
),
]
public function testMetadata(): void
{
/** @var AttributeMetadataInterface $attribute */
$attribute = DataFixtureStorageManager::getStorage()->get('attribute');

$uid = Bootstrap::getObjectManager()->get(Uid::class)->encode(
'customer_address',
$attribute->getAttributeCode()
);

$formattedValidationRules = Bootstrap::getObjectManager()->get(FormatValidationRulesCommand::class)->execute(
$attribute->getValidationRules()
);

$result = $this->graphQlQuery(
sprintf(self::QUERY, $attribute->getAttributeCode(), 'customer_address')
);

$this->assertEquals(
[
'attributesMetadata' => [
'items' => [
[
'uid' => $uid,
'code' => $attribute->getAttributeCode(),
'label' => $attribute->getFrontendLabel(),
'entity_type' => 'CUSTOMER_ADDRESS',
'frontend_input' => 'DATE',
'is_required' => false,
'default_value' => $attribute->getDefaultValue(),
'is_unique' => false,
'input_filter' => $attribute->getInputFilter(),
'validate_rules' => $formattedValidationRules
]
],
'errors' => []
]
],
$result
);
}
}
Loading

0 comments on commit 65fd385

Please sign in to comment.