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); } }