Skip to content

Pagination not updated after product attribute filtration

I have done following plugin to filter the products by a custom attribute ‘promotion_on’, it works, but pagination does not reflect filtration (it shows full product lists’ (without filtration) product page links -all)

<?php
namespace IwdatCatalogExtPluginCatalogModelResourceModelProduct;

class CollectionPlugin
{
    /**
     * @param Collection $subject
     * @param bool $printQuery
     * @param bool $logQuery
     */
    private $requestobj;
    public function __construct(MagentoFrameworkAppRequestHttp $request)
    {
        $this->requestobj = $request;
    }
    public function beforeLoad(MagentoCatalogModelResourceModelProductCollection $subject, $printQuery = false, $logQuery = false)
    {
    
       $thisRoute =  $this->requestobj->getRouteName();
        if (!$subject->isLoaded()) {
            // you can do your customzation/custom logic with $subject object
            
          
            if($thisRoute == 'offersx')
                $subject->addAttributeToFilter('promotion_on', 1); 
        }
  
        return $subject;//[$printQuery, $logQuery];
    }
}
?>

I tried overriding ResourceModel FullText/Collection , still no change in results.

<?php

namespace IwdatCatalogExtModelResourceModelFulltext;

use MagentoCatalogSearchModelSearchRequestGenerator;
use MagentoFrameworkDBSelect;
use MagentoFrameworkExceptionStateException;
use MagentoFrameworkSearchAdapterMysqlTemporaryStorage;
use MagentoFrameworkSearchResponseQueryResponse;
use MagentoFrameworkSearchRequestEmptyRequestDataException;
use MagentoFrameworkSearchRequestNonExistingRequestNameException;
use MagentoFrameworkApiSearchSearchResultFactory;
use MagentoFrameworkExceptionLocalizedException;
use MagentoFrameworkAppObjectManager;

/**
 * Fulltext Collection
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Collection extends MagentoCatalogSearchModelResourceModelFulltextCollection
{

    /**
     * @var  QueryResponse
     * @deprecated
     */
    protected $queryResponse;

    /**
     * Catalog search data
     *
     * @var MagentoSearchModelQueryFactory
     * @deprecated
     */
    protected $queryFactory = null;

    /**
     * @var MagentoFrameworkSearchRequestBuilder
     * @deprecated
     */
    private $requestBuilder;

    /**
     * @var MagentoSearchModelSearchEngine
     * @deprecated
     */
    private $searchEngine;

    /**
     * @var string
     */
    private $queryText;

    /**
     * @var string|null
     */
    private $order = null;

    /**
     * @var string
     */
    private $searchRequestName;

    /**
     * @var MagentoFrameworkSearchAdapterMysqlTemporaryStorageFactory
     */
    private $temporaryStorageFactory;

    /**
     * @var MagentoSearchApiSearchInterface
     */
    private $search;

    /**
     * @var MagentoFrameworkApiSearchSearchCriteriaBuilder
     */
    private $searchCriteriaBuilder;

    /**
     * @var MagentoFrameworkApiSearchSearchResultInterface
     */
    private $searchResult;

    /**
     * @var SearchResultFactory
     */
    private $searchResultFactory;

    /**
     * @var MagentoFrameworkApiFilterBuilder
     */
    private $filterBuilder;

    /**
     * @param MagentoFrameworkDataCollectionEntityFactory $entityFactory
     * @param PsrLogLoggerInterface $logger
     * @param MagentoFrameworkDataCollectionDbFetchStrategyInterface $fetchStrategy
     * @param MagentoFrameworkEventManagerInterface $eventManager
     * @param MagentoEavModelConfig $eavConfig
     * @param MagentoFrameworkAppResourceConnection $resource
     * @param MagentoEavModelEntityFactory $eavEntityFactory
     * @param MagentoCatalogModelResourceModelHelper $resourceHelper
     * @param MagentoFrameworkValidatorUniversalFactory $universalFactory
     * @param MagentoStoreModelStoreManagerInterface $storeManager
     * @param MagentoFrameworkModuleManager $moduleManager
     * @param MagentoCatalogModelIndexerProductFlatState $catalogProductFlatState
     * @param MagentoFrameworkAppConfigScopeConfigInterface $scopeConfig
     * @param MagentoCatalogModelProductOptionFactory $productOptionFactory
     * @param MagentoCatalogModelResourceModelUrl $catalogUrl
     * @param MagentoFrameworkStdlibDateTimeTimezoneInterface $localeDate
     * @param MagentoCustomerModelSession $customerSession
     * @param MagentoFrameworkStdlibDateTime $dateTime
     * @param MagentoCustomerApiGroupManagementInterface $groupManagement
     * @param MagentoSearchModelQueryFactory $catalogSearchData
     * @param MagentoFrameworkSearchRequestBuilder $requestBuilder
     * @param MagentoSearchModelSearchEngine $searchEngine
     * @param MagentoFrameworkSearchAdapterMysqlTemporaryStorageFactory $temporaryStorageFactory
     * @param MagentoFrameworkDBAdapterAdapterInterface $connection
     * @param string $searchRequestName
     * @param SearchResultFactory $searchResultFactory
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        MagentoFrameworkDataCollectionEntityFactory $entityFactory,
        PsrLogLoggerInterface $logger,
        MagentoFrameworkDataCollectionDbFetchStrategyInterface $fetchStrategy,
        MagentoFrameworkEventManagerInterface $eventManager,
        MagentoEavModelConfig $eavConfig,
        MagentoFrameworkAppResourceConnection $resource,
        MagentoEavModelEntityFactory $eavEntityFactory,
        MagentoCatalogModelResourceModelHelper $resourceHelper,
        MagentoFrameworkValidatorUniversalFactory $universalFactory,
        MagentoStoreModelStoreManagerInterface $storeManager,
        MagentoFrameworkModuleManager $moduleManager,
        MagentoCatalogModelIndexerProductFlatState $catalogProductFlatState,
        MagentoFrameworkAppConfigScopeConfigInterface $scopeConfig,
        MagentoCatalogModelProductOptionFactory $productOptionFactory,
        MagentoCatalogModelResourceModelUrl $catalogUrl,
        MagentoFrameworkStdlibDateTimeTimezoneInterface $localeDate,
        MagentoCustomerModelSession $customerSession,
        MagentoFrameworkStdlibDateTime $dateTime,
        MagentoCustomerApiGroupManagementInterface $groupManagement,
        MagentoSearchModelQueryFactory $catalogSearchData,
        MagentoFrameworkSearchRequestBuilder $requestBuilder,
        MagentoSearchModelSearchEngine $searchEngine,
        MagentoFrameworkSearchAdapterMysqlTemporaryStorageFactory $temporaryStorageFactory,
        MagentoFrameworkDBAdapterAdapterInterface $connection = null,
        $searchRequestName = 'catalog_view_container',
        SearchResultFactory $searchResultFactory = null
    ) {
        $this->queryFactory = $catalogSearchData;
        if ($searchResultFactory === null) {
            $this->searchResultFactory = MagentoFrameworkAppObjectManager::getInstance()
                ->get('MagentoFrameworkApiSearchSearchResultFactory');
        }
        parent::__construct(
            $entityFactory,
            $logger,
            $fetchStrategy,
            $eventManager,
            $eavConfig,
            $resource,
            $eavEntityFactory,
            $resourceHelper,
            $universalFactory,
            $storeManager,
            $moduleManager,
            $catalogProductFlatState,
            $scopeConfig,
            $productOptionFactory,
            $catalogUrl,
            $localeDate,
            $customerSession,
            $dateTime,
            $groupManagement,
            $catalogSearchData,
            $requestBuilder,
            $searchEngine,
            $temporaryStorageFactory,
            $connection,
            $searchRequestName,
            $searchResultFactory
        );
        $this->requestBuilder = $requestBuilder;
        $this->searchEngine = $searchEngine;
        $this->temporaryStorageFactory = $temporaryStorageFactory;
        $this->searchRequestName = $searchRequestName;
    }

    /**
     * @inheritdoc
     */
    protected function _renderFiltersBefore()
    {
        $this->getSearchCriteriaBuilder();
        $this->getFilterBuilder();
        $this->getSearch();

        if ($this->queryText) {
            $this->filterBuilder->setField('search_term');
            $this->filterBuilder->setValue($this->queryText);
            $this->searchCriteriaBuilder->addFilter($this->filterBuilder->create());
        }

        $priceRangeCalculation = $this->_scopeConfig->getValue(
            MagentoCatalogModelLayerFilterDynamicAlgorithmFactory::XML_PATH_RANGE_CALCULATION,
            MagentoStoreModelScopeInterface::SCOPE_STORE
        );
        if ($priceRangeCalculation) {
            $this->filterBuilder->setField('price_dynamic_algorithm');
            $this->filterBuilder->setValue($priceRangeCalculation);
            $this->searchCriteriaBuilder->addFilter($this->filterBuilder->create());
        }

        // ADDING CUSTOM FILTER START

        $this->filterBuilder->setField('promotion_on');
        $this->filterBuilder->setValue(1);
        $this->filterBuilder->setConditionType('eq');

        $this->searchCriteriaBuilder->addFilter($this->filterBuilder->create());

        // ADDING CUSTOM FILTER END

        $searchCriteria = $this->searchCriteriaBuilder->create();
        $searchCriteria->setRequestName($this->searchRequestName);
        try {
            $this->searchResult = $this->getSearch()->search($searchCriteria);
        } catch (EmptyRequestDataException $e) {
            /** @var MagentoFrameworkApiSearchSearchResultInterface $searchResult */
            $this->searchResult = $this->searchResultFactory->create()->setItems([]);
        } catch (NonExistingRequestNameException $e) {
            $this->_logger->error($e->getMessage());
            throw new LocalizedException(__('Sorry, something went wrong. You can find out more in the error log.'));
        }

        $temporaryStorage = $this->temporaryStorageFactory->create();
        $table = $temporaryStorage->storeApiDocuments($this->searchResult->getItems());

        $this->getSelect()->joinInner(
            [
                'search_result' => $table->getName(),
            ],
            'e.entity_id = search_result.' . TemporaryStorage::FIELD_ENTITY_ID,
            []
        );

        $this->_totalRecords = $this->searchResult->getTotalCount();

        if ($this->order && 'relevance' === $this->order['field']) {
            $this->getSelect()->order('search_result.'. TemporaryStorage::FIELD_SCORE . ' ' . $this->order['dir']);
        }
        //return parent::_renderFiltersBefore();
        return MagentoCatalogModelResourceModelProductCollection::_renderFiltersBefore();
    }

    /**
     * @deprecated
     * @return MagentoFrameworkApiSearchSearchCriteriaBuilder
     */
    private function getSearchCriteriaBuilder()
    {
        if ($this->searchCriteriaBuilder === null) {
            $this->searchCriteriaBuilder = ObjectManager::getInstance()
                ->get('MagentoFrameworkApiSearchSearchCriteriaBuilder');
        }
        return $this->searchCriteriaBuilder;
    }

    /**
     * @deprecated
     * @return MagentoFrameworkApiFilterBuilder
     */
    private function getFilterBuilder()
    {
        if ($this->filterBuilder === null) {
            $this->filterBuilder = ObjectManager::getInstance()->get('MagentoFrameworkApiFilterBuilder');
        }
        return $this->filterBuilder;
    }

    /**
     * @deprecated
     * @return MagentoSearchApiSearchInterface
     */
    private function getSearch()
    {
        if ($this->search === null) {
            $this->search = ObjectManager::getInstance()->get('MagentoSearchApiSearchInterface');
        }
        return $this->search;
    }

    /**
     * Return field faceted data from faceted search result
     *
     * @param string $field
     * @return array
     * @throws StateException
     */
    public function getFacetedData($field)
    {
        $this->_renderFilters();
        $result = [];
        $aggregations = $this->searchResult->getAggregations();
        // This behavior is for case with empty object when we got EmptyRequestDataException
        if (null !== $aggregations) {
            $bucket = $aggregations->getBucket($field . RequestGenerator::BUCKET_SUFFIX);
            if ($bucket) {
                foreach ($bucket->getValues() as $value) {
                    $metrics = $value->getMetrics();
                    $result[$metrics['value']] = $metrics;
                }
            } else {
                throw new StateException(__('Bucket does not exist'));
            }
        }
        return $result;
    }
}
?>

etc/frontend/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="MagentoCatalogModelResourceModelProductCollection">
        <plugin name="beforeproductCollectionPlugin" type="IwdatCatalogExtPluginCatalogModelResourceModelProductCollectionPlugin" />
    </type>
    <preference for="MagentoCatalogSearchModelResourceModelFulltextCollection" type="IwdatCatalogExtModelResourceModelFulltextCollection" />
</config>

etc/search_request.xml


<requests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="urn:magento:framework:Search/etc/search_request.xsd">

    <request query="catalog_view_container" index="catalogsearch_fulltext">    
        <queries>
            <query xsi:type="boolQuery" name="catalog_view_container" boost="1">
                <queryReference clause="should" ref="active_query"/>
            </query>
            <query name="active_query" xsi:type="filteredQuery">
                <filterReference clause="must" ref="active_query_filter"/>
            </query>
        </queries>
        <filters>
            <filter xsi:type="termFilter" name="active_query_filter" field="promotion_on" value="1"/>
        </filters>

        <from>0</from>
        <size>10000</size>
    </request>
</requests>

I do appreciate if anyone can guide me on how to resolve this, to apply pagination to filtered product collection, not to the full product collection.

Thanks and Best Regards

Indunil