Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature #3038 Use display_pattern on product view, product compare pages #3062

Draft
wants to merge 1 commit into
base: 2.10.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 <ecrocombe@outlook.com>
* @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 <ecrocombe@outlook.com>
*/
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 <ecrocombe@outlook.com>
* @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 <ecrocombe@outlook.com>
*/
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
16 changes: 16 additions & 0 deletions src/module-elasticsuite-catalog/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -418,4 +418,20 @@
</argument>
</arguments>
</type>

<!-- Disable erratic plugin on collection.
This plugin is not needed because Elasticsuite can achieve the same thing with an optimizer. -->
<type name="Magento\Catalog\Model\ResourceModel\Product\Collection">
<!-- 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>
Loading