| Current Path : /home/rtorresani/www/vendor/magento/module-swatches/Block/Product/Renderer/ |
| Current File : //home/rtorresani/www/vendor/magento/module-swatches/Block/Product/Renderer/Configurable.php |
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types = 1);
namespace Magento\Swatches\Block\Product\Renderer;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Helper\Product as CatalogProduct;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\Product\Image\UrlBuilder;
use Magento\ConfigurableProduct\Helper\Data;
use Magento\ConfigurableProduct\Model\ConfigurableAttributeData;
use Magento\Customer\Helper\Session\CurrentCustomer;
use Magento\Framework\Json\EncoderInterface;
use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\Framework\Stdlib\ArrayUtils;
use Magento\Store\Model\ScopeInterface;
use Magento\Swatches\Helper\Data as SwatchData;
use Magento\Swatches\Helper\Media;
use Magento\Swatches\Model\Swatch;
use Magento\Framework\App\ObjectManager;
use Magento\Swatches\Model\SwatchAttributesProvider;
/**
* Swatch renderer block
*
* @api
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @since 100.0.2
*/
class Configurable extends \Magento\ConfigurableProduct\Block\Product\View\Type\Configurable implements
\Magento\Framework\DataObject\IdentityInterface
{
/**
* Path to template file with Swatch renderer.
*/
const SWATCH_RENDERER_TEMPLATE = 'Magento_Swatches::product/view/renderer.phtml';
/**
* Path to default template file with standard Configurable renderer.
*/
const CONFIGURABLE_RENDERER_TEMPLATE = 'Magento_ConfigurableProduct::product/view/type/options/configurable.phtml';
/**
* Action name for ajax request
*/
const MEDIA_CALLBACK_ACTION = 'swatches/ajax/media';
/**
* Name of swatch image for json config
*/
const SWATCH_IMAGE_NAME = 'swatchImage';
/**
* Name of swatch thumbnail for json config
*/
const SWATCH_THUMBNAIL_NAME = 'swatchThumb';
/**
* Config path which contains number of swatches per product
*/
private const XML_PATH_SWATCHES_PER_PRODUCT = 'catalog/frontend/swatches_per_product';
/**
* @var Product
*/
protected $product;
/**
* @var SwatchData
*/
protected $swatchHelper;
/**
* @var Media
*/
protected $swatchMediaHelper;
/**
* Indicate if product has one or more Swatch attributes
*
* @deprecated 100.1.0 unused
*
* @var boolean
*/
protected $isProductHasSwatchAttribute;
/**
* @var SwatchAttributesProvider
*/
private $swatchAttributesProvider;
/**
* @var UrlBuilder
*/
private $imageUrlBuilder;
/**
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
* @param Context $context
* @param ArrayUtils $arrayUtils
* @param EncoderInterface $jsonEncoder
* @param Data $helper
* @param CatalogProduct $catalogProduct
* @param CurrentCustomer $currentCustomer
* @param PriceCurrencyInterface $priceCurrency
* @param ConfigurableAttributeData $configurableAttributeData
* @param SwatchData $swatchHelper
* @param Media $swatchMediaHelper
* @param array $data
* @param SwatchAttributesProvider|null $swatchAttributesProvider
* @param UrlBuilder|null $imageUrlBuilder
*/
public function __construct(
Context $context,
ArrayUtils $arrayUtils,
EncoderInterface $jsonEncoder,
Data $helper,
CatalogProduct $catalogProduct,
CurrentCustomer $currentCustomer,
PriceCurrencyInterface $priceCurrency,
ConfigurableAttributeData $configurableAttributeData,
SwatchData $swatchHelper,
Media $swatchMediaHelper,
array $data = [],
SwatchAttributesProvider $swatchAttributesProvider = null,
UrlBuilder $imageUrlBuilder = null
) {
$this->swatchHelper = $swatchHelper;
$this->swatchMediaHelper = $swatchMediaHelper;
$this->swatchAttributesProvider = $swatchAttributesProvider
?: ObjectManager::getInstance()->get(SwatchAttributesProvider::class);
$this->imageUrlBuilder = $imageUrlBuilder ?? ObjectManager::getInstance()->get(UrlBuilder::class);
parent::__construct(
$context,
$arrayUtils,
$jsonEncoder,
$helper,
$catalogProduct,
$currentCustomer,
$priceCurrency,
$configurableAttributeData,
$data
);
}
/**
* Get Key for caching block content
*
* @return string
* @since 100.1.0
*/
public function getCacheKey()
{
return parent::getCacheKey() . '-' . $this->getProduct()->getId();
}
/**
* Get block cache life time
*
* @return int
* @since 100.1.0
*/
protected function getCacheLifetime()
{
return parent::hasCacheLifetime() ? parent::getCacheLifetime() : 3600;
}
/**
* Get Swatch config data
*
* @return string
*/
public function getJsonSwatchConfig()
{
$attributesData = $this->getSwatchAttributesData();
$allOptionIds = $this->getConfigurableOptionsIds($attributesData);
$swatchesData = $this->swatchHelper->getSwatchesByOptionsId($allOptionIds);
$config = [];
foreach ($attributesData as $attributeId => $attributeDataArray) {
if (isset($attributeDataArray['options'])) {
$config[$attributeId] = $this->addSwatchDataForAttribute(
$attributeDataArray['options'],
$swatchesData,
$attributeDataArray
);
}
if (isset($attributeDataArray['additional_data'])) {
$config[$attributeId]['additional_data'] = $attributeDataArray['additional_data'];
}
}
return $this->jsonEncoder->encode($config);
}
/**
* Get number of swatches from config to show on product listing.
*
* Other swatches can be shown after click button 'Show more'
*
* @return string
*/
public function getNumberSwatchesPerProduct()
{
return $this->_scopeConfig->getValue(
self::XML_PATH_SWATCHES_PER_PRODUCT,
ScopeInterface::SCOPE_STORE
);
}
/**
* Set product to block
*
* @param Product $product
* @return $this
*/
public function setProduct(Product $product)
{
$this->product = $product;
return $this;
}
/**
* Override parent function
*
* @return Product
*/
public function getProduct()
{
if (!$this->product) {
$this->product = parent::getProduct();
}
return $this->product;
}
/**
* Get swatch attributes data.
*
* @return array
*/
protected function getSwatchAttributesData()
{
return $this->swatchHelper->getSwatchAttributesAsArray($this->getProduct());
}
/**
* Init isProductHasSwatchAttribute.
*
* @deprecated 100.2.0 Method isProductHasSwatchAttribute() is used instead of this.
*
* @codeCoverageIgnore
* @return void
*/
protected function initIsProductHasSwatchAttribute()
{
$this->isProductHasSwatchAttribute = $this->swatchHelper->isProductHasSwatch($this->getProduct());
}
/**
* Check that product has at least one swatch attribute
*
* @return bool
* @since 100.1.5
*/
protected function isProductHasSwatchAttribute()
{
$swatchAttributes = $this->swatchAttributesProvider->provide($this->getProduct());
return count($swatchAttributes) > 0;
}
/**
* Add Swatch Data for attribute
*
* @param array $options
* @param array $swatchesCollectionArray
* @param array $attributeDataArray
* @return array
*/
protected function addSwatchDataForAttribute(
array $options,
array $swatchesCollectionArray,
array $attributeDataArray
) {
$result = [];
foreach ($options as $optionId => $label) {
if (isset($swatchesCollectionArray[$optionId])) {
$result[$optionId] = $this->extractNecessarySwatchData($swatchesCollectionArray[$optionId]);
$result[$optionId] = $this->addAdditionalMediaData($result[$optionId], $optionId, $attributeDataArray);
$result[$optionId]['label'] = $label;
}
}
return $result;
}
/**
* Add media from variation
*
* @param array $swatch
* @param integer $optionId
* @param array $attributeDataArray
* @return array
*/
protected function addAdditionalMediaData(array $swatch, $optionId, array $attributeDataArray)
{
if (isset($attributeDataArray['use_product_image_for_swatch'])
&& $attributeDataArray['use_product_image_for_swatch']
) {
$variationMedia = $this->getVariationMedia($attributeDataArray['attribute_code'], $optionId);
if (! empty($variationMedia)) {
$swatch['type'] = Swatch::SWATCH_TYPE_VISUAL_IMAGE;
$swatch = array_merge($swatch, $variationMedia);
}
}
return $swatch;
}
/**
* Retrieve Swatch data for config
*
* @param array $swatchDataArray
* @return array
*/
protected function extractNecessarySwatchData(array $swatchDataArray)
{
$result['type'] = $swatchDataArray['type'];
if ($result['type'] == Swatch::SWATCH_TYPE_VISUAL_IMAGE && !empty($swatchDataArray['value'])) {
$result['value'] = $this->swatchMediaHelper->getSwatchAttributeImage(
Swatch::SWATCH_IMAGE_NAME,
$swatchDataArray['value']
);
$result['thumb'] = $this->swatchMediaHelper->getSwatchAttributeImage(
Swatch::SWATCH_THUMBNAIL_NAME,
$swatchDataArray['value']
);
} else {
$result['value'] = $swatchDataArray['value'];
}
return $result;
}
/**
* Generate Product Media array
*
* @param string $attributeCode
* @param integer $optionId
* @return array
*/
protected function getVariationMedia($attributeCode, $optionId)
{
$variationProduct = $this->swatchHelper->loadFirstVariationWithSwatchImage(
$this->getProduct(),
[$attributeCode => $optionId]
);
if (!$variationProduct) {
$variationProduct = $this->swatchHelper->loadFirstVariationWithImage(
$this->getProduct(),
[$attributeCode => $optionId]
);
}
$variationMediaArray = [];
if ($variationProduct) {
$variationMediaArray = [
'value' => $this->getSwatchProductImage($variationProduct, Swatch::SWATCH_IMAGE_NAME),
'thumb' => $this->getSwatchProductImage($variationProduct, Swatch::SWATCH_THUMBNAIL_NAME),
];
}
return $variationMediaArray;
}
/**
* Get swatch product image.
*
* @param Product $childProduct
* @param string $imageType
* @return string
*/
protected function getSwatchProductImage(Product $childProduct, $imageType)
{
if ($this->isProductHasImage($childProduct, Swatch::SWATCH_IMAGE_NAME)) {
$swatchImageId = $imageType;
$imageAttributes = ['type' => Swatch::SWATCH_IMAGE_NAME];
} elseif ($this->isProductHasImage($childProduct, 'image')) {
$swatchImageId = $imageType == Swatch::SWATCH_IMAGE_NAME ? 'swatch_image_base' : 'swatch_thumb_base';
$imageAttributes = ['type' => 'image'];
}
if (!empty($swatchImageId) && !empty($imageAttributes['type'])) {
return $this->imageUrlBuilder->getUrl($childProduct->getData($imageAttributes['type']), $swatchImageId);
}
}
/**
* Check if product have image.
*
* @param Product $product
* @param string $imageType
* @return bool
*/
protected function isProductHasImage(Product $product, $imageType)
{
return $product->getData($imageType) !== null && $product->getData($imageType) != SwatchData::EMPTY_IMAGE_VALUE;
}
/**
* Get configurable options ids.
*
* @param array $attributeData
* @return array
* @since 100.0.3
*/
protected function getConfigurableOptionsIds(array $attributeData)
{
$ids = [];
foreach ($this->getAllowProducts() as $product) {
/** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute $attribute */
foreach ($this->helper->getAllowAttributes($this->getProduct()) as $attribute) {
$productAttribute = $attribute->getProductAttribute();
$productAttributeId = $productAttribute->getId();
if (isset($attributeData[$productAttributeId])) {
$ids[$product->getData($productAttribute->getAttributeCode())] = 1;
}
}
}
return array_keys($ids);
}
/**
* Produce and return block's html output
*
* @return string
* @since 100.2.0
*/
public function toHtml()
{
$this->setTemplate(
$this->getRendererTemplate()
);
return parent::toHtml();
}
/**
* Return HTML code
*
* @return string
*/
protected function _toHtml()
{
return $this->getHtmlOutput();
}
/**
* Return renderer template
*
* Template for product with swatches is different from product without swatches
*
* @return string
*/
protected function getRendererTemplate()
{
return $this->isProductHasSwatchAttribute() ?
self::SWATCH_RENDERER_TEMPLATE : self::CONFIGURABLE_RENDERER_TEMPLATE;
}
/**
* @inheritDoc
* @deprecated 100.1.5 Now is used _toHtml() directly
*/
protected function getHtmlOutput()
{
return parent::_toHtml();
}
/**
* Get media callback url.
*
* @return string
*/
public function getMediaCallback()
{
return $this->getUrl(self::MEDIA_CALLBACK_ACTION, ['_secure' => $this->getRequest()->isSecure()]);
}
/**
* Return unique ID(s) for each object in system
*
* @return string[]
* @since 100.1.0
*/
public function getIdentities()
{
if ($this->product instanceof \Magento\Framework\DataObject\IdentityInterface) {
return $this->product->getIdentities();
} else {
return [];
}
}
/**
* Get Swatch image size config data.
*
* @return string
* @since 100.2.5
*/
public function getJsonSwatchSizeConfig()
{
$imageConfig = $this->swatchMediaHelper->getImageConfig();
$sizeConfig = [];
$sizeConfig[self::SWATCH_IMAGE_NAME]['width'] = $imageConfig[Swatch::SWATCH_IMAGE_NAME]['width'];
$sizeConfig[self::SWATCH_IMAGE_NAME]['height'] = $imageConfig[Swatch::SWATCH_IMAGE_NAME]['height'];
$sizeConfig[self::SWATCH_THUMBNAIL_NAME]['height'] = $imageConfig[Swatch::SWATCH_THUMBNAIL_NAME]['height'];
$sizeConfig[self::SWATCH_THUMBNAIL_NAME]['width'] = $imageConfig[Swatch::SWATCH_THUMBNAIL_NAME]['width'];
return $this->jsonEncoder->encode($sizeConfig);
}
}