Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Magento 2.1 EE: simplexml_load_string() error in custom widget #6594

Closed
enrico69 opened this issue Sep 13, 2016 · 17 comments
Closed

Magento 2.1 EE: simplexml_load_string() error in custom widget #6594

enrico69 opened this issue Sep 13, 2016 · 17 comments
Labels
bug report Component: Cms Fixed in 2.2.x The issue has been fixed in 2.2 release line Issue: Format is valid Gate 1 Passed. Automatic verification of issue format passed Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development Progress: needs update

Comments

@enrico69
Copy link

Preconditions

  1. OS of the server: Debian (Virtualized, with 3GB of memory)
  2. OS of the client: Windows 7
  3. * Browser of the client*: Chrome Version 52.0.2743.116 m (64-bit). Also tried with Firefox 44.0.2
  4. MySQL: Ver 14.14 Distrib 5.6.31
  5. PHP: PHP 7.0.8-1~dotdeb+8.1 (cli) ( NTS )

Steps to reproduce

  1. Create a custom widget from a XML file
  2. Put a text field
  3. In the backend Content->Widget section, add the widget to a page
  4. In the widget content, set some HTML code like this:
    <p>Bonjour &eacute;&agrave;&ugrave;&egrave; &ocirc;</p>

Expected result

  1. The text should be displayed

Actual result

A warning is raised :
Exception #0 (Exception): Warning: simplexml_load_string(): Entity: line 1: parser error : Entity 'eacute' not defined in /var/www/xx/vendor/magento/framework/View/Model/Layout/Merge.php on line 493

Notes:

  • if, instead of the text field, a I put a WYSIWYG one, and put some HTML code, it will generate entities encoded HTML
  • if I put only raw text: no problem.
  • more weird: if I put only raw text, then I save, everything is OK. And if I come later, put some HTML code (directly or via the WYSIWYG), and save, I have a warning:

image

@veloraven
Copy link
Contributor

@enrico69 thank you for your feedback.
Please identify which version of Magento you are running.

@enrico69 enrico69 changed the title simplexml_load_string() error in custom widget Magento 2.1 EE: simplexml_load_string() error in custom widget Sep 13, 2016
@enrico69
Copy link
Author

Sorry. That's done.

@sevos1984
Copy link
Contributor

Could you please paste your xml for custom widget here?

@enrico69
Copy link
Author

<?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="myclient_corporateWidget" class="Myclient\CorporateWidget\Block\Widget\CorporateWidget">
        <label translate="true">Myclient Corporate Widget</label>
        <description>Widget containing informations about Myclient</description>
        <parameters>
            <parameter name="widgetTitle" xsi:type="text"  visible="true" sort_order="10" >
                <label translate="true">Title</label>
            </parameter>
            <parameter name="videoHtmlCode" xsi:type="text"  visible="true" sort_order="10" >
                <label translate="true">Video Url</label>
            </parameter>
            <parameter name="logoFile" xsi:type="text"  visible="true" sort_order="10" >
                <label translate="true">Logo</label>
            </parameter>
            <parameter name="picture1File" xsi:type="select" source_model="Myclient\CorporateWidget\Model\Listing\Picture" visible="true" sort_order="10" >
        <label translate="true">Picture #1</label>
            </parameter>
            <parameter name="pic1Text" xsi:type="block"  visible="true" sort_order="10" >
                <label translate="true">Picture #1 description</label>
                <block class="Mycompany\Tools\Block\Adminhtml\Widget\TextArea" />
            </parameter>
            <parameter name="picture2File" xsi:type="select" source_model="Myclient\CorporateWidget\Model\Listing\Picture" visible="true" sort_order="10" >
        <label translate="true">Picture #2</label>
            </parameter>
            <parameter name="pic2Text" xsi:type="block"  visible="true" sort_order="10" >
                <label translate="true">Picture #2 description</label>
                <block class="Mycompany\Tools\Block\Adminhtml\Widget\TextArea" />
            </parameter>
            <parameter name="picture3File" xsi:type="select" source_model="Myclient\CorporateWidget\Model\Listing\Picture" visible="true" sort_order="10" >
        <label translate="true">Picture #3</label>
            </parameter>
            <parameter name="pic3Text" xsi:type="block"  visible="true" sort_order="10" >
                <label translate="true">Picture #3 description</label>
                <block class="Mycompany\Tools\Block\Adminhtml\Widget\TextArea" />
            </parameter>
        </parameters>
    </widget>
</widgets>

@sevos1984
Copy link
Contributor

Can't reproduce with your xml but without your classes. How do you add content right to your widget without a block? What layout update do you select? Maybe you have some non-default locale set?

@enrico69
Copy link
Author

Hi
I use a standard locale (fr_FR). Below is the code of the block:

<?php
namespace Mycompany\Tools\Block\Adminhtml\Widget;

use Magento\Framework\Data\Form\Element\Factory;
use Magento\Backend\Block\Template\Context;
use Magento\Backend\Block\Widget\Form\Element;
use Magento\Framework\Module\Dir\Reader;
use Magento\Framework\Data\Form\Element\AbstractElement;

class TextArea extends Element
{
    /**
     * @var Factory
     */
    protected $factoryElement;

    /**
     * @var Magento\Framework\Module\Dir\Reader 
     */
    protected $reader;

    /**
     * 
     * @param Context $context
     * @param Factory $factoryElement
     * @param type $data
     */
    public function __construct(
        Reader $reader,
        Context $context,
        Factory $factoryElement,
        $data = []
    ) {
        $this->factoryElement = $factoryElement;
        $this->reader = $reader;
        parent::__construct($context, $data);
    }

    /**
     * Prepare chooser element HTML
     *
     * @param \Magento\Framework\Data\Form\Element\AbstractElement $element Form Element
     * @return \Magento\Framework\Data\Form\Element\AbstractElement
     */
    public function prepareElementHtml(AbstractElement $element)
    {
        $textArea = $this->factoryElement->create('textarea', ['data' => $element->getData()])
            ->setId($element->getId())
            ->setForm($element->getForm())
            ->setClass('widget-option input-textarea admin__control-text');

        if ($element->getRequired()) {
            $textArea->addClass('required-entry');
        }

        $element->setData(
            'after_element_html',
            $this->_getAfterElementHtml() . $textArea->getElementHtml()
        );

        return $element;
    }

    /**
     * @return string
     */
    protected function _getAfterElementHtml()
    {
        $filePath = $this->reader->getModuleDir('view', 'Mycompany_Tools');
        $filePath .= DIRECTORY_SEPARATOR . 'adminhtml' . DIRECTORY_SEPARATOR . 'templates' 
        . DIRECTORY_SEPARATOR . 'widget'. DIRECTORY_SEPARATOR . 'htmlAddition.php';

        ob_start();
        include $filePath;
        return ob_get_clean();
    }
}

And here the CSS I add :

<style>
    .admin__field-control.control .control-value {
        display: none !important;
    }
</style>

I followed a couple of tutorial in order to compensate the lack of TextArea field for the widgets.

@sevos1984
Copy link
Contributor

Is this still reproducible in latest release branch?

@sevos1984
Copy link
Contributor

We are closing this issue because it hasn’t been updated in more than two weeks. If you can still reproduce this issue, please create a new GitHub issue report.

@toannguyen3105
Copy link

How to fix bug?

@TommyKolkman
Copy link

@sevos1984 Can you please open this again? I'm on Magento 2.1.1 and I've got this error as well:

Example: I've got some German texts that are too long, in a widget text field, so I want to skip them to the next line by using ­ as a html entity.

This breaks the entire site.

{{1 exception(s):
Exception #0 (Exception): Warning: simplexml_load_string(): Entity: line 54: parser error : Entity 'shy' not defined in /data/web/magento2/vendor/magento/framework/View/Model/Layout/Merge.php on line 493}}

Now, problem is, this is added as a serialized array to the widget_instance. It instantly breaks your database.

What I also found out that this mostly happens when you add data through Content > Widgets, not through adding widgets through pages. I suspect TinyMCE does some escaping itself.

My guess is that the problem can be solved here, but I'm not sure.

Magento\Widget\Model\Widget\Instance:253

@antbates91
Copy link

antbates91 commented Mar 2, 2017

I did find some sort of solution for this issue, although I'm not sure if its really a bug because technically those elements are invalid XML and shouldn't be use in widgets. However most clients do just put in these types of characters and then Magento converts them into HTML Entities on Save and this is just read straight into XML.

If you put a preference on the _loadXmlString() method in Magento\Framework\View\Model\Layout\Merge line 491

You can do something like:

protected function _loadXmlString($xmlString)
    {
        $unescapedValues = ['&nbsp;', '&eacute;', '&agrave;', '&ugrave;', '&egrave;', '&ocirc;'];
        
        foreach ($unescapedValues as $value) {
            // wrap in CDATA to escape
            $xmlString = str_replace($value, "<![CDATA[$value]]>", $xmlString);
        }
        
        return simplexml_load_string($xmlString, 'Magento\Framework\View\Layout\Element');
    }

@qbo-tech
Copy link

qbo-tech commented May 11, 2017

@antbates1991 your solution works.

This isssue should be reopned as the problem still exists with Magento 2.1.6.

@korostii
Copy link
Contributor

@qbo-tech, the closed issues rarely get reopened here because they rarely get any attention from someone with an ability to reopen it.
If you want to bring any attention to it, creating a new issue with reference to this one might do the trick.

@magento-team
Copy link
Contributor

Internal ticket to track issue progress: MAGETWO-70469

@magento-engcom-team magento-engcom-team added 2.1.x Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development bug report Component: Cms Issue: Format is valid Gate 1 Passed. Automatic verification of issue format passed Progress: needs update labels Sep 11, 2017
@magento-engcom-team magento-engcom-team added the Fixed in 2.2.x The issue has been fixed in 2.2 release line label Sep 18, 2017
@Loxzibit
Copy link
Contributor

Loxzibit commented Nov 28, 2017

For anyone who doesn't want to wait for 2.2.x you can use this small module to apply the fix https://github.com/WeareJH/m2-core-bug-simplexml-widget

@benyanke
Copy link

@antbates1991 Thank you - this worked for me as well. Since the entity ndash is what was failing, I added that to the array, like:

    protected function _loadXmlString($xmlString)
    {

        // Added bugfix from https://github.com/magento/magento2/issues/6594#issuecomment-283650111
        $unescapedValues = ['&nbsp;', '&eacute;', '&agrave;', '&ugrave;', '&egrave;', '&ocirc;', '&ndash;'];


        foreach ($unescapedValues as $value) {
            // wrap in CDATA to escape
            $xmlString = str_replace($value, "<![CDATA[$value]]>", $xmlString);
        }

        return simplexml_load_string($xmlString, 'Magento\Framework\View\Layout\Element');

    }

Helpful info to anyone else having the issue - you may need to add an additional item to the array based on your err msg.

@kanduvisla
Copy link
Contributor

I run into this problem now after an update from Magento 2.1.5 to 2.2.6 :-(

I'm not sure if this is intended behaviour, but what I find strange is that all the content of my WYSIWYG-editor is parsed as being "layout". If I look at the content of $xmlString, I get something like this:




<?xml version="1.0"?><layout xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><p><img title="..." src="path/to/image.jpg" alt="..." width="650" height="434" /></p>
  | <p>Some text with a &hellip; Bla bla <a href="path/to/url"><strong>fruitwater</strong></a> is, een verse smoothie, &hellip; genieten zal je</p>
  | <h2>Header</h2>
  | <p>Lorem ipsum etc...</p>
 

<body>
--
  | <referenceContainer name="root">
  | <block class="Ho\Templatehints\Block\Hints\Init" name="ho.templatehints"/>
  | </referenceContainer>
  | </body>
  | <body>
  | <referenceContainer name="header.panel">
  | <block class="Magento\Directory\Block\Currency" name="currency" before="store_language" template="Magento_Directory::currency.phtml"/>
  | </referenceContainer>
  | </body>
  | <head><script type="text/javascript">window.NREUM\|\|(NREUM={}),__nr_require=function(e,n,t){function r(t){if(!n[t]){var o=n[t]={exports:{}};e[t][0].call(o.exports,function(n){var o=e[t][1][n];return r(o\|\|n)},o,o.exports)}return n[t].exports}if("function"==typeof __nr_require)return __nr_require;for(var o=0;o<t.length;o++)r(t[o]);return r}({1:[function(e,n,t){function r(){}funct

... etc ...

Is this correct? Should my HTML be in the layout merger? Seems a little odd to me...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug report Component: Cms Fixed in 2.2.x The issue has been fixed in 2.2 release line Issue: Format is valid Gate 1 Passed. Automatic verification of issue format passed Issue: Ready for Work Gate 4. Acknowledged. Issue is added to backlog and ready for development Progress: needs update
Projects
None yet
Development

No branches or pull requests