Introduction
In the last time I have seen a couple of questions on the forums about how to parse smilies, so I decided to write a tutorial on it, but since BBcodes are related to smilies I decided to put that in my tutorial as well.
In this tutorial we will create a class that will take care of the conversion from BBcode to XHTML 1.1 compliant code and it will be able to parse smilies into images.
Please note that this tutorial will expect some basic knowledge about classes and OOP. If you are unfamiliar with that subject you may see my tutorial called Introduction to Object Oriented Programming in PHP4. A bit of regular expression knowledge would be useful as well.
The parser will have the following features
* Parse smileys
* Parse BBcodes:
o Links
o Email links
o Bold
o Italic
o Underline
o Center (alignment)
o Right (alignment)
o Images
* XHTML 1.1 compliant code
The initial class
We will start by creating our class, a constructor for it, make some options and create the functions we will need:
CODE
<?php
class parser
{
var $parse_bbcodes; // Boolean - true = on | false = off
var $parse_smilies; // Boolean - true = on | false = off
var $smiley_url; // String - sets the URL to the smiley folder
function parser()
{
// Set some default values:
$this->parse_bbcodes = true;
$this->parse_smilies = true;
$this->smiley_url = "/smileys";
}
function parse($data)
{
}
function _parse_bbcodes($data)
{
}
function _parse_smilies($data)
{
}
}
?>
The first function (parser) is the constructor. It is run when an object of the class parser is created. The second function will be the function that the user will call, with the text to parse in the parameter called $data. The next too functions is called by the function parse and will parse bbcodes and smilies, respectively.
Creating the parse function
The parse function is very simple:
CODE
function parse($data)
{
$data = htmlentities($data);
if($this->parse_bbcodes)
{
$data = $this->_parse_bbcodes($data);
}
if($this->parse_smilies)
{
$data = $this->_parse_smilies($data);
}
$data = nl2br($data);
return $data;
}
The nl2br function converts linebreaks to HTML linebreaks. The htmlentities function makes sure that any HTML code the user input will just be shown. The rest should be fairly simple.
Parsing smilies
First I will start by showing you the entire parse smilies function, the I will tell about it:
CODE
function _parse_smilies($data)
{
$smilies = array(
':)' => 'smile.gif',
':(' => 'sad.gif',
);
if(substr($this->smiley_url,-1) != '/' && !empty($this->smiley_url))
{
$this->smiley_url .= '/';
}
foreach($smilies as $code => $image)
{
$data = str_replace($code,"<img src='{$this->smiley_url}{$image}' alt='{$code}' />",$data);
}
return $data;
}
First we have an array of smilies where the key is the code, and the value is the filename. Next we will check if the smiley url has a trailing slash, else we will add it. Then we run through each smiley and replace the code with an image. Finally we return the data again.
Parsing the BBcodes
Parsing the BBcodes is probably the most complex thing in this tutorial (not too complex though). First the entire function:
CODE
function _parse_bbcodes($data)
{
$data = preg_replace("`[(b|i|u|url|mail|img|center|right)][/(b|i|u|url|mail|img|center|right)]`",'',$data);
$data = preg_replace("`[url](.*)[/url]`sUi","<a href='\1'>\1</a>",$data);
$data = preg_replace("`[url=(.*)](.*)[/url]`sUi","<a href='\1'>\2</a>",$data);
$data = preg_replace("`[mail](.*)[/mail]`sUi","<a href='mailto:\1'>\1</a>",$data);
$data = preg_replace("`[mail=(.*)](.*)[/mail]`sUi","<a href='mailto:\1'>\2</a>",$data);
$data = preg_replace("`[b](.*)[/b]`sUi","<span style='font-weight: bold;'>\1</span>",$data);
$data = preg_replace("`[i](.*)[/i]`sUi","<span style='font-style: italic;'>\1</span>",$data);
$data = preg_replace("`[u](.*)[/u]`sUi","<span style='text-decoration: underline;'>\1</span>",$data);
$data = preg_replace("`[center](.*)[/center]`sUi","<div style='text-align: center;'>\1</div>",$data);
$data = preg_replace("`[right](.*)[/right]`sUi","<div style='text-align: right;'>\1</div>",$data);
$data = preg_replace("`[img](.*)[/img]`sUi","<img src='\1' alt='Posted Image' style='border: 0px;' />",$data);
return $data;
}
The first function removes BBcode tags with nothing in them, just to make the output smaller. The next functions deals with: URLs, email links, bold, italic, underline, center (alignment), right (alignment) and images.
You could extend this with colors, sizes, other fonts, ordered lists and unorders lists and lots of other things.
For more information about regular expressions, consult the PHP manual on Regular Expression Functions
Full code
For your convenience I will show you the entire code on this page:CODE
<?php
class parser
{
var $parse_bbcodes; // Boolean - true = on | false = off
var $parse_smilies; // Boolean - true = on | false = off
var $smiley_url; // String - sets the URL to the smiley folder
function parser()
{
// Set some default values:
$this->parse_bbcodes = true;
$this->parse_smilies = true;
$this->smiley_url = "/smileys";
}
function parse($data)
{
$data = htmlentities($data);
if($this->parse_bbcodes)
{
$data = $this->_parse_bbcodes($data);
}
if($this->parse_smilies)
{
$data = $this->_parse_smilies($data);
}
$data = nl2br($data);
return $data;
}
function _parse_bbcodes($data)
{
$data = preg_replace("`[(b|i|u|url|mail|img|center|right)][/(b|i|u|url|mail|img|center|right)]`",'',$data);
$data = preg_replace("`[url](.*)[/url]`sUi","<a href='\1'>\1</a>",$data);
$data = preg_replace("`[url=(.*)](.*)[/url]`sUi","<a href='\1'>\2</a>",$data);
$data = preg_replace("`[mail](.*)[/mail]`sUi","<a href='mailto:\1'>\1</a>",$data);
$data = preg_replace("`[mail=(.*)](.*)[/mail]`sUi","<a href='mailto:\1'>\2</a>",$data);
$data = preg_replace("`[b](.*)[/b]`sUi","<span style='font-weight: bold;'>\1</span>",$data);
$data = preg_replace("`[i](.*)[/i]`sUi","<span style='font-style: italic;'>\1</span>",$data);
$data = preg_replace("`[u](.*)[/u]`sUi","<span style='text-decoration: underline;'>\1</span>",$data);
$data = preg_replace("`[center](.*)[/center]`sUi","<div style='text-align: center;'>\1</div>",$data);
$data = preg_replace("`[right](.*)[/right]`sUi","<div style='text-align: right;'>\1</div>",$data);
$data = preg_replace("`[img](.*)[/img]`sUi","<img src='\1' alt='Posted Image' style='border: 0px;' />",$data);
return $data;
}
function _parse_smilies($data)
{
$smilies = array(
':)' => 'smile.gif',
':(' => 'sad.gif',
);
if(substr($this->smiley_url,-1) != '/' && !empty($this->smiley_url))
{
$this->smiley_url .= '/';
}
foreach($smilies as $code => $image)
{
$data = str_replace($code,"<img src='{$this->smiley_url}{$image}' alt='{$code}' />",$data);
}
return $data;
}
}
?>
Testing the code:
You may use this to test the parser. Remember to change parser.php to something else if you named your parser file something else. Note that you will have to actually create some smiley images, add them to your array and define the smiley url before you can use the parser to parse smileys. Else you may just view the HTML source to see that it has actually parsed it.
CODE
<?php
include 'parser.php';
$parser = new parser();
$default_text = <<<EOF
This is a sample text. [url=http://phpfreaks.com]PHP Freaks[/url] is a PHP website :)
[b]bold[/b] [b]bold again[/b] [i]italic[/i] [u]underline[/u]
left
[center]center[/center]
[right]right[/right]
[url]http://phpfreaks.com[/url]
[mail=somebody@example.com]Somebody's mail[/mail]
[mail]somebody@example.com[/mail]
[center][url=http://google.com][img]http://www.google.com/intl/en/images/logo.gif[/img][/url][/center]
EOF;
$text = !empty($_POST['text']) ? $_POST['text'] : $default_text;
$ps_checked = (bool)$_POST['parse_smilies'] ? " checked='checked'" : null;
$pbbc_checked = (bool)$_POST['parse_bbcodes'] ? " checked='checked'" : null;
echo <<<EOF
<form action='{$_SERVER['REQUEST_URI']}' method='post'>
<label><input type='checkbox' name='parse_smilies' value='1'{$ps_checked}> Parse smilies</input></label><br />
<label><input type='checkbox' name='parse_bbcodes' value='1'{$pbbc_checked}> Parse BBcodes</input></label><br /><br />
<label>Text to parse:<br /><textarea cols='10' rows='15' style='width: 100%;' name='text'>{$text}</textarea></label><br /><br />
<button type='submit'>Parse text</button>
</form>
EOF;
if(!empty($_POST['text']))
{
$parser->parse_smilies = (bool) $_POST['parse_smilies'];
$parser->parse_bbcodes = (bool) $_POST['parse_bbcodes'];
$text = $parser->parse($_POST['text']);
echo <<<EOF
<hr />
<div style='overflow: auto; height: 200px;'>{$text}</div>
EOF;
}
?>
Conclusion
This is the end of my smilies and BBcodes tutorial. You should have learned something about regular expressions, perhaps a little bit about OOP and of course how you make a smiley and BBcode converter.
Happy Programming.