Skip to content

Commit

Permalink
#ESP-252 Add layered navigation attributes management
Browse files Browse the repository at this point in the history
 * Add layered navigation attributes management
 * Add No value filter for boolean
 * Fix applying boolean filters on GraphQL
  • Loading branch information
botisSmile committed Oct 12, 2021
1 parent b0ed615 commit 1ab9b09
Show file tree
Hide file tree
Showing 10 changed files with 444 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Smile\ElasticsuiteCore\Api\Index\Mapping\FieldInterface;
use Smile\ElasticsuiteCore\Api\Index\MappingInterface;
use Smile\ElasticsuiteCore\Helper\Mapping as MappingHelper;
use Smile\ElasticsuiteCatalog\Model\Attribute\LayeredNavAttributesProvider;

/**
* List of attributes used in query building.
Expand Down Expand Up @@ -75,33 +76,41 @@ class AttributeList
*/
private $requestFieldMapper;

/**
* @var LayeredNavAttributesProvider
*/
private $layeredNavAttributesProvider;

/**
* Constructor.
*
* @param AttributeCollectionFactory $attributeCollectionFactory Product attribute collection factory.
* @param StoreManagerInterface $storeManager Store manager.
* @param IndexOperationInterface $indexManager Search engine index manager.
* @param MappingHelper $mappingHelper Mapping helper.
* @param RequestFieldMapper $requestFieldMapper Search request field mapper.
* @param string $indexName Search engine index name.
* @param string $typeName Search engine type name.
* @param AttributeCollectionFactory $attributeCollectionFactory Product attribute collection factory.
* @param StoreManagerInterface $storeManager Store manager.
* @param IndexOperationInterface $indexManager Search engine index manager.
* @param MappingHelper $mappingHelper Mapping helper.
* @param RequestFieldMapper $requestFieldMapper Search request field mapper.
* @param LayeredNavAttributesProvider $layeredNavAttributesProvider Layered navigation attributes provider.
* @param string $indexName Search engine index name.
* @param string $typeName Search engine type name.
*/
public function __construct(
AttributeCollectionFactory $attributeCollectionFactory,
StoreManagerInterface $storeManager,
IndexOperationInterface $indexManager,
MappingHelper $mappingHelper,
RequestFieldMapper $requestFieldMapper,
LayeredNavAttributesProvider $layeredNavAttributesProvider,
$indexName = 'catalog_product',
$typeName = 'product'
) {
$this->attributeCollectionFactory = $attributeCollectionFactory;
$this->storeManager = $storeManager;
$this->indexManager = $indexManager;
$this->mappingHelper = $mappingHelper;
$this->requestFieldMapper = $requestFieldMapper;
$this->indexName = $indexName;
$this->typeName = $typeName;
$this->attributeCollectionFactory = $attributeCollectionFactory;
$this->storeManager = $storeManager;
$this->indexManager = $indexManager;
$this->mappingHelper = $mappingHelper;
$this->requestFieldMapper = $requestFieldMapper;
$this->layeredNavAttributesProvider = $layeredNavAttributesProvider;
$this->indexName = $indexName;
$this->typeName = $typeName;
}

/**
Expand Down Expand Up @@ -129,6 +138,13 @@ public function getAttributeCollection()

$this->attributeCollection->addFieldToFilter('attribute_code', $fieldNames)
->addFieldToFilter('backend_type', ['neq' => 'datetime']);

if (!empty($this->layeredNavAttributesProvider->getList())) {
$this->attributeCollection->addFieldToFilter(
'attribute_code',
['nin' => array_keys($this->layeredNavAttributesProvider->getList())]
);
}
}

return $this->attributeCollection;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?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 Botis <botis@smile.fr>
* @copyright 2021 Smile
* @license Open Software License ("OSL") v. 3.0
*/

namespace Smile\ElasticsuiteCatalog\Api;

/**
* LayeredNavAttributeInterface class.
*
* @category Smile
* @package Smile\ElasticsuiteCatalog
* @author Botis <botis@smile.fr>
*/
interface LayeredNavAttributeInterface
{
/**
* Get attribute code.
*
* @return string
*/
public function getAttributeCode(): string;

/**
* Get ES filter field.
*
* @return string
*/
public function getFilterField(): string;

/**
* Get additional aggregation data.
*
* @return array
*/
public function getAdditionalAggregationData(): array;

/**
* Skip attribute.
*
* @return bool
*/
public function skipAttribute(): bool;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Magento\CatalogGraphQl\DataProvider\Product\LayeredNavigation\LayerBuilderInterface;
use Magento\Framework\Api\Search\AggregationInterface;
use Magento\Framework\Api\Search\BucketInterface;
use Smile\ElasticsuiteCatalog\Model\Attribute\LayeredNavAttributesProvider;
use Smile\ElasticsuiteCore\Helper\Mapping;

/**
Expand Down Expand Up @@ -52,6 +53,11 @@ class Attribute // Not implementing the LayerBuilderInterface because it did not
*/
private $attributeRepository;

/**
* @var LayeredNavAttributesProvider
*/
protected $layeredNavAttributesProvider;

/**
* @var array
*/
Expand All @@ -61,19 +67,22 @@ class Attribute // Not implementing the LayerBuilderInterface because it did not
];

/**
* @param \Magento\Framework\ObjectManagerInterface $objectManager Object Manager
* @param AttributeRepository $attributeRepository Attribute Repository
* @param array $bucketNameFilter Bucket Filter
* @param \Magento\Framework\ObjectManagerInterface $objectManager Object Manager.
* @param AttributeRepository $attributeRepository Attribute Repository.
* @param LayeredNavAttributesProvider $layeredNavAttributesProvider Layered navigation attributes provider.
* @param array $bucketNameFilter Bucket Filter.
*/
public function __construct(
\Magento\Framework\ObjectManagerInterface $objectManager,
AttributeRepository $attributeRepository,
LayeredNavAttributesProvider $layeredNavAttributesProvider,
$bucketNameFilter = []
) {
// Using Object Manager for BC with Magento <2.3.4.
$this->layerFormatter = $objectManager->get(LayerFormatter::class);
$this->bucketNameFilter = \array_merge($this->bucketNameFilter, $bucketNameFilter);
$this->attributeRepository = $attributeRepository;
$this->layeredNavAttributesProvider = $layeredNavAttributesProvider;
}

/**
Expand All @@ -92,6 +101,7 @@ public function build(AggregationInterface $aggregation, ?int $storeId): array
if (substr($bucketName, 0, strlen($prefix)) === $prefix) {
$attributeCode = substr($bucketName, strlen($prefix));
}
$attributeCode = $this->layeredNavAttributesProvider->getLayeredNavAttributeByFilterField($bucketName) ?? $attributeCode;

$label = $attributeCode;
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?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 Botis <botis@smile.fr>
* @copyright 2021 Smile
* @license Open Software License ("OSL") v. 3.0
*/
namespace Smile\ElasticsuiteCatalog\Model\Attribute;

use Smile\ElasticsuiteCatalog\Api\LayeredNavAttributeInterface;

/**
* Layered navigation attributes provider.
*
* @category Smile
* @package Smile\ElasticsuiteCatalog
* @author Botis <botis@smile.fr>
*/
class LayeredNavAttributesProvider
{
/**
* @var LayeredNavAttributeInterface[]
*/
protected $attributes = [];

/**
* LayeredNavAttributesProvider constructor.
*
* @param LayeredNavAttributeInterface[] $attributes Attributes.
*/
public function __construct($attributes = [])
{
$this->attributes = $attributes;
}

/**
* Get Layered navigation attributes list.
*
* @return LayeredNavAttributeInterface[]
*/
public function getList(): array
{
$attributes = [];
foreach ($this->attributes as $attribute) {
if (!$attribute->skipAttribute()) {
$attributes[$attribute->getAttributeCode()] = $attribute;
}
}

return $attributes;
}

/**
* Get layered navigation attribute.
*
* @param string $attributeCode Attribute code.
*
* @return LayeredNavAttributeInterface|null
*/
public function getLayeredNavAttribute(string $attributeCode): ?LayeredNavAttributeInterface
{
return $this->getList()[$attributeCode] ?? null;
}

/**
* Get layered navigation attribute by filter field.
*
* @param string $filterField Filter field.
*
* @return string|null
*/
public function getLayeredNavAttributeByFilterField(string $filterField): ?string
{
foreach ($this->getList() as $attribute) {
if ($attribute->getFilterField() === $filterField) {
return $attribute->getAttributeCode();
}
}

return null;
}

/**
* Check if it is a layered navigation attribute.
*
* @param string $attributeCode Attribute code.
*
* @return bool
*/
public function isLayeredNavAttribute(string $attributeCode): bool
{
return isset($this->getList()[$attributeCode]);
}
}
Loading

0 comments on commit 1ab9b09

Please sign in to comment.