Skip to content

Commit

Permalink
Merge pull request #136 from aleksandrsm/pdp-visibility-filter
Browse files Browse the repository at this point in the history
Resolving an issue where visibility filter for PDP requests was skipped due to ES query emulation
  • Loading branch information
aleksandrsm authored Jul 11, 2022
2 parents 046db6d + 747a863 commit 9c47234
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 9c47234

Please sign in to comment.