У меня странная проблема с Magento 2.2, которая заставляет меня биться головой о стену.
У меня есть следующие файлы в пользовательском модуле:
PallidVisions / Swatches / вид / интерфейс / макет / catalog_product_view_type_configurable.xml:
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<!-- TODO: take this stuff out of the head and put it into the body -->
<head>
<css src="PallidVisions_Swatches::css/swatches.css" />
<link src="PallidVisions_Swatches::js/swatch-modifications.js" />
</head>
<body>
<referenceBlock name="product.info.options.wrapper">
<block class="PallidVisions\Swatches\Block\Product\View\Type\Configurable" name="product.info.options.data" template="PallidVisions_Swatches::swatch-data.phtml" />
</referenceBlock>
</body>
</page>
PallidVisions / Swatches / просмотр / интерфейс / шаблоны / образчик-data.phtml:
<div id="test"></div>
PallidVisions / Swatches / Block / Продукт / Вид / Тип / Configurable.php:
<?php
/**
* Overrides Magento\Swatches catalog super product configurable
* part block, modifying it so that out of stock options will show up in
* the list of options, but be labeled as such and be disabled.
*
* Based on the solution posted here:
* https://magento.stackexchange.com/questions/216373/magento-2-2-how-to-show-out-of-stock-in-configurable-product
*
* This was written for Magento 2.2.5 and might need modification to be
* compatible with future releases.
*/
namespace PallidVisions\Swatches\Block\Product\View\Type;
use Magento\Catalog\Block\Product\Context;
use Magento\Catalog\Helper\Product as CatalogProduct;
use Magento\Catalog\Model\Product;
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;
use Magento\Framework\Locale\Format;
class Configurable extends \Magento\Swatches\Block\Product\Renderer\Configurable {
// Defined in the parent of this parent's class, but since it's private and
// I need it, I have to implement it again here.
private $localeFormat;
private $variationPrices;
// List of all associated products, including those that are out of stock
protected $childProducts;
/*************************************************************************/
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
) {
parent::__construct(
$context,
$arrayUtils,
$jsonEncoder,
$helper,
$catalogProduct,
$currentCustomer,
$priceCurrency,
$configurableAttributeData,
$swatchHelper,
$swatchMediaHelper,
$data,
$swatchAttributesProvider
);
$this->localeFormat = ObjectManager::getInstance()->get(Format::class);
$this->variationPrices = ObjectManager::getInstance()->get(
\Magento\ConfigurableProduct\Model\Product\Type\Configurable\Variations\Prices::class
);
$this->childProducts = $this->getProduct()->getTypeInstance()->getUsedProducts($this->getProduct());
}
/*************************************************************************/
// Overrides Magento\ConfigurableProduct\Block\Product\View\Type\Configurable::getJsonConfig
public function getJsonConfig() {
$store = $this->getCurrentStore();
$currentProduct = $this->getProduct();
$options = $this->helper->getOptions($currentProduct, $this->childProducts);
$attributesData = $this->configurableAttributeData->getAttributesData($currentProduct, $options);
$config = [
'attributes' => $attributesData['attributes'],
'template' => str_replace('%s', '<%- data.price %>', $store->getCurrentCurrency()->getOutputFormat()),
'currencyFormat' => $store->getCurrentCurrency()->getOutputFormat(),
'optionPrices' => $this->getOptionPrices(),
'optionStock' => $this->getOptionStocks(),
'priceFormat' => $this->localeFormat->getPriceFormat(),
'prices' => $this->variationPrices->getFormattedPrices($this->getProduct()->getPriceInfo()),
'productId' => $currentProduct->getId(),
'chooseText' => __('Choose an Option...'),
'images' => $this->getOptionImages(),
'index' => isset($options['index']) ? $options['index'] : [],
];
if ($currentProduct->hasPreconfiguredValues() && !empty($attributesData['defaultValues'])) {
$config['defaultValues'] = $attributesData['defaultValues'];
}
$config = array_merge($config, $this->_getAdditionalConfig());
return $this->jsonEncoder->encode($config);
}
/*************************************************************************/
// Overrides Magento\ConfigurableProduct\Block\Product\View\Type\Configurable::getOptionImages
// This function is exactly the same with the exception of where the product
// data comes from.
protected function getOptionImages() {
$images = [];
foreach ($this->childProducts as $product) {
$productImages = $this->helper->getGalleryImages($product) ?: [];
foreach ($productImages as $image) {
$images[$product->getId()][] = [
'thumb' => $image->getData('small_image_url'),
'img' => $image->getData('medium_image_url'),
'full' => $image->getData('large_image_url'),
'caption' => $image->getLabel(),
'position' => $image->getPosition(),
'isMain' => $image->getFile() == $product->getImage(),
'type' => str_replace('external-', '', $image->getMediaType()),
'videoUrl' => $image->getVideoUrl(),
];
}
}
return $images;
}
/*************************************************************************/
// Overrides Magento\ConfigurableProduct\Block\Product\View\Type\Configurable::getOptionPrices.
// This function is exactly the same with the exception of where the product
// data comes from.
protected function getOptionPrices() {
$prices = [];
foreach ($this->childProducts as $product) {
$tierPrices = [];
$priceInfo = $product->getPriceInfo();
$tierPriceModel = $priceInfo->getPrice('tier_price');
$tierPricesList = $tierPriceModel->getTierPriceList();
foreach ($tierPricesList as $tierPrice) {
$tierPrices[] = [
'qty' => $this->localeFormat->getNumber($tierPrice['price_qty']),
'price' => $this->localeFormat->getNumber($tierPrice['price']->getValue()),
'percentage' => $this->localeFormat->getNumber(
$tierPriceModel->getSavePercent($tierPrice['price'])
),
];
}
$prices[$product->getId()] = [
'oldPrice' => [
'amount' => $this->localeFormat->getNumber(
$priceInfo->getPrice('regular_price')->getAmount()->getValue()
),
],
'basePrice' => [
'amount' => $this->localeFormat->getNumber(
$priceInfo->getPrice('final_price')->getAmount()->getBaseAmount()
),
],
'finalPrice' => [
'amount' => $this->localeFormat->getNumber(
$priceInfo->getPrice('final_price')->getAmount()->getValue()
),
],
'tierPrices' => $tierPrices,
];
}
return $prices;
}
/*************************************************************************/
protected function getOptionStocks() {
$stocks = [];
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$stockObject=$objectManager->get('Magento\CatalogInventory\Api\StockRegistryInterface');
foreach ($this->childProducts as $product) {
$productStockObj = $stockObject->getStockItem($product->getId());
$isInStock = !$productStockObj['manage_stock'] | $productStockObj['is_in_stock'] ? '1' : '0';
$stocks[$product->getId()] = ['stockStatus' => $isInStock];
}
return $stocks;
}
}
Если я удаляю атрибут class = "..." из элемента block в моем макете xml, блок визуализируется, и я вижу div из моего шаблона внутри моего источника. Если, однако, я указываю класс, блок молча исчезает. Я не получаю ошибок, чтобы помочь моей диагностике, почему это не работает. Это просто не рендерится. Я попытался изменить имя класса на класс, который не существует, и это заставило Magento выдать ошибку, поэтому он видит класс в Configurable.php. Это просто не рендеринг по какой-то причине.
Спасибо!