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

Fix #29971 - Layered navigation swatches ignore show tooltip setting #30115

Open
wants to merge 3 commits into
base: 2.5-develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
77 changes: 48 additions & 29 deletions app/code/Magento/Swatches/Model/Plugin/FilterRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,63 +3,82 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\Swatches\Model\Plugin;

/**
* Class FilterRenderer
*/
use Closure;
use Magento\Catalog\Model\Layer\Filter\FilterInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\View\LayoutInterface;
use Magento\LayeredNavigation\Block\Navigation\FilterRenderer as Subject;
use Magento\Swatches\Block\LayeredNavigation\RenderLayered;
use Magento\Swatches\Helper\Data;
use Magento\Swatches\ViewModel\Product\Renderer\Configurable as ConfigurableViewModel;

class FilterRenderer
{
/**
* @var \Magento\Framework\View\LayoutInterface
* @var LayoutInterface
*/
protected $layout;

/**
* Path to RenderLayered Block
*
* @var string
* @var Data
*/
protected $block = \Magento\Swatches\Block\LayeredNavigation\RenderLayered::class;
protected $swatchHelper;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make property private

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


/**
* @var \Magento\Swatches\Helper\Data
* @var ConfigurableViewModel|null
*/
protected $swatchHelper;
private $configurableViewModel;

/**
* @param \Magento\Framework\View\LayoutInterface $layout
* @param \Magento\Swatches\Helper\Data $swatchHelper
* @var string
*/
protected $block = RenderLayered::class;

/**
* @param LayoutInterface $layout
* @param Data $swatchHelper
* @param ConfigurableViewModel|null $configurableViewModel
*/
public function __construct(
\Magento\Framework\View\LayoutInterface $layout,
\Magento\Swatches\Helper\Data $swatchHelper
LayoutInterface $layout,
Data $swatchHelper,
?ConfigurableViewModel $configurableViewModel = null
) {
$this->layout = $layout;
$this->swatchHelper = $swatchHelper;
$this->configurableViewModel = $configurableViewModel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may not follow BC development rules in plugins.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

?? ObjectManager::getInstance()->get(ConfigurableViewModel::class);
}

/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
* @param \Magento\LayeredNavigation\Block\Navigation\FilterRenderer $subject
* @param \Closure $proceed
* @param \Magento\Catalog\Model\Layer\Filter\FilterInterface $filter
* Override block rendered for swatch attribute in layered navigation
*
* @param Subject $subject
* @param Closure $proceed
* @param FilterInterface $filter
*
* @return mixed
* @throws \Magento\Framework\Exception\LocalizedException
* @throws LocalizedException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function aroundRender(
\Magento\LayeredNavigation\Block\Navigation\FilterRenderer $subject,
\Closure $proceed,
\Magento\Catalog\Model\Layer\Filter\FilterInterface $filter
Subject $subject,
Closure $proceed,
FilterInterface $filter
) {
if ($filter->hasAttributeModel()) {
if ($this->swatchHelper->isSwatchAttribute($filter->getAttributeModel())) {
return $this->layout
->createBlock($this->block)
->setSwatchFilter($filter)
->toHtml();
}
if ($filter->hasAttributeModel() && $this->swatchHelper->isSwatchAttribute($filter->getAttributeModel())) {
return $this->layout
->createBlock($this->block)
->setSwatchFilter($filter)
->setData('configurable_view_model', $this->configurableViewModel)
->toHtml();
}

return $proceed($filter);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,38 @@
* See COPYING.txt for license details.
*/

use Magento\Framework\Escaper;
use Magento\Framework\View\Helper\SecureHtmlRenderer;
use Magento\Swatches\Block\LayeredNavigation\RenderLayered;
use Magento\Swatches\ViewModel\Product\Renderer\Configurable as ConfigurableViewModel;

// phpcs:disable PSR2.ControlStructures.SwitchDeclaration
// phpcs:disable Generic.WhiteSpace.ScopeIndent

/** @var $block \Magento\Swatches\Block\LayeredNavigation\RenderLayered */
/** @var \Magento\Framework\View\Helper\SecureHtmlRenderer $secureRenderer */
/** @var \Magento\Framework\Escaper $escaper */
/** @var RenderLayered $block */
/** @var SecureHtmlRenderer $secureRenderer */
/** @var Escaper $escaper */
?>
<?php $swatchData = $block->getSwatchData(); ?>
<div class="swatch-attribute swatch-layered <?= $block->escapeHtmlAttr($swatchData['attribute_code']) ?>"
data-attribute-code="<?= $block->escapeHtmlAttr($swatchData['attribute_code']) ?>"
data-attribute-id="<?= $block->escapeHtmlAttr($swatchData['attribute_id']) ?>">
<?php /** @var ConfigurableViewModel $configurableViewModel */ ?>
<?php $configurableViewModel = $block->getConfigurableViewModel() ?>
<div class="swatch-attribute swatch-layered <?= $escaper->escapeHtmlAttr($swatchData['attribute_code']) ?>"
data-attribute-code="<?= $escaper->escapeHtmlAttr($swatchData['attribute_code']) ?>"
data-attribute-id="<?= $escaper->escapeHtmlAttr($swatchData['attribute_id']) ?>">
<div class="swatch-attribute-options clearfix">
<?php foreach ($swatchData['options'] as $option => $label): ?>
<a href="<?= $block->escapeUrl($label['link']) ?>" rel="nofollow"
aria-label="<?= $block->escapeHtmlAttr($label['label']) ?>"
<a href="<?= $escaper->escapeUrl($label['link']) ?>" rel="nofollow"
aria-label="<?= $escaper->escapeHtmlAttr($label['label']) ?>"
class="swatch-option-link-layered">
<?php if (isset($swatchData['swatches'][$option]['type'])): ?>
<?php switch ($swatchData['swatches'][$option]['type']) {
case '3':
?>
<div class="swatch-option <?= $block->escapeHtmlAttr($label['custom_style']) ?>"
<div class="swatch-option <?= $escaper->escapeHtmlAttr($label['custom_style']) ?>"
tabindex="-1"
data-option-type="3"
data-option-id="<?= $block->escapeHtmlAttr($option) ?>"
data-option-label="<?= $block->escapeHtmlAttr($label['label']) ?>"
data-option-id="<?= $escaper->escapeHtmlAttr($option) ?>"
data-option-label="<?= $escaper->escapeHtmlAttr($label['label']) ?>"
data-option-tooltip-thumb=""
data-option-tooltip-value=""
></div>
Expand All @@ -43,79 +50,77 @@
'swatch_image',
$swatchData['swatches'][$option]['value']
);
$escapedUrl = $block->escapeUrl($swatchImagePath);
$escapedUrl = $escaper->escapeUrl($swatchImagePath);
?>
<div class="swatch-option image <?= $block->escapeHtmlAttr($label['custom_style']) ?>"
<div class="swatch-option image <?= $escaper->escapeHtmlAttr($label['custom_style']) ?>"
tabindex="-1"
data-option-type="2"
data-option-id="<?= $block->escapeHtmlAttr($option) ?>"
data-option-label="<?= $block->escapeHtmlAttr($label['label']) ?>"
data-option-tooltip-thumb="<?= $block->escapeUrl($swatchThumbPath) ?>"
data-option-id="<?= $escaper->escapeHtmlAttr($option) ?>"
data-option-label="<?= $escaper->escapeHtmlAttr($label['label']) ?>"
data-option-tooltip-thumb="<?= $escaper->escapeUrl($swatchThumbPath) ?>"
data-option-tooltip-value="">
</div>
<?php
$element = 'swatchImageOption' .$escaper->escapeJs($option);
$script = 'var ' .$element
.' = document.querySelector(\'div[data-option-id="' .$escaper->escapeJs($option)
.'"]\');' .PHP_EOL;
$script .= $element .'.style.background = "url(\''
.$escapedUrl .'\') no-repeat center";' .PHP_EOL;
$script .= $element .'.style.backgroundSize = "initial";';
$element = 'swatchImageOption' . $escaper->escapeJs($option);
$script = 'var ' . $element
. ' = document.querySelector(\'div[data-option-id="' . $escaper->escapeJs($option)
. '"]\');' . PHP_EOL;
$script .= $element . '.style.background = "url(\''
. $escapedUrl . '\') no-repeat center";' . PHP_EOL;
$script .= $element . '.style.backgroundSize = "initial";';
?>
<?= /* @noEscape*/ $secureRenderer->renderTag('script', [], $script, false); ?>
<?= /* @noEscape*/ $secureRenderer->renderTag('script', [], $script, false) ?>
<?php break;
case '1':
?>
<div class="swatch-option color <?= $block->escapeHtmlAttr($label['custom_style']) ?>"
<div class="swatch-option color <?= $escaper->escapeHtmlAttr($label['custom_style']) ?>"
tabindex="-1"
data-option-type="1"
data-option-id="<?= $block->escapeHtmlAttr($option) ?>"
data-option-label="<?= $block->escapeHtmlAttr($label['label']) ?>"
data-option-id="<?= $escaper->escapeHtmlAttr($option) ?>"
data-option-label="<?= $escaper->escapeHtmlAttr($label['label']) ?>"
data-option-tooltip-thumb=""
data-option-tooltip-value="<?= $block->escapeHtmlAttr(
data-option-tooltip-value="<?= $escaper->escapeHtmlAttr(
$swatchData['swatches'][$option]['value']
) ?>">
</div>
<?php
$element = 'swatchImageOption' .$escaper->escapeJs($option);
$element = 'swatchImageOption' . $escaper->escapeJs($option);
$backgroundValue = $escaper->escapeJs(
str_replace('\'', '\\\'', $swatchData['swatches'][$option]['value'])
);
$script = 'var ' .$element
.' = document.querySelector(\'div[data-option-id="' .$escaper->escapeJs($option)
.'"]\');' .PHP_EOL;
$script .= $element .'.style.background = "' .$backgroundValue
.' no-repeat center";' .PHP_EOL;
$script .= $element .'.style.backgroundSize = "initial";';
$script = 'var ' . $element
. ' = document.querySelector(\'div[data-option-id="' . $escaper->escapeJs($option)
. '"]\');' . PHP_EOL;
$script .= $element . '.style.background = "' . $backgroundValue
. ' no-repeat center";' . PHP_EOL;
$script .= $element . '.style.backgroundSize = "initial";';
?>
<?= /* @noEscape*/ $secureRenderer->renderTag('script', [], $script, false); ?>
<?= /* @noEscape*/ $secureRenderer->renderTag('script', [], $script, false) ?>
<?php break;
case '0':
default:
?>
<div class="swatch-option text <?= $block->escapeHtmlAttr($label['custom_style']) ?>"
<div class="swatch-option text <?= $escaper->escapeHtmlAttr($label['custom_style']) ?>"
tabindex="-1"
data-option-type="0"
data-option-id="<?= $block->escapeHtmlAttr($option) ?>"
data-option-label="<?= $block->escapeHtmlAttr($label['label']) ?>"
data-option-id="<?= $escaper->escapeHtmlAttr($option) ?>"
data-option-label="<?= $escaper->escapeHtmlAttr($label['label']) ?>"
data-option-tooltip-thumb=""
data-option-tooltip-value=""
><?= $block->escapeHtml($swatchData['swatches'][$option]['value']) ?></div>
><?= $escaper->escapeHtml($swatchData['swatches'][$option]['value']) ?></div>
<?php break;
} ?>
<?php endif; ?>
</a>
<?php endforeach; ?>
</div>
</div>
<?php $scriptString = <<<script

require(["jquery", "Magento_Swatches/js/swatch-renderer"], function ($) {
$('.swatch-layered.{$block->escapeJs($swatchData['attribute_code'])}')
.find('[data-option-type="1"], [data-option-type="2"], [data-option-type="0"], [data-option-type="3"]')
.SwatchRendererTooltip();
});

script;
?>
<?= /* @noEscape */ $secureRenderer->renderTag('script', [], $scriptString, false) ?>
<script type="text/x-magento-init">
{
".swatch-layered.<?= $escaper->escapeJs($swatchData['attribute_code']) ?>": {
"Magento_Swatches/js/layered/swatch-renderer": {
"showTooltip": <?= $escaper->escapeJs($configurableViewModel->getShowSwatchTooltip()) ?>
}
}
}
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

define([
'jquery',
'Magento_Swatches/js/swatch-renderer'
], function ($) {
'use strict';

$.widget('mage.layeredSwatchRenderer', {
options: {
showTooltip: 1,
swatchElementSelector: '[data-option-type="1"], [data-option-type="2"], ' +
'[data-option-type="0"], [data-option-type="3"]'
},

/**
* @private
*/
_create: function () {
if (this.options.showTooltip === 1) {
$(this.element).find(this.options.swatchElementSelector).SwatchRendererTooltip();
}
}
});

return $.mage.layeredSwatchRenderer;
});