PDA

View Full Version : BBCode Parser



MRushton
11-02-2010, 09:45 AM
/**
* A class to allow easy parsing of BBCode
*
* @author Michael Rushton <michael@squiloople.com>
* @version 1.0
* @copyright 2010 Michael Rushton - http://squiloople.com
*
* Feel free to use and redistribute this code
*/

namespace Parsers;

final class BBCodeParser
{

/**
* Array to contain regular expressions of BB tags
*
* @access private
* @var array
*/

private $_bbTags = array(

'/\([\x20-\x7E]+?)\[\/b\]/i',
'/\([\x20-\x7E]+?)\[\/i\]/i',
'/\[u\]([\x20-\x7E]+?)\[\/u\]/i',
'/\[s\]([\x20-\x7E]+?)\[\/s\]/i',
'/\[sub\]([\x20-\x7E]+?)\[\/sub\]/i',
'/\[sup\]([\x20-\x7E]+?)\[\/sup\]/i',
'/\[img\]([\x20-\x7E]+?)\[\/img\]/i',
'/\[url\]([\x20-\x7E]+?)\[\/url\]/i',
'/\[email\]([\x20-\x7E]+?)\[\/email\]/i',
'/\[quote\]([\x20-\x7E]+?)\[\/quote\]/i',
'/\[color=([0-9a-f]{6})\]([\x20-\x7E]+?)\[\/color\]/i',
'/\[size=([1-9]?[0-9])\]([\x20-\x7E]+?)\[\/size\]/i',
'/\[font=([a-z\x20]+)\]([\x20-\x7E]+?)\[\/font\]/i',
'/\[img=([\x20-\x7E]+?)\]([\x20-\x7E]+?)\[\/img\]/i',
'/\+)\]([\x20-\x7E]+?)\[\/url\]/i',
'/\[email=([\x20-\x5A\x5C\x5E-\x7E]+)\]([\x20-\x7E]+?)\[\/email\]/i',
'/\[quote=([\x20-\x5A\x5C\x5E-\x7E]+)\]([\x20-\x7E]+?)\[\/quote\]/i',

);

/**
* Array to contain HTML tag replacements
*
* @access private
* @var array
*/

private $_htmlTags = array(

'<strong>$1</strong>',
'<em>$1</em>',
'<span style="text-decoration:underline">$1</span>',
'<del>$1</del>',
'<sub>$1</sub>',
'<sup>$1</sup>',
'<img src="$1" alt="" />',
'<a href="$1">$1</a>',
'<a href="mailto:$1">$1</a>',
'<fieldset>$1</fieldset>',
'<span style="color:#$1;background-color:transparent">$2</span>',
'<span style="font-size:$1px">$2</span>',
'<span style="font-family:\'$1\', sans-serif">$2</span>',
'<img src="$2" alt="$1" />',
'<a href="$1">$2</a>',
'<a href="mailto:$1">$2</a>',
'<fieldset><legend>$1</legend>$2</fieldset>',

);

/**
* Create "Text => <tag>Text</tag>" style BB tags
*
* @access public
* @param string
* @param string
*/

public function createTag($bb, $html = false)
{

// If an HTML tag is not specified, emulate the BB tag

$html = $html ?: $bb;

// Create a new BB tag regular expression of the form: Text

$this->_bbTags[] = '/\[' . $bb . '\]([\x20-\x7E]+?)\[\/' . $bb . '\]/i';

// Create a new HTML tag replacement of the form <tag>Text</tag>

$this->_htmlTags[] = '<' . $html . '>$1</' . $html . '>';

}

/**
* Create "Text => <tag option="option">Text</tag>" style BB tags
*
* @access public
* @param string
* @param string
*/

public function createParameterTag($bb, $html)
{

// Create a new BB tag regular expression of the form

$this->_bbTags[] = '/\[' . $bb . '=([\x20-\x5A\x5C\x5E-\x7E]+)\]([\x20-\x7E]+?)\[\/' . $bb . '\]/i';

// Create a new HTML tag replacement of the form <tag option="option">Text</tag>

$this->_htmlTags[] = '<' . $html . '>$2</' . strtok($html, ' ') . '>';

}

/**
* Create "[smile] => :)" style BB tags
*
* @access public
* @param string
* @param string
*/

public function createSpecialTag($bb, $html)
{

// Create a new BB tag regular expression of the form [tag] (does not require usual brackets)

$this->_bbTags[] = '/' . preg_quote($bb) . '/i';

// Create a new replacement (does not need to be an HTML tag)

$this->_htmlTags[] = $html;

}

/**
* Return the parsed string
*
* @access public
* @param string
* @return string
*/

public function parseString($string)
{

// Ensure that the loop runs at least once

$count = 1;

// Only replace tags if the string has not been fully parsed

while ($count !== 0) {

// Replace BB tags with HTML tags; will repeat if successful

$string = preg_replace($this->_bbTags, $this->_htmlTags, $string, -1, $count);

}

// Return the parsed string

return $string;

}

}


Usage example:



$stringParser = new BBCodeParser;

echo $stringParser->parseString('[url=http://example.com][b]Bold Example (([\x20-\x5A\x5C\x5E-\x7E)');

// <a href="http://example.com"><strong>Bold</strong></a>

$stringParser->createTag('p');
$stringParser->createTag('d', 'div');

echo $stringParser->parseString('[d]Paragraph 1Paragraph 2[/div]');

// <div><p>Paragraph 1</p><p>Paragraph 2</p></div>

$stringParser->createParameterTag('span', 'span id="$1"');

echo $stringParser->parseString('This has a parameter');

// <span id="special">This is special</span>

$stringParser->createSpecialTag(':)', '<img src="smile.png" alt="smile" />');

echo $stringParser->parseString('Look at my smile: :)');

// Look at my smile: <img src="smile.png" alt="smile" />


The default tags are:



Bold
Italics
[u]Underline
Strikethrough
Subscript
Superscript
image.png
http://example.com
michael@example.com

Quote
Red
15px
Arial
smile.png
Example (http://example.com)
Michael (michael@example.com)

Quote

SmoothieVemund
11-02-2010, 03:32 PM
Real cool. I want to use this in a textarea with a form. How can I do that?

<form action="post_massage.php" method="post">
<textarea rows="5" cols="55" name="post" wrap="physical">Enter your favorite quote!</textarea><br />
<input type="submit" />
</form>

MRushton
11-02-2010, 06:16 PM
If you're looking to insert/update a row into the table on the form submission, try this. Note, however, that where I have "new Parsers/BBCodeParser", it should say "new Parsers\BBCodeParser". Unfortunately, this forum seems to strip backslashes.




if (isset($_POST['post'])) {

require_once 'BBCodeParser.php';

$stringParser = new Parsers/BBCodeParser;

$parsedString = $mysqli->real_escape_string($stringParser->parseString($_POST['post']));

try {

if (!$mysqli->query("INSERT INTO `table` (`post`) VALUES ('" . $parsedString . "')") {
throw new Exception('Unable to insert the post into the database.');
}

}

catch (Exception $e) {
echo $e->getMessage();
}

}

MRushton
11-02-2010, 06:23 PM
To do list:

1. Include
tags which do not parse contents within
2. Enforce XHTML conformity
3. Make createOptionTag() more flexible (at the moment, to emulate the replacement for &#91;quote=parameter]Text&#91;/quote] one would need to do createOptionTag('quote', 'fieldset><legend>$1</legend'), which isn't very nice).
4. createTag(), createParameterTag(), and createSpecialTag() should return an array containing the BBCode regular expression and its HTML replacement.