123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- 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';
- /**
- * @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
- );
- }
- }
- 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(
- 'catalog/frontend/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;
- }
- /**
- * @return array
- */
- protected function getSwatchAttributesData()
- {
- return $this->swatchHelper->getSwatchAttributesAsArray($this->getProduct());
- }
- /**
- * @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;
- }
- /**
- * @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);
- }
- }
- /**
- * @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;
- }
- /**
- * @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;
- }
- /**
- * @deprecated 100.1.5 Now is used _toHtml() directly
- * @return string
- */
- protected function getHtmlOutput()
- {
- return parent::_toHtml();
- }
- /**
- * @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);
- }
- }
|