Skip to content

Commit

Permalink
Resolving an issue where visibility filter for PDP requests was skipp…
Browse files Browse the repository at this point in the history
…ed due to ES query emulation
  • Loading branch information
aleksandrsm committed Apr 8, 2022
1 parent 6974ea2 commit 747a863
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
/**
* @category ScandiPWA
* @package ScandiPWA_CatalogGraphQl
* @author Aleksandrs Mokans <[email protected]>
* @copyright Copyright (c) 2022 Scandiweb, Ltd (https://scandiweb.com)
*/
declare(strict_types=1);

namespace ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor;

use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\VisibilityStatusProcessor as CoreVisibilityStatusProcessor;
use Magento\Framework\Api\SearchCriteriaInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\GraphQl\Model\Query\ContextInterface;
use ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CriteriaCheck;

/**
* Class VisibilityStatusProcessor
* @package ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor
*/
class VisibilityStatusProcessor extends CoreVisibilityStatusProcessor
{
/**
* Process collection to add additional joins, attributes, and clauses to a product collection.
* Rewrite: avoids joining the visibility attribute, if the filter was already present in searchCriteria
*
* @param Collection $collection
* @param SearchCriteriaInterface $searchCriteria
* @param array $attributeNames
* @param ContextInterface|null $context
* @return Collection
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @throws LocalizedException
*/
public function process(
Collection $collection,
SearchCriteriaInterface $searchCriteria,
array $attributeNames,
ContextInterface $context = null
): Collection {
$collection->joinAttribute('status', 'catalog_product/status', 'entity_id', null, 'inner');

$visibilityFilter = CriteriaCheck::getVisibilityFilter($searchCriteria);

if (!$visibilityFilter) {
$collection->joinAttribute('visibility', 'catalog_product/visibility', 'entity_id', null, 'inner');
}

return $collection;
}
}
19 changes: 19 additions & 0 deletions src/Model/Resolver/Products/DataProvider/Product/CriteriaCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,23 @@ static public function isSingleProductFilterType($filter) {

return $type === 'eq' && in_array($field, ['url_key', 'id', 'entity_id', 'sku']);
}

/**
* @param SearchCriteriaInterface $searchCriteria
* @return Filter|null
*/
static public function getVisibilityFilter(SearchCriteriaInterface $searchCriteria): ?Filter
{
foreach ($searchCriteria->getFilterGroups() as $filterGroup) {
$filters = $filterGroup->getFilters();

foreach ($filters as $filter) {
if ($filter->getField() === 'visibility') {
return $filter;
}
}
}

return null;
}
}
86 changes: 86 additions & 0 deletions src/Plugin/AddVisibilityFilterOnSingleProductRequests.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
/**
* @category ScandiPWA
* @package ScandiPWA_CatalogGraphQl
* @author Aleksandrs Mokans <[email protected]>
* @copyright Copyright (c) 2022 Scandiweb, Ltd (https://scandiweb.com)
*/
declare(strict_types=1);

namespace ScandiPWA\CatalogGraphQl\Plugin;

use Magento\Framework\Api\FilterBuilder;
use Magento\Framework\Api\Search\FilterGroupBuilder;
use Magento\Framework\Api\SearchCriteriaInterface;
use Magento\Framework\Api\Filter;
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ProductSearch\ProductCollectionSearchCriteriaBuilder;
use ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CriteriaCheck;

/**
* Class AddVisibilityFilterOnSingleProductRequests
* @package ScandiPWA\CatalogGraphQl\Model\Plugin
*/
class AddVisibilityFilterOnSingleProductRequests
{
/**
* @var FilterBuilder
*/
protected FilterBuilder $filterBuilder;

/**
* @var FilterGroupBuilder
*/
protected FilterGroupBuilder $filterGroupBuilder;

/**
* @param FilterBuilder $filterBuilder
* @param FilterGroupBuilder $filterGroupBuilder
*/
public function __construct(
FilterBuilder $filterBuilder,
FilterGroupBuilder $filterGroupBuilder
) {
$this->filterBuilder = $filterBuilder;
$this->filterGroupBuilder = $filterGroupBuilder;
}

/**
* Applies visibility filter to single product collection loads
* Necessary, because ES querywas skipped for performance
* @param ProductCollectionSearchCriteriaBuilder $subject
* @param SearchCriteriaInterface $searchCriteriaForCollection
* @param SearchCriteriaInterface $searchCriteria
* @return SearchCriteriaInterface
*/
public function afterBuild(
ProductCollectionSearchCriteriaBuilder $subject,
SearchCriteriaInterface $searchCriteriaForCollection,
SearchCriteriaInterface $searchCriteria
): SearchCriteriaInterface {
if (CriteriaCheck::isOnlySingleIdFilter($searchCriteria) &&
$visibilityFilter = CriteriaCheck::getVisibilityFilter($searchCriteria)) {
$filterForCollection = $this->createVisibilityFilter($visibilityFilter);
$this->filterGroupBuilder->addFilter($filterForCollection);
$visibilityGroup = $this->filterGroupBuilder->create();
$filterGroups = $searchCriteriaForCollection->getFilterGroups();
$filterGroups[] = $visibilityGroup;
$searchCriteriaForCollection->setFilterGroups($filterGroups);
}

return $searchCriteriaForCollection;
}

/**
* Creates a collection filter based off of ES filter
* @param Filter $filter
* @return Filter
*/
public function createVisibilityFilter(Filter $filter): Filter
{
return $this->filterBuilder
->setField($filter->getField())
->setValue($filter->getValue())
->setConditionType($filter->getConditionType())
->create();
}
}
8 changes: 8 additions & 0 deletions src/etc/graphql/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@

<preference for="Magento\CatalogGraphQl\Model\Resolver\Products\Query\Filter"
type="ScandiPWA\CatalogGraphQl\Model\Resolver\Products\Query\Filter"/>
<preference
for="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\VisibilityStatusProcessor"
type="ScandiPWA\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\VisibilityStatusProcessor"/>

<type name="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\ProductSearch\ProductCollectionSearchCriteriaBuilder">
<plugin name="add_visibility_filter_on_single_product_requests"
type="ScandiPWA\CatalogGraphQl\Plugin\AddVisibilityFilterOnSingleProductRequests"/>
</type>

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

0 comments on commit 747a863

Please sign in to comment.