1

I'd like to add static blocks like

{{block type="cms/block" block_id="this_is_the_block_id"}}

in the product description (and/or short description).

We currently have an Magento CE 1.9 installation with the "Static Blocks Everywhere" extension (https://www.magentocommerce.com/magento-connect/catalog/product/view/id/13663/) which should be migrated to a Magento CE 2.1 installation. There is no similar Magento 2 extension. Many of our current product desriptions are containing static blocks.

1 Answer 1

2

basically, you have to process the description through the Block Filter class.

Lately, I had to do this for Categories to allow widgets, the same should work for block directives (although the directive looks slightly different in Magento2)

{{block id="123"}}

To execute the filter on the description when a category is loaded I added a plugin on the repository get Method and to execute it also when categories are loaded through a colelction I added an observer on the catalog_category_collection_load_after function.

I'll try to translate it to product ;)

First the loading for a single Object:

In your di.xml, define a new Plugin on the ProductRepository:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Catalog\Api\ProductRepositoryInterface">
        <plugin name="filterProductDescription" type="Vendor\Module\Plugin\ProductRepository\FilterProductDescription"/>
    </type>
</config>

Then you need to create the Plugin Class in your module:

<?php
declare(strict_types = 1);
namespace Vendor\Module\Plugin\ProductRepository;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Product;
use Magento\Cms\Model\Template\FilterProvider;

class FilterProductDescription
{
    const ATTR_DESCRIPTION = 'description';
    /**
     * @var FilterProvider
     */
    private $filterProvider;

    public function __construct(
        FilterProvider $filterProvider
    ) {
        $this->filterProvider = $filterProvider;
    }

    /**
     * @param ProductRepositoryInterface $subject
     * @param ProductInterface|Product $product
     * @return ProductInterface
     */
    public function afterGet($subject, ProductInterface $product): ProductInterface
    {
        if (false === $product->hasData(static::ATTR_DESCRIPTION)) {
            return $product;
        }

        $filteredDescription = $this->filterProvider->getBlockFilter()
            ->filter($product->getData(static::ATTR_DESCRIPTION));

        $product->setData(static::ATTR_DESCRIPTION, $filteredDescription);

        return $product;
    }
}

Now to also apply the filter, when a product collection is loaded, you need to add the same logic to the collection.

You can do this by adding an observer in the events.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="catalog_product_collection_load_after">
        <observer name="filterProductDescription" instance="Vendor\Module\Observer\ProductCollection\FilterProductDescription" />
    </event>
</config>

and finally implement the observer class:

<?php
declare(strict_types = 1);
namespace Vendor\Module\Observer\ProductCollection;

use Magento\Cms\Model\Template\FilterProvider;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Catalog\Model\ResourceModel\Product\Collection as ProductCollection;

class FilterProductDescription implements ObserverInterface
{
    const ATTR_DESCRIPTION = 'description';
    /**
     * @var FilterProvider
     */
    private $filterProvider;

    public function __construct(
        FilterProvider $filterProvider
    ) {
        $this->filterProvider = $filterProvider;
    }


    /**
     * @param Observer $observer
     * @return void
     */
    public function execute(Observer $observer)
    {
        /** @var ProductCollection $productCollection */
        $productCollection = $observer->getData('product_collection');

        foreach ($productCollection->getItems() as $product) {
            $filteredDescription = $this->filterProvider->getBlockFilter()
                ->filter($product->getData(static::ATTR_DESCRIPTION));
            $product->setData(static::ATTR_DESCRIPTION, $filteredDescription);
        }
    }
}
3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.