PDA

View Full Version : Bug in 4.1.5 enhanced editor with custom bb-code?


Marco64Th
08-20-2011, 07:43 AM
When using 4.1.5 with the Enhanced (WYSIWYG) editor i can not edit a post that contains a custom bb-code that was added with a plugin. In the editor the parsed text is shown instead of the original bb-code.

It could also be of course that i am setting an option wrong.

I performed the following test:

- Create 2 identical bb-codes, 1 using the BB-Code Manager ("test") and 1 added by plugins ("test2").

BB-Code Manager:
132151

- Next i created 2 plugins:
--- Hook location: bbcode_create
if (!function_exists("handle_bbcode_test2"))
{
function handle_bbcode_test2(&$parser, $code, $type)
{
global $vbulletin, $vbphrase, $show;

$result = "Option: $type<br />Param: $code";
return $result;
}
}

--- Hook Location: bbcode_fetch_tags
$tag_list['option']['test2'] = array(
'callback' => 'handle_external',
'strip_empty' => 0,
'stop_parse' => 0,
'disable_smilies' => 0,
'disable_wordwrap' => 0,
'strip_space_after' => 0,
'external_callback' => 'handle_bbcode_test2'
);

- Now i created a test post using both the test bb-codes (screen shows editing the test post using the Basic Editor):

132152

- The result of the post shows like:

132153

Now i can edit this post as many times as i want using the basic editor (or standard editor) and it will always be the same: when editing the tag is preserved, when viewing the tag is processed.

- If i now edit the same post with the enhanced editor however, i only get the parsed text in the edit window. But only for the bb-code that was added with a plugin:

132154

This makes it impossible to edit the post and preserve the bb-code.

Am i doing something wrong or is this a bug?

kh99
08-20-2011, 01:17 PM
It looks like the problem is that the code that converts from standard to wysiwyg is set up not to parse custom bbcodes, so they stay bbcode tags even in wysiwyg mode. fetch_tag_list() doesn't return the custom bbcodes, and when code in class_wysiwygparser.php does the standard to wysiwyg conversion, when it loads the custom tags, it changes the callback to 'handle_wysiwyg_unparsable'.

In any case, I don't know what you can do abut it short of editing vb files because there doesn't seem to be hooks in the right places. But if you were to edit the files, you could add your tag to the list of unparsed tags in class_bbcode_alt:

/**
* List of tags the WYSIWYG BB code parser should not parse.
*
* @var array
*/
var $unparsed_tags = array(

Marco64Th
08-20-2011, 03:38 PM
It looks like the problem is that the code that converts from standard to wysiwyg is set up not to parse custom bbcodes, so they stay bbcode tags even in wysiwyg mode.We probably mean the same, but it is the other way round. In WYSIWYG mode they do not stay as bb-codes, but you get the parsed result in your edit window.

I have done some more testing and in 4.1.3 it still worked as expected, this started with 4.1.4.

I have by now also posted it in the bug tracker: http://tracker.vbulletin.com/browse/VBIV-13004

Will look into solving it tomorrow, but as you say i doubt that can be done without patching vB, so not a real option.

kh99
08-20-2011, 03:41 PM
We probably mean the same, but it is the other way round. In WYSIWYG mode they do not stay as bb-codes,

Right, I believe it's the conversion of the text from "non-wysiwyg" to wysiwyg mode that is the problem.

Marco64Th
08-20-2011, 04:26 PM
Might be able to do something at the bbcode_fetch_tags hook, but then i would need to be able to know if the taglist is for the Wysiwyg editor or not. Will look into it tomorrow.

kh99
08-21-2011, 01:13 AM
Yes, I was thinking that you could change your callback there if you knew where it was called from, but I think I gave up on that when I noticed that the tag list is cached. But maybe it would still work.

You could probably have your callback do something different if you knew where it was being called from. Maybe there's some global you can check or something. (I think you can actually get an array of calling functions using the debug_backtrace() function, but that seems pretty ugly).

Marco64Th
08-21-2011, 04:36 AM
Did check early in the morning but didn't see your reply then.

Did a lot of testing and i first thought i was on the right track by changing the hook bbcode_fetch_tags to:
if (class_exists('vB_BbCodeParser_Wysiwyg'))
{
// If the class is defined we assume that we where called from an Enhanced editor page.
// This will most likely go wrong if there are both a basic editor and an enhanced editor on the same page.
// Set the tag to be preformatted
$tag_list['option']['test2'] = array(
'callback' => 'handle_preformatted_tag',
'strip_empty' => false,
'stop_parse' => true,
'disable_smilies' => true,
'disable_wordwrap' => true,
);
}
else
{
// Set the option for the tag to be handled by the regular (non-Wysiwyg) bbCodeParser
$tag_list['option']['test2'] = array(
'callback' => 'handle_external',
'strip_empty' => false,
'stop_parse' => true,
'disable_smilies' => true,
'disable_wordwrap' => true,
'strip_space_after' => 1,
'external_callback' => 'handle_bbcode_test2'
);
}
This had the risk of 2 editors being used on the same page and class_exists() only checks if the class is defined. Possible leading to a false positive in some rare situations. But as fetch_tag_list() is defined outside of the class and the class object not available, the other ways of checking can not be used. But that was an acceptable solution for me.

I thought it all worked but when testing a bit more i found out that if there is an option used in the tag (lucky i tested with bb codes that had an option), the option would be stripped due to a call to handle_preformatted_tag() by class vB_BbCodeParser_Wysiwyg:
function handle_preformatted_tag($code)
{
$current_tag =& $this->current_tag;
$tag_name = (isset($current_tag['name_orig']) ? $current_tag['name_orig'] : $current_tag['name']);

return "[$tag_name]" . $this->emulate_pre_tag($code) . "[/$tag_name]";
}

Notice that this function does not return options.

So i had to do it in another way.

What i finally came up with, and this works in all situation i tested, was to change the handler (hook: bbcode_create) to:
if (!function_exists("handle_bbcode_test2"))
{
function handle_bbcode_test2(&$parser, $code, $type)
{
global $vbulletin, $vbphrase, $show;

// (Marco64TH) Work around for bug in vB 4.1.4 & 4.1.5 (and maybe higher).
// See bug report: http://tracker.vbulletin.com/browse/VBIV-13004
//
// With vBulletin 4.1.4 and higher if editing a post using the Enhanced (Wysiwyg) editor, the editor window would show the parsed version
// of the bb-code instead of the original bb-code.
if (SIMPLE_VERSION >= 414 AND get_class($parser) == "vB_BbCodeParser_Wysiwyg")
{
$current_tag =& $parser->current_tag;
$tag_name = (isset($current_tag['name_orig']) ? $current_tag['name_orig'] : $current_tag['name']);

// Return the rebuild version of the original tag
return "[$tag_name" . ($type ? "=$type" : "") . "]" . $parser->emulate_pre_tag($code) . "[/$tag_name]";
}
else
{
// Return the parsed version of the tag
return "Option: $type<br />Param: $code";
}
}
}
Some remarks:
- We are now operating inside the class, so we can simply check the class.
- More control over the output.
- This example should work for any tagname with or without options.
- Downside is that i have added a check on the vBulletin versionnumber. If this issue ever is going to be changed, then you will need to update the plugin with the highest versionnumber.
- The emulate_pre_tag() will not be needed for all types of bb-codes. But as i am working on (yet another) Syntax Highlighter i thought it best to stay as close to the default tags like "code" and "php".

kh99
08-21-2011, 12:21 PM
Nice, thanks for posting your fix.


- We are now operating inside the class, so we can simply check the class.

I don't know if I ever would have thought of that.

Marco64Th
08-21-2011, 12:41 PM
It would still fail if they decided to rename the class somewhere in the future. Don't really like to depend on such a constant, but got to do something.