cancel
Showing results for 
Search instead for 
Did you mean: 

Special characters not showing up in widgets

0 Kudos

Special characters not showing up in widgets

Feature request from TommyKolkman, posted on GitHub Aug 24, 2016

Magento widgets strip special characters like a "+".

If I add something like:

{{widget type="Elephant\CFTextAndImage\Block\Widget\CFTextAndImage" language="nl_nl" title_default="++Hallo++"}}

The plusses are stripped. Now, in this case that's not that much of a problem, but in some cases we use base64 values there. When the base64 value has a plus, the value is instantly corrupted.

I've tried to track it down and came to the conclusion that there is a problem with the following file:

https://github.com/magento/magento2/blob/develop/lib/internal/Magento/Framework/Filter/Template.php

The problem is in the tokenizer.

 /**
     * Return associative array of parameters.
     *
     * @param string $value raw parameters
     * @return array
     */
    protected function getParameters($value)
    {
        $tokenizer = new Template\Tokenizer\Parameter();
        $tokenizer->setString($value);
        $params = $tokenizer->tokenize();
        foreach ($params as $key => $value) {
            if (substr($value, 0, 1) === '$') {
                $params[$key] = $this->getVariable(substr($value, 1), null);
            }
        }
        return $params;
    }

The $value, before added to the tokenizer is still correct. Afterwards, however, it's missing the plusses.

Now, I've tried writing up my own replacement for the tokenizer as quick fix, but that won't do. Can you guys fix this?

Temp fix (via di.xml of course):

    // $params = $tokenizer->tokenize();

    $params         = array();
    $count          = 0;
    $widget_values  = explode( '"', $value );
    $param_key      = '';

    foreach( $widget_values as $widget_value ){
        if( $count == 2 ){
            $count = 0;
        }
        if( $count == 0 ){
            // It's a key
            $param_key = trim( rtrim( $widget_value, '=' ) );
        } else {
            // It's a value
            $params[ $param_key ] = trim( $widget_value );
        }
        $count++;
    }
3 Comments
Not applicable

Comment from veloraven, posted on GitHub Aug 26, 2016

@TommyKolkman thank you for your report. Please, provide the used Magento version. Please, also format this issue according to the Issue reporting guidelines: with steps to reproduce, actual result and expected result.

Not applicable

Comment from TommyKolkman, posted on GitHub Aug 29, 2016

Version 2.0.8.

Steps to reproduce: Add a widget directive with text fields, add some plusses (or other characters) to them. Save it in a page, and check the output.

Expected result: The text result with plusses (or other characters).

Actual result: No special characters are shown, just normal (a-z, 0-9) text.

Hope I'm clear enough now.

Not applicable

Comment from picamator, posted on GitHub Sep 01, 2016

@TommyKolkman thank you, it's clear now. We will start to proceed that issue as a technical improvement.

As for the time being you could try these solutions:

  1. for + use +
  2. for base64_encode string - substitute space to + and return as an object, see code sample bellow

Here is a widget xml:

<?xml version="1.0" encoding="UTF-8"?>
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd">
    <widget id="test_title_widget_xml" class="Magento\Test\Block\Widget\Title">
        <label translate="true">Test Widget With XML config</label>
        <description>Test Widget</description>
        <parameters>
            <parameter name="testField" xsi:type="text"  visible="true" sort_order="0" >
                <label translate="true">Test text</label>
            </parameter>
            <parameter name="testSrc" xsi:type="text"  visible="true" sort_order="0" >
                <label translate="true">Test src text</label>
            </parameter>

            <parameter name="template" xsi:type="select" visible="true" required="true" sort_order="10">
                <label translate="true">Template</label>
                <options>
                    <option name="default" value="widget/title/default.phtml" selected="true">
                        <label translate="true">Default Template</label>
                    </option>
                </options>
            </parameter>
        </parameters>
    </widget>
</widgets>

Here is a block:

<?php
namespace Magento\Test\Block\Widget;

class Title extends \Magento\Framework\View\Element\Template implements \Magento\Widget\Block\BlockInterface
{
    /**
     * Retrieve test 64 encoded object
     * 
     * @return object
     */
    public function getTestSrc64Encode()
    {
        $testsrc=$this->getData('testSrc');
        $testsrc=strtr($testSrc, ' ', '+');

        return (object) $testSrc;
    }
}

Here is a template:

    <div class="test-widget-title" style="border:1px solid red;">
        <h3>Widget title</h3>
        <div><?php echo $block->getData('testField'); ?></div>
        <div><img alt="Embedded Image" src="data&colon;image/png;base64,<?php echo $block->getTestSrc64Encode()->scalar; ?>" alt="Test image" /></div>
    </div>

So having that widget you can simple put string with htmlspecialcharts to "Test text" and base64_encode image e.g. Magento Logo to "Test src text".