The advantage to using BBCode instead of allowing XHTML in user input is that it allows users to safely format their content without the risk of invalid code breaking the page formatting. It also tends to be easier to understand BBCode over XHTML due to its simplified syntax.
Anyway, here is how we'll do it. We're going to use the preg_replace function to convert the text using regex patterns. This function accepts both strings or arrays as patterns and replacements, so this allows us to convert all types of BBCode in one call of the function. We just create an indexed array of regex patterns and a matching array of replacements, so that's what we'll to first:
Code: Select all
// The array of regex patterns to look for
$format_search = array(
'#\[b\](.*?)\[/b\]#is', // Bold ([b]text[/b]
'#\[i\](.*?)\[/i\]#is', // Italics ([i]text[/i]
'#\[u\](.*?)\[/u\]#is', // Underline ([u]text[/u])
'#\[s\](.*?)\[/s\]#is', // Strikethrough ([s]text[/s])
'#\[quote\](.*?)\[/quote\]#is', // Quote ([quote]text[/quote])
'#\[code\](.*?)\[/code\]#is', // Monospaced code [code]text
'#\[size=([1-9]|1[0-9]|20)\](.*?)\[/size\]#is', // Font size 1-20px text)
'#\[color=\#?([A-F0-9]{3}|[A-F0-9]{6})\](.*?)\[/color\]#is', // Font color (text)
'#\(.*?)\[/url\]#i', // Hyperlink with descriptive text ([url=http://url]text)
'#\[url\]((?:ftp|https?)://.*?)\[/url\]#i', // Hyperlink (http://url)
'#\[img\](https?://.*?\.(?:jpg|jpeg|gif|png|bmp))\[/img\]#i' // Image ([img]http://url_to_image[/img])
);
// The matching array of strings to replace matches with
$format_replace = array(
'<strong>$1</strong>',
'<em>$1</em>',
'<span style="text-decoration: underline;">$1</span>',
'<span style="text-decoration: line-through;">$1</span>',
'<blockquote>$1</blockquote>',
'<pre>$1</'.'pre>',
'<span style="font-size: $1px;">$2</span>',
'<span style="color: #$1;">$2</span>',
'<a href="$1">$2</a>',
'<a href="$1">$1</a>',
'<img src="$1" alt="" />'
); [/code]
As you can see, $format_search is a list of regex patters (read the comments to see what each one does) and $format_replace is a list of the XHTML versions.
More about the regex used here:
We used '#' as the opening and closing delimiters instead of the usual '/' so we don't have to escape the '/' with a backslash
The characters after the closing '#' are modifiers, 'i' makes it case insensitive and 's' makes the search work across multiple lines
(.*?) matches any and all characters up to the first instance of the next part of the pattern (i.e. '(.*?)[/b]' matches everything until it finds '[/b]')
In the replacements, '$1' matches the first parenthesized part of the pattern, '$2' the second, etc.
All we have to do now is pass these arrays to the function:
Code: Select all
$str = preg_replace($format_search, $format_replace, $str);
Code: Select all
function bbcode_format($str){
// Convert all special HTML characters into entities to display literally
$str = htmlentities($str);
// The array of regex patterns to look for
$format_search = array(
'#\[b\](.*?)\[/b\]#is', // Bold ([b]text[/b]
'#\[i\](.*?)\[/i\]#is', // Italics ([i]text[/i]
'#\[u\](.*?)\[/u\]#is', // Underline ([u]text[/u])
'#\[s\](.*?)\[/s\]#is', // Strikethrough ([s]text[/s])
'#\[quote\](.*?)\[/quote\]#is', // Quote ([quote]text[/quote])
'#\[code\](.*?)\[/code\]#is', // Monospaced code [code]text
'#\[size=([1-9]|1[0-9]|20)\](.*?)\[/size\]#is', // Font size 1-20px text)
'#\[color=\#?([A-F0-9]{3}|[A-F0-9]{6})\](.*?)\[/color\]#is', // Font color (text)
'#\(.*?)\[/url\]#i', // Hyperlink with descriptive text ([url=http://url]text)
'#\[url\]((?:ftp|https?)://.*?)\[/url\]#i', // Hyperlink (http://url)
'#\[img\](https?://.*?\.(?:jpg|jpeg|gif|png|bmp))\[/img\]#i' // Image ([img]http://url_to_image[/img])
);
// The matching array of strings to replace matches with
$format_replace = array(
'<strong>$1</strong>',
'<em>$1</em>',
'<span style="text-decoration: underline;">$1</span>',
'<span style="text-decoration: line-through;">$1</span>',
'<blockquote>$1</blockquote>',
'<pre>$1</'.'pre>',
'<span style="font-size: $1px;">$2</span>',
'<span style="color: #$1;">$2</span>',
'<a href="$1">$2</a>',
'<a href="$1">$1</a>',
'<img src="$1" alt="" />'
);
// Perform the actual conversion
$str = preg_replace($format_search, $format_replace, $str);
// Convert line breaks in the <br /> tag
$str = nl2br($str);
return $str;
} [/code]
This is just a simple implementation of regular expressions to find and replace special character sequences. You may want to improve the replacement format for things like quotes or code blocks to make them more useful. You can also add CSS classes to the replacements to make things look nice.