PDA

View Full Version : Parse BBCode in new messages forum block ?


Mornagest
01-14-2016, 09:44 AM
Hello,

I'm using the sidebar on my forum, that uses forum blocks to show last threads, random image from members albums, and so on.

We have a little problem with BBCode, which is not parsed in the sidebar blocks. For example, if I write this text in red and italic, it will be displayed like this in the sidebar :

if I write this text in red and italic

According to that message (http://www.vbulletin.com/forum/forum/vbulletin-4/vbulletin-4-questions-problems-and-troubleshooting/420020-showing-forum-smilies-on-sidebar-as-well?p=3630649#post3630649), it isn't possible to parse BBCode in sidebar without modification, so, that's why I ask this here...

I hope I'm clear enough :o

Many thanks for your answers !

MarkFL
01-14-2016, 03:20 PM
Are you using a custom "Forum Block" to display the content of recent posts in the sidebar?

Is the post content actually displayed, or is it available as a tooltip?

Are you showing the entire post, or a truncated preview? If it is truncated, then you run into the issue of "orphaned" BBCode/HTML tags.

Can you post a screenshot of your forum block displaying post content?

Mornagest
01-14-2016, 05:04 PM
Hi Mark, and thank you for your answer ! :)

The forum block is by default, the one that shows new messages.

The post content is showing, but truncated (as shown in the attached image).

As far as I understand, because of this truncation, the BBCode end tags aren't considered so the tags aren't parsed ?

In the attachment, the text "Qu?te les dessous de Port-Couchant" and so on... is supposed to be in italic.

Is there a fix ? Please consider that we introduced some custom tags, and I don't know if we could fix this for those custom tags...

Thank you !

MarkFL
01-14-2016, 06:10 PM
I think that to get the default "New Forum Posts" block to parse BBCodes, a core file would have to be edited. I try to avoid this whenever possible. If you set about editing your core files, then these edits have to be made each time you upgrade vBulletin.

The other alternative would be to create a custom forum block that roughly duplicates the default block's function, and then you could manipulate the post text however you want, including calling the BBCode parsing function and handling potentially orphaned tags if you choose to truncate the content. Another alternative for long posts would be to put the post content in an element with a maximum height, and a vertical scrollbar is introduced as needed.

Let me know your thoughts on these issues, and I will see what I can do with it. :)

Mornagest
01-14-2016, 06:57 PM
I wouldn't want to edit core files as I'm not sure to avoid damages on my forum...

So maybe the custom forum block is the best way. Anyway, I would like very much to truncate too long messages, as some members send veeeery long posts (as there is a roleplay part on our forum). If this is possible to keep the truncation and close orphan tags, this would be the best for our use !

Again, many thanks, Mark ;)

MarkFL
01-16-2016, 04:37 AM
Here is how I configured the custom block:

https://vborg.vbsupport.ru/attachment.php?attachmentid=154027&stc=1&d=1452925677

And this is the "Content":

global $vbulletin, $db;

require_once('./includes/functions_user.php');
require_once('./includes/class_bbcode.php');
$bbcode_parser = new vB_BbCodeParser($vbulletin, fetch_tag_list());

$number_of_posts = 5;
$post_length = 25;

$output = '<ul class="restore">';

$recent_posts = $vbulletin->db->query_read("
SELECT post.*, thread.title, thread.forumid
FROM " . TABLE_PREFIX . "post AS post
INNER JOIN " . TABLE_PREFIX . "thread AS thread
ON thread.threadid = post.threadid
ORDER BY post.dateline DESC
");

$pcount = 0;

while ($tpost = $db->fetch_array($recent_posts) AND $pcount < $number_of_posts)
{
if (($vbulletin->userinfo['forumpermissions'][$tpost['forumid']] & $vbulletin->bf_ugp_forumpermissions['canview']) AND (($tpost['visible'] == 1) OR can_moderate($tpost['forumid'])))
{
$pcount++;
$avatar_url = fetch_avatar_url($tpost['userid']);
$avatar = $avatar_url[0];

if (!$avatar)
{
$avatar = './images/misc/unknown.gif';
}

$tpost['title'] = fetch_censored_text($tpost['title']);
$tpost['pagetext'] = $bbcode_parser->parse($tpost['pagetext'], $tpost['forumid'], $tpost['allowsmilie']);
$tpost['pagetext'] = html_entity_decode($tpost['pagetext']);
$tpost['pagetext'] = Html::trim($tpost['pagetext'], $post_length);

$output .= '<li class="avatarcontent floatcontainer widget_post_bit">';
$output .= '<div class="widget_post_userinfo">';
$output .= '<div class="cms_widget_post_useravatar widget_post_useravatar">';
$output .= '<a class="smallavatar comments_member_avatar_link" href="member.php?' . $tpost['userid'] . '-' . $tpost['username'] . '">';
$output .= '<img alt="' . $tpost['username'] . '" src="' . $avatar . '" title="' . $tpost['username'] . '">';
$output .= '</a></div></div>';
$output .= '<div class="smallavatartext widget_post_comment">';
$output .= '<p class="widget_post_content">';
$output .= $tpost['pagetext'];
$output .= '</p><h5 class="widget_post_header">';
$output .= '<a class="title" href="showthread.php?' . $tpost['threadid'] . '-' . str_replace(' ', '-', $tpost['title']) . '&p=' . $tpost['postid'] . '#post' . $tpost['postid'] . '">' . $tpost['title'] . '</a>';
$output .= '</h5><div class="meta">';
$output .= vbdate($vbulletin->options['dateformat'], $tpost['dateline'], 1) . ',';
$output .= '<span class="time">';
$output .= vbdate($vbulletin->options['timeformat'], $tpost['dateline']);
$output .= '</span><br></div></div></li>';
}
}

unset ($recent_posts);
$output .= '</ul>';
return $output;

class Html{

protected
$reachedLimit = false,
$totalLen = 0,
$maxLen = 25,
$toRemove = array();

public static function trim($html, $maxLen = 25){

$dom = new DomDocument();
$dom->loadHTML($html);

$html = new static();
$toRemove = $html->walk($dom, $maxLen);

// remove any nodes that passed our limit
foreach($toRemove as $child)
$child->parentNode->removeChild($child);

// remove wrapper tags added by DD (doctype, html...)
if(version_compare(PHP_VERSION, '5.3.6') < 0){
// http://stackoverflow.com/a/6953808/1058140
$dom->removeChild($dom->firstChild);
$dom->replaceChild($dom->firstChild->firstChild->firstChild, $dom->firstChild);
return $dom->saveHTML();
}

return $dom->saveHTML($dom->getElementsByTagName('body')->item(0));
}

protected function walk(DomNode $node, $maxLen){
if($this->reachedLimit){
$this->toRemove[] = $node;
}else{
// only text nodes should have text,
// so do the splitting here
if($node instanceof DomText){
$this->totalLen += $nodeLen = strlen($node->nodeValue);

// use mb_strlen / mb_substr for UTF-8 support
if($this->totalLen > $maxLen){
$node->nodeValue = substr($node->nodeValue, 0, $nodeLen - ($this->totalLen - $maxLen)) . '...';
$this->reachedLimit = true;
}
}

// if node has children, walk its child elements
if(isset($node->childNodes))
foreach($node->childNodes as $child)
$this->walk($child, $maxLen);
}

return $this->toRemove;
}
}

Near the top, you can control how many posts a user will see, and how many characters of the post will be displayed, by altering these two lines:

$number_of_posts = 5;
$post_length = 25;


Users will only see posts they have permission to see. Give this a try and let me know how it works for you. :)

Note: You must have PHP version 5.3 or higher in order for this to work.

Mornagest
01-16-2016, 10:24 AM
Hello Mark, and thank you for your help ! :)

It seems to work properly, except for the character encoding. I'm not accustomed with this but I guess this is a conflict between UTF-8 and ISO-8859.

Here are some examples of those errors :

- Débat autour de suppression [...]
- J'ai reçu un mp d'un nouveau [...]
- L?’homme tomba [...]

Any idea ?

Thank you again !

MarkFL
01-16-2016, 12:24 PM
Okay, try changing:

$tpost['pagetext'] = html_entity_decode($tpost['pagetext']);

to:

$tpost['pagetext'] = htmlentities($tpost['pagetext'], ENT_QUOTES, 'ISO-8859-15');
$tpost['pagetext'] = html_entity_decode($tpost['pagetext'], ENT_QUOTES, 'ISO-8859-15');

--------------- Added 1452962816 at 1452962816 ---------------

Here's a version that will show complete posts within a scrollable element, and if you have my acronym and username markup products installed, it will parse those as well:

global $vbulletin, $db;

require_once('./includes/functions_user.php');
require_once(DIR . '/includes/class_bbcode.php');
$bbcode_parser = new vB_BbCodeParser($vbulletin, fetch_tag_list());

$number_of_posts = 10;

$output = '<ul class="restore">';

$recent_posts = $vbulletin->db->query_read("
SELECT post.*, thread.title, thread.forumid
FROM " . TABLE_PREFIX . "post AS post
INNER JOIN " . TABLE_PREFIX . "thread AS thread
ON thread.threadid = post.threadid
ORDER BY post.dateline DESC
");

$pcount = 0;

while ($tpost = $db->fetch_array($recent_posts) AND $pcount < $number_of_posts)
{
if (($vbulletin->userinfo['forumpermissions'][$tpost['forumid']] & $vbulletin->bf_ugp_forumpermissions['canview']) AND (($tpost['visible'] == 1) OR can_moderate($tpost['forumid'])))
{
$pcount++;
$avatar_url = fetch_avatar_url($tpost['userid']);
$avatar = $avatar_url[0];

if (!$avatar)
{
$avatar = $vbulletin->stylevars['imgdir_misc']['imagedir'] . '/unknown.gif';
}

$tpost['title'] = fetch_censored_text($tpost['title']);
$tpost['pagetext'] = $bbcode_parser->parse($tpost['pagetext'], $tpost['forumid'], $tpost['allowsmilie']);
$tpost['pagetext'] = str_replace('<p>', '', $tpost['pagetext']);
$tpost['pagetext'] = str_replace('</p>', '', $tpost['pagetext']);
$tpost['pagetext'] = htmlentities($tpost['pagetext'], ENT_QUOTES, 'ISO-8859-15');
$tpost['pagetext'] = html_entity_decode($tpost['pagetext'], ENT_QUOTES, 'ISO-8859-15');
if ($vbulletin->options['markfl_unm_active'])
{
require_once('./usernamemarkup.php');
$tpost['pagetext'] = parse_unm($tpost['pagetext']);
}
if ($vbulletin->options['markfl_thread_active'] AND $vbulletin->options['markfl_acrojax_enable'] AND $vbulletin->options['markfl_acrojax_list'])
{
require_once('./acronyms.php');
if (do_acronyms())
{
if (strpos($vbulletin->options['markfl_acrojax_areas'], 'Posts') !== false)
{
$tpost['pagetext'] = parse_acronyms($tpost['pagetext']);
}
}
}

$output .= '<li class="avatarcontent floatcontainer widget_post_bit">';
$output .= '<div class="widget_post_userinfo">';
$output .= '<div class="cms_widget_post_useravatar widget_post_useravatar">';
$output .= '<a class="smallavatar comments_member_avatar_link" href="member.php?do=getinfo&username=' . $tpost['username'] . '">';
$output .= '<img alt="' . $tpost['username'] . '" src="' . $avatar . '" title="' . $tpost['username'] . '">';
$output .= '</a></div></div>';
$output .= '<div class="smallavatartext widget_post_comment">';
$output .= '<div style="max-height: 100px; overflow: auto; background: #E8FFE8;" class="widget_post_content">';
$output .= $tpost['pagetext'];
$output .= '</div><h5 class="widget_post_header">';
$output .= '<a class="title" href="showthread.php?' . $tpost['threadid'] . '-' . str_replace(' ', '-', $tpost['title']) . '&p=' . $tpost['postid'] . '#post' . $tpost['postid'] . '">' . $tpost['title'] . '</a>';
$output .= '</h5><div class="meta">';
$output .= vbdate($vbulletin->options['dateformat'], $tpost['dateline'], 1) . ',';
$output .= '<span class="time">';
$output .= vbdate($vbulletin->options['timeformat'], $tpost['dateline']);
$output .= '</span><br></div></div></li>';
}
}

unset ($recent_posts);
$output .= '</ul>';
return $output;

Mornagest
01-16-2016, 07:29 PM
Hello Mark,

I tried but this changed nothing. Out of curiosity, I tried with 'UTF-8' instead and the message preview doesn't appear, only the link to the post and the name of the member who posted.

I forgot to mention that our server runs on Ubuntu, so the encoding may be UTF-8 ?

Thank you again ! :)

MarkFL
01-16-2016, 07:40 PM
Hello Mark,

I tried but this changed nothing. Out of curiosity, I tried with 'UTF-8' instead and the message preview doesn't appear, only the link to the post and the name of the member who posted.

I forgot to mention that our server runs on Ubuntu, so the encoding may be UTF-8 ?

Thank you again ! :)

I have access to both a Windows and a Linux server, and it parses special characters with no problem on both. Since I cannot duplicate the issue you are having, I would have to come to your site to see what I have to do to get it running for you.

Send the credentials for a temporary admin account to me by PM, and I can take a look within the next several days at the latest.

Mornagest
01-16-2016, 07:55 PM
I sent you this PM :) thanks !

MarkFL
01-18-2016, 03:47 PM
Just to follow up, I had to use the "scrollable" code in post #8 on the OP's site (minus the background color) because the code to truncate the post content would not work with UTF-8 encoding. :)

Mornagest
01-18-2016, 07:04 PM
Aow, I wanted to like that post but I cannot like two posts from one member in a row... it's the thought that counts !

MarkFL
02-24-2016, 04:15 AM
Aow, I wanted to like that post but I cannot like two posts from one member in a row... it's the thought that counts !

I have finally turned this into a product, found here:

Forum Sideblock - Recent Posts (with BBCodes parsed) (https://vborg.vbsupport.ru/showthread.php?t=321920)

I listed you as a co-author as promised. :)