| : | Javascript | : | PHP Index | : | MySQL | : |
| : | Source | : | : | Explanation | : | : | Example | : | : | Todo | : | : | Feedback | : |
A class that can parse ubb tags and convert them into html
Added: 2010-11-03 15:08:55
<?
/**
* Excudo UbbCode
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://devshed.excudo.net/license/new-bsd
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to marty@excudo.net so we can send you a copy immediately.
*
* @category Excudo
* @package UbbCode
* @copyright Copyright (c) 2005-2010 Excudo. (http://www.excudo.net)
* @license http://devshed.excudo.net/license/new-bsd New BSD License
*/
/***
* file: UbbCode.php
*/
/**
* Class that converts so called 'ubb' code tags into html
*
*/
class Excudo_UbbCode
{
/**
* Name used as index for the settings variable in which the flag is stored
* whether or not we want to perform the conversion for bold (strong) tags
* @see _settings
*/
const ENABLE_BOLD = 'bold';
/**
* Name used as index for the settings variable in which the flag is stored
* whether or not we want to perform the conversion for italic (em) tags
* @see _settings
*/
const ENABLE_ITALICS = 'italics';
/**
* Name used as index for the settings variable in which the flag is stored
* whether or not we want to perform the conversion for underline tags
* @see _settings
*/
const ENABLE_UNDERLINE = 'underline';
/**
* Name used as index for the settings variable in which the flag is stored
* whether or not we want to perform the conversion for image tags
* @see _settings
*/
const ENABLE_IMAGES = 'images';
/**
* Name used as index for the settings variable in which the flag is stored
* whether or not we want to perform the conversion for image tags
* @see _settings
*/
const ENABLE_LINKS = 'links';
/**
* Name used as index for the settings variable in which the flag is stored
* whether or not we want to perform the conversion for (un)ordered lists
* @see _settings
*/
const ENABLE_LISTS = 'list';
/**
* Name used as index for the settings variable in which the flag is stored
* whether or not we want to perform the conversion for colouring the text
* @see _settings
*/
const ENABLE_COLOURS = 'colours';
/**
* Name used as index for the settings variable in which the flag is stored
* whether or not we want to filter the input with php's htmlentities function
* @see _settings
*/
const ENABLE_ENTITIES = 'htmlentities';
/**
* Name used as index for the settings variable in which the flag is stored
* whether or not we want to filter the input with php's nl2br function
* (this will convert regular newlines into <br>s
* @see _settings
*/
const ENABLE_NL2BR = 'nl2br';
/**
* [b]text[/b]
*/
const REGEX_BOLD = "/(\[b\])(.*)(\[\/b\])/Usi";
/**
* [i]text[/i]
*/
const REGEX_ITALICS = "/(\[i\])(.*)(\[\/i\])/Usi";
/**
* [u]text[/u]
*/
const REGEX_UNDERLINE = "/(\[u\])(.*)(\[\/u\])/Usi";
/**
* [color=colorCode]text[/color]
*/
const REGEX_COLOURS = "/(\[color\s*=\s*(.+)\])(.*)(\[\/color\])/Usi";
/**
* cannot be triggered by a ubb-tag. it tries to generate nicer html by including the text colour in the previous html element
*/
const REGEX_COLOUR_FIX = "/(<(.+)>)(<span style=\"color:(.+)\">)(.+)(<\/span>)/Ui";
/**
* [url=some-url]linkname[/url]
*/
const REGEX_LINKS1 = "_\[url=(.+?)\](.+?)\[/url\]_si";
/**
* [url]some-url[/url]
*/
const REGEX_LINKS2 = "_\[url\](.+?)\[/url\]_si";
/**
* [img=url-image]image description[/img]
*/
const REGEX_IMAGES1 = "_\[img=(.+?)\](.+?)\[/img\]_si";
/**
* [img]url-image[/img]
*/
const REGEX_IMAGES2 = "_\[img\](.+?)\[/img\]_si";
/**
* [list]
* * unordered item 1
* * unordered item 2
* [/list]
* [list]
* # ordered item 1
* # ordered item 2
* [/list]
*/
const REGEX_LISTS = "/(\[list\])(.*)(\[\/list\])/Usi";
/**
* This array will determine which type of conversion we do
*
* @var array
*/
protected $_settings = array(
self::ENABLE_BOLD => true,
self::ENABLE_ITALICS => true,
self::ENABLE_UNDERLINE => true,
self::ENABLE_IMAGES => true,
self::ENABLE_LINKS => true,
self::ENABLE_COLOURS => true,
self::ENABLE_ENTITIES => true,
self::ENABLE_LISTS => true,
self::ENABLE_NL2BR => false,
);
/**
* Constructor.
*
* @param array $arr This array has to consist of the indexes that
*
* @return Excudo_UbbCode
*/
public function __construct(array $arr = array())
{
$this->setSettings($arr);
}
/**
* The function that will convert any string containing ubb-codes to a string containing the
* corresponding html0tags
*
* @param String $string String that needs to be converted
*
* @return String
*/
public function convert($string)
{
if ($this->_settings[self::ENABLE_ENTITIES])
{
$string = htmlspecialchars($string);
}
if ($this->_settings[self::ENABLE_BOLD])
{
$string = preg_replace(self::REGEX_BOLD, "<strong>\\2</strong>", $string);
}
if ($this->_settings[self::ENABLE_ITALICS])
{
$string = preg_replace(self::REGEX_ITALICS, "<em>\\2</em>", $string);
}
if ($this->_settings[self::ENABLE_UNDERLINE])
{
$string = preg_replace(self::REGEX_UNDERLINE, "<u>\\2</u>", $string);
}
if ($this->_settings[self::ENABLE_COLOURS])
{
$string = preg_replace(self::REGEX_COLOURS, "<span style=\"color: \\2;\">\\3</span>", $string);
}
if ($this->_settings[self::ENABLE_LINKS])
{
$string = preg_replace(self::REGEX_LINKS1, '<a href="\\1">\\2</a>' , $string);
$string = preg_replace(self::REGEX_LINKS2, '<a href="\\1">\\1</a>' , $string);
}
if ($this->_settings[self::ENABLE_IMAGES])
{
$string = preg_replace(self::REGEX_IMAGES1, '<img alt="\\1" src="\\2" />' , $string);
$string = preg_replace(self::REGEX_IMAGES2, '<img src="\\1">' , $string);
}
if ($this->_settings[self::ENABLE_LISTS])
{
// $string = preg_replace_callback(self::REGEX_LISTS, array("self", "createListItems"), $string);
$this->createLists($string);
}
// optimize colours by inluding style element in preceding html tag (if there is one)
$string = preg_replace(self::REGEX_COLOUR_FIX, "<\\2 style=\"color:\\4;\">\\5", $string);
return $this->_settings[self::ENABLE_NL2BR] ? nl2br($string) : $string;
}
/**
* This function scans the string for ubb-list-tags and converts them into html-lists
*
* @param String $string The whole string we want to convert, possibly containing one or more
* lists. String is passed by argument!
*
* @return void
*/
protected function createLists(&$string)
{
// try to find the first ubb closing tag, because that is the first deepest nested list
$offsetEnd = strpos($string, "[/list]") + strlen("[/list]");
if (False !== $offsetEnd)
{
$offset = strrpos(substr($string, 0, $offsetEnd), "[list]");
while ($offsetEnd && $offset)
{
$ubbList = substr($string, $offset, ($offsetEnd - $offset));
$htmlList = $this->htmlList($ubbList);
$string = str_replace($ubbList, $htmlList, $string);
$offsetEnd = strpos($string, "[/list]") + strlen("[/list]");
if (False !== $offsetEnd)
{
$offset = strrpos(substr($string, 0, $offsetEnd), "[list]");
}
}
}
else
{
; // no lists present
}
}
/**
* Converst an ubb-list into an html-list
*
* @param String $string A string that starts with [list], ends with [/list] and that contains
bullet-symbols (* or #)
* @return String
*/
protected function htmlList($string)
{
$content = str_replace("\r", "\n", str_replace("\r\n", "\n", $string));
$ol = strpos($content, "#");
$li = strpos($content, "*");
if ($ol > $li)
{
$content = str_replace("[list]", "<ol>", $content);
$content = str_replace("[/list]", "</ol>", $content);
$li = "#";
}
else
{
$content = str_replace("[list]", "<ul>", $content);
$content = str_replace("[/list]", "</ul>", $content);
$li = "*";
}
$body = trim(preg_replace("/([".$li."])(.*)(\n)/Usi", "<li>\\2</li>", $content));
$bodyClean = preg_replace("/(\s+)(<li>)/", "\\2", $body);
return $bodyClean;
}
/**
* Provides a way to set all settings with 1 function call
*
* @param array $arr Array containing all the settings
*
* @see setSetting()
*
* @return void
*/
public function setSettings(array $arr)
{
foreach ($arr AS $key => $value)
{
$this->setSetting($key, $value);
}
}
/**
* Checks if the setting exists and if the value for that settings is a boolean
* and if that is the case, sets the setting to that value.
*
* @throws Excudo_UbbCode_Exception
*
* @param String $key
* @param Boolean $value
*
* @return void
*/
public function setSetting($key, $value)
{
if (isset($this->_settings[$key]))
{
if (!is_bool($value))
{
throw new Excudo_UbbCode_Exception($value." is not a boolean value. please pass either true or false to this function");
}
else
{
$this->_settings[$key] = $value;
}
}
else
{
throw new Exception($key." doesnt exist");
}
}
/**
* Provides a magic-way to set a setting.
* usage: Excudo_UbbCode $obj->bold = true;
*
* @param String $name the name of the setting
* @param Boolean $value the value for the setting
*
* @return void
*/
public function __set($name, $value)
{
$this->setSetting($name, $value);
}
/**
* Provides a magic-way to get a setting
* usage: echo (Excudo_UbbCode) $obj->bold;
*
* @param String $name the name of the setting
*
* @return void
*/
public function __get($name) {
if (array_key_exists($name, $this->_settings)) {
return $this->_settings[$name];
}
$trace = debug_backtrace();
trigger_error(
'Undefined property via __get(): ' . $name .
' in ' . $trace[0]['file'] .
' on line ' . $trace[0]['line'],
E_USER_NOTICE);
return null;
}
}
/***
* file: Exception.php
*/
/**
* Exception class for exceptions that occur within the Excudo Packages
*/
class Excudo_Exception extends Exception
{
}
/***
* file: UbbCode/Exception.php
*/
/**
* Exception class for exceptions that occur within the UbbCode class
*/
class Excudo_UbbCode_Exception extends Excudo_Exception
{
}
?>