khanat-opennel-code/code/web/api/common/bbCode.php
2013-06-08 14:56:58 +02:00

998 lines
32 KiB
PHP

<?php
/* Copyright (C) 2009 Winch Gate Property Limited
*
* This file is part of ryzom_api.
* ryzom_api is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ryzom_api 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with ryzom_api. If not, see <http://www.gnu.org/licenses/>.
*/
// setup bbCode formatter
bbCode::$ig = RYZOM_IG;
/**
* Image proxy
*/
if(!defined('IMG_PROXY')){
$url = 'http://'.$_SERVER['HTTP_HOST'].'/app_forum/tools/imageproxy.php';
define('IMG_PROXY', $url);
}
if (!function_exists('proxy_image_url')) {
function proxy_image_url($href, $attrs=''){
return IMG_PROXY.'?'.($attrs != '' ? $attrs.'&' : '').'url='.urlencode($href);
}
}
abstract class bbCodeParser {
/**
* @var bool
*/
private $_ig;
/**
* @var array
*/
private $tags_ignore;
private $tags_block_open;
private $tags_block_close;
private $tags_ignore_depth;
/**
* @var array
*/
private $open_tags;
/**
* @var string
*/
private $last_closed_tag;
/**
* @var int
*/
private $current_tag;
/**
* @var array
*/
private $state;
/**
* @param bool $ig if true, use ingame markup
*/
function __construct($ig) {
$this->_ig = $ig;
// ignore bbcode between these tags
$this->tags_ignore = array(
'noparse', 'code',
'url', 'img', 'mail', 'page', 'forum', 'topic', 'post', 'wiki', 'time', 'date'
);
// these create block level html code, so '\n' or ' ' or '\t' around them needs to be cleared
$this->tags_block_open = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'quote', 'list', 'p');
$this->tags_block_close = $this->tags_block_open;
if ($this->_ig) {
// ingame <p> is not block level when closing, so dont strip there
$key = array_search('p', $this->tags_block_close, true);
unset($this->tags_block_close[$key]);
}
$this->state = array();
// reset internals
$this->reset();
}
/**
* Format bbcode tag
*
* @param string $tag tag name
* @param string $open open markup
* @param string $close close markup
* @param string $attr tag attributes
* @param string $text text between tags
*/
abstract function format($tag, $open, $close, $attr, $text);
/**
* Wrapper to call Child->format(...)
*
* @param array $tag assoc array with tag info
* @return string
*/
function handle_tag($tag) {
return $this->format($tag['tag'], $tag['open'], $tag['close'], $tag['attr'], $tag['text']);
}
/**
* Reset internals
*/
function reset() {
$this->current_tag = 0;
$this->tags_ignore_depth = 0;
// 0'th position is used as result
$this->open_tags = array(
0 => array('tag' => '', 'open' => '', 'close' => '', 'attr' => '', 'text' => '')
);
$this->last_closed_tag = false;
}
/**
* Save working state
*/
private function _state_save() {
$this->state[] = array($this->current_tag, $this->tags_ignore_depth, $this->open_tags, $this->last_closed_tag);
$this->reset();
}
/**
* Restore working state
*/
private function _state_restore() {
if (!empty($this->state)) {
list($this->current_tag, $this->tags_ignore_depth, $this->open_tags, $this->last_closed_tag) = array_pop($this->state);
}
}
/**
* Main worker. Parse $text for bbCode tags
*
* NOTE: Text must already be safe for HTML, ie. treated with htmlspecialchars()
*
* @param string $text
* @return string formatted string
*/
function bbcode($text) {
$text = str_replace("\r\n", "\n", $text);
$split = preg_split('/(\[[a-zA-Z0-9_\/]*?(?:[= ].*?)?\])/', $text, null, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
foreach ($split as $chunk) {
if (substr($chunk, 0, 1) == '[' && substr($chunk, -1, 1) == ']') {
if (substr($chunk, 0, 2) == '[/') {
$this->close($chunk);
} else {
$this->open($chunk);
}
} else {
$this->text($chunk);
}
}
return $this->result();
}
/**
* Push tag with args to stack
* Do not strip whitespace because tag might be invalid
*
* @param string $chunk full tag string, eg. [tag=attr]
*/
function open($chunk) {
list($tag, $attr) = $this->split_params($chunk);
// test for [noparse]
if ($this->tags_ignore_depth > 0) {
$this->text($chunk);
} else {
$this->current_tag++;
// remember tag, attributes and complete string that was used in markup
$this->open_tags[$this->current_tag] = array('tag' => $tag, 'attr' => $attr, 'open' => $chunk, 'close' => '', 'text' => '');
}
if (in_array($tag, $this->tags_ignore)) {
$this->tags_ignore_depth++;
}
}
/**
* Close tag and call tag handler to format output
*
* @param $chunk full tag string, eg. [/tag]
*/
function close($chunk) {
// extract tag name from [/name]
$tag = strtolower(substr($chunk, 2, -1));
if ($this->tags_ignore_depth > 0 && in_array($tag, $this->tags_ignore)) {
$this->tags_ignore_depth--;
}
// stack underrun
if ($this->current_tag < 0) {
$this->text($chunk);
return;
}
// ignore block
if ($this->tags_ignore_depth > 0) {
$this->text($chunk);
return;
}
// tag mismatch
if ($this->open_tags[$this->current_tag]['tag'] !== $tag) {
// try to find first open tag for this
$key = false;
for ($i = $this->current_tag - 1; $i > 0; $i--) {
if (isset($this->open_tags[$i]['tag']) && $this->open_tags[$i]['tag'] === $tag) {
$key = $i;
break;
}
}
if ($key === false) {
$this->text($chunk);
return;
}
// tag is open so we need to 'rewind' a bit
for ($i = $this->current_tag; $i > $key; $i--) {
$tmp_tag = $this->pop_stack();
$this->text($tmp_tag['open'] . $tmp_tag['text']);
}
}
// close tag
$open = $this->pop_stack();
// handle bbcode
$open['close'] = $chunk;
$block_level = false;
if (in_array($tag, $this->tags_block_open)) {
$block_level = true;
// for block level element, trim whitespace from inside tag
// [tag]<ws>...text...<ws>[/tag]
$open['text'] = $this->trim_ws($open['text']);
}
$result = $this->handle_tag($open);
// strip whitespace from text before tag 'text...<ws>[tag]'
if ($block_level) {
$ts = $this->rtrim_ws($this->open_tags[$this->current_tag]['text']);
$this->open_tags[$this->current_tag]['text'] = $ts;
}
$this->text($result);
$this->last_closed_tag = $open['tag'];
}
function text($text) {
// strip whitespace after closing '[/tag]<ws>...text'
if (in_array($this->last_closed_tag, $this->tags_block_close)) {
$text = $this->ltrim_ws($text);
}
$this->open_tags[$this->current_tag]['text'] .= $text;
$this->last_closed_tag = false;
}
function result() {
// close tags that are still open
while ($this->current_tag > 0) {
$open = $this->pop_stack();
if ($this->tags_ignore_depth > 0) {
$this->tags_ignore_depth--;
// need to reparse text that's after ignore tag
$this->_state_save();
$text = $open['open'] . $this->bbcode($open['text']);
$this->_state_restore();
} else {
// tag was not closed proprely, include start tag with result
$text = $open['open'] . $open['text'];
}
$this->text($text);
};
return $this->open_tags[0]['text'];
}
/**
* Pop tag and text from stack and return them
*
* @return array [0] = tag, [1] = text
*/
function pop_stack() {
// remove from stack
$open = $this->open_tags[$this->current_tag];
unset($this->open_tags[$this->current_tag]);
$this->current_tag--;
return $open;
}
/**
* Trim from end of string
* 'text...\s{0,}\n{1}\s{0,}'
*
* @param string $ts
* @return string
*/
function rtrim_ws($ts){
// we want to get rid of all spaces/tabs, but only single \n, so rtrim($ts, " \t\n\r") would not work
$ts = rtrim($ts, " \t");
if (substr($ts, -1, 1) === "\n") {
$ts = substr($ts, 0, -1);
$ts = rtrim($ts, " \t");
}
return $ts;
}
/**
* Trim from start of string
* '\s{0,}\n{1}...text'
*
* @param string $ts
* @return string
*/
function ltrim_ws($ts){
// we want to get rid of all spaces/tabs, but only single \n, so ltrim($ts, " \t\n\r") would not work
$ts = ltrim($ts, " \t");
if (substr($ts, 0, 1) === "\n") {
$ts = substr($ts, 1);
}
return $ts;
}
/**
* Trim from both sides
* '\s{0,}\n{1}...text...\s{0,}\n{1}\s{0,}
*
* @param string $ts
* @return string
*/
function trim_ws($ts){
$ts = $this->ltrim_ws($ts);
$ts = $this->rtrim_ws($ts);
return $ts;
}
/**
* Extract tag parameters from [tag=params] or [tag key1=val1 key2=val2]
*
* @param type $tag
* @return type
*/
function split_params($chunk) {
if (substr($chunk, 0, 1) == '[') {
$b = '\[';
$e = '\]';
} else {
$b = '';
$e = '';
}
// [1] [2] [3]
if (preg_match('/^' . $b . '([\*a-zA-Z0-9]*?)' . '(=| )' . '(.*?)' . $e . '$/', $chunk, $match)) {
$tagName = strtolower($match[1]);
if ($match[2] == '=') {
// = means single parameter
$tagParam = $match[3];
} else {
// <space> means multiple parameters
$tagParam = array();
$args = preg_split('/[ ]/', $match[3], null, PREG_SPLIT_NO_EMPTY);
foreach ($args as $arg) {
$pairs = explode('=', $arg);
// preg_replace will remove possible quotes around value
if (isset($pairs[1])) {
$tagParam[strtolower($pairs[0])] = preg_replace('@("|\'|)(.*?)\\1@', '$2', $pairs[1]);
} else {
$tagParam[] = preg_replace('@("|\'|)(.*?)\\1@', '$2', $pairs[0]);
}
}
}
} else {
if (substr($chunk, 0, 1) == '[' && substr($chunk, -1, 1) == ']') {
$chunk = substr($chunk, 1, -1);
}
$tagName = strtolower($chunk);
$tagParam = '';
}
return array($tagName, $tagParam);
}
}
class bbCode extends bbCodeParser {
static $legacy_sync = 1348956841;
static $legacy_shard = array(
'ani' => 2363920179,
'lea' => 2437578274,
'ari' => 2358620001,
);
static $ig = false;
static $timezone = 'UTC';
static $clock12h = false;
static $shardid = false;
static $lang = 'en';
static $disabledTags = array();
//
const COLOR_P = '#d0d0d0'; // normal text
//
const COLOR_BBCODE_TAG = '#444444';
static function bbDisabled($tag) {
return in_array(strtolower($tag), self::$disabledTags);
}
static function getFontSize($value) {
$size = 16;
switch (strtolower($value)) {
case '1': case 'xx-small': $size = 9; break;
case '2': case 'x-small' : $size = 10; break;
case '3': case 'small' : $size = 13; break;
case '4': case 'medium' : $size = 16; break;
case '5': case 'large' : $size = 18; break;
case '6': case 'x-large' : $size = 24; break;
case '7': case 'xx-large': $size = 32; break;
//case '8': case 'smaller' : break;
//case '9': case 'larger' : break;
}
return $size;
}
static function bb_noparse($code) {
return preg_replace(array('/\[/', '/\]/'), array('&#91;', '&#93;'), $code);
}
static function bb_code($code) {
return '<pre>' . self::bb_noparse($code) . '</pre>';
}
static function bb_list($list) {
$result = '';
$list = str_replace("\n[", '[', $list);
$result = '<ul>' . preg_replace('/\s*\[\*\]\s*/is', "</li><li>", $list) . '</li></ul>';
return preg_replace('#<ul>\s*</li>#is', '<ul>', $result);
}
static function bb_quote($author, $text) {
if (self::$ig) {
// prevents [color] tag to take over color
$author = self::bb_color(self::COLOR_P, $author);
$text = self::bb_color(self::COLOR_P, $text);
// left/right border, top/bottom border height
$l = '<td width="1" bgcolor="#888888" height="1"></td>';
$r = '<td width="1" bgcolor="#888888" height="1"></td>';
return // 98% gives bit padding on the right
'<table width="98%" cellpadding="0" cellspacing="0" border="0">' .
'<tr><td width="1" height="5"></td><td></td><td></td></tr>' . // top padding - no border
'<tr>' . $l . '<td bgcolor="#888888"></td>' . $r . '</tr>' . // top border
'<tr>' . $l . '<td bgcolor="#000000" l_margin="5" height="3"></td>' . $r . '</tr>' . // author top padding
'<tr>' . $l . '<td bgcolor="#000000" l_margin="5">' . $author . '</td>' . $r . '</tr>' . // author
'<tr>' . $l . '<td bgcolor="#000000" l_margin="5" height="2"></td>' . $r . '</tr>' . // author bottom padding
'<tr>' . $l . '<td bgcolor="#555555" l_margin="10" height="3"></td>' . $r . '</tr>' . // quote top padding
'<tr>' . $l . '<td bgcolor="#555555" l_margin="10">' . $text . '</td>' . $r . '</tr>' . // quote
'<tr>' . $l . '<td bgcolor="#555555" l_margin="10" height="2"></td>' . $r . '</tr>' . // quote bottom padding
'<tr>' . $l . '<td bgcolor="#888888"></td>' . $r . '</tr>' . // bottom border
'<tr><td width="1" height="8"></td><td></td><td></td></tr>' . // bottom padding - no border
'</table>';
} else {
return '' .
'<div class="post-quote">' .
'<cite>' . $author . '</cite>' .
'<blockquote>' . $text . '</blockquote>' .
'</div>';
}
}
static function bb_h($nr, $color, $text) {
$tag = 'h' . $nr;
if (self::$ig) {
if ($color != '') {
$text = '<font color="' . $color . '">' . $text . '</font>';
}
return '<' . $tag . '>' . $text . '</' . $tag . '>';
} else {
if ($color != '') {
$style = ' style="color: ' . $color . ';"';
} else {
$style = '';
}
return '<' . $tag . $style . '>' . $text . '</' . $tag . '>';
}
}
static function bb_url($href, $text) {
// &quot;http://..../&quot; remove &quot; if present
if (substr($href, 0, 6) == '&quot;') {
if (substr($href, -6) == '&quot;') {
$href = substr($href, 6, -6);
} else {
$href = substr($href, 6);
}
}
if ($href == '')
$href = $text;
if ($text == '') {
$text = $href;
$text = wordwrap($text, 65, ' ', true);
}
$disable = self::bbDisabled('url');
// if not disabled and in ryzom and is proper url (<scheme>://<host>/)
if (!$disable && self::$ig) {
$url = @parse_url(strtolower($href));
$disable = true;
if (!empty($url['scheme']) && !empty($url['host'])) {
if (in_array($url['scheme'], array('http', 'https'))) {
if (in_array($url['host'], array('app.ryzom.com'))) {
if (empty($url['query']) || stripos($url['query'], 'redirect') === false) {
// http://atys.ryzom.com/
// and does not contain redirect
// - allow url in game browser
$disable = false;
}
}
}
} // !empty
}// isRYZOM
if ($disable) {
// empty href will give proper link color without 'underline' - perfect for 'disabled' links
if ($href == '') {
$text = '<a href="">' . $text . '</a>';
} else {
$href = wordwrap($href, 65, ' ', true);
$text = wordwrap($text, 65, ' ', true);
$text = '<a href="">' . $text . '</a> ' . self::bb_color(self::COLOR_BBCODE_TAG, '(' . $href . ')');
}
return $text;
}
// make sure http:// (or ftp:// or mailto:// etc is present), if not, add it
if (!preg_match('#://#', $href)) {
$href = 'http://' . $href;
}
return sprintf('<a href="%s"' . (self::$ig ? '' : ' target="_blank"') . '>%s</a>', $href, $text);
}
static function bb_img($attr, $href) {
if (self::bbDisabled('img')) {
return self::bb_noparse('[img]' . $href . '[/img]');
}
// $href is treated with htmlspecialchars() so any & in url is &amp;
$href = str_replace('&amp;', '&', $href);
// images from current server directly
if ($attr=='src' || strstr($href, $_SERVER['HTTP_HOST']) !== false){
return '<img src="' . $href . '" />';
}
$url = proxy_image_url($href);
return '<a href="' . $url . '&no_proxy=1"><img src="' . $url . '" /></a>';
}
static function bb_banner($lang, $ckey) {
// $lang and $ckey should already be escaped for HTML, so urlencode() in here would double escape them
// - channel it thru image proxy. proxy does caching better and uses '304 Not Modified' status
$src = 'http://atys.ryzom.com/api/banner.php?ckey=' . $ckey . '&langid=' . $lang . '&size=500';
return self::bb_img('', $src);
}
static function bb_mail($user) {
$url = 'http://' . $_SERVER['HTTP_HOST'] . '/app_mail/?page=compose/to/' . urlencode($user);
return '<a href="' . $url . '">' . $user . '</a>';
}
static function bb_profile($ptype, $pname) {
// types from app_profile
$types = array('user', 'player', 'npc', 'fauna', 'entity', 'source');
$ptype = array_search($ptype, $types, true);
// if type not found, then fall back to player
if ($ptype === false)
$ptype = 1;
$url = 'http://' . $_SERVER['HTTP_HOST'] . '/app_profile/?ptype=' . intval($ptype) . '&pname=' . urlencode($pname);
return '<a href="' . $url . '">' . $pname . '</a>';
}
static function bb_color($color, $str) {
if ($color == '') {
return $str;
}
if (self::$ig) {
return '<font color="' . $color . '">' . $str . '</font>';
} else {
return '<span style="color: ' . $color . ';">' . $str . '</span>';
}
}
static function bb_size($size, $str) {
$size = self::getFontSize($size);
if (self::$ig) {
return '<font size="' . $size . 'px">' . $str . '</font>';
} else {
return '<span style="font-size: ' . $size . 'px;">' . $str . '</span>';
}
}
static function bb_pre($str) {
return '<pre>' . $str . '</pre>';
}
static function bb_p($str) {
return '<p>' . $str . '</p>';
}
// Added by ulukyn. WebIg compatibility.
static function bb_center($str) {
if (self::$ig) {
return '<table width="100%" cellpadding="0" cellspacing="0"><tr><td align="center" valign="middle">' . $str . '</td></tr></table>';
} else {
return '<div style="text-align: center;">' . $str . '</div>';
}
}
/** Table format : (added by ulukyn)
* A1| A2|A3
* B1| B2 |B3
* C1|C2 |C3
*/
static function bb_table($attr, $content) {
$width = isset($attr['width'])?$attr['width']:'100%';
$border = isset($attr['border'])?$attr['border']:'0';
$bgcolor = isset($attr['bgcolor'])?' bgcolor="'.$attr['bgcolor'].'" ':'';
$ret = '<table width="'.$width.'" border="'.$border.'" cellpadding="0" cellspacing="0" '.$bgcolor.' >';
$lines = explode("\n", $content);
foreach ($lines as $line) {
if ($line) {
$ret .= '<tr>';
$cols = explode('|', $line);
foreach ($cols as $text) {
if (!$text)
continue;
$params = array('valign' => 'middle');
if ($text[0] == '#') {
$paramsdef = explode(' ', $text);
$paramlist = substr(array_shift($paramsdef), 1);
$paramlist = explode(',', $paramlist);
foreach ($paramlist as $p) {
list($name, $value) = explode('=', $p);
$params[ _h(str_replace('"', '', $name))] = _h(str_replace('"', '', $value));
}
if ($paramsdef)
$text = implode(' ', $paramsdef);
}
$param_html = '';
foreach ($params as $name => $value)
$param_html .= $name.'="'.$value.'" ';
if ($text && $text[0] == ' ' && $text[strlen($text)-1] == ' ')
$align = 'center';
else if ($text && $text[0] == ' ')
$align = 'right';
else
$align = 'left';
$ret .= '<td '.$param_html.' align="'.$align.'">'.$text.'</td>';
}
$ret .= '</tr>';
}
}
$ret .= '</table>';
return $ret;
}
static function bb_page_link($page, $txt) {
if ($page == '') {
$page = $txt;
}
$tmp = explode('/', $page);
foreach ($tmp as $k => $v) {
$tmp[$k] = urlencode($v);
}
$url = 'http://' . $_SERVER['HTTP_HOST'] . '/app_forum/?page=' . join('/', $tmp);
return '<a href="' . $url . '">' . $txt . '</a>';
}
static function bb_forum_link($page, $id, $txt) {
$page = $page . '/view/' . $id;
if ($id == '') {
$page.= $txt;
}
return self::bb_page_link($page, $txt);
}
// Added by Ulukyn
static function bb_wiki_link($page, $txt) {
$need_new_txt = false;
if ($page == '') {
$page = $txt;
$need_new_txt = true;
}
if (substr($page, 0, 22) == 'http://atys.ryzom.com/')
$url = 'http://atys.ryzom.com/start/app_wiki.php?page=' . substr($page, 21);
else {
$tmp = explode('/', $page);
if (count($tmp) != 2) {
return 'Syntax: [wiki]/[page], ex: en/Chronicles';
} else {
$wiki = $tmp[0];
$page = $tmp[1];
}
if (self::$ig) {
$url = 'http://atys.ryzom.com/start/app_wiki.php?page=/projects/pub' . $wiki . '/wiki/' . $page;
}
else
$url = 'http://atys.ryzom.com/projects/pub' . $wiki . '/wiki/' . $page;
if ($need_new_txt)
$txt = 'WIKI [' . $page . ']';
}
return '<a href="' . $url . '"' . (self::$ig ? '' : ' target="_blank"') . '>' . $txt . '</a>';
}
static function bb_biu($tag, $txt) {
$tag = strtolower($tag);
if (self::$ig) {
switch ($tag) {
// FIXME: darken/lighter or tint current color
case 'b': $txt = self::bb_color('white', $txt);
break;
case 'i': $txt = self::bb_color('#ffffd0', $txt);
break;
case 'u': $txt = '<a href="ah:">' . self::bb_color(self::COLOR_P, $txt) . '</a>';
break;
default : $txt = self::bb_color(self::COLOR_BBCODE_TAG, $txt);
break; // fallback
}
return $txt;
}
switch ($tag) {
case 'b': $tag = 'strong';
break;
case 'i': $tag = 'em';
break;
case 'u': $tag = 'u';
break;
default: $tag = 'span'; // fallback
}
return '<' . $tag . '>' . $txt . '</' . $tag . '>';
}
static function bb_date($attr, $txt) {
$time = strtotime($txt);
$shardid = isset($attr['shard']) ? $attr['shard'] : self::$shardid;
if ($time === false || $shardid === false)
return 'ERR:[' . $txt . ']';
if (isset(self::$legacy_shard[$shardid])) {
$tick = self::$legacy_shard[$shardid];
if (self::$legacy_sync > $time) {
// only modify game cycle when asked time is before sync
$tick = ($time - self::$legacy_sync) * 10 + $tick;
}
} else {
$tick = ryzom_time_tick($shardid);
// tick is for NOW, adjust it to match time given
$now = time();
$tick = ($time - $now) * 10 + $tick;
}
$rytime = ryzom_time_array($tick, $shardid);
$txt = ryzom_time_txt($rytime, self::$lang);
return $txt;
}
static function bb_lang($attr, $txt) {
if (_user()->lang == $attr)
return $txt;
else
return '';
}
static function bb_time($options, $txt) {
$time = strtotime($txt);
if ($time == 0) {
return $txt;
}
$timezone = self::$timezone;
$show_time = '';
$show_date = '';
$show_timer = '';
if (is_array($options)) {
foreach ($options as $key => $val) {
switch ($key) {
case 'timezone':
// fix some timezones for php
switch ($val) {
case 'pst': // fall thru
case 'pdt': $val = 'US/Pacific';
break;
}
$timezone = $val;
break;
case 'date' :
$show_date = $val == 'off' ? false : $val;
break;
case 'time' :
$show_time = $val == 'off' ? false : $val;
break;
case 'timer':
$show_timer = $val == 'off' ? false : $val;
break;
}//switch
}//foreach
}
$ret = array();
$old_timezone = date_default_timezone_get();
@date_default_timezone_set($timezone);
if ($show_date !== false) {
$date = ryzom_absolute_time($time);
//ryzom_absolute_time does not have year, so we need to add it
$current_y = date('Y', time());
$y = date('Y', $time);
if ($y != $current_y) {
$date.= ' ' . $y;
}
$ret[] = self::bb_color($show_date, $date);
}
if ($show_time !== false) {
$fmtTime = self::$clock12h ? 'g:i:s a T' : 'H:i:s T';
$ret[] = self::bb_color($show_time, date($fmtTime, $time));
}
date_default_timezone_set($old_timezone);
if ($show_timer !== false) {
if ($show_time === false && $show_date === false) {
$f = '%s';
} else {
$f = '(%s)';
}
$ret[] = self::bb_color($show_timer, sprintf($f, ryzom_relative_time($time)));
}
return join(' ', $ret);
}
/**
* This function is called by bbCodeParser class
*
* @see bbCodeParser::format
*/
public function format($tag, $open, $close, $attr, $text) {
// silly functions all have different parameters
switch ($tag) {
case 'noparse' :
$result = self::bb_noparse($text);
break;
case 'code' :
$result = self::bb_code($text);
break;
case 'quote' :
$result = self::bb_quote($attr, $text);
break;
case 'h1' : // fall thru
case 'h2' : // fall thru
case 'h3' : // fall thru
case 'h4' : // fall thru
case 'h5' : // fall thru
case 'h6' :
$nr = (int) substr($tag, -1);
$color = isset($attr['color']) ? $attr['color'] : '';
$result = self::bb_h($nr, $color, $text);
break;
case 'color' :
$result = self::bb_color($attr, $text);
break;
case 'size' :
$result = self::bb_size($attr, $text);
break;
case 'list' :
$result = self::bb_list($text);
break;
case 'img' :
$result = self::bb_img($attr, $text);
break;
case 'banner' :
$result = self::bb_banner($attr, $text);
break;
case 'pre' :
$result = self::bb_pre($text);
break;
case 'p' :
$result = self::bb_p($text);
break;
case 'table' :
$result = self::bb_table($attr, $text);
break;
case 'center' :
$result = self::bb_center($text);
break;
case 'url' :
$result = self::bb_url($attr, $text);
break;
case 'mail' :
$result = self::bb_mail($text);
break;
case 'profile' :
$result = self::bb_profile($attr, $text);
break;
case 'page' :
$result = self::bb_page_link($attr, $text);
break;
case 'forum' : // fall thru
case 'topic' : // fall thru
case 'post' :
$result = self::bb_forum_link($tag, $attr, $text);
break;
case 'wiki' :
$result = self::bb_wiki_link($attr, $text);
break;
case 'b' : // fall thru
case 'i' : // fall thru
case 'u' :
$result = self::bb_biu($tag, $text);
break;
case 'time' :
$result = self::bb_time($attr, $text);
break;
case 'date' :
$result = self::bb_date($attr, $text);
break;
case 'lang' :
$result = self::bb_lang($attr, $text);
break;
default :
$result = $open . $text . $close;
break;
}
return $result;
}
/**
* Replaces some BBcode with HTML code
*
* NOTE: $text should be already escaped for HTML
*
* @param string $text html escaped input text
* @param array $disabledTags
*/
static function parse($text, $disabledTags = array()) {
static $parser = null;
if ($parser === null) {
$parser = new self(self::$ig);
}
$parser->reset();
self::$disabledTags = $disabledTags;
return $parser->bbcode($text);
}
}