salesagility / SuiteCRM

SuiteCRM - Open source CRM for the world
https://www.suitecrm.com
GNU Affero General Public License v3.0
4.53k stars 2.1k forks source link

Html fields showing the string value of the html, not the html itself #4957

Closed mattlorimer closed 6 years ago

mattlorimer commented 6 years ago

Html fields are to show html. The are showing the string value of the html, not the html itself. The literal string is being shown on version 7.9.9

Before there was nothing being shown on Edit and DetailViews. The update now shows the literal string representation of the fields html.

Studio shows the HTML in the edit of the field as the display value of the HTML like you would in a web browser.

Your Environment

gmiweb commented 6 years ago

Environment

gmiweb commented 6 years ago

There is a workaround I did to get expected behavior. Create an after_retrieve hook and change the bean->your_html_field_name to display as HTML by setting it to the return value of html_entity_decode() This will work for the detailView.

EditView will wrap your html in an input element. To fix this, modify your editviewdefs.php file and add customCode to the field you need to display as HTML. Set the value of 'customCode' => '{$fields.your_html_field_name.value}'

There was no need to modify core code, but the expected behavior needs fixed.

simonnowos commented 6 years ago

I tried your workaround for EditView with Version 7.8.16 but the behaviour here is that it displays all the html-code of the field without executing it.

gmiweb commented 6 years ago

That is interesting... Given your description was the original issue I had. Hence my work around solution for me. Are you able to have your HTML field display properly executed HTML code without doing anything out of the box?

simonnowos commented 6 years ago

My "live" system runs 7.8.8 and here the html-fields work like they should do. On my test-instance I updated the system to 7.8.16 and here initially the html-fields are shown as Input-Fields with displaying the html in the input area. And with your workaround i get the behaviour as descriped above. invoice-create-7-8-16

simonnowos commented 6 years ago

Hey gmiweb,

I want to try again. Could you explain your first step to me more deep?

"Create an after_retrieve hook and change the bean->your_html_field_name to display as HTML by setting it to the return value of html_entity_decode()"

How could i set this up?

gmiweb commented 6 years ago

When I tested my html fields they did not work as expected. The code returned as a string rather than rendered HTML.

I assume you know how to create a logic hook, so I will detail after that point.

The $bean->your_html_field_name is the reference to your SugarBean's custom HTML field. Then on the logic hook call, I set the field to the function result from html_entity_decode($bean->custom_field_name)

class CustomFields extends SugarBean {
    function formatHTMLFields(&$bean, $event, $arguments) {
        $bean->jan_category_display = html_entity_decode($bean->jan_category_display);
        $bean->guard_category_display = html_entity_decode($bean->guard_category_display);
    }
}

This code snippet is the key $bean->custom_field_name = html_entity_decode($bean->custom_field_name); in the logic hook. Note the after_retrieve hook seems to only be called on an existing bean. So, when you create a new one, it is not called. I still get the string value of my default HTML when creating a new SugarBean.

screen shot 2018-04-09 at 3 12 55 pm

Desired output below:

screen shot 2018-04-09 at 3 13 45 pm screen shot 2018-04-09 at 3 13 19 pm

Not much more to describe here. The PHP function returns the desired HTML instead of a string, so my browser renders it as expected. Otherwise, only the string value is returned.

Looks like I need to do this for a new record now as well. I did not notice that until I reviewed my steps for this reply. Thank you!

simonnowos commented 6 years ago

Thank you very much! But I'm still a newby to SuiteCRM with limited experience. So i have no idea about logic hooks and unfortunately can't follow your instructions therefore.

gmiweb commented 6 years ago

I recommend you read this article.

It details exactly how to create the specified hook better than I can. Let me know if you need anything else. Also note, this hook only is called when a record is retrieved from the database. It will not be called on a new record request.

simonnowos commented 6 years ago

I tried to set the hook up.

The fieldname is hwbn_c

/xxx/crm/custom/modules/AOS_Invoices/logic_hooks.php

<?php

    $hook_version = 1;
    $hook_array = Array();

    $hook_array['after_retrieve'] = Array();
    $hook_array['after_retrieve'][] = Array(
        //Processing index. For sorting the array.
        1,

        //Label. A string value to identify the hook.
        '$bean->hwbn_c = html_entity_decode($bean->hwbn_c);',

        //The PHP file where your class is located.
        'domain/crm/custom/modules/aos_Invoices/logic_hooks_class.php',

        //The class the method is in.
        'CustomFields extends SugarBean',

        //The method to call.
        'after_retrieve_method'
    );

?>

domain/crm/custom/modules/AOS_Invoices/logic_hooks_class.php

<?php

    if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

    class CustomFields extends SugarBean {
    function formatHTMLFields(&$bean, $event, $arguments) {
        $bean->jan_category_display = html_entity_decode($bean->jan_category_display);
        $bean->guard_category_display = html_entity_decode($bean->guard_category_display);
    }
}

?>

Is this correct? It doesn't work (I did quick repair before) The html-field is on editview for AOS_Invoices.

gmiweb commented 6 years ago

Based on what you provided, I doubt your hook is even being called.

Your hook registration needs to look like this: Make sure your register hook file is name and located here _'domain/crm/custom/modules/aos_Invoices/logichooks.php'

<?php
// Do not store anything in this file that is not part of the array or the hook version.  This file will    
// be automatically rebuilt in the future. 

$hook_version = 1; 
$hook_array = Array(); 
// position, file, function 
$hook_array['after_retrieve'] = Array(); 
$hook_array['after_retrieve'][] = Array(
    1,
    'Cleans up HTML fields for display', 
    'domain/crm/custom/modules/aos_Invoices/logic_hooks_class.php',
    'CustomFields',
    'formatHTMLFields'
); 

Your hook class should look like this: _domain/crm/custom/modules/aos_Invoices/logic_hooksclass.php

<?php
require_once('data/SugarBean.php');

// CustomFields is the class name you referenced in your register hook file above.
class CustomFields extends SugarBean {
    // formatHTMLFields is the function name you registered in your hook file above.
    // This function will execute only when the after_retrieve event is triggered.
    function formatHTMLFields(&$bean, $event, $arguments) {
        // In your case, the $bean will be an instance of AOS_Invoices.
        // So, you will only be able to access it's properties and methods.
        $bean->hwbn_c = html_entity_decode($bean->hwbn_c);
    }
}

Now, out of convention, I like to name file files by their class names they hold. In your case, logic_hooks_class.php should be named custom_fields.php. If you do this, update the logic_hooks.php file name reference.

simonnowos commented 6 years ago

Thank you for your effort! Unfortunately i don't get it to work. Don't know whats wrong. I tried it in 7.8.18 and 7.10.4 on different test-instances.

gmiweb commented 6 years ago

Have you tested to see if your logic hook is getting called?

simonnowos commented 6 years ago

How do test it? Is an entry in the suitecrm log created?

gmiweb commented 6 years ago

You can use any debugger or write to a log file of your choice. I use xdebug and also write my own log files. Good luck.

SNDK77 commented 6 years ago

Same problem here, for us this is high priority, we use the HTML fields to show instructions and help.

simonnowos commented 6 years ago

I didn't get your solution to work, maybe I'm just too unexperienced, I found a little trick to help me out for now until this bug is fixed. I insert the the hmtl-string directly the editviewdefs.php:

array ( 'name' => 'hwbn_c', 'studio' => 'visible', 'label' => 'LBL_HWBN', 'customCode' => '<h1>Order-Number</h1>', ),

ih0ry commented 6 years ago

Hello, I posted my solution here https://suitecrm.com/suitecrm/forum/suitecrm-7-0-discussion/14615-html-field-not-being-displayed?start=15#62151 All that you need to do is to extend html field. Just follow these steps(if you do not need to have html editor or you are not planing to change html content from editview you can skip steps 3 and 4):

  1. Create html field
    'instructions' => array(
    'name' => 'instructions',
    'vname' => 'LBL_INSTRUCTIONS',
    'type' => 'html',
    'comment' => '',
    'inline_edit' => false
    ),
  2. Create folder for custom field custom/include/SugarFields/Fields/Html/
  3. Define controller for our custom html fields. Create file custom/include/SugarFields/Fields/Html/SugarFieldHtml.php with content:
    
    <?php

include_once 'include/SugarFields/Fields/Html/SugarFieldHtml.php';

class CustomSugarFieldHtml extends SugarFieldHtml {

/**
 * @param string $parentFieldArray
 * @param array $vardef
 * @param array $displayParams
 * @param integer $tabindex
 * @return string
 */
public function getEditViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex) {

    $sugarCleaner = new SugarCleaner();
    $vardef['value'] = $sugarCleaner::cleanHtml($this->getVardefValue($vardef));

    require_once 'include/SuiteEditor/SuiteEditorConnector.php';

    $settings = SuiteEditorConnector::getSuiteSettings($vardef['value'], 600);

    // set real field name
    $settings['textareaId'] = $vardef['name'];
    // and remove onclick actions
    $settings['clickHandler'] = 'function(e){}';
    $settings['tinyMCESetup'] = "{
            setup: function(editor) {},
            plugins: ['code', 'table', 'link'],
        }";

    $this->ss->assign('BODY_EDITOR', SuiteEditorConnector::getHtml($settings));
    $this->ss->assign('value', $vardef['value']);

    $this->setup($parentFieldArray, $vardef, $displayParams, $tabindex);
    return $this->fetch($this->findTemplate('EditView'));
}

private function getVardefValue($vardef) {
    if (empty($vardef['value'])) {
        if (!empty($vardef['default'])) {
            return $vardef['default'];
        } elseif (!empty($vardef['default_value'])) {
            return $vardef['default_value'];
        }
    }

    return utf8_decode($vardef['value']);
}

}

4. Redefine editview of the field in order to support html editor. Create file **custom/include/SugarFields/Fields/Html/EditView.tpl** with content: 
```smarty
{literal}
    {{$BODY_EDITOR}}
{/literal}
<div id='{{$vardef.name}}_div'>
    <textarea id='{{$vardef.name}}' tabindex='0' name='{{$vardef.name}}' cols="100" rows="40" style="display: none;">{{$value}}</textarea>
</div>
  1. To display this field properly you need to create detailview of the html field(since it is not included in default definition of the type). Create file custom/include/SugarFields/Fields/Html/DetailView.tpl with content:
    <span class="sugar_field" id="{{if empty($displayParams.idName)}}{{sugarvar key='name'}}{{else}}{{$displayParams.idName}}{{/if}}">{{$vardef.value}}</span>
    {{if !empty($displayParams.enableConnectors)}}
    {{sugarvar_connector view='DetailView'}}
    {{/if}}
  2. Repair