Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraphQl Custom Attributes Options output need optimization #39614

Open
wants to merge 10 commits into
base: 2.4-develop
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2018 Adobe
* All Rights Reserved.
*/
declare(strict_types=1);

namespace Magento\EavGraphQl\Model\Output\Value\Options;

use Magento\Eav\Model\AttributeRepository;
use Magento\Framework\ObjectManager\ResetAfterRequestInterface;

/**
* Custom attribute value provider for customer
*/
class GetCustomSelectedOptionAttributes implements GetAttributeSelectedOptionInterface
class GetCustomSelectedOptionAttributes implements GetAttributeSelectedOptionInterface, ResetAfterRequestInterface
{
/**
* @var AttributeRepository
*/
private AttributeRepository $attributeRepository;

/**
* @var array
*/
private array $optionsCache = [];

/**
* @param AttributeRepository $attributeRepository
*/
@@ -29,22 +35,59 @@ public function __construct(AttributeRepository $attributeRepository)

/**
* @inheritDoc
*
* @param string $entity
* @param string $code
* @param string $value
* @return array|null
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function execute(string $entity, string $code, string $value): ?array
{
$attribute = $this->attributeRepository->get($entity, $code);

$result = [];
$selectedValues = explode(',', $value);
foreach ($attribute->getOptions() as $option) {
if (!in_array($option->getValue(), $selectedValues)) {
continue;
$options = $this->getAttributeOptions($entity, $code);
foreach ($selectedValues as $selectedValue) {
if (isset($options[$selectedValue])) {
$result[] = [
'value' => $selectedValue,
'label' => $options[$selectedValue],
];
}
$result[] = [
'value' => $option->getValue(),
'label' => $option->getLabel()
];
}

return $result;
}

/**
* Get cached attribute options
*
* @param string $entity
* @param string $code
* @return array
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
private function getAttributeOptions(string $entity, string $code): array
{
$attribute = $this->attributeRepository->get($entity, $code);

if (!isset($this->optionsCache[$entity][$code])) {
$options = $attribute->getOptions();
$optionsLabel = [];
foreach ($options as $option) {
$optionsLabel[$option->getValue()] = $option->getLabel();
}
$this->optionsCache[$entity][$code] = $optionsLabel;
}

return $this->optionsCache[$entity][$code];
}

/**
* @inheritDoc
*/
public function _resetState(): void
{
$this->optionsCache = [];
}
}
40 changes: 28 additions & 12 deletions app/code/Magento/EavGraphQl/Model/Resolver/EntityFieldChecker.php
Original file line number Diff line number Diff line change
@@ -1,39 +1,50 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2018 Adobe
* All Rights Reserved.
*/
declare(strict_types=1);

namespace Magento\EavGraphQl\Model\Resolver;

use Magento\Eav\Model\Entity\Type;
use Magento\Framework\App\ResourceConnection;
use Magento\Eav\Model\Config as EavConfig;
use Magento\Framework\Exception\LocalizedException;

/**
*
* Check if the fields belongs to an entity
*/
class EntityFieldChecker
{
/**
* Entity tables cache
*
* @var array
*/

private array $entityTables = [];

/***
* @var ResourceConnection
*/
private ResourceConnection $resource;

/**
* @var Type
* @var EavConfig
*/
private Type $eavEntityType;
private EavConfig $eavConfig;

/**
* @param ResourceConnection $resource
* @param Type $eavEntityType
* @param EavConfig $eavConfig
*/
public function __construct(ResourceConnection $resource, Type $eavEntityType)
{
public function __construct(
ResourceConnection $resource,
EavConfig $eavConfig
) {
$this->resource = $resource;
$this->eavEntityType = $eavEntityType;
$this->eavConfig = $eavConfig;
}

/**
@@ -42,13 +53,18 @@ public function __construct(ResourceConnection $resource, Type $eavEntityType)
* @param string $entityTypeCode
* @param string $field
* @return bool
* @throws LocalizedException
*/
public function fieldBelongToEntity(string $entityTypeCode, string $field): bool
{
if (isset($this->entityTables[$entityTypeCode])) {
$table = $this->entityTables[$entityTypeCode];
} else {
$table = $this->eavConfig->getEntityType($entityTypeCode)->getAdditionalAttributeTable();
$this->entityTables[$entityTypeCode] = $table;
}
$connection = $this->resource->getConnection();
$columns = $connection->describeTable(
$this->eavEntityType->loadByCode($entityTypeCode)->getAdditionalAttributeTable()
);
$columns = $connection->describeTable($table);

return array_key_exists($field, $columns);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
* Copyright 2018 Adobe
* All Rights Reserved.
*/
declare(strict_types=1);

@@ -31,6 +31,11 @@ class GetFilteredAttributes
*/
private EntityFieldChecker $entityFieldChecker;

/**
* @var array
*/
private array $filteredAttributesCache = [];

/**
* @param AttributeRepository $attributeRepository
* @param SearchCriteriaBuilder $searchCriteriaBuilder
@@ -56,6 +61,10 @@ public function __construct(
*/
public function execute(array $filterArgs, string $entityType): array
{
$key = $this->getFilteredAttributesKey($filterArgs, $entityType);
if (isset($this->filteredAttributesCache[$key])) {
return $this->filteredAttributesCache[$key];
}
$errors = [];
foreach ($filterArgs as $field => $value) {
if ($this->entityFieldChecker->fieldBelongToEntity(strtolower($entityType), $field)) {
@@ -79,9 +88,28 @@ public function execute(array $filterArgs, string $entityType): array

$attributesList = $this->attributeRepository->getList(strtolower($entityType), $searchCriteria)->getItems();

return [
$this->filteredAttributesCache[$key] = [
'items' => $attributesList,
'errors' => $errors
];

return $this->filteredAttributesCache[$key];
}

/**
* Get a key for filtered attributes cache
*
* @param array $filterArgs
* @param string $entityType
* @return string
*/
private function getFilteredAttributesKey(array $filterArgs, string $entityType): string
{
$key = $entityType;
foreach ($filterArgs as $field => $value) {
$key .= '_' . $field . '_' . $value;
}

return sha1($key);
}
}