From 7a4a3a5b0d4a067dd89bc8e8474aacab2bbe763b Mon Sep 17 00:00:00 2001 From: Alfreds Genkins Date: Mon, 7 Sep 2020 12:26:03 +0300 Subject: [PATCH] Magento 2.4 support --- composer.json | 6 +- src/Model/Resolver/Products/Query/Search.php | 34 ++------- src/SearchAdapter/Query/Builder/Match.php | 78 ++++++++++++-------- 3 files changed, 57 insertions(+), 61 deletions(-) diff --git a/composer.json b/composer.json index b6823ec..1c429b7 100644 --- a/composer.json +++ b/composer.json @@ -14,8 +14,8 @@ "magento/module-rule": "*", "magento/module-graph-ql": "*", "magento/module-store": "*", - "magento/module-elasticsearch": "*", - "magento/module-catalog-graph-ql": "^100.3", + "magento/module-elasticsearch": "^101", + "magento/module-catalog-graph-ql": "^100.4", "magento/module-configurable-product-graph-ql": "^100.3", "magento/module-bundle-graph-ql": "^100.3", "magento/module-swatches": "*", @@ -30,4 +30,4 @@ "ScandiPWA\\CatalogGraphQl\\": "src/" } } -} \ No newline at end of file +} diff --git a/src/Model/Resolver/Products/Query/Search.php b/src/Model/Resolver/Products/Query/Search.php index d0b06d0..f640dca 100644 --- a/src/Model/Resolver/Products/Query/Search.php +++ b/src/Model/Resolver/Products/Query/Search.php @@ -15,7 +15,6 @@ use Magento\CatalogGraphQl\Model\Resolver\Products\SearchResult; use Magento\CatalogGraphQl\Model\Resolver\Products\SearchResultFactory; use Magento\Search\Api\SearchInterface; -use Magento\Framework\Api\Search\SearchCriteriaInterfaceFactory; use Magento\Search\Model\Search\PageSizeProvider; use Magento\CatalogGraphQl\Model\Resolver\Products\Query\FieldSelection; @@ -43,11 +42,6 @@ class Search extends CoreSearch */ private $pageSizeProvider; - /** - * @var SearchCriteriaInterfaceFactory - */ - private $searchCriteriaFactory; - /** * @var FieldSelection */ @@ -72,16 +66,15 @@ class Search extends CoreSearch * @param SearchInterface $search * @param SearchResultFactory $searchResultFactory * @param PageSizeProvider $pageSize - * @param SearchCriteriaInterfaceFactory $searchCriteriaFactory * @param FieldSelection $fieldSelection * @param ProductSearch $productsProvider * @param SearchCriteriaBuilder $searchCriteriaBuilder + * @param DataPostProcessor $productPostProcessor */ public function __construct( SearchInterface $search, SearchResultFactory $searchResultFactory, PageSizeProvider $pageSize, - SearchCriteriaInterfaceFactory $searchCriteriaFactory, FieldSelection $fieldSelection, ProductSearch $productsProvider, SearchCriteriaBuilder $searchCriteriaBuilder, @@ -91,7 +84,6 @@ public function __construct( $search, $searchResultFactory, $pageSize, - $searchCriteriaFactory, $fieldSelection, $productsProvider, $searchCriteriaBuilder @@ -100,7 +92,6 @@ public function __construct( $this->search = $search; $this->searchResultFactory = $searchResultFactory; $this->pageSizeProvider = $pageSize; - $this->searchCriteriaFactory = $searchCriteriaFactory; $this->fieldSelection = $fieldSelection; $this->productsProvider = $productsProvider; $this->searchCriteriaBuilder = $searchCriteriaBuilder; @@ -124,27 +115,18 @@ public function getResult( $realPageSize = $searchCriteria->getPageSize(); $realCurrentPage = $searchCriteria->getCurrentPage(); - - // Current page must be set to 0 and page size to max for search to grab all ID's as temporary workaround + //Because of limitations of sort and pagination on search API we will query all IDS $pageSize = $this->pageSizeProvider->getMaxPageSize(); $searchCriteria->setPageSize($pageSize); $searchCriteria->setCurrentPage(0); $itemsResults = $this->search->search($searchCriteria); - //Create copy of search criteria without conditions (conditions will be applied by joining search result) - $searchCriteriaCopy = $this->searchCriteriaFactory->create() - ->setSortOrders($searchCriteria->getSortOrders()) - ->setPageSize($realPageSize) - ->setCurrentPage($realCurrentPage); - - $searchResults = $this->productsProvider->getList($searchCriteriaCopy, $itemsResults, $queryFields); + //Address limitations of sort and pagination on search API apply original pagination from GQL query + $searchCriteria->setPageSize($realPageSize); + $searchCriteria->setCurrentPage($realCurrentPage); + $searchResults = $this->productsProvider->getList($searchCriteria, $itemsResults, $queryFields); - //possible division by 0 - if ($realPageSize) { - $maxPages = (int)ceil($searchResults->getTotalCount() / $realPageSize); - } else { - $maxPages = 0; - } + $totalPages = $realPageSize ? ((int)ceil($searchResults->getTotalCount() / $realPageSize)) : 0; $searchCriteria->setPageSize($realPageSize); $searchCriteria->setCurrentPage($realCurrentPage); @@ -170,7 +152,7 @@ public function getResult( 'searchAggregation' => $itemsResults->getAggregations(), 'pageSize' => $realPageSize, 'currentPage' => $realCurrentPage, - 'totalPages' => $maxPages, + 'totalPages' => $totalPages, ] ); } diff --git a/src/SearchAdapter/Query/Builder/Match.php b/src/SearchAdapter/Query/Builder/Match.php index a139935..bbe0fd4 100644 --- a/src/SearchAdapter/Query/Builder/Match.php +++ b/src/SearchAdapter/Query/Builder/Match.php @@ -12,10 +12,10 @@ use Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\AttributeProvider; use Magento\Elasticsearch\Model\Adapter\FieldMapper\Product\FieldProvider\FieldType\ResolverInterface as TypeResolver; +use Magento\Elasticsearch\Model\Config; use Magento\Elasticsearch\SearchAdapter\Query\ValueTransformerPool; use Magento\Elasticsearch\Model\Adapter\FieldMapperInterface; use Magento\Elasticsearch\SearchAdapter\Query\Builder\Match as CoreMatch; -use Magento\Framework\App\ObjectManager; /** * Class Match @@ -47,40 +47,55 @@ class Match extends CoreMatch * @var ValueTransformerPool */ private $valueTransformerPool; + /** + * @var Config + */ + private $config; /** - * Match constructor. - * * @param FieldMapperInterface $fieldMapper - * @param array $preprocessorContainer - * @param AttributeProvider|null $attributeProvider - * @param TypeResolver|null $fieldTypeResolver - * @param ValueTransformerPool|null $valueTransformerPool + * @param AttributeProvider $attributeProvider + * @param TypeResolver $fieldTypeResolver + * @param ValueTransformerPool $valueTransformerPool + * @param Config $config */ public function __construct( FieldMapperInterface $fieldMapper, - array $preprocessorContainer, - AttributeProvider $attributeProvider = null, - TypeResolver $fieldTypeResolver = null, - ValueTransformerPool $valueTransformerPool = null + AttributeProvider $attributeProvider, + TypeResolver $fieldTypeResolver, + ValueTransformerPool $valueTransformerPool, + Config $config ) { $this->fieldMapper = $fieldMapper; - - $this->attributeProvider = $attributeProvider ?? ObjectManager::getInstance() - ->get(AttributeProvider::class); - $this->fieldTypeResolver = $fieldTypeResolver ?? ObjectManager::getInstance() - ->get(TypeResolver::class); - $this->valueTransformerPool = $valueTransformerPool ?? ObjectManager::getInstance() - ->get(ValueTransformerPool::class); - - parent::__construct($fieldMapper, $preprocessorContainer, $attributeProvider, $fieldTypeResolver, - $valueTransformerPool); + $this->attributeProvider = $attributeProvider; + $this->fieldTypeResolver = $fieldTypeResolver; + $this->valueTransformerPool = $valueTransformerPool; + $this->config = $config; + + parent::__construct( + $fieldMapper, + $attributeProvider, + $fieldTypeResolver, + $valueTransformerPool, + $config + ); } /** - * {@inheritDoc} + * Creates valid ElasticSearch search conditions from Match queries. + * + * The purpose of this method is to create a structure which represents valid search query + * for a full-text search. + * It sets search query condition, the search query itself, and sets the search query boost. + * + * The search query boost is an optional in the search query and therefore it will be set to 1 by default + * if none passed with a match query. + * + * @param array $matches + * @param array $queryValue + * @return array */ - protected function buildQueries(array $matches, array $queryValue): array + protected function buildQueries(array $matches, array $queryValue) { $conditions = []; @@ -91,29 +106,28 @@ protected function buildQueries(array $matches, array $queryValue): array $transformedTypes = []; foreach ($matches as $match) { - $attributeAdapter = $this->attributeProvider->getByAttributeCode($match['field']); + $resolvedField = $this->fieldMapper->getFieldName( + $match['field'], + ['type' => FieldMapperInterface::TYPE_QUERY] + ); + + $attributeAdapter = $this->attributeProvider->getByAttributeCode($resolvedField); $fieldType = $this->fieldTypeResolver->getFieldType($attributeAdapter); $valueTransformer = $this->valueTransformerPool->get($fieldType ?? 'text'); $valueTransformerHash = \spl_object_hash($valueTransformer); if (!isset($transformedTypes[$valueTransformerHash])) { $transformedTypes[$valueTransformerHash] = $valueTransformer->transform($value); } - $transformedValue = $transformedTypes[$valueTransformerHash]; if (null === $transformedValue) { //Value is incompatible with this field type. continue; } - - $resolvedField = $this->fieldMapper->getFieldName( - $match['field'], - ['type' => FieldMapperInterface::TYPE_QUERY] - ); - + $matchCondition = $match['matchCondition'] ?? $condition; $conditions[] = [ 'condition' => $queryValue['condition'], 'body' => [ - $condition => [ + $matchCondition => [ $resolvedField => [ 'query' => $transformedValue, 'boost' => $match['boost'] ?? 1,