diff --git a/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/DataProvider/ProductSearch.php b/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/DataProvider/ProductSearch.php index 13bd29e83d8..7475763be5a 100644 --- a/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/DataProvider/ProductSearch.php +++ b/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/DataProvider/ProductSearch.php @@ -8,6 +8,7 @@ declare(strict_types=1); namespace Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider; use Magento\Catalog\Api\Data\ProductSearchResultsInterfaceFactory; +use Magento\Catalog\Model\Product\Visibility; use Magento\Catalog\Model\ResourceModel\Product\Collection; use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionPostProcessor; @@ -18,6 +19,7 @@ use Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection\SearchResultAp use Magento\Framework\Api\Search\SearchResultInterface; use Magento\Framework\Api\SearchCriteriaInterface; use Magento\Framework\Api\SearchResultsInterface; +use Magento\Framework\App\ObjectManager; use Magento\GraphQl\Model\Query\ContextInterface; /** @@ -55,6 +57,11 @@ class ProductSearch */ private $searchCriteriaBuilder; + /** + * @var Visibility + */ + private $catalogProductVisibility; + /** * @param CollectionFactory $collectionFactory * @param ProductSearchResultsInterfaceFactory $searchResultsFactory @@ -62,6 +69,7 @@ class ProductSearch * @param CollectionPostProcessor $collectionPostProcessor * @param SearchResultApplierFactory $searchResultsApplierFactory * @param ProductCollectionSearchCriteriaBuilder $searchCriteriaBuilder + * @param Visibility $catalogProductVisibility */ public function __construct( CollectionFactory $collectionFactory, @@ -69,7 +77,8 @@ class ProductSearch CollectionProcessorInterface $collectionPreProcessor, CollectionPostProcessor $collectionPostProcessor, SearchResultApplierFactory $searchResultsApplierFactory, - ProductCollectionSearchCriteriaBuilder $searchCriteriaBuilder + ProductCollectionSearchCriteriaBuilder $searchCriteriaBuilder, + Visibility $catalogProductVisibility ) { $this->collectionFactory = $collectionFactory; $this->searchResultsFactory = $searchResultsFactory; @@ -77,6 +86,7 @@ class ProductSearch $this->collectionPostProcessor = $collectionPostProcessor; $this->searchResultApplierFactory = $searchResultsApplierFactory; $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->catalogProductVisibility = $catalogProductVisibility; } /** @@ -106,6 +116,9 @@ class ProductSearch $this->getSortOrderArray($searchCriteriaForCollection) )->apply(); + $collection->setFlag('search_resut_applied', true); + + $collection->setVisibility($this->catalogProductVisibility->getVisibleInSiteIds()); $this->collectionPreProcessor->process($collection, $searchCriteriaForCollection, $attributes, $context); $collection->load(); $this->collectionPostProcessor->process($collection, $attributes); diff --git a/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php b/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php index 0cc00bb7b32..b03d1bd068b 100644 --- a/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php +++ b/vendor/magento/module-catalog-graph-ql/Model/Resolver/Products/SearchCriteria/CollectionProcessor/FilterProcessor/CategoryFilter.php @@ -9,6 +9,7 @@ namespace Magento\CatalogGraphQl\Model\Resolver\Products\SearchCriteria\Collecti use Magento\Catalog\Model\CategoryFactory; use Magento\Catalog\Model\ResourceModel\Category as CategoryResourceModel; +use Magento\Catalog\Model\ResourceModel\Product\Collection; use Magento\Framework\Api\Filter; use Magento\Framework\Api\SearchCriteria\CollectionProcessor\FilterProcessor\CustomFilterInterface; use Magento\Framework\Data\Collection\AbstractDb; @@ -18,6 +19,36 @@ use Magento\Framework\Data\Collection\AbstractDb; */ class CategoryFilter implements CustomFilterInterface { + /** + * Equal + */ + private const CONDITION_TYPE_EQ = 'eq'; + + /** + * Not Equal + */ + private const CONDITION_TYPE_NEQ = 'neq'; + + /** + * In + */ + private const CONDITION_TYPE_IN = 'in'; + + /** + * Not In + */ + private const CONDITION_TYPE_NIN = 'nin'; + + /** + * Supported condition types + */ + private const CONDITION_TYPES = [ + self::CONDITION_TYPE_EQ, + self::CONDITION_TYPE_NEQ, + self::CONDITION_TYPE_IN, + self::CONDITION_TYPE_NIN, + ]; + /** * @var CategoryFactory */ @@ -51,26 +82,46 @@ class CategoryFilter implements CustomFilterInterface */ public function apply(Filter $filter, AbstractDb $collection) { - $conditionType = $filter->getConditionType(); - if ($conditionType !== 'eq') { - return true; - } - - $categoryIds = $filter->getValue(); - if (!is_array($categoryIds)) { - $categoryIds = [$categoryIds]; - } - - $categoryProducts = []; - foreach ($categoryIds as $categoryId) { - $category = $this->categoryFactory->create(); - $this->categoryResourceModel->load($category, $categoryId); - $categoryProducts[$categoryId] = $category->getProductCollection()->getAllIds(); - $collection->addCategoryFilter($category); + $conditionType = $filter->getConditionType() ?: self::CONDITION_TYPE_IN; + $value = $filter->getValue(); + if ($value && in_array($conditionType, self::CONDITION_TYPES)) { + if ($conditionType === self::CONDITION_TYPE_EQ) { + $category = $this->getCategory((int) $value); + /** @var Collection $collection */ + /** This filter adds ability to sort by position*/ + $collection->addCategoryFilter($category); + } elseif (!$collection->getFlag('search_resut_applied')) { + /** Prevent filtering duplication as the filter should be already applied to the search result */ + $values = is_array($value) ? $value : explode(',', (string) $value); + $categoryIds = []; + foreach ($values as $value) { + $category = $this->getCategory((int) $value); + $children = []; + $childrenStr = $category->getIsAnchor() ? $category->getChildren(true) : ''; + if ($childrenStr) { + $children = explode(',', $childrenStr); + } + array_push($categoryIds, $value, ...$children); + } + /** @var Collection $collection */ + $collection->addCategoriesFilter([$conditionType => array_map('intval', $categoryIds)]); + } } - $categoryProductIds = array_unique(array_merge([], ...$categoryProducts)); - $collection->addIdFilter($categoryProductIds); return true; } + + /** + * Retrieve the category model by ID + * + * @param int $id + * @return \Magento\Catalog\Model\Category + */ + private function getCategory(int $id): \Magento\Catalog\Model\Category + { + /** @var \Magento\Catalog\Model\Category $category */ + $category = $this->categoryFactory->create(); + $this->categoryResourceModel->load($category, $id); + return $category; + } }