src/module-elasticsuite-catalog/Model/ResourceModel/Category/FilterableAttribute.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 Romain Ruaud <romain.ruaud@smile.fr>
* @copyright 2020 Smile
* @license Open Software License ("OSL") v. 3.0
*/
namespace Smile\ElasticsuiteCatalog\Model\ResourceModel\Category;
use Magento\Catalog\Api\Data\CategoryInterface;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
use Smile\ElasticsuiteCatalog\Model\Attribute\Source\FilterDisplayMode;
/**
* Resource Model For Category Layered Navigation Filters.
*
* @category Smile
* @package Smile\ElasticsuiteCatalog
* @author Romain Ruaud <romain.ruaud@smile.fr>
*/
class FilterableAttribute extends AbstractDb
{
/**
* @var \Magento\Framework\EntityManager\MetadataPool
*/
private $metadataPool;
/**
* FilterableAttributeList constructor.
*
* @param \Magento\Framework\Model\ResourceModel\Db\Context $context Context
* @param \Magento\Framework\EntityManager\MetadataPool $metadataPool Metadata Pool
* @param null $connectionName Connection Name
*/
public function __construct(
\Magento\Framework\Model\ResourceModel\Db\Context $context,
MetadataPool $metadataPool,
$connectionName = null
) {
$this->metadataPool = $metadataPool;
parent::__construct($context, $connectionName);
}
/**
* Retrieve Layered Navigation Filters for a given category.
*
* @param int $categoryId The category Id
*
* @return array
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function loadAttributesData(int $categoryId)
{
$binds = [':category_id' => $categoryId];
$select = $this->getConnection()->select();
$select->from($this->getMainTable())->where(sprintf("%s = :category_id", $this->getIdFieldName()));
return $this->getConnection()->fetchAll($select, $binds);
}
/**
* Save Layered Navigation Filters configuration for a given category.
*
* @param int $categoryId The category Id
* @param array $data layered navigation filters configuration data.
*
* @return array
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function saveAttributesData(int $categoryId, array $data)
{
$rows = [];
$this->deleteByCategoryId($categoryId);
$fields = $this->getConnection()->describeTable($this->getMainTable());
foreach ($data as $item) {
$item[$this->getIdFieldName()] = $categoryId;
$row = $this->buildRow($item, $fields);
if ($this->isValid($row)) {
$rows[] = $row;
}
}
$result = true;
if (!empty($rows)) {
$result = (bool) $this->getConnection()->insertArray($this->getMainTable(), array_keys($fields), $rows);
}
return $result;
}
/**
* Delete layered filters configuration by Category Id.
*
* @param int $categoryId Category Id
*
* @return bool
*/
public function deleteByCategoryId(int $categoryId)
{
$deleteCondition = [sprintf("%s = ?", $this->getIdFieldName()) => $categoryId];
return (bool) $this->getConnection()->delete($this->getMainTable(), $deleteCondition);
}
/**
* Resource initialization
*
* @SuppressWarnings(PHPMD.CamelCaseMethodName) Method is inherited.
*
* @return void
*/
protected function _construct()
{
$idField = $this->metadataPool->getMetadata(CategoryInterface::class)->getIdentifierField();
$this->_init('smile_elasticsuitecatalog_category_filterable_attribute', $idField);
}
/**
* Compute row data for later insert.
*
* @param array $item The item to build
* @param array $fields The fields to keep
*
* @return array
*/
private function buildRow($item, $fields)
{
// Remove position for not pinned items.
if (empty($item['is_pinned']) || filter_var($item['is_pinned'], FILTER_VALIDATE_BOOLEAN) === false) {
$item['position'] = null;
}
foreach (array_keys($fields) as $field) {
$useDefault = 'use_default_' . $field;
if (isset($item[$useDefault]) && (filter_var($item[$useDefault], FILTER_VALIDATE_BOOLEAN) === true)) {
$item[$field] = null;
}
}
// Remove non-existent columns and sort the other according to fields order.
return array_replace(array_flip(array_keys($fields)), array_intersect_key($item, $fields));
}
/**
* Check if a given row is relevant to save.
*
* @param array $row A row to be saved in table.
*
* @return boolean
*/
private function isValid($row)
{
$result = false;
// Check if facet_display_mode is defaulted.
if ((int) $row['facet_display_mode'] !== FilterDisplayMode::AUTO_DISPLAYED) {
$result = true;
}
// Check remaining fields are not null.
unset($row[$this->getIdFieldName()]);
unset($row['attribute_id']);
unset($row['facet_display_mode']);
// @codingStandardsIgnoreStart
if (!empty(array_filter($row, function ($str) { return $str !== null && strlen($str); }))) { // Preserve 0 values.
$result = true;
}
// @codingStandardsIgnoreEnd
return $result;
}
}