Project Homepage: http://code.google.com/p/cryobb/
Download: http://code.google.com/p/cryobb/downloads/list
Demo: http://nucleussystems.com/cryobb/ (thanks goes to jonah bron for hosting)
Version updates coming..
- Check for and fix invalid tag nests
- Allow tags in parameters
CryoBB
CryoBB (create your own bulletin board) is a library that enables developers to create and parse their own defined BB Code tags - without the need to create a complex parser or write complex functions in their code base when adding or modifying BB Code tags.
With CryoBB, the developer simply defines what tags to use, what emoticons to use, and how they should behave.
CryoBB can be used to create a fully functional powerful BB Code parsing engine.. including most commonly used BB Code tags, cool tags found on other custom BB Code systems, and also to create never-before-seen custom tags.
Features
Code: Select all
* Create tags and define their HTML replacements and how they behave
* Simple tags.. e.g. [b] [u] [i] [img]
* Tags with parameters, even optional parameters! e.g. [quote="name"]text[/quote] or [quote]text[/quote]
* Define your own placeholder macro in your HTML replacement
* Use text between tags as a parameter, such as [url]http://www.example.com[/url]
* Create tags that do not have their contents parsed, such as [code]text* Apply built-in or user defined functions to tags parameters and contents (highlight code syntax or do something really cool?)
* Apply built-in or user defined function to a tags contents based on parameter
* Turns new lines into HTML line breaks
* Because of full-tag matching and replacing, your entire page will not be riddled with ridiculous formatting
* Correctly parses nested bb code tags of the same kind (e.g. nested quote tags)
* Recursively parses inside of bb code tags to correctly parse nested tags (e.g. text)
* Naming convention complies with standards for autoloading interoperability (http://groups.google.com/group/php-stan ... osal?pli=1)[/code]
Source
Please download from the download link instead of copying/pasting these files.
CryoBB/Base.php
Code: Select all
<?php
/**
* CryoBB
*
* CryoBB (create your own bulletin board) is a library that enables developers
* to create and parse their own defined BB Code tags - without the need to
* create a complex parser or write complex functions in their code base when
* adding or modifying BB Code tags.
*
* With CryoBB, the developer simply defines what tags to use, what emoticons
* to use, and how they should behave.
*
* CryoBB can be used to create a fully functional powerful BB Code parsing
* engine.. including most commonly used BB Code tags, cool tags found on other
* custom BB Code systems, and also to create never-before-seen custom tags.
*
* Features
* ----------------------------------------------------------------------------
* Create tags and define their HTML replacements and how they behave
* Simple tags.. e.g. [b] [u] [i] [img]
* Tags with parameters, even optional parameters! e.g.
* [quote="name"]text[/quote] or [quote]text[/quote]
* Define your own placeholder macro in your HTML replacements
* Use text between tags as a parameter, such as
* [url]http://www.example.com[/url]
* Create tags that do not have their contents parsed, such as
* [code]text[/code] or [text]text[/text]
* Apply built-in or user defined functions to tags parameters and contents
* (highlight code syntax or do something really cool?)
* Apply built-in or user defined functions to a tags contents based on
* the parameter supplied
* Turns new lines into HTML line breaks
* Because of full-tag matching and replacing, your entire page will not be
* riddled with ridiculous formatting
* Correctly parses nested bb code tags of the same kind (e.g. nested quote
* tags)
* Recursively parses inside of bb code tags to correctly parse nested tags
* (e.g. [b][u][i]text[/i][/u][/b])
* Naming convention complies with standards for autoloading interoperability
* (http://groups.google.com/group/php-standards/web/psr-0-final-proposal?pli=1)
* ----------------------------------------------------------------------------
*
*
* @Todo
* ----------------------------------------------------------------------------
* Improve regular expressions
* Create a hyperlinking function that turns non bb coded URLs into clickable
* hyperlinks.
* Better error reporting and verbosity
* ----------------------------------------------------------------------------
*
*
* Version History
* ----------------------------------------------------------------------------
* 1.0.0 - Initial Release
* ----------------------------------------------------------------------------
*
* @package CryoBB
* @filename Base.php
* @version 1.0.0
* @author Scott Martin <sjm.dev1[at]gmail[dot]com>
* @date November 5th, 2010
* @license GNU GPL V3
<CryoBB>
Copyright (C) <2010> <Scott Martin>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
class CryoBB_Base
{
//string is stored here while being manipulated
private $str = '';
//the tags and definitions supplied by dev
private $tags = array();
//the emoticons supplied by dev
private $emoticons = array();
//array of tags to replace
private $replaceMatches = array();
//array of tags to extract (no content parsing)
private $extractMatches = array();
//strings that shouldn't be parsed
private $extractions = array();
//possible placeholders present in text
private $falsePositiveExtracts = array();
//the regexp for matching tags
private $matchRegexp;
//the regexp for matching tags to extract
private $extractRegexp;
/**
* Converts input string to HTML
*
* According to parameters supplied, parses input string containing bb code
* and emoticons into their HTML equivelants.
*
* @access public
* @param string $str - the input string to be parsed for bb code and
* emoticons
* @param boolean $parseBB - true to parse bb code, false not to
* @param boolean $parseEmoticons - true to parse emoticons, false not to
* @param isXHTML - true to use <br /> line breaks, false to use <br>
* (php >= 5.3.0)
* @access public
* @return string - input string converted to HTML according to parameters
*/
public function make($str, $parseBB=true, $parseEmoticons=true, $isXHTML=true)
{
$emoticonsParsed = false;
$this->str = $str;
//don't parse any tags if we don't have to
if ($parseBB && !empty($this->tags) && (strpos($this->str, '[') !== false) && (strpos($this->str, ']') !== false))
{
//make regexp's for tags and tags to extract
$this->extractRegexp = $this->makeRegexps(true);
$this->matchRegexp = $this->makeRegexps(false);
//extract tags that don't need their contents parsed
$this->extractMatches = $this->matchExtracts();
$this->replaceFalsePositiveExtracts();
$this->makeExtractions();
//make the tags that do need parsed
$this->replaceMatches = $this->matchTags($this->str);
$this->makeTags($this->replaceMatches);
//parse emoticons
if ($parseEmoticons)
{
$this->makeEmoticons();
$emoticonsParsed = true;
}
//replace tags that have been extracted
$this->replaceExtractions();
$this->revertFalsePositiveExtracts();
$this->makeTags($this->extractMatches);
}
//parse emoticons if we haven't yet
if (!$emoticonsParsed && $parseEmoticons)
{
$this->makeEmoticons();
}
//make line breaks
$this->makeLineBreaks($isXHTML);
//and return this thing of beauty we have created
return $this->str;
}
/**
* Makes regular expressions
*
* Makes regular expressions based on the tags supplied via the addTags()
* method. Based on the value of parameter $extract, a regular expression is
* returned to match all tags or the tags to be extracted from the input
* string. Called from public method make()
*
* @param boolean $extract - true to generate extraction regexp, false to
* generate all tag matching regexp.
* @access private
* @return mixed - string regexp when tag list is not empty and/or extraction
* tags can be found, false if otherwise
*/
private function makeRegexps($extract)
{
$tagList = array_keys($this->tags);
$regexp = '';
foreach ($tagList AS $tag)
{
if ($extract && !$this->tags[$tag]->parseContents)
{
$regexp .= '|' . $tag;
} else if (!$extract && $this->tags[$tag]->parseContents)
{
$regexp .= '|' . $tag;
}
}
return (!empty($regexp) === true)
? '#\[(' . substr($regexp, 1) . ')(=.+?)?\]((?:[^[]|\[(?!/?\\1(=.+?)?\])|(?R))+)\[/\\1\]#si'
: false;
}
/**
* Gathers tags that need to be extracted from the string.
*
* Matches and gathers tags that need to be extracted from the string because
* their contents should not be parsed for bb code or emoticons. Called from
* public method make()
*
* @param void
* @access private
* @return array
*/
private function matchExtracts()
{
if ($this->extractRegexp)
{
preg_match_all($this->extractRegexp, $this->str, $matches, PREG_SET_ORDER);
}
return !empty($matches) ? $matches : array();
}
/**
* Removes strings that could interfere with placing extracted strings back
* into the output string.
*
* When extracting strings for bb code tags that do not need their contents
* parsed, a placeholder is used in order to know which string to place back
* into which section of the string. If a placeholder string is present in
* the input string, this method will convert it to something that won't be
* interpreted as a real placeholder. Called from public method make()
*
* @param void
* @access private
* @return void
*/
private function replaceFalsePositiveExtracts()
{
if (!empty($this->extractMatches) && stripos($this->str, '{extract:'))
{
if (preg_match_all('/\{extract:\w+:\d+\}/i', $this->str, $matches, PREG_SET_ORDER))
{
$this->falsePositiveExtracts = $matches;
foreach ($matches AS $match)
{
$this->str = str_replace(
$match[0], str_ireplace('extract', 'nonextract', $match[0]),
$this->str
);
}
}
}
}
/**
* Replaces false positive placeholder strings back into the output string.
*
* When a false positive placeholder is replaced with a non-placeholder string
* via replaceFalsePositiveExtracts(), this method reverts this false positive
* placeholder back into the original string it was. Called from public
* method make()
*
* @param void
* @access private
* @return void
*/
private function revertFalsePositiveExtracts()
{
if (!empty($this->falsePositiveExtracts))
{
foreach ($this->falsePositiveExtracts AS $falsePositiveExtract)
{
$this->str = str_replace(
str_replace('extract', 'nonextract', $falsePositiveExtract[0]),
$falsePositiveExtract[0],
$this->str
);
}
}
}
/**
* Extrags tags strings from input string
*
* Extracts tags strings from input string that do not need their contents
* parsed and replaces them with a placeholder, allowing for them to be
* put back into the output string later. Called from public method make()
*
* @param void
* @access private
* @return void
*/
private function makeExtractions()
{
if (!empty($this->extractMatches))
{
foreach ($this->extractMatches AS $match)
{
$this->extractions[$match[1]][] = $match;
$this->str = str_replace(
$match[0],
'{extract:' . $match[1] . ':' . (count($this->extractions[$match[1]])-1) . '}',
$this->str
);
}
}
}
/**
* Matches bb code tags and their contents
*
* Recursively matches bb code tags and their contents based on the regexp
* in property $matchRegexp. Recursion is necessary to capture nested bb
* code elements. Stores matches in an array and returns them.
*
* @param $str - the string to match for bb code tags
* @access private
* @return mixed - array of matches if found, false if no matches found
*/
private function matchTags($str)
{
$ret = array();
if ((strpos($str, '[') !== false) && (strpos($str, ']') !== false))
{
if (preg_match_all($this->matchRegexp, $str, $matches, PREG_SET_ORDER))
{
$ret = array_merge($ret, $matches);
foreach ($matches AS $match)
{
if ($newMatches = $this->matchTags($match[3]))
{
$ret = array_merge($ret, $newMatches);
}
}
return $ret;
}
}
return false;
}
/**
* Replaces extracted strings back into the output string
*
* Replaces placeholder strings made by makeExtractions() with their original
* strings.
*
* @param void
* @access private
* @return void
*/
private function replaceExtractions()
{
if (!empty($this->extractMatches))
{
foreach ($this->extractions AS $name => $matches)
{
$it=0;
foreach ($matches AS $match)
{
$this->str = str_replace('{extract:' . $name . ':' . $it . '}', $match[0], $this->str);
$it++;
}
}
}
}
/**
* Adds a bb code tag or multiple bb code tags to this bbcode ojbect
*
* Adds tag definitions to $this->tags properties. Multiple tag definitions
* can be added at once. Checks to make sure tags are instances of CryoBB_Tag
*
* @param object $tags - retrieved by funct_get_args()
* @access public
* @return void
*/
public function addTags()
{
$tags = func_get_args();
foreach ($tags AS $tag)
{
if (is_object($tag) && $tag instanceof CryoBB_Tag)
{
$this->tags[strtolower($tag->tag)] = $tag;
} else
{
trigger_error(
'CryoBB_Base::addTags() expects all parameters to be an instance of BB_Tag',
E_USER_WARNING
);
}
}
}
/**
* Adds emoticon definitions to this object.
*
* @param object $emoticons
* @access public
* @return void
*/
public function addEmoticons($emoticons)
{
if (is_object($emoticons) && $emoticons instanceof CryoBB_Emoticons)
{
$this->emoticons = $emoticons;
} else
{
trigger_error(
'CryoBB_Base:addEmoticons() expects parameter 1 to be an instance of BB_Emoticons',
E_USER_WARNING
);
}
}
/**
* Converts emoticon text to HTML
*
* Converts emoticon text to HTML (presumably images) based on the definition
* of the emoticons.
*
* @param void
* @access private
* @return void
*/
private function makeEmoticons()
{
if (!empty($this->emoticons))
{
$func = $this->emoticons->isCaseSensitive ? 'str_replace' : 'str_ireplace';
$this->str = $func(
array_keys($this->emoticons->emoticons),
array_values($this->emoticons->emoticons),
$this->str
);
}
}
/**
* Applies a function to contents between opening and closing bb code tags
*
* If specified, applies a function to the contents of a bb code tag, along
* with any parameters specified.
*
* @param array $match - the bb code tag match
* @access private
* @return string
*/
private function applyFunctionToContents($match)
{
$params = $match[3];
if (!empty($this->tags[$match[1]]->applyFunctionToContents[1]))
{
$params = $this->tags[$match[1]]->applyFunctionToContents[1];
array_unshift($params, $match[3]);
}
return call_user_func_array($this->tags[$match[1]]->applyFunctionToContents[0], $params);
}
/**
* Applies a function to a bb code tag's parameter
*
* If specified, applies a function to the parameter of a bbcode tag, along
* with any parameter specified
*
* @param array $match - the bb code tag match
* @param integer $index - the index to perform the function on (2 if
* parameter supplied, 3 if using the contents of the tag as a parameter
* @return string
*/
private function applyFunctionToParameter($match, $index=2)
{
$params = $match[$index];
if (!empty($this->tags[$match[1]]->applyFunctionToParameter[1]))
{
$params = $this->tags[$match[1]]->applyFunctionToParameter[1];
array_unshift($params, $match[$index]);
}
return call_user_func_array($this->tags[$match[1]]->applyFunctionToParameter[0], $params);
}
/**
* Applies a function to a tags contents based on the parameter supplied to
* the tag
*
* @param array $match - the bb code tag match
* @access private
* @return string
*/
private function applyFunctionParameterCapture($match)
{
$params = array($match[2], $match[3]);
if (!empty($this->tags[$match[1]]->applyFunctionParameterCapture[1]))
{
$params = array_merge($params, $this->tags[$match[1]]->applyFunctionParameterCapture[1]);
}
return call_user_func_array($this->tags[$match[1]]->applyFunctionParameterCapture[0], $params);
}
/**
* Replaces bb code tags with their HTML equivelants
*
* Does the necessary magic to turn bb code tags, parameters, and contents
* into the desired output based on tag definitions.
*
* @param array $matches - an array of bb code matches found in the seached
* string
* @access private
* @return void
*/
private function makeTags($matches)
{
foreach ($matches AS $match)
{
$match[1] = strtolower($match[1]);
if (count($this->tags[$match[1]]->applyFunctionToContents))
{
$match[3] = $this->applyFunctionToContents($match);
}
if (!$this->tags[$match[1]]->parameter)
{
$this->str = $this->makeSimpleTag($match);
continue;
}
if ($this->tags[$match[1]]->parameter == 1)
{
$this->str = $this->makeParameterTag($match);
}
}
}
/**
* Replaces a simple tag (e.g. [b]text[/b]) with it's HTML counterparts
*
* @param array $match - the tag match from regexp search
* @access private
* @return string
*/
private function makeSimpleTag($match)
{
return str_replace(
$match[0],
$this->tags[$match[1]]->replacements[0] . $match[3] . $this->tags[$match[1]]->replacements[1],
$this->str
);
}
/**
* Replaces a bb code tag with a parameter with it's HTML counterparts
*
* @param array $match - the tag match from regexp search
* @access private
* return mixed - string if parameter required and found, null if parameter
* required and not found
*/
private function makeParameterTag($match)
{
//no parameter was found
if (empty($match[2]) === true)
{
//it's ok
if (empty($this->tags[$match[1]]->replacements[0]) !== true)
{
//but we might use contained text as parameter
if ($this->tags[$match[1]]->useTextAsParameter)
{
return $this->makeParameterTagText($match);
}
//no parameter found
return $this->makeParameterTagNoParameter($match);
}
//it's not ok - nothing to do
return $match[0];
}
//parameter found, all is well
return $this->makeParameterTagParameter($match);
}
/**
* Replaces a bb code tag with it's HTML counterparts when the text between
* the opening and closing tags is used as a parameter.
*
* @param array $match - the tag match from the regexp search
* @access private
* @return string
*/
private function makeParameterTagText($match)
{
//apply function to parameter
if (count($this->tags[$match[1]]->applyFunctionToParameter))
{
$match[3] = $this->applyFunctionToParameter($match, 3);
}
//apply function based on parameter capture
if (count($this->tags[$match[1]]->applyFunctionParameterCapture))
{
$match[3] = $this->applyFunctionParameterCapture($match);
}
//replace and return
return str_replace(
$match[0],
str_replace($this->tags[$match[1]]->replacements[2], $match[3], $this->tags[$match[1]]->replacements[0][0])
. $match[3]
. str_replace(
$this->tags[$match[1]]->replacements[2],
$match[3],
$this->tags[$match[1]]->replacements[0][1]
),
$this->str
);
}
/**
* Replaces bb code tag with parameter specified with HTML counterparts
* when no parameter is found and the tag definition allows this behavior.
*
* @param $match - the tag match from the regexp search
* @access private
* @return string
*/
private function makeParameterTagNoParameter($match)
{
return str_replace(
$match[0],
$this->tags[$match[1]]->replacements[0][0] . $match[3] . $this->tags[$match[1]]->replacements[0][1],
$this->str
);
}
/**
* Replaces bb code tag with parameter with HTML output when the parameter is
* specified.
*
* @param array $match - the tag match from the regexp search
* @access private
* @return string
*/
private function makeParameterTagParameter($match)
{
//remove = sign
$match[2] = substr($match[2], 1);
//remove containing quotes, if found
if ((substr($match[2], 0, 1) == '"' && substr($match[2], -1) == '"')|| (substr($match[2], 0, 1) == '\'' && substr($match[2], -1) == '\''))
{
$match[2] = substr(substr($match[2], 0, strlen($match[2]) - 1), 1);
}
//apply function to parameter
if (count($this->tags[$match[1]]->applyFunctionToParameter))
{
$match[2] = $this->applyFunctionToParameter($match);
}
//apply function based on parameter capture
if (count($this->tags[$match[1]]->applyFunctionParameterCapture))
{
$match[3] = $this->applyFunctionParameterCapture($match);
}
//replace and return
return str_replace(
$match[0],
str_replace($this->tags[$match[1]]->replacements[2], $match[2], $this->tags[$match[1]]->replacements[1][0])
. $match[3] . str_replace(
$this->tags[$match[1]]->replacements[2],
$match[2],
$this->tags[$match[1]]->replacements[1][1]
),
$this->str
);
}
/**
* Replaces new lines with line breaks
*
* Replaces new lines with line breaks. If php version is >= 5.3.0, boolean
* value can be passed to make() and then passed to this method to change
* XHTML style line breaks (<br />) to regular line breaks (<br>)
*
* @param boolean $isXHTML
* @access private
* @return void
*/
private function makeLineBreaks($isXHTML)
{
$this->str = (version_compare(PHP_VERSION, '5.3.0') >= 0)
? nl2br($this->str, $isXHTML)
: nl2br($this->str);
}
}Code: Select all
<?php
/**
* Class to define tags and how they behave
*
* @package CryoBB
* @filename Tag.php
* @version 1.0.0
* @author Scott Martin <sjm.dev1[at]gmail[dot]com>
* @date November 5th, 2010
* @license GNU GPL V3
*/
class CryoBB_Tag
{
//tag name
private $tag;
//tag has parameter?
private $parameter = false;
//use text between tags as parameter?
private $useTextAsParameter = false;
//html replacements for bb code tags
private $replacements;
//parse the contents between bb code tags for additional bbcode tags?
private $parseContents = true;
//apply a function to bbcode tag parameter
private $applyFunctionToParameter = array();
//apply a function to contents between bb code tags?
private $applyFunctionToContents = array();
//apply a function to contents based on parameter
private $applyFunctionParameterCapture = array();
private $placeholder = '';
/**
* Sets the tag name
*
* @access public
* @param string $tag - the name of the BB code tag
* @return void
*/
public function __construct($tag)
{
if (!ctype_alnum($tag))
{
trigger_error('CryoBB_Tag::__construct() parameter should be alphanumeric', E_USER_WARNING);
return false;
}
$this->tag = $tag;
}
/**
* Sets the HTML replacement tags for the opening and closing BB code tags
*
* @access public
* @param array $replacement
* @return void
*/
public function setReplacements($replacement)
{
$this->replacements = $replacement;
}
/**
* Notifies this object that this bb code tag has a parameter
*
* @access public
* @param boolean $bool
* @access void
*/
public function hasParameter($bool=true)
{
$this->parameter = (bool) $bool;
}
/**
* Notifies this object to use the text between the opening and closing BB
* code tags as a parameter.
*
* @access public
* @param boolean $bool
* @return void
*/
public function useTextAsParameter($bool=true)
{
$this->useTextAsParameter = (bool) $bool;
}
/**
* Tells this object whether or not to parse the contents between this tags'
* open and close for more BB code tags.
*
* @access public
* @param boolean $bool
* @return void
*/
public function parseContents($bool)
{
$this->parseContents = (bool) $bool;
}
/**
* Tells the object to apply a function to the contents between this tags'
* open and close.
*
* @access public
* @param mixed $function - string function name or array($objectInstance, 'methodName')
* @param array $params - parameters to pass to the function
* @return void
*/
public function applyFunctionToContents($function, $params=array())
{
if (!is_callable($function))
{
trigger_error('CryoBB_Tag::applyFunction() - function passed as parameter 1 is not callable', E_USER_WARNING);
return false;
}
$this->applyFunctionToContents = array($function, $params);
}
/**
* Tells the object to apply a function to this tag's parameter
*
* @access public
* @param mixed $function - string function name or array($objectInstance, 'methodName')
* @param array $params - parameters to pass to the function
* @return void
*/
public function applyFunctionToParameter($function, $params=array())
{
if (!is_callable($function))
{
trigger_error('CryoBB_Tag::applyFunctionToParamter() - function passed as parameter 1 is not callable', E_USER_WARNING);
return false;
}
$this->applyFunctionToParameter = array($function, $params);
}
/**
* Tells the object to apply a function to this tag's contents based on the parameter
*
* @access public
* @param mixed $function - string function name or array($objectInstance, 'methodName')
* @param array $params - parameters to pass to the function
* @return void
*/
public function applyFunctionParameterCapture($function, $params=array())
{
if (!is_callable($function))
{
trigger_error('CryoBB_Tag::applyFunctionParameterCapture() - function passed as parameter 1 is not callable', E_USER_WARNING);
return false;
}
$this->applyFunctionParameterCapture = array($function, $params);
}
//accessor for object properties
public function __get($var)
{
return isset($this->$var) ? $this->$var : false;
}
}Code: Select all
<?php
/**
* Class to provide emoticon capability for CryoBB.
*
* @package CryoBB
* @filename Emoticons.php
* @version 1.0.0
* @author Scott Martin <sjm.dev1[at]gmail[dot]com>
* @date November 5th, 2010
* @license GNU GPL V3
*/
class CryoBB_Emoticons
{
//emoticon holder
private $emoticons = array();
//determines if emoticon text replacement is case sensitive
private $isCaseSensitive = false;
/**
* Sets whether emoticon text replacement is case sensitive or not
*
* @param boolean $bool
* @access public
* @return void
*/
public function isCaseSensitive($bool)
{
$this->isCaseSensitive = (bool) $bool;
}
/**
* Adds an array of emoticons in the format of 'text' => 'image'
*
* @param array $array
* @access public
* @return void
*/
public function addEmoticons($array)
{
foreach ($array AS $k => $v)
{
$this->emoticons[$k] = $v;
}
}
/**
* Adds a single emoticon
*
* @param string $text - text to be replaced with $image
* @param string $image - image to replace the $text with
* @access public
* @return void
*/
public function addEmoticon($text, $image)
{
$this->emoticons[$text] = $image;
}
//getter
public function __get($var)
{
return isset($this->$var) ? $this->$var : false;
}
}Code: Select all
<?php
/**
* Class to provide common functions applied to tag contents or parameters
*
* @package CryoBB
* @filename CommonFunctions.php
* @version 1.0.0
* @author Scott Martin <sjm.dev1[at]gmail[dot]com>
* @date November 5th, 2010
* @license GNU GPL V3
*/
class CryoBB_CommonFunctions
{
/**
* Makes an absolute URL out of a parameter or contents that should be a URL.
*
* @param string $str
* @access public
* @return string
*/
public function absoluteURL($str)
{
$str = trim($str);
return preg_match('#^(ftp|http|https)://#i', $str) ? $str : 'http://' . $str;
}
}Upload the CryoBB sub directory from the archive to your web server, and create your setup file. Your setup file will define your tags and emoticons and how they behave.
Creating the setup file.
Require the needed files (they will be autoloaded if your framework supports autoloading)
Code: Select all
require_once 'CryoBB/Base.php';
require_once 'CryoBB/Tag.php';
require_once 'CryoBB/Emoticons.php';
require_once 'CryoBB/CommonFunctions.php';Code: Select all
$base = new CryoBB_Base();Each tag you define will be an instance of CryoBB_Tag with the tag name as the parameter for the constructor. Tag name must be alpha-numeric.
For instance, setting up a [ b ] bb code tag would start like this.
Code: Select all
$b = new CryoBB_Tag('b');Code: Select all
$b->setReplacements(array('<strong>', '</strong>'));Underline and italics are just as simple.
Code: Select all
//set up underline bb code tag
$u = new CryoBB_Tag('u');
$u->setReplacements(array('<span style="text-decoration: underline;">', '</span>'));
//set up italic bb code tag
$i = new CryoBB_Tag('i');
$i->setReplacements(array('<em>', '</em>'));It is useful to have [ code ] or [ text ] (or whatever you want to call your tag) tags so people can post code or other items they don't want parsed for bb code and emoticons. It is simple to set up using the parseContents() method.
Setting up a code bb tag would be like this:
Code: Select all
$code = new CryoBB_Tag('code');
$code->parseContents(false);
$code->setParameter(array('<pre>', '</pre>'));Tags that have optional parameter such as [ quote="name"] or simply
are set up like follows:
The hasParameter() method was called to let our tag know it can have a parameter.Code: Select all
$quote = new CryoBB_Tag('quote'); $quote->hasParameter(); $quote->setReplacements( array( array('<div><strong>Quote:</strong><blockquote>', '</blockquote>'), array('<div><strong>{placeholder} wrote:</strong></div><blockquote>'), '{placeholder}' ) );
Then, setReplacements was called with a parameter of arrays.
The first array consists of opening and closing tags if the optional parameter is not supplied ( e.g. [ quote ]text[ /quote ]).
The second array consists of opening and closing tags if the optional parameter IS supplied ( e.g. [ quote="name" ]text[ /quote] )
The third element is a string for the placeholder you want to use to replace the parameter with in the HTML you specify.
Tags with mandatory parameter
Suppose you want to set up a color bb code tag but must have the parameter specified. It is as easy as setting up the optional parameter tag but leaving the first array empty in setReplacements()
Applying functions to tag contents or parametersCode: Select all
$color = new CryoBB_Tag('color'); $color->hasParameter(); $color->setReplacements( array( array(), //empty, because parameter MUST be specified array('<span style="color: {color};">', '</span>'), '{color}' ) );
Applying built in or user-defined functions to a tags contents or parameters is what allows the developer to create custom tags that have custom behavior.
For examples sake, I'm going to create an [upper] bb code tag that applies strtoupper() to the contents between the opening and closing bb tags
Using the applyFunctionToContents() method you define what function you want to apply to the contents of the tag. You can also pass in an object and function... and parameters to the function.Code: Select all
$upper = new CryoBB_Tag('upper'); $upper->applyFunctionToContents('strtoupper'); $upper->setReplacements(array('<div>', '</div>'));
You can do the same to apply a function to a tags parameter using the applyFunctionToParameter() method.Code: Select all
$tag->applyFunctionToContents(array(new SomeClass, 'someFunction'), array('param1', 'param2', 'etc'));
Apply function to tags contents based on parameter
This is really cool and will allow you to do something like this boards [ syntax="language" ] bb code tag. It will apply a function to the tags contents based on the parameter input by the user.
To set this up would look like this:
Using the CryoBB_CommonFunctions classCode: Select all
//create syntax class/function to use class bbsyntax { function highlight($param, $contents) { switch ($param) { case 'php': //highlight the contents, but for example sake just say it's php return 'this is php code: ' . $contents; break; case 'javascript': return 'this is javascript code: ' . $contents; break; } //parameter unknown, return contents return $contents; } } //create tag $syntax = new CryoBB_Tag('syntax'); $syntax->hasParameter(); $syntax->parseContents(false); $syntax->applyFunctionParameterCapture(array(new bbsyntax, 'highlight')); $syntax->setReplacements( array( array(), array('<strong>{param}</strong>:<br><pre>', '</pre>') ) );
This class is intended to be a common functions class for bb code tags. I will implement the absoluteURL() method of that class to create IMG and URL bb code tags. It will make sure that the URL's put in for the image source or anchor link have a protocol (instead of just www or nothing at all)
You may have noticed the URL tag uses the useTextAsParameter() method. This method is called when the parameter may be inside the tags contents or defined in the parameter, such as [ url ]url here[ /url ] or [ url="url here" ]text here[ /url ]Code: Select all
//url tag $url = new CryoBB_Tag('url'); $url->hasParameter(); $url->useTextAsParameter(); $url->applyFunctionToParameter(array(new CryoBB_CommonFunctions, 'absoluteURL'))); $url->setReplacements( array( array('<a href="{urlplaceholder}" target="_blank">', '</a>'), array('<a href="{urlplaceholder}" target="_blank">', '</a>') ) ); //img tag $img = new CryoBB_Tag('img'); $img->applyFunctionToContents(array(new CryoBB_CommonFunctions, 'absoluteURL'))); $img->setReplacements(array('<img src="', '" alt="Image"');
Adding emoticons
Adding emoticons is very easy. Just pass an array of 'textkey' => 'image', such as:
Tying it together - adding tags and emoticons to baseCode: Select all
$emoticons = new CryoBB_Emoticons(); $emoticons->addEmoticons( array( ':smile:' => '<img src="emoticons/smile.gif" alt="Smile">', ':sad:' => '<img src="emoticons/sad.gif" alt="Sad">' ) );
Now you need to hook your defined tags and emoticons into the CryoBB base class
For tags - just pass your tag objects to the base's addTags() methodFor emoticons - just pass your emoticon object to the base's addEmoticons() methodCode: Select all
$base->addTags($b, $u, $i, $code, $etc, $etc, $etc);You're set up!Code: Select all
$base->addEmoticons($emoticons);
Now that you've defined your tags and emoticons and attached them to the base, you're ready to convert users bb code input into your defined HTML output.
Just call the $base->make() method on the input string.
That's itCode: Select all
echo $base->make($_POST['input']);
The make() method has several parameters - make($input, $parseBB=true, $parseEmoticons=true, $isXHTML=true)
So to parse bb code but not emoticons..To parse emoticons but not bb codeCode: Select all
echo $base->make($_POST['input'], true, false);The $isXHTMl parameter will allow you to specify <br> instead of < br /> line breaks if using php >= 5.3.0Code: Select all
echo $base->make($_POST['input'], false);
In Summary
Once you have your setup file created with your tags and emoticons defined, you're on cruise control. The definitions are powerful enough to allow you to create ordinary and custom bb code tags - even cool ones like perhaps [youtube] or even syntax highlighting integrated with geshi.
Download and have a play and let me know what you think!