Skip to content

Commit

Permalink
Feature Smile-SA#3038 Use display_pattern on product view, product co…
Browse files Browse the repository at this point in the history
…mpare pages

(disabled by default)
  • Loading branch information
Edward Crocombe authored and rbayet committed Sep 12, 2023
1 parent 1788eda commit c5574ab
Show file tree
Hide file tree
Showing 6 changed files with 300 additions and 2 deletions.
94 changes: 92 additions & 2 deletions src/module-elasticsuite-catalog/Helper/ProductAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
use Magento\Framework\App\Helper\Context;
use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory;
use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory as AttributeCollectionFactory;
use Magento\Framework\Locale\LocaleFormatter;
use Magento\Store\Model\ScopeInterface;

/**
* ElasticSuite product attributes helper.
Expand All @@ -27,15 +29,103 @@
*/
class ProductAttribute extends AbstractAttribute
{
/**
* @var string Config path to determine if we should use display battern on frontend.
*/
const XML_PATH_FRONTEND_PRODUCT_DISPLAY_PATTERN_ENABLED
= 'smile_elasticsuite_catalogsearch_settings/catalogsearch/frontend_product_display_pattern_enabled';

/**
* @var string Attribute column containing pattern.
*/
const DISPLAY_PATTERN_COLUMN = 'display_pattern';

/**
* @var string Attribute column containing precision.
*/
const DISPLAY_PRECISION_COLUMN = 'display_precision';

/**
* @var string Default display pattern if not otherwise specified.
*/
const DEFAULT_DISPLAY_PATTERN = '%s';

/**
* @var string Round value to this many decimal places if not otherwise specified.
*/
const DEFAULT_DISPLAY_PRECISION = 2;

/**
* @var int The maximum possible replacements for each pattern in each subject string.
*/
const REPLACEMENT_LIMIT = 1;

/**
* @var \Magento\Framework\Locale\LocaleFormatter $localeFormatter
*/
protected $localeFormatter;

/**
* Constructor.
*
* @param Context $context Helper context.
* @param AttributeFactory $attributeFactory Factory used to create attributes.
* @param AttributeCollectionFactory $collectionFactory Attribute collection factory.
* @param LocaleFormatter $localeFormatter Format numbers to a locale
*/
public function __construct(Context $context, AttributeFactory $attributeFactory, AttributeCollectionFactory $collectionFactory)
{
public function __construct(
Context $context,
AttributeFactory $attributeFactory,
AttributeCollectionFactory $collectionFactory,
LocaleFormatter $localeFormatter
) {
$this->localeFormatter = $localeFormatter;
parent::__construct($context, $attributeFactory, $collectionFactory);
}

/**
* Is Display Pattern on Frontend Enabled ?
*
* @return bool
*/
public function isFrontendProductDisplayPatternEnabled(): bool
{
return (bool) $this->scopeConfig->getValue(
self::XML_PATH_FRONTEND_PRODUCT_DISPLAY_PATTERN_ENABLED,
ScopeInterface::SCOPE_STORE
);
}

/**
* Format Product Attribute Value with Display Pattern
*
* Value's stored as numeric (i.e `8` or `355`) and the attribute has a display pattern (i.e `% %s` or `%s mm`)
* will be formatted as `% 8` or `355 mm`
*
* @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute Product Attribute to format
* @param int|float|string $value Product Attribute Value to format
*
* @return string Formatted string
*/
public function formatProductAttributeValueDisplayPattern($attribute, $value)
{
// Translate attribute pattern, or default, without variable.
// @codingStandardsIgnoreStart
$pattern = $attribute->getData(self::DISPLAY_PATTERN_COLUMN)
? (string) __($attribute->getData(self::DISPLAY_PATTERN_COLUMN))
: (string) self::DEFAULT_DISPLAY_PATTERN;
// @codingStandardsIgnoreEnd

// Get attribute display precision or default.
// @codingStandardsIgnoreStart
$precision = is_numeric($attribute->getData(self::DISPLAY_PRECISION_COLUMN) ?? '')
? (int) abs($attribute->getData(self::DISPLAY_PRECISION_COLUMN))
: (int) self::DEFAULT_DISPLAY_PRECISION;
// @codingStandardsIgnoreEnd

// Round value to precision and format to locale string.
$amount = (string) $this->localeFormatter->formatNumber(round((float) $value, $precision));
// Insert number value into translated string.
return (string) preg_replace('/' . self::DEFAULT_DISPLAY_PATTERN . '/', $amount, $pattern, self::REPLACEMENT_LIMIT);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?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 Edward Crocombe <[email protected]>
* @copyright 2020 Smile
* @license Open Software License ("OSL") v. 3.0
*/
namespace Smile\ElasticsuiteCatalog\Plugin\Catalog\Product\View;

use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
use Smile\ElasticsuiteCatalog\Helper\ProductAttribute;

/**
* Catalog Product List Compare plugin.
*
* @category Smile
* @package Smile\ElasticsuiteCatalog
* @author Edward Crocombe <[email protected]>
*/
class ListComparePlugin
{
/**
* @var null|\Magento\Catalog\Api\Data\ProductAttributeInterface[]
*/
private $attributes;

/**
* @var \Smile\ElasticsuiteCatalog\Helper\ProductAttribute
*/
private $productAttributeHelper;

/**
* @var \Magento\Catalog\Api\ProductAttributeRepositoryInterface $productAttributeRepository
*/
private $productAttributeRepository;

/**
* Constructor.
*
* @param ProductAttribute $productAttributeHelper ElasticSuite product attributes helper.
* @param ProductAttributeRepositoryInterface $productAttributeRepository Formats numbers to a locale
*/
public function __construct(
ProductAttribute $productAttributeHelper,
ProductAttributeRepositoryInterface $productAttributeRepository
) {
$this->productAttributeHelper = $productAttributeHelper;
$this->productAttributeRepository = $productAttributeRepository;
}

/**
* Add display pattern for frontend display
*
* @param \Magento\Catalog\Block\Product\Compare\ListCompare $subject Plugin Subject
* @param \Magento\Framework\Phrase|string $result Plugin Result
* @param \Magento\Catalog\Model\Product $product Product
* @param \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute Product Attribute
*
* @return \Magento\Framework\Phrase|string
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterGetProductAttributeValue(
\Magento\Catalog\Block\Product\Compare\ListCompare $subject,
$result,
$product,
$attribute
) {
if (!$this->productAttributeHelper->isFrontendProductDisplayPatternEnabled()) {
return $result;
}

$value = $attribute->getFrontend()->getValue($product);
if (is_numeric($value) && strlen($attribute->getData('display_pattern') ?? '') > 0) {
$result = $this->productAttributeHelper->formatProductAttributeValueDisplayPattern($attribute, $value);
}

return $result;
}

/**
* Retrieve Product Compare Attributes
*
* Default getAttributes retrieves columns from eav_attribute table only,
* both the display_pattern and display_precision values are on the catalog_eav_attribute table.
*
* @param \Magento\Catalog\Block\Product\Compare\ListCompare $subject Plugin Subject
* @param \Magento\Eav\Model\Entity\Attribute\AbstractAttribute[] $result Plugin Result
*
* @return \Magento\Catalog\Api\Data\ProductAttributeInterface[]
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterGetAttributes(\Magento\Catalog\Block\Product\Compare\ListCompare $subject, $result)
{
if (!$this->productAttributeHelper->isFrontendProductDisplayPatternEnabled()) {
return $result;
}

if ($this->attributes === null) {
$this->attributes = [];
foreach (array_keys($result) as $attributeCode) {
$this->attributes[$attributeCode] = $this->productAttributeRepository->get($attributeCode);
}
}

return $this->attributes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?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 Edward Crocombe <[email protected]>
* @copyright 2020 Smile
* @license Open Software License ("OSL") v. 3.0
*/
namespace Smile\ElasticsuiteCatalog\Plugin\Catalog\Product\View;

use Smile\ElasticsuiteCatalog\Helper\ProductAttribute;

/**
* Catalog Product View Attributes plugin.
*
* @category Smile
* @package Smile\ElasticsuiteCatalog
* @author Edward Crocombe <[email protected]>
*/
class AttributesPlugin
{
/**
* @var \Smile\ElasticsuiteCatalog\Helper\ProductAttribute
*/
private $productAttributeHelper;

/**
* Constructor.
*
* @param ProductAttribute $productAttributeHelper ElasticSuite product attributes helper.
*/
public function __construct(
ProductAttribute $productAttributeHelper
) {
$this->productAttributeHelper = $productAttributeHelper;
}

/**
* Add display pattern for frontend display
*
* @param \Magento\Catalog\Block\Product\View\Attributes $subject Plugin Subject
* @param array $result Additional data
* @param string[] $excludeAttr Attribute Codes to exclude
*
* @return array Additional data
* @throws \Magento\Framework\Exception\LocalizedException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterGetAdditionalData(\Magento\Catalog\Block\Product\View\Attributes $subject, $result, array $excludeAttr = [])
{
if (!$this->productAttributeHelper->isFrontendProductDisplayPatternEnabled()) {
return $result;
}

$product = $subject->getProduct();
$attributes = $product->getAttributes();
foreach ($attributes as $attribute) {
// If attribute is already in array, then isVisibleOnFrontend = `true`.
if (isset($result[$attribute->getAttributeCode()])) {
// @codingStandardsIgnoreStart
$value = isset($result[$attribute->getAttributeCode()]['value'])
? $result[$attribute->getAttributeCode()]['value']
: '';
// @codingStandardsIgnoreEnd

if (is_numeric($value) && strlen($attribute->getData('display_pattern') ?? '') > 0) {
$result[$attribute->getAttributeCode()]['value']
= $this->productAttributeHelper->formatProductAttributeValueDisplayPattern($attribute, $value);
}
}
}

return $result;
}
}
5 changes: 5 additions & 0 deletions src/module-elasticsuite-catalog/etc/adminhtml/system.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment><![CDATA[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.]]></comment>
</field>
<field id="frontend_product_display_pattern_enabled" translate="label" type="select" sortOrder="45" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
<label>Enable Display Pattern on Frontend</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<comment><![CDATA[If enabled, will also show the Attributes Value using Display Pattern on Product Pages (Product Detail and Compare), not just in Layered Navigation. ]]></comment>
</field>
<field id="index_child_product_sku" translate="label" type="select" sortOrder="50" showInDefault="1" showInWebsite="1" showInStore="1" canRestore="1">
<label>Enable indexing child product SKU in dedicated subfield</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
Expand Down
1 change: 1 addition & 0 deletions src/module-elasticsuite-catalog/etc/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<category_filter_use_url_rewrites>1</category_filter_use_url_rewrites>
<expanded_facets>3</expanded_facets>
<adaptive_slider_enabled>0</adaptive_slider_enabled>
<frontend_product_display_pattern_enabled>0</frontend_product_display_pattern_enabled>
<index_child_product_sku>0</index_child_product_sku>
<compute_child_product_discount>0</compute_child_product_discount>
</catalogsearch>
Expand Down
9 changes: 9 additions & 0 deletions src/module-elasticsuite-catalog/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -425,4 +425,13 @@
<!-- This plugin is defined in magento/module-inventory-catalog -->
<plugin name="outOfStockSorting" disabled="true"/>
</type>

<!-- Show product attributes on frontend with display pattern -->
<type name="Magento\Catalog\Block\Product\View\Attributes">
<plugin name="format_product_view_attribute_display_pattern" type="Smile\ElasticsuiteCatalog\Plugin\Catalog\Product\View\AttributesPlugin" />
</type>
<type name="Magento\Catalog\Block\Product\Compare\ListCompare">
<plugin name="format_product_compare_attribute_display_pattern" type="Smile\ElasticsuiteCatalog\Plugin\Catalog\Product\View\ListComparePlugin" />
</type>

</config>

0 comments on commit c5574ab

Please sign in to comment.