Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolving an issue where visibility filter for PDP requests was skipped due to ES query emulation #136

Merged
merged 1 commit into from
Jul 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php
/**
* @category ScandiPWA
* @package ScandiPWA_CatalogGraphQl
* @author Aleksandrs Mokans <info@scandiweb.com>
* @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 <info@scandiweb.com>
* @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