How to use html content in magento2 widget

Today I am going to discuss about some limitation of Magento2 widget. You can create different type of widget with different input field. Suppose you create a TextArea and you try to entry some html content here, then what happened? Ideally you can’t do in default Magento2 installation, it just breaks the edit functionality. So in that case you need some care about this. So today I build an extension for overcome this situation.

So need to overwrite widget save and load controller.

Step 1: Pluginize ‘BuildWidget’ controller and ‘LoadOptions’ controller


# SR/RewriteWidget/etc/adminhtml/di.xml
<?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\Widget\Controller\Adminhtml\Widget\BuildWidget">
        <plugin name="rewrite_widget_build_widget" type="SR\RewriteWidget\Plugin\Widget\Controller\Adminhtml\Widget\BuildWidget" sortOrder="1"/>
    </type>
    <type name="Magento\Widget\Controller\Adminhtml\Widget\LoadOptions">
        <plugin name="rewrite_widget_load_options" type="SR\RewriteWidget\Plugin\Widget\Controller\Adminhtml\Widget\LoadOptions" sortOrder="1"/>
    </type>
</config>

Step 2: Create SR/RewriteWidget/Plugin/Widget/Controller/Adminhtml/Widget/BuildWidget.php


namespace SR\RewriteWidget\Plugin\Widget\Controller\Adminhtml\Widget;

class BuildWidget
{
    /**
     * @var \Magento\Widget\Model\Widget
     */
    protected $widget;

    /**
     * @var \SR\RewriteWidget\Helper\Data
     */
    protected $helper;

    /**
     * @param \Magento\Widget\Model\Widget $widget
     * @param \SR\RewriteWidget\Helper\Data $helper
     */
    public function __construct(
        \Magento\Widget\Model\Widget $widget,
        \SR\RewriteWidget\Helper\Data $helper
    ) {
        $this->widget = $widget;
        $this->helper = $helper;
    }

    /**
     * Format widget pseudo-code for inserting into wysiwyg editor
     *
     * @return void
     */
    public function aroundExecute(
        \Magento\Widget\Controller\Adminhtml\Widget\BuildWidget $subject,
        \Closure $proceed
    ) {
        $type = $subject->getRequest()->getPost('widget_type');
        $params = $subject->getRequest()->getPost('parameters', []);
        $asIs = $subject->getRequest()->getPost('as_is');

        if($type == 'SR\RewriteWidget\Block\Widget\Content') {

            foreach($params as $key => $value) {
                $params[$key] = $this->helper->encodeWidgetValues($value);
            }
        }

        $html = $this->widget->getWidgetDeclaration($type, $params, $asIs);
        $subject->getResponse()->setBody($html);
    }
}

Step 3: Create SR/RewriteWidget/Plugin/Widget/Controller/Adminhtml/Widget/LoadOptions.php


namespace SR\RewriteWidget\Plugin\Widget\Controller\Adminhtml\Widget;

class LoadOptions
{
    /**
     * @var \Magento\Framework\ObjectManagerInterface
     */
    protected $objectManager;

    /**
     * @var \Magento\Framework\App\ViewInterface
     */
    protected $view;

    /**
     * @var \Magento\Widget\Helper\Conditions
     */
    private $conditionsHelper;

    /**
     * @param \Magento\Framework\ObjectManagerInterface $objectManager
     * @param \Magento\Framework\App\ViewInterface $view
     */
    public function __construct(
        \Magento\Framework\ObjectManagerInterface $objectManager,
        \Magento\Framework\App\ViewInterface $view
    ) {
        $this->view = $view;
        $this->objectManager = $objectManager;
    }
    /**
     * Ajax responder for loading plugin options form
     *
     * @return void
     */
    public function aroundExecute(
        \Magento\Widget\Controller\Adminhtml\Widget\LoadOptions $subject,
        \Closure $proceed
    ) {
        try {
            $this->view->loadLayout();
            if ($paramsJson = $subject->getRequest()->getParam('widget')) {
                $request = $this->objectManager->get('Magento\Framework\Json\Helper\Data')->jsonDecode($paramsJson);
                if (is_array($request)) {
                    $optionsBlock = $this->view->getLayout()->getBlock('wysiwyg_widget.options');
                    if (isset($request['widget_type'])) {
                        $optionsBlock->setWidgetType($request['widget_type']);
                    }
                    if (isset($request['values'])) {
                        if($optionsBlock->getWidgetType() == 'SR\RewriteWidget\Block\Widget\Content') {
                            $helper = $this->objectManager->create('SR\RewriteWidget\Helper\Data');
                            foreach($request['values'] as $key => $value) {
                                $request['values'][$key] = $helper->decodeWidgetValues($value)
                            }
                        } else {
                            $request['values'] = array_map('htmlspecialchars_decode', $request['values']);
                            if (isset($request['values']['conditions_encoded'])) {
                                $request['values']['conditions'] =
                                    $this->getConditionsHelper()->decode($request['values']['conditions_encoded']);
                            }
                        }
                        $optionsBlock->setWidgetValues($request['values']);
                    }
                }
                $this->view->renderLayout();
            }
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            $result = ['error' => true, 'message' => $e->getMessage()];
            $subject->getResponse()->representJson(
                $this->objectManager->get('Magento\Framework\Json\Helper\Data')->jsonEncode($result)
            );
        }
    }

    /**
     * @return \Magento\Widget\Helper\Conditions
     * @deprecated
     */
    private function getConditionsHelper()
    {
        if (!$this->conditionsHelper) {
            $this->conditionsHelper = ObjectManager::getInstance()->get(\Magento\Widget\Helper\Conditions::class);
        }

        return $this->conditionsHelper;
    }
}

Step 3: Create SR/RewriteWidget/Helper/Data.php


namespace SR\RewriteWidget\Helper;

class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
    protected $_reservedData = array(
        'type', 'name_in_layout', 'area', 'module_name',
        'name', '_is_changed', '_renderer_name'
    );

    public function decodeWidgetValues($values)
    {
        if (!is_array($values)) {
            return base64_decode(strtr($values, ':_-', '+/='));
        }

        foreach ($values as $key => $value) {
            if ( is_scalar($value) && !in_array($key, $this->_reservedData) ) {
                $values[$key] = base64_decode(strtr($values, ':_-', '+/='));
            }
        }

        return $values;
    }

    public function encodeWidgetValues($values)
    {
        if ( !is_array($values) && !in_array($values, $this->_reservedData) ) {
            return strtr(base64_encode($values), '+/=', ':_-');
        }

        foreach ($values as $key => $value) {
            if (is_scalar($value)) {
                $values[$key] = strtr(base64_encode($value), '+/=', ':_-');
            }
        }

        return $values;
    }
}

And finally, in my widget block, I had to decode all data on-the-fly:


# SR\RewriteWidget\Block\Widget\Content

namespace SR\RewriteWidget\Block\Widget;

class Content extends \Magento\Framework\View\Element\Template implements \Magento\Widget\Block\BlockInterface
{
	/**
	 * @var \SR\RewriteWidget\Helper\Data
	 */
	protected $helper;

	/**
	 * @var \Magento\Cms\Model\Template\FilterProvider
	 */
	protected $filterProvider;

	/**
	 * Constructor
	 *
	 * @param \Magento\Framework\View\Element\Template\Context $context
	 * @param \SR\RewriteWidget\Helper\Data $helper
	 * @param array $data
	 */
	public function __construct(
		\Magento\Framework\View\Element\Template\Context $context,
		\SR\RewriteWidget\Helper\Data $helper,
		\Magento\Cms\Model\Template\FilterProvider $filterProvider,
		array $data = []
	) {
		parent::__construct($context, $data);
		$this->helper = $helper;
		$this->filterProvider = $filterProvider;
	}

	public function getData($key = '', $index = null)
	{
		if ('' === $key) {
			$data = $this->helper->decodeWidgetValues($this->_data);
		} else {
			$data = parent::getData($key, $index);
			if (is_scalar($data)) {
				$data = $this->helper->decodeWidgetValues($data);
			}

			$data = $this->filterProvider->getPageFilter()->filter($data);
		}

		return $data;
	}
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s