src/module-elasticsuite-catalog/Model/Layer/Filter/Category.php
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer
* versions in the future.
*
* @category Smile
* @package Smile\ElasticsuiteCatalog
* @author Aurelien FOUCRET <aurelien.foucret@smile.fr>
* @copyright 2020 Smile
* @license Open Software License ("OSL") v. 3.0
*/
namespace Smile\ElasticsuiteCatalog\Model\Layer\Filter;
use Smile\ElasticsuiteCatalog\Model\Search\Request\Field\Mapper as RequestFieldMapper;
/**
* Product category filter implementation.
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*
* @category Smile
* @package Smile\ElasticsuiteCatalog
* @author Aurelien FOUCRET <aurelien.foucret@smile.fr>
*/
class Category extends \Magento\CatalogSearch\Model\Layer\Filter\Category
{
/**
* Configuration path for URL rewrite usage.
*/
const XML_CATEGORY_FILTER_USE_URL_REWRITE = 'smile_elasticsuite_catalogsearch_settings/catalogsearch/category_filter_use_url_rewrites';
/**
* @var \Magento\Catalog\Model\Layer\Filter\DataProvider\Category
*/
private $dataProvider;
/**
* @var \Magento\Framework\Escaper
*/
private $escaper;
/**
* @var boolean
*/
private $useUrlRewrites;
/**
* @var \Magento\Catalog\Model\ResourceModel\Category\Collection|\Magento\Catalog\Model\Category[]
*/
protected $childrenCategories;
/**
* @var \Smile\ElasticsuiteCore\Api\Search\ContextInterface
*/
private $searchContext;
/**
* @var RequestFieldMapper
*/
private $requestFieldMapper;
/**
* Constructor.
*
* @SuppressWarnings(PHPMD.BooleanArgumentFlag)
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*
* @param \Magento\Catalog\Model\Layer\Filter\ItemFactory $filterItemFactory Filter item factory.
* @param \Magento\Store\Model\StoreManagerInterface $storeManager Store manager.
* @param \Magento\Catalog\Model\Layer $layer Search layer.
* @param \Magento\Catalog\Model\Layer\Filter\Item\DataBuilder $itemDataBuilder Item data builder.
* @param \Magento\Framework\Escaper $escaper HTML escaper.
* @param \Magento\Catalog\Model\Layer\Filter\DataProvider\CategoryFactory $dataProviderFactory Data provider.
* @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig Scope configuration.
* @param \Smile\ElasticsuiteCore\Api\Search\ContextInterface $context Search Context.
* @param RequestFieldMapper $requestFieldMapper Search request field mapper.
* @param boolean $useUrlRewrites Uses URLs rewrite for rendering.
* @param array $data Custom data.
*/
public function __construct(
\Magento\Catalog\Model\Layer\Filter\ItemFactory $filterItemFactory,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Catalog\Model\Layer $layer,
\Magento\Catalog\Model\Layer\Filter\Item\DataBuilder $itemDataBuilder,
\Magento\Framework\Escaper $escaper,
\Magento\Catalog\Model\Layer\Filter\DataProvider\CategoryFactory $dataProviderFactory,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Smile\ElasticsuiteCore\Api\Search\ContextInterface $context,
RequestFieldMapper $requestFieldMapper,
$useUrlRewrites = false,
array $data = []
) {
parent::__construct(
$filterItemFactory,
$storeManager,
$layer,
$itemDataBuilder,
$escaper,
$dataProviderFactory,
$data
);
$this->escaper = $escaper;
$this->dataProvider = $dataProviderFactory->create(['layer' => $this->getLayer()]);
$this->searchContext = $context;
$this->requestFieldMapper = $requestFieldMapper;
$this->useUrlRewrites = ($useUrlRewrites === true) ? (bool) $scopeConfig->isSetFlag(
self::XML_CATEGORY_FILTER_USE_URL_REWRITE,
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$storeManager->getStore()->getId()
) : false;
}
/**
* {@inheritDoc}
*/
public function apply(\Magento\Framework\App\RequestInterface $request)
{
$categoryId = $request->getParam($this->_requestVar) ? : $request->getParam('id');
if (!empty($categoryId)) {
$this->dataProvider->setCategoryId($categoryId);
$category = $this->dataProvider->getCategory();
$this->searchContext->setCurrentCategory($category);
$this->applyCategoryFilterToCollection($category);
if ($request->getParam('id') != $category->getId() && $this->dataProvider->isValid()) {
$this->getLayer()->getState()->addFilter($this->_createItem($category->getName(), $categoryId));
}
}
return $this;
}
/**
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
*
* {@inheritDoc}
*/
protected function _getItemsData()
{
$items = [];
/** @var \Magento\CatalogSearch\Model\ResourceModel\Fulltext\Collection $productCollection */
$productCollection = $this->getLayer()->getProductCollection();
$optionsFacetedData = $productCollection->getFacetedData('categories');
$currentCategory = $this->dataProvider->getCategory();
$categories = $this->getChildrenCategories();
if ($currentCategory->getIsActive()) {
foreach ($categories as $category) {
if (isset($optionsFacetedData[(int) $category->getId()])) {
$productCount = $optionsFacetedData[$category->getId()]['count'];
if ($category->getIsActive() && $productCount > 0) {
$item = [
'label' => $this->escaper->escapeHtml($category->getName()),
'value' => $category->getId(),
'count' => $optionsFacetedData[$category->getId()]['count'],
'url' => $this->getCategoryFilterUrl($category),
];
$items[] = $item;
}
}
}
}
return $items;
}
/**
* Apply the category filter to the layer product collection.
*
* @param \Magento\Catalog\Api\Data\CategoryInterface $category Category.
*
* @return $this
*/
protected function applyCategoryFilterToCollection(\Magento\Catalog\Api\Data\CategoryInterface $category)
{
$this->getLayer()->getProductCollection()->addCategoryFilter($category);
return $this;
}
/**
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
*
* {@inheritDoc}
*/
protected function _initItems()
{
$data = $this->_getItemsData();
$items = [];
foreach ($data as $itemData) {
$item = $this->_createItem($itemData['label'], $itemData['value'], $itemData['count']);
$items[] = $item;
if ($this->useUrlRewrites() === true) {
$item->setUrlRewrite($itemData['url']);
}
}
$this->_items = $items;
return $this;
}
/**
* Indicates if the filter uses url rewrites or not.
*
* @return bool
*/
protected function useUrlRewrites()
{
return $this->useUrlRewrites;
}
/**
* Retrieve currently selected category children categories.
*
* @return \Magento\Catalog\Model\ResourceModel\Category\Collection|\Magento\Catalog\Model\Category[]
*/
protected function getChildrenCategories()
{
if ($this->childrenCategories === null) {
$currentCategory = $this->dataProvider->getCategory();
$this->childrenCategories = $currentCategory->getChildrenCategories();
}
return $this->childrenCategories;
}
/**
* Retrieve ES filter field.
*
* @return string
*/
protected function getFilterField()
{
return $this->requestFieldMapper->getMappedFieldName('category_ids');
}
/**
* Category data provider.
*
* @return \Magento\Catalog\Model\Layer\Filter\DataProvider\Category
*/
protected function getDataProvider()
{
return $this->dataProvider;
}
/**
* Retrieve Category Url to build filter
*
* @param \Magento\Catalog\Api\Data\CategoryInterface $category Category.
*
* @return string
*/
protected function getCategoryFilterUrl($category)
{
return $category->getUrl();
}
}