Skip to content

Commit 9c47234

Browse files
authored
Merge pull request #136 from aleksandrsm/pdp-visibility-filter
Resolving an issue where visibility filter for PDP requests was skipped due to ES query emulation
2 parents 046db6d + 747a863 commit 9c47234

File tree

4 files changed

+166
-0
lines changed

4 files changed

+166
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
/**
3+
* @category ScandiPWA
4+
* @package ScandiPWA_CatalogGraphQl
5+
* @author Aleksandrs Mokans <[email protected]>
6+
* @copyright Copyright (c) 2022 Scandiweb, Ltd (https://scandiweb.com)
7+
*/
8+
declare(strict_types=1);
9+
10+
namespace ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor;
11+
12+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
13+
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\VisibilityStatusProcessor as CoreVisibilityStatusProcessor;
14+
use Magento\Framework\Api\SearchCriteriaInterface;
15+
use Magento\Framework\Exception\LocalizedException;
16+
use Magento\GraphQl\Model\Query\ContextInterface;
17+
use ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CriteriaCheck;
18+
19+
/**
20+
* Class VisibilityStatusProcessor
21+
* @package ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor
22+
*/
23+
class VisibilityStatusProcessor extends CoreVisibilityStatusProcessor
24+
{
25+
/**
26+
* Process collection to add additional joins, attributes, and clauses to a product collection.
27+
* Rewrite: avoids joining the visibility attribute, if the filter was already present in searchCriteria
28+
*
29+
* @param Collection $collection
30+
* @param SearchCriteriaInterface $searchCriteria
31+
* @param array $attributeNames
32+
* @param ContextInterface|null $context
33+
* @return Collection
34+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
35+
* @throws LocalizedException
36+
*/
37+
public function process(
38+
Collection $collection,
39+
SearchCriteriaInterface $searchCriteria,
40+
array $attributeNames,
41+
ContextInterface $context = null
42+
): Collection {
43+
$collection->joinAttribute('status', 'catalog_product/status', 'entity_id', null, 'inner');
44+
45+
$visibilityFilter = CriteriaCheck::getVisibilityFilter($searchCriteria);
46+
47+
if (!$visibilityFilter) {
48+
$collection->joinAttribute('visibility', 'catalog_product/visibility', 'entity_id', null, 'inner');
49+
}
50+
51+
return $collection;
52+
}
53+
}

src/Model/Resolver/Products/DataProvider/Product/CriteriaCheck.php

+19
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,23 @@ static public function isSingleProductFilterType($filter) {
7373

7474
return $type === 'eq' && in_array($field, ['url_key', 'id', 'entity_id', 'sku']);
7575
}
76+
77+
/**
78+
* @param SearchCriteriaInterface $searchCriteria
79+
* @return Filter|null
80+
*/
81+
static public function getVisibilityFilter(SearchCriteriaInterface $searchCriteria): ?Filter
82+
{
83+
foreach ($searchCriteria->getFilterGroups() as $filterGroup) {
84+
$filters = $filterGroup->getFilters();
85+
86+
foreach ($filters as $filter) {
87+
if ($filter->getField() === 'visibility') {
88+
return $filter;
89+
}
90+
}
91+
}
92+
93+
return null;
94+
}
7695
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
/**
3+
* @category ScandiPWA
4+
* @package ScandiPWA_CatalogGraphQl
5+
* @author Aleksandrs Mokans <[email protected]>
6+
* @copyright Copyright (c) 2022 Scandiweb, Ltd (https://scandiweb.com)
7+
*/
8+
declare(strict_types=1);
9+
10+
namespace ScandiPWA\CatalogGraphQl\Plugin;
11+
12+
use Magento\Framework\Api\FilterBuilder;
13+
use Magento\Framework\Api\Search\FilterGroupBuilder;
14+
use Magento\Framework\Api\SearchCriteriaInterface;
15+
use Magento\Framework\Api\Filter;
16+
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ProductSearch\ProductCollectionSearchCriteriaBuilder;
17+
use ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CriteriaCheck;
18+
19+
/**
20+
* Class AddVisibilityFilterOnSingleProductRequests
21+
* @package ScandiPWA\CatalogGraphQl\Model\Plugin
22+
*/
23+
class AddVisibilityFilterOnSingleProductRequests
24+
{
25+
/**
26+
* @var FilterBuilder
27+
*/
28+
protected FilterBuilder $filterBuilder;
29+
30+
/**
31+
* @var FilterGroupBuilder
32+
*/
33+
protected FilterGroupBuilder $filterGroupBuilder;
34+
35+
/**
36+
* @param FilterBuilder $filterBuilder
37+
* @param FilterGroupBuilder $filterGroupBuilder
38+
*/
39+
public function __construct(
40+
FilterBuilder $filterBuilder,
41+
FilterGroupBuilder $filterGroupBuilder
42+
) {
43+
$this->filterBuilder = $filterBuilder;
44+
$this->filterGroupBuilder = $filterGroupBuilder;
45+
}
46+
47+
/**
48+
* Applies visibility filter to single product collection loads
49+
* Necessary, because ES querywas skipped for performance
50+
* @param ProductCollectionSearchCriteriaBuilder $subject
51+
* @param SearchCriteriaInterface $searchCriteriaForCollection
52+
* @param SearchCriteriaInterface $searchCriteria
53+
* @return SearchCriteriaInterface
54+
*/
55+
public function afterBuild(
56+
ProductCollectionSearchCriteriaBuilder $subject,
57+
SearchCriteriaInterface $searchCriteriaForCollection,
58+
SearchCriteriaInterface $searchCriteria
59+
): SearchCriteriaInterface {
60+
if (CriteriaCheck::isOnlySingleIdFilter($searchCriteria) &&
61+
$visibilityFilter = CriteriaCheck::getVisibilityFilter($searchCriteria)) {
62+
$filterForCollection = $this->createVisibilityFilter($visibilityFilter);
63+
$this->filterGroupBuilder->addFilter($filterForCollection);
64+
$visibilityGroup = $this->filterGroupBuilder->create();
65+
$filterGroups = $searchCriteriaForCollection->getFilterGroups();
66+
$filterGroups[] = $visibilityGroup;
67+
$searchCriteriaForCollection->setFilterGroups($filterGroups);
68+
}
69+
70+
return $searchCriteriaForCollection;
71+
}
72+
73+
/**
74+
* Creates a collection filter based off of ES filter
75+
* @param Filter $filter
76+
* @return Filter
77+
*/
78+
public function createVisibilityFilter(Filter $filter): Filter
79+
{
80+
return $this->filterBuilder
81+
->setField($filter->getField())
82+
->setValue($filter->getValue())
83+
->setConditionType($filter->getConditionType())
84+
->create();
85+
}
86+
}

src/etc/graphql/di.xml

+8
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@
5353

5454
<preference for="Magento\CatalogGraphQl\Model\Resolver\Products\Query\Filter"
5555
type="ScandiPWA\CatalogGraphQl\Model\Resolver\Products\Query\Filter"/>
56+
<preference
57+
for="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\VisibilityStatusProcessor"
58+
type="ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\VisibilityStatusProcessor"/>
59+
60+
<type name="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ProductSearch\ProductCollectionSearchCriteriaBuilder">
61+
<plugin name="add_visibility_filter_on_single_product_requests"
62+
type="ScandiPWA\CatalogGraphQl\Plugin\AddVisibilityFilterOnSingleProductRequests"/>
63+
</type>
5664

5765
<type name="Magento\Framework\App\ResourceConnection">
5866
<plugin name="get_catalog_category_product_index_table_name" type="Magento\Catalog\Model\Indexer\Category\Product\Plugin\TableResolver"/>

0 commit comments

Comments
 (0)