I have tried several different methods to artificially add an extra filter to the product grid (Category page).
There is an issue where after adding a filter to the product collection, the total record count is not updated, the pagination shows a wrong number of pages and the layered navigation filters does not re-calculate the product count per filter.
EDIT: Just to make it clear, all the methods I tried did filter the products correctly, but did not update the total record count (top of grid), page count (bottom of grid) and count per filter on the left nav.
Here are the methods I have tried:
Method 1
Plugin on \Magento\Catalog\Model\ResourceModel\Product\Collection
<type name="Magento\Catalog\Model\ResourceModel\Product\Collection">
<plugin name="AddFilter" type="Company\RegionManager\Model\AddFilter"/>
</type>
with following code:
public function aroundAddFieldToFilter(ProductCollection $collection, \Closure $proceed, $fields, $condition = null)
{
$collection->addAttributeToFilter('deal_active', array('eq' => 'yes'));
return $fields ? $proceed($fields, $condition) : $collection;
}
Method 2
Plugin on \Magento\Catalog\Model\Layer
<type name="Magento\Catalog\Model\Layer">
<plugin name="pluginRegionFilter" type="Company\RegionManager\Model\RegionFilter" sortOrder="1" disabled="false"/>
</type>
with following code:
public function afterGetProductCollection($subject, \Magento\Catalog\Model\ResourceModel\Product\Collection $collection) {
$collection->addAttributeToSelect('*');
$collection->addAttributeToFilter('deal_active', array('eq' => 'yes'));
return $collection;
}
Method 3
Trying to get rid of caching on getSize by creating a plugin on \Magento\Framework\Data\Collection\AbstractDb
<type name="Magento\Framework\Data\Collection\AbstractDb">
<plugin name="pluginCollectionSize" type="Company\RegionManager\Model\CollectionSize" sortOrder="1" disabled="false"/>
</type>
Using following code:
public function afterGetSize($subject, $result) {
$sql = $subject->getSelectCountSql();
$addSql = "SELECT count(*) FROM ($sql) AS taro01";
$addTotal = $subject->getConnection()->fetchOne($addSql, []);
$result += intval($addTotal) - 1;
return $result;
}
This method combined with Method 2 gave a better result but still far, pagination is off and record count considers current page records only, not total records.
Method 4
Overriding \Magento\Catalog\Block\Product\ProductList\Toolbar
<preference for="Magento\Catalog\Block\Product\ProductList\Toolbar" type="Company\RegionManager\Block\Html\Toolbar" />
using code:
public function getTotalNum()
{
return $this->getCollection()->getSize();
}
In the hopes of bypassing caching. (did not change anything)
Method 5
Trying to go deeper in the code.. Overriding \Magento\Catalog\Block\Product\ListProduct
<preference for="Magento\Catalog\Block\Product\ListProduct" type="Company\RegionManager\Block\Product\ListProduct" />
Overriding the _getProductCollection() method by adding a filter:
protected function _getProductCollection()
{
if ($this->_productCollection === null) {
$layer = $this->getLayer();
/* @var $layer \Magento\Catalog\Model\Layer */
if ($this->getShowRootCategory()) {
$this->setCategoryId($this->_storeManager->getStore()->getRootCategoryId());
}
// if this is a product view page
if ($this->_coreRegistry->registry('product')) {
// get collection of categories this product is associated with
$categories = $this->_coreRegistry->registry('product')
->getCategoryCollection()->setPage(1, 1)
->load();
// if the product is associated with any category
if ($categories->count()) {
// show products from this category
$this->setCategoryId(current($categories->getIterator()));
}
}
$origCategory = null;
if ($this->getCategoryId()) {
try {
$category = $this->categoryRepository->get($this->getCategoryId());
} catch (NoSuchEntityException $e) {
$category = null;
}
if ($category) {
$origCategory = $layer->getCurrentCategory();
$layer->setCurrentCategory($category);
}
}
$this->_productCollection = $layer->getProductCollection();
$this->prepareSortableFieldsByCategory($layer->getCurrentCategory());
if ($origCategory) {
$layer->setCurrentCategory($origCategory);
}
}
$this->_productCollection->addAttributeToSelect('*');
$this->_productCollection->addAttributeToFilter('deal_active', array('eq' => 'yes'));
return $this->_productCollection;
}
Same result as all the other methods.
I am out of ideas.. anyone managed to add a filter to a category page and have the pagination, record count and layered navigation recalculate counts successfully?
Thanks!