BB Code Parser
Item 1 of 9
1 <?php 2 3 /** 4 * Class: BB Code Parser 5 * 6 * Parses a text document with BB code into HTML 7 * 8 * @author Dan Pupius 9 * @version 1.1 10 * @copyright ©2004 Daniel Pupius <http://pupius.co.uk> 11 * @filesource 12 */ 13 class BB_Parser { 14 15 /** 16 * @var boolean Whether or not to allow images 17 * @access private 18 */ 19 var $_allow_images = true; 20 21 /** 22 * @var boolean Whether or not to allow links 23 * @access private 24 */ 25 var $_allow_links = true; 26 27 /** 28 * @var boolean Whether or not to allow formatting such as bold, italic, underline 29 * @access private 30 */ 31 var $_allow_formatting = true; 32 33 /** 34 * @var boolean Whether to escape html characters before BB parse 35 * @access private 36 */ 37 var $_allow_html = false; 38 39 /** 40 * @var boolean Whether to convert line breaks into html line breaks 41 * @access private 42 */ 43 var $_convert_nl2br = true; 44 45 /** 46 * @var boolean Whether to wrap content in <p> tags 47 * @access private 48 */ 49 var $_force_paragraph = true; 50 51 /** 52 * @var boolean Make quotes and apostrophe's pretty 53 * @access private 54 */ 55 var $_pretty_chars = true; 56 57 58 /*****************************************************************************************/ 59 60 61 62 /** 63 * Setter and getter for allow images 64 * 65 * @param boolean $val True/False 66 * @access public 67 */ 68 function set_allow_images($val) { $this->_allow_images = ($val)?true:false; } 69 function get_allow_images($val) { return $this->_allow_images; } 70 71 72 /** 73 * Setter and getter for allow links 74 * 75 * @param boolean $val True/False 76 * @access public 77 */ 78 function set_allow_links($val) { $this->_allow_links = ($val)?true:false; } 79 function get_allow_links($val) { return $this->_allow_links; } 80 81 82 /** 83 * Setter and getter for allow formatting 84 * 85 * @param boolean $val True/False 86 * @access public 87 */ 88 function set_allow_formatting($val) { $this->_allow_formatting = ($val)?true:false; } 89 function get_allow_formatting($val) { return $this->_allow_formatting; } 90 91 92 /** 93 * Setter and getter for allow html 94 * 95 * @param boolean $val True/False 96 * @access public 97 */ 98 function set_allow_html($val) { $this->_allow_html = ($val)?true:false; } 99 function get_allow_html($val) { return $this->_allow_html; } 100 101 102 /** 103 * Setter and getter for convert nl2br 104 * 105 * @param boolean $val True/False 106 * @access public 107 */ 108 function set_convert_nl2br($val) { $this->_convert_nl2br = ($val)?true:false; } 109 function get_convert_nl2br($val) { return $this->_convert_nl2br; } 110 111 /** 112 * Setter and getter for convert force_paragraph 113 * 114 * @param boolean $val True/False 115 * @access public 116 */ 117 function set_para($val) { $this->_force_paragraph = ($val)?true:false; } 118 function get_para($val) { return $this->_force_paragraph; } 119 120 /*****************************************************************************************/ 121 122 /** 123 * Formats a string of code by adding line numbers to the start 124 * 125 * @param string $code Code of some kind 126 * @return string formatted 127 * @access public 128 */ 129 function format_code($code) { 130 $code = str_replace("“",""",$code); 131 $code = str_replace("”",""",$code); 132 $code = str_replace("’","'",$code); 133 134 $lines = split("\n",$code); 135 136 $count = 1; 137 foreach($lines as $key => $val) { 138 if($count < 10) $no = "<span class=\"linenumber\">$count</span> "; 139 else if($count < 100) $no = "<span class=\"linenumber\">$count</span> "; 140 else if($count < 1000) $no = "<span class=\"linenumber\">$count</span> "; 141 142 $lines[$key] = $no . $val; 143 $count++; 144 } 145 return implode("\n",$lines); 146 } 147 148 149 /** 150 * Creates an image tag for an image 151 * 152 * @param string $img Image URL (relative to webroot or absolute) 153 * @return string formatted 154 * @access public 155 */ 156 function create_imgtag($img,$class="") { 157 if(strpos($img,"http://") === false) $url = $GLOBALS['url_base'] . $img; 158 else $url = $img; 159 160 $arr = getimagesize($url); 161 162 if($class!="") $class = " class=\"$class\""; 163 164 return "<img$class src=\"$img\" " . $arr[3] . " alt=\"$img\" />"; 165 166 } 167 168 169 170 /** 171 * Parses a string based on current settings and returns a processed version 172 * 173 * @param string $string String to process 174 * @return string Pricessed string 175 * @access public 176 */ 177 function parse($string,$firstclass="") { 178 179 180 181 //remove HTML 182 if(!$this->_allow_html) $string = htmlentities($string); 183 184 //convert line breaks 185 if($this->_convert_nl2br) $string = preg_replace("/\n/im","<br />\n",$string); 186 187 //make chars pretty before adding the html 188 if($this->_pretty_chars) { 189 $string = preg_replace("/\s* — \s*/"," — ",$string); 190 $string = preg_replace("/([a-zA-Z0-9])'([a-zA-Z0-9])/","\\1’\\2",$string); 191 $string = preg_replace("/([^a-zA-Z0-9])"([\[a-zA-Z0-9])/","\\1“\\2",$string); 192 $string = preg_replace("/([a-zA-Z0-9\]])"([^a-zA-Z0-9])/","\\1”\\2",$string); 193 } 194 195 //do basic formatting 196 if($this->_allow_formatting) { 197 $string = preg_replace("(\[b\](.+?)\[\/b])is",'<strong>$1</strong>',$string); 198 $string = preg_replace("(\[i\](.+?)\[\/i])is",'<em>$1</em>',$string); 199 $string = preg_replace("(\[u\](.+?)\[\/u])is",'<span style=\"text-decoration:underline\">$1</span>',$string); 200 $string = preg_replace("(\[s\](.+?)\[\/s])is",'<span style=\"text-decoration:line-through\">$1</span>',$string); 201 $string = preg_replace("(\[size=(.+?)\](.+?)\[\/size\])is","<span style=\"font-size: $1px\">$2</span>",$string); 202 203 $string = preg_replace("/\[quote\](.+?)\[\/quote\]/is","</p>\n<p class=\"quote\">$1</p>\n<p>", $string); 204 $string = preg_replace("/\[code\](.+?)\[\/code\]/ise","'</p>\n<pre class=\"code\">'.BB_Parser::format_code('$1').'</pre>\n<p>'", $string); 205 } 206 207 if($this->_allow_links) { 208 $url_chars = " a-zA-Z0-9\:\/\-\?\&\.\=\_\~\#\'\%"; 209 $mail_chars = $url_chars . "@"; 210 211 //convert urls 212 $string = preg_replace("/\[url\](.*?)\[\/url\]/", '<a href="$1">$1</a>', $string); 213 $string = preg_replace("(\[url href\=(.*?)\](.*?)\[/url\])", '<a href="$1">$2</a>', $string); 214 $string = preg_replace("(\[url class\=(.*?) href\=(.*?)\](.*?)\[/url\])", '<a class="$1" href="$2">$3</a>', $string); 215 216 217 //convert images 218 $string = preg_replace("/\[img\](.+?)\[\/img\]/ise","BB_Parser::create_imgtag('$1')", $string); 219 $string = preg_replace("/\[img class\=(.*?)\](.+?)\[\/img\]/ise","BB_Parser::create_imgtag('$2','$1')", $string); 220 221 //convert emails 222 //$string = preg_replace("/\[email\](.*?)\[\/email\]/", '<a class="email" href="mailto:$1">$1</a>', $string); 223 //$string = preg_replace("/([email to\=(.*?)\](.*?)\[/email\])e", "'<a class=\"email\" href=\"mailto:'.urlencode('$1').'\">$2</a>'", $string); 224 } 225 226 //make sure string is in a paragraph 227 if($firstclass!="" && $this->_force_paragraph) $string = "\n<p class=\"$firstclass\">$string</p>\n\n"; 228 else if($this->_force_paragraph) $string = "\n<p>$string</p>\n\n"; 229 230 //but remove empty paragraphs just in case 231 $string = str_replace("<p></p>","",$string); 232 233 return $string; 234 } 235 236 237 /** 238 * Echos the parsed string 239 * 240 * @param string $string String to process 241 * @access public 242 */ 243 function output($string,$firstclass="") { echo $this->parse($string,$firstclass); } 244 245 } 246 247 /* 248 $bb = new BB_Parser; 249 $bb->output(' 250 [email to=dan@pupius.co.uk]Email me[/email] 251 [email]dan@pupius.co.uk[/email] 252 [url class=external href=http://www.bbc.co.uk]BBC News[/url] 253 '); 254 */ 255 256 ?> 257