Skip to content

Commit

Permalink
Feature #2437 Ignoring 0 and false values by default
Browse files Browse the repository at this point in the history
to avoid boolean attributes facet coverage changing dramatically.
Also includes the ability to use admin sort to always display the "Yes"
value before the "No" in the layered navigation filter.
  • Loading branch information
rbayet committed Mar 14, 2022
1 parent 6db3c23 commit 82d3967
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Magento\Framework\Data\Form;
use Magento\Framework\Registry;
use Smile\ElasticsuiteCatalog\Model\Attribute\Source\FilterSortOrder;
use Smile\ElasticsuiteCore\Api\Index\Mapping\FieldInterface;
use Smile\ElasticsuiteCore\Search\Request\BucketInterface;
use Magento\Framework\Data\Form\Element\Fieldset;
use Magento\Catalog\Api\Data\EavAttributeInterface;
Expand Down Expand Up @@ -105,6 +106,16 @@ public function afterSetForm(Front $subject, Front $result, Form $form)
$form->getElement('is_searchable')->setDisabled(1);
}

if (($this->getAttribute()->getSourceModel() == 'Magento\Eav\Model\Entity\Attribute\Source\Boolean')
|| ($this->getAttribute()->getBackendType() == 'int')
|| ($this->getAttribute()->getFrontendClass() == 'validate-digits')
|| ($this->getAttribute()->getBackendType() == 'decimal' || $this->getAttribute()->getFrontendClass() == 'validate-number')
|| (in_array($this->getAttribute()->getFrontendInput(), ['select', 'multiselect'])
|| $this->getAttribute()->getSourceModel() != '')
) {
$this->addIncludeZeroFalseField($fieldset);
}

$this->appendFieldsDependency($subject);

return $result;
Expand Down Expand Up @@ -399,6 +410,30 @@ private function appendSliderDisplayRelatedFields($form, $subject)
return $this;
}

/**
* Add field allowing to configure if zero/false values should be indexed or ignored.
*
* @param Fieldset $fieldset Target fieldset
*
* @return FrontPlugin
*/
private function addIncludeZeroFalseField(Fieldset $fieldset)
{
$fieldset->addField(
'include_zero_false_values',
'select',
[
'name' => 'include_zero_false_values',
'label' => __('Include zero or false values'),
'values' => $this->booleanSource->toOptionArray(),
'note' => __(
'If set to Yes, zero (integer or numeric attribute) or false (boolean attribute) values will be indexed in the search engine (default is No). Also applies to source model keys/values of Dropdown/Multiple Select attributes.'
),
],
'used_for_sortby'
);
}

/**
* Manage dependency between fields.
*
Expand Down
25 changes: 22 additions & 3 deletions src/module-elasticsuite-catalog/Helper/AbstractAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ abstract class AbstractAttribute extends Mapping
*/
private $attributeMappers = [];

/**
* @var array
*/
private $attributeCleaners = [];

/**
* @param Context $context Helper context.
* @param AttributeFactory $attributeFactory Factory used to create attributes.
Expand Down Expand Up @@ -162,6 +167,8 @@ public function getFieldType(AttributeInterface $attribute)
* multivalued attributes merging on composite products).
* ES doesn't care of having array of int when it an int is required.
*
* @SuppressWarnings(PHPMD.ElseExpression)
*
* @param AttributeInterface $attribute Product attribute.
* @param integer $storeId Store id.
* @param mixed $value Raw value to be parsed.
Expand All @@ -174,13 +181,26 @@ public function prepareIndexValue(AttributeInterface $attribute, $storeId, $valu
$values = [];

$mapperKey = 'simple_' . $attribute->getId();

if (!isset($this->attributeMappers[$mapperKey])) {
$this->attributeMappers[$mapperKey] = function ($value) use ($attribute) {
return $this->prepareSimpleIndexAttributeValue($attribute, $value);
};
}

if (!isset($this->attributeCleaners[$mapperKey])) {
if ($attribute->getIncludeZeroFalseValues()) {
// Filter empty values while keeping "0" (int or float) and "false" value.
$this->attributeCleaners[$mapperKey] = function ($value) {
return (($value === false) || strlen($value));
};
} else {
// Filter out empty values. Also removes "0" and "false" values.
$this->attributeCleaners[$mapperKey] = function ($value) {
return !empty($value);
};
}
}

if ($this->usesSource($attribute) && !is_array($value)) {
$value = explode(',', $value);
}
Expand All @@ -190,8 +210,7 @@ public function prepareIndexValue(AttributeInterface $attribute, $storeId, $valu
}

$value = array_map($this->attributeMappers[$mapperKey], $value);
// Filter empty values while keeping "0" (int or float) and "false" value.
$value = array_filter($value, function ($v) { return (($v === false) || strlen($v)); });
$value = array_filter($value, $this->attributeCleaners[$mapperKey]);
$value = array_values($value);
$values[$attributeCode] = $value;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Smile\ElasticsuiteCatalog\Api\LayeredNavAttributeInterface;
use Smile\ElasticsuiteCatalog\Helper\ProductAttribute;
use Smile\ElasticsuiteCatalog\Model\Attribute\LayeredNavAttributesProvider;
use Smile\ElasticsuiteCore\Search\Request\BucketInterface;

/**
* Product boolean filter implementation.
Expand Down Expand Up @@ -184,6 +185,12 @@ protected function _initItems()
$item->setApplyFilterValue(array_values($applyValue));
}

if (($this->getAttributeModel()->getFacetSortOrder() == BucketInterface::SORT_ORDER_MANUAL)
&& (count($this->_items) > 1)
) {
krsort($this->_items, SORT_NUMERIC);
}

return $this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,22 @@ class AttributePlugin
*/
private $indicesConfig;

/**
* @var \Magento\Framework\Indexer\IndexerRegistry
*/
private $indexerRegistry;

/**
* AttributePlugin constructor.
*
* @param \Smile\ElasticsuiteCore\Index\Indices\Config $indicesConfig Indices config.
*/
public function __construct(\Smile\ElasticsuiteCore\Index\Indices\Config $indicesConfig)
{
public function __construct(
\Smile\ElasticsuiteCore\Index\Indices\Config $indicesConfig,
\Magento\Framework\Indexer\IndexerRegistry $indexerRegistry
) {
$this->indicesConfig = $indicesConfig;
$this->indexerRegistry = $indexerRegistry;
}

/**
Expand All @@ -50,15 +58,24 @@ public function afterSave(
\Magento\Catalog\Api\Data\ProductAttributeInterface $result
) {
$cleanCache = false;
$needReindex = false;

if ($subject->dataHasChangedFor('search_weight')) {
$cleanCache = true;
}

if ($subject->dataHasChangedFor('include_zero_false_values')) {
$needReindex = true;
}

if ($cleanCache) {
$this->indicesConfig->reset();
}

if ($needReindex) {
$this->indexerRegistry->get(\Magento\CatalogSearch\Model\Indexer\Fulltext::INDEXER_ID)->invalidate();
}

return $result;
}
}
26 changes: 26 additions & 0 deletions src/module-elasticsuite-catalog/Setup/CatalogSetup.php
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,32 @@ public function addSortOrderMissingFields(SchemaSetupInterface $setup)
);
}

/**
* Add "include_zero_false_values" field to catalog_eav_attribute table.
*
* @param \Magento\Framework\Setup\SchemaSetupInterface $setup Schema Setup
*
* @return void
*/
public function addIncludeZeroFalseValues(SchemaSetupInterface $setup)
{
$connection = $setup->getConnection();
$table = $setup->getTable('catalog_eav_attribute');

// Append a column 'include_zero_false_values' into the db.
$connection->addColumn(
$table,
'include_zero_false_values',
[
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_BOOLEAN,
'nullable' => false,
'default' => 0,
'size' => 1,
'comment' => 'Should the search engine index zero (integer or decimal attribute) or false (boolean attribute) values',
]
);
}

/**
* Update attribute value for an entity with a default value.
* All existing values are erased by the new value.
Expand Down
3 changes: 3 additions & 0 deletions src/module-elasticsuite-catalog/Setup/InstallSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ public function install(SchemaSetupInterface $setup, ModuleContextInterface $con
// Introduced in version 1.5.1.
$this->catalogSetup->addSortOrderMissingFields($setup);

// Introduced in version 1.5.2.
$this->catalogSetup->addIncludeZeroFalseValues($setup);

$setup->endSetup();
}
}
4 changes: 4 additions & 0 deletions src/module-elasticsuite-catalog/Setup/UpgradeSchema.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ public function upgrade(
$this->catalogSetup->addSortOrderMissingFields($setup);
}

if (version_compare($context->getVersion(), '1.5.2', '<')) {
$this->catalogSetup->addIncludeZeroFalseValues($setup);
}

$setup->endSetup();
}
}
2 changes: 1 addition & 1 deletion src/module-elasticsuite-catalog/etc/module.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Smile_ElasticsuiteCatalog" setup_version="1.5.1">
<module name="Smile_ElasticsuiteCatalog" setup_version="1.5.2">
<sequence>
<module name="Smile_ElasticsuiteCore" />
<module name="Magento_Search" />
Expand Down
2 changes: 2 additions & 0 deletions src/module-elasticsuite-catalog/i18n/en_US.csv
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,5 @@ Attributes,Attributes
"No value matching the search <b>%1</b>.","No value matching the search <b>%1</b>."
"Enable adaptive slider","Enable adaptive slider"
"If enabled, when necessary to support the presence of outlier values in the navigation context (for instance, a very high price amidst a majority of low prices), the price slider behavior changes so that the middle of the slider range corresponds to the median price instead of the price at the middle of the range.","If enabled, when necessary to support the presence of outlier values in the navigation context (for instance, a very high price amidst a majority of low prices), the price slider behavior changes so that the middle of the slider range corresponds to the median price instead of the price at the middle of the range."
"Include zero or false values","Include zero or false values"
"If set to Yes, zero (integer or numeric attribute) or false (boolean attribute) values will be indexed in the search engine (default is No). Also applies to source model keys/values of Dropdown/Multiple Select attributes.","If set to Yes, zero (integer or numeric attribute) or false (boolean attribute) values will be indexed in the search engine (default is No). Also applies to source model keys/values of Dropdown/Multiple Select attributes."
2 changes: 2 additions & 0 deletions src/module-elasticsuite-catalog/i18n/fr_FR.csv
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,5 @@ Attributes,Attributs
"No value matching the search <b>%1</b>.","Aucun résultat pour la recherche <b>%s</b>."
"Enable adaptive slider","Activer le slider adaptatif"
"If enabled, when necessary to support the presence of outlier values in the navigation context (for instance, a very high price amidst a majority of low prices), the price slider behavior changes so that the middle of the slider range corresponds to the median price instead of the price at the middle of the range.","Si activé, lorsque c'est nécessaire pour supporter la présence de valeurs extrêmes dans le contexte de navigation (par exemple, un prix très élevé au milieu d'une majorité de prix bas), le comportement du slider de prix change de façon à ce que le milieu de la plage du slider corresponde au prix médian au lieu du prix situé au milieu de la plage de prix."
"Include zero or false values","Inclure les valeurs à zéro ou 'false'"
"If set to Yes, zero (integer or numeric attribute) or false (boolean attribute) values will be indexed in the search engine (default is No). Also applies to source model keys/values of Dropdown/Multiple Select attributes.","Si réglé à Oui, les valeurs à zéro (attribute entier ou numérique) ou 'false/Non' (attribut booléen) seront indexées dans le moteur de recherche (ce n'est pas le cas par défaut). S'applique également aux clefs/valeurs des modèles sources des attributs Dropdown/Multiple Select."

0 comments on commit 82d3967

Please sign in to comment.