.
*/
/**
* Collection of tag functions.
*
* @package Tag
*/
Txp::get('\Textpattern\Tag\Registry')
->register('page_title')
->register('css')
->register('image')
->register('thumbnail')
->register('output_form')
->register('txp_yield', 'yield')
->register('txp_if_yield', 'if_yield')
->register('feed_link')
->register('link_feed_link')
->register('linklist')
->register('tpt_link', 'link')
->register('linkdesctitle')
->register('link_name')
->register('link_url')
->register('link_author')
->register('link_description')
->register('link_date')
->register('link_category')
->register('link_id')
->register('if_first', 'if_first_link', 'link')
->register('if_last', 'if_last_link', 'link')
->register('email')
->register('password_protect')
->register('recent_articles')
->register('recent_comments')
->register('related_articles')
->register('popup')
->register('category_list')
->register('section_list')
->register('search_input')
->register('search_term')
->register('link_to', 'link_to_next')
->register('link_to', 'link_to_prev', 'prev')
->register('next_title')
->register('prev_title')
->register('site_name')
->register('site_slogan')
->register('link_to_home')
->register('txp_pager', 'newer', true)
->register('txp_pager', 'older', false)
->register('txp_pager', 'pages')
->register('text')
->register('article_id')
->register('article_url_title')
->register('if_article_id')
->register('posted')
->register('posted', 'modified', 'modified')
->register('posted', 'expires', 'expires')
->register('if_expires')
->register('if_expired')
->register('comments_count')
->register('comments_invite')
->register('comments_form')
->register('comments_error')
->register('if_comments_error')
->register('comments')
->register('comments_preview')
->register('if_comments_preview')
->register('comment_permlink')
->register('comment_id')
->register('comment_name')
->register('comment_email')
->register('comment_web')
->register('comment_time')
->register('comment_message')
->register('comment_anchor')
->register(array('\Textpattern\Tag\Syntax\Authors', 'renderAuthors'), 'authors')
->register('author')
->register('author_email')
->register('if_author')
->register('if_article_author')
->register('body')
->register('title')
->register('excerpt')
->register('article_category', 'category1')
->register('article_category', array('category2', array('number' => 2)))
->register('category')
->register('section')
->register('keywords')
->register('if_keywords')
->register('if_description')
->register('if_article_image')
->register('article_image')
->register('search_result_title')
->register('search_result_excerpt')
->register('search_result_url')
->register('search_result_date')
->register('search_result_count')
->register('image_index')
->register('image_display')
->register('images')
->register('image_info')
->register('image_url')
->register('image_author')
->register('image_date')
->register('if_first', 'if_first_image', 'image')
->register('if_last', 'if_last_image', 'image')
->register('if_thumbnail')
->register('if_comments')
->register('if_comments_allowed')
->register('if_comments_disallowed')
->register('if_individual_article')
->register('if_article_list')
->register('meta_keywords')
->register('meta_description')
->register('meta_author')
->register('permlink')
->register('lang')
->register('breadcrumb')
->register('if_excerpt')
->register('if_search')
->register('if_search_results')
->register('if_category')
->register('if_article_category')
->register('if_first', 'if_first_category', 'category')
->register('if_last', 'if_last_category', 'category')
->register('if_section')
->register('if_article_section')
->register('if_first', 'if_first_section', 'section')
->register('if_last', 'if_last_section', 'section')
->register('if_logged_in')
->register('if_request')
->register('php')
->register('txp_header', 'header')
->register('custom_field')
->register('if_custom_field')
->register('site_url')
->register('error_message')
->register('error_status')
->register('if_status')
->register('page_url')
->register('if_different')
->register('if_first', 'if_first_article')
->register('if_last', 'if_last_article')
->register('if_plugin')
->register('file_download_list')
->register('file_download')
->register('file_download_link')
->register('file_download_size')
->register('file_download_time', 'file_download_created')
->register('file_download_time', 'file_download_modified', 'modified')
->register('file_download_id')
->register('file_download_name')
->register('file_download_category')
->register('file_download_author')
->register('file_download_downloads')
->register('file_download_description')
->register('if_first', 'if_first_file', 'file')
->register('if_last', 'if_last_file', 'file')
->register('hide')
->register('rsd')
->register('variable')
->register('if_variable')
->register('article')
->register('article_custom')
->register('txp_die')
->register('txp_eval', 'evaluate')
->register('comments_help')
->register('comment_input', 'comment_name_input')
->register('comment_input', 'comment_email_input', 'email', 'clean_url')
->register('comment_input', array('comment_web_input', array('placeholder' => 'http(s)://')), 'web', 'clean_url')
->register('comment_message_input')
->register('comment_remember')
->register('comment_preview')
->register('comment_submit')
// Global attributes (false just removes unknown attribute warning)
->registerAttr(false, 'class, html_id, labeltag')
->registerAttr(true, 'not, txp-process, breakby, breakclass, wrapform, evaluate')
->registerAttr('txp_escape', 'escape')
->registerAttr('txp_wraptag', 'wraptag, label, trim, replace, default');
// -------------------------------------------------------------
function page_title($atts)
{
global $parentid, $thisarticle, $q, $c, $author, $context, $s, $pg, $sitename;
extract(lAtts(array('separator' => ' | '), $atts));
$appending = txpspecialchars($separator.$sitename);
$parent_id = (int) $parentid;
$pageStr = ($pg ? $separator.gTxt('page').' '.$pg : '');
if ($parent_id) {
$out = gTxt('comments_on').' '.escape_title(safe_field("Title", 'textpattern', "ID = $parent_id")).$appending;
} elseif (isset($thisarticle['title'])) {
$out = escape_title($thisarticle['title']).$appending;
} elseif ($q) {
$out = gTxt('search_results').' '.gTxt('txt_quote_double_open').txpspecialchars($q).gTxt('txt_quote_double_close').$pageStr.$appending;
} elseif ($c) {
$out = txpspecialchars(fetch_category_title($c, $context)).$pageStr.$appending;
} elseif ($s && $s != 'default') {
$out = txpspecialchars(fetch_section_title($s)).$pageStr.$appending;
} elseif ($author) {
$out = txpspecialchars(get_author_name($author)).$pageStr.$appending;
} elseif ($pg) {
$out = gTxt('page').' '.$pg.$appending;
} else {
$out = txpspecialchars($sitename);
}
return $out;
}
// -------------------------------------------------------------
function css($atts)
{
global $css, $doctype, $pretext;
extract(lAtts(array(
'format' => 'url',
'media' => 'screen',
'name' => $css,
'rel' => 'stylesheet',
'theme' => $pretext['skin'],
'title' => '',
), $atts));
if (empty($name)) {
$name = 'default';
}
$out = '';
$format = strtolower(preg_replace('/\s+/', '', $format));
list($mode, $format) = explode('.', $format.'.'.$format);
if (has_handler('css.url')) {
$url = callback_event('css.url', '', false, compact('name', 'theme'));
} elseif ($mode === 'flat') {
$url = array();
$skin_dir = urlencode(get_pref('skin_dir'));
foreach (do_list_unique($name) as $n) {
$url[] = hu.$skin_dir.'/'.urlencode($theme).'/'.Txp::get('Textpattern\Skin\Css')->getDir().'/'.urlencode($n).'.css';
}
} else {
$url = hu.'css.php?n='.urlencode($name).'&t='.urlencode($theme);
}
switch ($format) {
case 'link':
foreach ((array)$url as $href) {
$out .= tag_void('link', array(
'rel' => $rel,
'type' => $doctype != 'html5' ? 'text/css' : '',
'media' => $media,
'title' => $title,
'href' => $href,
)).n;
}
break;
default:
$out .= txpspecialchars(is_array($url) ? implode(',', $url) : $url);
break;
}
return $out;
}
// -------------------------------------------------------------
function component($atts)
{
global $doctype, $pretext, $txp_context;
static $mimetypes = null, $dir = null,
$internals = array('id', 's', 'c', 'context', 'q', 'm', 'pg', 'p', 'month', 'author'),
$defaults = array(
'format' => 'url',
'form' => '',
'context' => null,
'rel' => '',
'title' => '',
);
if (!isset($mimetypes)) {
$mimetypes = Txp::get('Textpattern\Skin\Form')->getMimeTypes();
$dir = urlencode(Txp::get('Textpattern\Skin\Form')->getDir());
}
extract(lAtts($defaults, $atts, false));
if (empty($form)) {
return;
}
$format = strtolower(preg_replace('/\s+/', '', $format));
list($mode, $format) = explode('.', $format.'.'.$format);
$theme = urlencode($pretext['skin']);
$out = '';
$qs = get_context($context, $internals) + array_diff_key($atts, $defaults);
if ($mode === 'flat') {
$url = array();
$skin_dir = urlencode(get_pref('skin_dir'));
foreach (do_list_unique($form) as $n) {
$type = pathinfo($n, PATHINFO_EXTENSION);
if (isset($mimetypes[$type])) {
$url[] = hu.$skin_dir.'/'.$theme.'/'.$dir.'/'.urlencode($type).'/'.urlencode($n).($qs ? join_qs($qs) : '');
} else {
$url[] = pagelinkurl(array('f' => $n) + $qs);
}
}
} else {
$url = pagelinkurl(array('f' => $form) + $qs);
}
switch ($format) {
case 'url':
case 'flat':
$out .= is_array($url) ? implode(',', $url) : $url;
break;
case 'link':
foreach ((array)$url as $href) {
$out .= tag_void('link', array(
'rel' => $rel,
'title' => $title,
'href' => $href,
)).n;
}
break;
case 'script':
foreach ((array)$url as $href) {
$out .= tag(null, 'script', array(
'title' => $title,
'type' => $doctype != 'html5' ? 'application/javascript' : '',
'src' => $href,
)).n;
}
break;
case 'image':
foreach ((array)$url as $href) {
$out .= tag_void('img', array(
'title' => $title,
'src' => $href,
)).n;
}
break;
default:
foreach ((array)$url as $href) {
$out .= href($title ? $title : $href, $href, array(
'rel' => $rel,
)).n;
}
}
return $out;
}
// -------------------------------------------------------------
function image($atts)
{
return thumbnail(array('thumbnail' => isset($atts['thumbnail']) ? $atts['thumbnail'] : false) + $atts);
}
// -------------------------------------------------------------
function thumbnail($atts)
{
global $doctype;
extract(lAtts(array(
'escape' => true,
'title' => '',
'class' => '',
'html_id' => '',
'height' => '',
'id' => '',
'link' => 0,
'link_rel' => '',
'loading' => null,
'name' => '',
'poplink' => 0, // Deprecated, 4.7
'style' => '',
'wraptag' => '',
'width' => '',
'thumbnail' => null,
), $atts));
if (isset($atts['poplink'])) {
trigger_error(gTxt('deprecated_attribute', array('{name}' => 'poplink')), E_USER_NOTICE);
}
if ($imageData = imageFetchInfo($id, $name)) {
$thumb_ = $thumbnail || !isset($thumbnail) ? 'thumb_' : '';
if ($thumb_ && empty($imageData['thumbnail'])) {
$thumb_ = '';
if (!isset($thumbnail)) {
return;
}
}
extract($imageData);
if ($escape) {
$alt = txp_escape(array('escape' => $escape), $alt);
}
if ($title === true) {
$title = $caption;
}
if ($width == '' && ($thumb_ && $thumb_w || !$thumb_ && $w)) {
$width = ${$thumb_.'w'};
}
if ($height == '' && ($thumb_ && $thumb_h || !$thumb_ && $h)) {
$height = ${$thumb_.'h'};
}
$out = ''.$out.'';
}
return $wraptag ? doTag($out, $wraptag, $class, '', $html_id) : $out;
}
}
// -------------------------------------------------------------
function output_form($atts, $thing = null)
{
global $txp_atts, $yield, $txp_yield;
if (empty($atts['form'])) {
trigger_error(gTxt('form_not_specified'));
return '';
}
$form = $atts['form'];
$to_yield = isset($atts['yield']) ? $atts['yield'] : false;
unset($atts['form'], $atts['yield'], $txp_atts['form'], $txp_atts['yield']);
if ($form === true && empty($atts)) {
return fetch_form(do_list_unique($to_yield));
}
if (!empty($to_yield)) {
$to_yield = $to_yield === true ? $atts : array_fill_keys(do_list_unique($to_yield), null);
empty($txp_atts) or $txp_atts = array_diff_key($txp_atts, $to_yield);
}
if (isset($atts['format'])) {// component
empty($txp_atts) or $atts = array_diff_key($atts, $txp_atts);
return component($atts + array('form' => $form));
} elseif (is_array($to_yield)) {
$atts = lAtts($to_yield, $atts) or $atts = array();
}
foreach ($atts as $name => $value) {
if (!isset($txp_yield[$name])) {
$txp_yield[$name] = array();
}
$txp_yield[$name][] = array($value, false);
}
$yield[] = $thing;
$out = parse_form($form);
array_pop($yield);
foreach ($atts as $name => $value) {
$result = array_pop($txp_yield[$name]);
if (!empty($result[1])) {
unset($txp_atts[$name]);
}
}
return $out;
}
// -------------------------------------------------------------
function txp_yield($atts, $thing = null)
{
global $yield, $txp_yield, $txp_atts, $txp_item;
extract(lAtts(array(
'name' => '',
'else' => false,
'default' => false,
'item' => null
), $atts));
if (isset($item)) {
$inner = isset($txp_item[$item]) ? $txp_item[$item] : null;
} elseif ($name === '') {
$end = empty($yield) ? null : end($yield);
if (isset($end)) {
$inner = parse($end, empty($else));
}
} elseif (!empty($txp_yield[$name])) {
list($inner) = end($txp_yield[$name]);
$txp_yield[$name][key($txp_yield[$name])][1] = true;
}
if (!isset($inner)) {
$escape = isset($txp_atts['escape']) ? $txp_atts['escape'] : null;
$inner = $default !== false ?
($default === true ? page_url(array('type' => $name, 'escape' => $escape)) : $default) :
($thing ? parse($thing) : $thing);
}
return $inner;
}
function txp_if_yield($atts, $thing = null)
{
global $yield, $txp_yield, $txp_item;
extract(lAtts(array(
'name' => '',
'else' => false,
'value' => null,
'item' => null
), $atts));
if (isset($item)) {
$inner = isset($txp_item[$item]) ? $txp_item[$item] : null;
} elseif ($name === '') {
$end = empty($yield) ? null : end($yield);
if (isset($end)) {
$inner = $value === null ? ($else ? getIfElse($end, false) : true) : parse($end, empty($else));
}
} elseif (empty($txp_yield[$name])) {
$inner = null;
} else {
list($inner) = end($txp_yield[$name]);
}
return parse($thing, isset($inner) && ($value === null || (string)$inner === (string)$value || $inner && $value === true));
}
// -------------------------------------------------------------
function feed_link($atts, $thing = null)
{
global $s, $c;
extract(lAtts(array(
'category' => $c,
'flavor' => 'rss',
'format' => 'a',
'label' => '',
'limit' => '',
'section' => ($s == 'default' ? '' : $s),
'title' => gTxt('rss_feed_title'),
), $atts));
$url = pagelinkurl(array(
$flavor => '1',
'section' => $section,
'category' => $category,
'limit' => $limit,
));
if ($flavor == 'atom') {
$title = ($title == gTxt('rss_feed_title')) ? gTxt('atom_feed_title') : $title;
}
$title = txpspecialchars($title);
$type = ($flavor == 'atom') ? 'application/atom+xml' : 'application/rss+xml';
if ($format == 'link') {
return '';
}
$txt = ($thing === null ? $label : parse($thing));
$out = href($txt, $url, array(
'type' => $type,
'title' => $title,
));
return $out;
}
// -------------------------------------------------------------
function link_feed_link($atts)
{
global $c;
extract(lAtts(array(
'category' => $c,
'flavor' => 'rss',
'format' => 'a',
'label' => '',
'title' => gTxt('rss_feed_title'),
'wraptag' => '',
'class' => __FUNCTION__,
), $atts));
$url = pagelinkurl(array(
$flavor => '1',
'area' => 'link',
'category' => $category,
));
if ($flavor == 'atom') {
$title = ($title == gTxt('rss_feed_title')) ? gTxt('atom_feed_title') : $title;
}
$title = txpspecialchars($title);
$type = ($flavor == 'atom') ? 'application/atom+xml' : 'application/rss+xml';
if ($format == 'link') {
return '';
}
$out = href($label, $url, array(
'type' => $type,
'title' => $title,
));
return ($wraptag) ? doTag($out, $wraptag, $class) : $out;
}
// -------------------------------------------------------------
function linklist($atts, $thing = null)
{
global $s, $c, $context, $thislink, $thispage, $pretext;
extract(lAtts(array(
'break' => '',
'category' => '',
'author' => '',
'realname' => '',
'auto_detect' => 'category, author',
'class' => __FUNCTION__,
'form' => 'plainlinks',
'id' => '',
'pageby' => '',
'limit' => 0,
'offset' => 0,
'month' => '',
'time' => null,
'sort' => 'linksort asc',
'wraptag' => '',
), $atts));
$where = array();
$filters = isset($atts['category']) || isset($atts['author']) || isset($atts['realname']);
$context_list = (empty($auto_detect) || $filters) ? array() : do_list_unique($auto_detect);
$pageby = ($pageby == 'limit') ? $limit : $pageby;
if ($category) {
$where[] = "category IN ('".join("','", doSlash(do_list_unique($category)))."')";
}
if ($id) {
$where[] = "id IN ('".join("','", doSlash(do_list_unique($id, array(',', '-'))))."')";
}
if ($author) {
$where[] = "author IN ('".join("','", doSlash(do_list_unique($author)))."')";
}
if ($realname) {
$authorlist = safe_column("name", 'txp_users', "RealName IN ('".join("','", doArray(doSlash(do_list_unique($realname)), 'urldecode'))."')");
if ($authorlist) {
$where[] = "author IN ('".join("','", doSlash($authorlist))."')";
}
}
// If no links are selected, try...
if (!$where && !$filters) {
foreach ($context_list as $ctxt) {
switch ($ctxt) {
case 'category':
// ...the global category in the URL.
if ($context == 'link' && !empty($c)) {
$where[] = "category = '".doSlash($c)."'";
}
break;
case 'author':
// ...the global author in the URL.
if ($context == 'link' && !empty($pretext['author'])) {
$where[] = "author = '".doSlash($pretext['author'])."'";
}
break;
}
// Only one context can be processed.
if ($where) {
break;
}
}
}
if (!$where && $filters) {
// If nothing matches, output nothing.
return '';
}
if ($time === null || $time || $month) {
$where[] = buildTimeSql($month, $time === null ? 'past' : $time, 'date');
}
if (!$where) {
// If nothing matches, start with all links.
$where[] = "1 = 1";
}
$where = join(" AND ", $where);
// Set up paging if required.
if ($limit && $pageby) {
$pg = (!$pretext['pg']) ? 1 : $pretext['pg'];
$pgoffset = $offset + (($pg - 1) * $pageby);
if (empty($thispage)) {
$grand_total = safe_count('txp_link', $where);
$total = $grand_total - $offset;
$numPages = ($pageby > 0) ? ceil($total/$pageby) : 1;
// Send paging info to txp:newer and txp:older.
$pageout['pg'] = $pg;
$pageout['numPages'] = $numPages;
$pageout['s'] = $s;
$pageout['c'] = $c;
$pageout['context'] = 'link';
$pageout['grand_total'] = $grand_total;
$pageout['total'] = $total;
$thispage = $pageout;
}
} else {
$pgoffset = $offset;
}
$qparts = array(
$where,
'ORDER BY '.sanitizeForSort($sort),
($limit) ? 'LIMIT '.intval($pgoffset).', '.intval($limit) : '',
);
$rs = safe_rows_start("*, UNIX_TIMESTAMP(date) AS uDate", 'txp_link', join(' ', $qparts));
if ($rs) {
$count = 0;
$last = numRows($rs);
$out = array();
while ($a = nextRow($rs)) {
++$count;
$thislink = $a;
$thislink['date'] = $thislink['uDate'];
$thislink['is_first'] = ($count == 1);
$thislink['is_last'] = ($count == $last);
unset($thislink['uDate']);
$out[] = ($thing) ? parse($thing) : parse_form($form);
$thislink = '';
}
if ($out) {
return doWrap($out, $wraptag, $break, $class);
}
}
return '';
}
// -------------------------------------------------------------
// NOTE: tpt_ prefix used because link() is a PHP function. See publish.php.
function tpt_link($atts)
{
global $thislink;
extract(lAtts(array(
'rel' => '',
'id' => '',
'name' => '',
'escape' => true,
), $atts));
$rs = $thislink;
$sql = array();
if ($id) {
$sql[] = "id = ".intval($id);
} elseif ($name) {
$sql[] = "linkname = '".doSlash($name)."'";
}
if ($sql) {
$rs = safe_row("linkname, url", 'txp_link', implode(" AND ", $sql)." LIMIT 1");
}
if (!$rs) {
trigger_error(gTxt('unknown_link'));
return '';
}
return tag(
$escape ? txp_escape(array('escape' => $escape), $rs['linkname']) : $rs['linkname'], 'a',
($rel ? ' rel="'.txpspecialchars($rel).'"' : '').
' href="'.txpspecialchars($rs['url']).'"'
);
}
// -------------------------------------------------------------
function linkdesctitle($atts)
{
global $thislink;
assert_link();
extract(lAtts(array('rel' => '', 'escape' => true), $atts));
$description = ($thislink['description'])
? ' title="'.txpspecialchars($thislink['description']).'"'
: '';
return tag(
$escape ? txp_escape(array('escape' => $escape), $thislink['linkname']) : $thislink['linkname'], 'a',
($rel ? ' rel="'.txpspecialchars($rel).'"' : '').
' href="'.doSpecial($thislink['url']).'"'.$description
);
}
// -------------------------------------------------------------
function link_name($atts)
{
global $thislink;
assert_link();
extract(lAtts(array('escape' => null), $atts));
return ($escape === null)
? txpspecialchars($thislink['linkname'])
: $thislink['linkname'];
}
// -------------------------------------------------------------
function link_url()
{
global $thislink;
assert_link();
return doSpecial($thislink['url']);
}
// -------------------------------------------------------------
function link_author($atts)
{
global $thislink, $s;
assert_link();
extract(lAtts(array(
'link' => 0,
'title' => 1,
'section' => '',
'this_section' => '',
), $atts));
if ($thislink['author']) {
$author_name = get_author_name($thislink['author']);
$display_name = txpspecialchars(($title) ? $author_name : $thislink['author']);
$section = ($this_section) ? ($s == 'default' ? '' : $s) : $section;
$author = ($link)
? href($display_name, pagelinkurl(array(
's' => $section,
'author' => $author_name,
'context' => 'link',
)))
: $display_name;
return $author;
}
}
// -------------------------------------------------------------
function link_description($atts)
{
global $thislink;
assert_link();
extract(lAtts(array('escape' => null), $atts));
if ($thislink['description']) {
return ($escape === null) ?
txpspecialchars($thislink['description']) :
$thislink['description'];
}
}
// -------------------------------------------------------------
function link_date($atts)
{
global $thislink, $dateformat;
assert_link();
extract(lAtts(array(
'format' => $dateformat,
'gmt' => '',
'lang' => '',
), $atts));
return safe_strftime($format, $thislink['date'], $gmt, $lang);
}
// -------------------------------------------------------------
function link_category($atts)
{
global $thislink;
assert_link();
extract(lAtts(array('title' => 0), $atts));
if ($thislink['category']) {
$category = ($title)
? fetch_category_title($thislink['category'], 'link')
: $thislink['category'];
return $category;
}
}
// -------------------------------------------------------------
function link_id()
{
global $thislink;
assert_link();
return $thislink['id'];
}
// -------------------------------------------------------------
function email($atts, $thing = null)
{
extract(lAtts(array(
'email' => '',
'linktext' => gTxt('contact'),
'title' => '',
), $atts));
if ($email) {
if ($thing !== null) {
$linktext = parse($thing);
}
// Obfuscate link text?
if (is_valid_email($linktext)) {
$linktext = Txp::get('\Textpattern\Mail\Encode')->entityObfuscateAddress($linktext);
}
return href(
$linktext,
Txp::get('\Textpattern\Mail\Encode')->entityObfuscateAddress('mailto:'.$email),
($title ? ' title="'.txpspecialchars($title).'"' : '')
);
}
return '';
}
// -------------------------------------------------------------
function password_protect($atts, $thing = null)
{
ob_start();
extract(lAtts(array(
'login' => null,
'pass' => null,
'privs' => null,
), $atts));
if ($pass === null) {
$access = ($user = is_logged_in($login)) !== false && ($privs === null || in_list($user['privs'], $privs));
} else {
$au = serverSet('PHP_AUTH_USER');
$ap = serverSet('PHP_AUTH_PW');
// For PHP as (f)cgi, two rules in htaccess often allow this workaround.
$ru = serverSet('REDIRECT_REMOTE_USER');
if (!$au && !$ap && strpos($ru, 'Basic') === 0) {
list($au, $ap) = explode(':', base64_decode(substr($ru, 6)));
}
$access = $au === $login && $ap === $pass;
}
if ($access === false && $pass !== null) {
header('WWW-Authenticate: Basic realm="Private"');
}
if ($thing === null) {
if ($access === false) {
txp_die(gTxt('auth_required'), '401');
}
return '';
}
return parse($thing, $access);
}
// -------------------------------------------------------------
function recent_articles($atts, $thing = null)
{
global $prefs;
$atts = lAtts(array(
'break' => 'br',
'category' => '',
'class' => __FUNCTION__,
'form' => '',
'label' => gTxt('recent_articles'),
'labeltag' => '',
'limit' => 10,
'offset' => 0,
'section' => '',
'sort' => 'Posted DESC',
'wraptag' => '',
'no_widow' => '',
), $atts);
if (!isset($thing) && !$atts['form']) {
$thing = '';
}
unset($atts['no_widow']);
return article_custom($atts, $thing);
}
// -------------------------------------------------------------
function recent_comments($atts, $thing = null)
{
global $prefs;
global $thisarticle, $thiscomment;
extract(lAtts(array(
'break' => br,
'class' => __FUNCTION__,
'form' => '',
'limit' => 10,
'offset' => 0,
'sort' => 'posted DESC',
'wraptag' => '',
), $atts));
$sort = preg_replace('/\bposted\b/', 'd.posted', $sort);
$expired = ($prefs['publish_expired_articles']) ? '' : " AND (".now('expires')." <= t.Expires OR t.Expires IS NULL) ";
$rs = startRows("SELECT d.name, d.email, d.web, d.message, d.discussid, UNIX_TIMESTAMP(d.Posted) AS time, t.ID AS thisid,
UNIX_TIMESTAMP(t.Posted) AS posted, t.Title AS title, t.Section AS section, t.Category1, t.Category2, t.url_title
FROM ".safe_pfx('txp_discuss')." AS d INNER JOIN ".safe_pfx('textpattern')." AS t ON d.parentid = t.ID
WHERE t.Status >= ".STATUS_LIVE.$expired." AND d.visible = ".VISIBLE."
ORDER BY ".sanitizeForSort($sort)."
LIMIT ".intval($offset).", ".intval($limit));
if ($rs) {
$out = array();
$old_article = $thisarticle;
while ($c = nextRow($rs)) {
if ($form === '' && $thing === null) {
$out[] = href(
txpspecialchars($c['name']).' ('.escape_title($c['title']).')',
permlinkurl($c).'#c'.$c['discussid']
);
} else {
$thiscomment['name'] = $c['name'];
$thiscomment['email'] = $c['email'];
$thiscomment['web'] = $c['web'];
$thiscomment['message'] = $c['message'];
$thiscomment['discussid'] = $c['discussid'];
$thiscomment['time'] = $c['time'];
// Allow permlink guesstimation in permlinkurl(), elsewhere.
$thisarticle['thisid'] = $c['thisid'];
$thisarticle['posted'] = $c['posted'];
$thisarticle['title'] = $c['title'];
$thisarticle['section'] = $c['section'];
$thisarticle['url_title'] = $c['url_title'];
if ($thing === null && $form !== '') {
$out[] = parse_form($form);
} else {
$out[] = parse($thing);
}
}
}
if ($out) {
unset($GLOBALS['thiscomment']);
$thisarticle = $old_article;
return doWrap($out, $wraptag, $break, $class);
}
}
return '';
}
// -------------------------------------------------------------
function related_articles($atts, $thing = null)
{
global $thisarticle, $prefs;
assert_article();
$atts = lAtts(array(
'break' => br,
'class' => __FUNCTION__,
'form' => '',
'limit' => 10,
'offset' => 0,
'match' => 'Category',
'no_widow' => '',
'section' => '',
'sort' => 'Posted DESC',
'wraptag' => '',
), $atts);
$match = array_intersect(do_list_unique(strtolower($atts['match'])), array_merge(array('category', 'category1', 'category2', 'author', 'keywords'), getCustomFields()));
$categories = $cats = array();
foreach ($match as $cf) {
switch ($cf) {
case 'category':
case 'category1':
case 'category2':
foreach(($cf == 'category' ? array('category1', 'category2') : array($cf)) as $cat) {
if (!empty($thisarticle[$cat])) {
$cats[] = $thisarticle[$cat];
}
}
$categories[] = ucwords($cf);
break;
case 'author':
$atts['author'] = $thisarticle['authorid'];
break;
default:
if (empty($thisarticle[$cf])) {
return '';
}
$atts[$cf] = $thisarticle[$cf];
break;
}
}
if (!empty($cats)) {
$atts['category'] = implode(',', $cats);
} elseif ($categories) {
return '';
}
$atts['match'] = implode(',', $categories);
$atts['exclude'] = $thisarticle['thisid'];
if ($atts['form'] === '' && $thing === null) {
$thing = '';
}
unset($atts['no_widow']);
return article_custom($atts, $thing);
}
// -------------------------------------------------------------
function popup($atts)
{
global $s, $c, $permlink_mode;
extract(lAtts(array(
'label' => gTxt('browse'),
'wraptag' => '',
'class' => '',
'section' => '',
'this_section' => 0,
'type' => 'category',
), $atts));
$type = substr($type, 0, 1);
if ($type == 's') {
$rs = safe_rows_start("name, title", 'txp_section', "name != 'default' ORDER BY name");
} else {
$rs = safe_rows_start("name, title", 'txp_category', "type = 'article' AND name != 'root' ORDER BY name");
}
if ($rs) {
$out = array();
$current = ($type == 's') ? $s : $c;
$sel = '';
$selected = false;
while ($a = nextRow($rs)) {
extract($a);
if ($name == $current) {
$sel = ' selected="selected"';
$selected = true;
}
$out[] = '';
$sel = '';
}
if ($out) {
$section = ($this_section) ? ($s == 'default' ? '' : $s) : $section;
$out = n.'';
if ($label) {
$out = $label.br.$out;
}
if ($wraptag) {
$out = doTag($out, $wraptag, $class);
}
if (($type == 's' || $permlink_mode == 'messy')) {
$action = hu;
$his = ($section !== '') ? n.hInput('s', $section) : '';
} else {
// Clean URLs for category popup.
$action = pagelinkurl(array('s' => $section));
$his = '';
}
return '
';
}
}
}
// -------------------------------------------------------------
// Output href list of site categories.
function category_list($atts, $thing = null)
{
global $s, $c, $thiscategory;
static $cache = array(), $level = 0;
extract(lAtts(array(
'active_class' => '',
'break' => br,
'categories' => '',
'class' => __FUNCTION__,
'exclude' => '',
'form' => '',
'html_id' => '',
'label' => '',
'labeltag' => '',
'parent' => '',
'section' => '',
'children' => 1,
'sort' => empty($atts['categories']) ? 'name ASC' : '',
'this_section' => 0,
'type' => 'article',
'wraptag' => '',
'limit' => '',
'offset' => '',
), $atts));
$categories = $categories === true ?
array(isset($thiscategory['name']) ? $thiscategory['name'] : ($c ? $c : 'root')) :
do_list_unique($categories);
if (isset($atts['categories']) && empty($categories)) {
return '';
}
$roots = ($parent === true ? array(isset($thiscategory['name']) ? $thiscategory['name'] : ($c ? $c : 'root')) : do_list_unique($parent)) or $roots = $categories or $roots = array('root');
$level++;
$section = ($this_section) ? ($s == 'default' ? '' : $s) : $section;
$multiple = count($roots) > 1;
$root = implode(',', $roots);
$children = $children === true ? PHP_INT_MAX : intval(is_numeric($children) ? $children : !empty($children));
$sql_query = "type = '".doSlash($type)."'".($sort ? ' order by '.sanitizeForSort($sort) : ($categories ? " order by FIELD(name, ".implode(',', quote_list($categories)).")": ''));
$sql_limit = $limit !== '' || $offset ? "LIMIT ".intval($offset).", ".($limit === '' || $limit === true ? PHP_INT_MAX : intval($limit)) : '';
$exclude = $exclude ? ($exclude === true ? $roots : do_list_unique($exclude)) : array();
$sql_exclude = $exclude && $sql_limit ? " and name not in(".implode(',', quote_list($exclude)).")" : '';
$nocache = !$children || $sql_limit || $children == $level;
$hash = md5($nocache ? uniqid() : $sql_query);
if (!isset($cache[$hash])) {
$cache[$hash] = array();
}
if (!isset($cache[$hash][$root]) || !$multiple && $root != 'root' && empty($cache[$hash][$root][$root])) {
$cache[$hash][$root] = array();
if (!$children || !in_array('root', $roots)) {
$cats = safe_rows('name, parent, title, description, lft, rgt', 'txp_category', "name IN (".implode(',', quote_list($roots)).") and $sql_query") or $cats = array();
$retrieve = false;
$between = array();
foreach ($cats as $cat) {
extract($cat);
$name = doSlash($name);
$between[] = $children ? "lft>=$lft and rgt<=$rgt" : "name='$name' or parent='$name'";
if ($rgt - $lft > 1) {
$retrieve = true;
}
}
$cats = $retrieve ? safe_rows('name, parent, title, description', 'txp_category', "name!='root' $sql_exclude and (".implode(' or ', $between).") and $sql_query $sql_limit") : $cats;
} else {
$cats = safe_rows('name, parent, title, description', 'txp_category', "name !='root' $sql_exclude and $sql_query $sql_limit");
}
foreach ($cats as $cat) {
extract($cat);
$node = $children == $level ? $root : $name;
if (!isset($cache[$hash][$node])) {
$cache[$hash][$node] = array();
}
$cache[$hash][$node][$name] = $cat;
if ($children != $level) {
if ($multiple && in_array($name, $roots)) {
$cache[$hash][$root][$name] = $cat;
}
if (!isset($cache[$hash][$parent])) {
$cache[$hash][$parent] = array();
}
$cache[$hash][$parent][$name] = $cat;
if ($multiple && in_array($parent, $roots)) {
$cache[$hash][$root][$name] = $cat;
}
}
}
}
$oldcategory = isset($thiscategory) ? $thiscategory : null;
$out = array();
$count = 0;
$last = count($cache[$hash][$root]);
foreach ($cache[$hash][$root] as $name => $thiscategory) {
if (!in_array($name, $exclude) && (!$categories || in_array($name, $categories))) {
$count++;
if (!isset($thing) && !$form) {
extract($thiscategory);
$out[] = tag(txpspecialchars($title), 'a',
(($active_class && (0 == strcasecmp($c, $name))) ? ' class="'.txpspecialchars($active_class).'"' : '').
' href="'.pagelinkurl(array(
's' => $section,
'c' => $name,
'context' => $type,
)).'"'
).(
isset($cache[$hash][$name]) && $children > $level && count($cache[$hash][$name]) > 1
? category_list(array(
'parent' => $name,
'exclude' => ($exclude ? implode(',', $exclude).',' : '').$name,
'label' => '',
'html_id' => '',
) + $atts)
: ''
);
} else {
$thiscategory['type'] = $type;
$thiscategory['is_first'] = ($count == 1);
$thiscategory['is_last'] = ($count == $last);
if (isset($atts['section'])) {
$thiscategory['section'] = $section;
}
$out[] = $form ? parse_form($form) : parse($thing);
}
} else {
$last--;
}
}
$thiscategory = $oldcategory;
$level--;
if ($nocache || $level <= 0) {
unset($cache[$hash]);
}
return $out ? ($label ? doLabel($label, $labeltag) : '').doWrap($out, $wraptag, compact('break', 'class', 'html_id')) : '';
}
// -------------------------------------------------------------
// Output href list of site sections.
function section_list($atts, $thing = null)
{
global $sitename, $s, $thissection;
extract(lAtts(array(
'active_class' => '',
'break' => br,
'class' => __FUNCTION__,
'default_title' => $sitename,
'exclude' => '',
'form' => '',
'html_id' => '',
'include_default' => '',
'sections' => '',
'sort' => '',
'wraptag' => '',
'offset' => '',
'limit' => '',
), $atts));
$sql_limit = '';
$sql_sort = sanitizeForSort($sort);
$sql = array();
if ($limit !== '' || $offset) {
$sql_limit = " LIMIT ".intval($offset).", ".($limit === '' ? PHP_INT_MAX : intval($limit));
}
if ($sections === true) {
$sql[] = '1';
} elseif ($sections) {
if ($include_default) {
$sections .= ', default';
}
$sections = join(',', quote_list(do_list_unique($sections)));
$sql[] = "name IN ($sections)";
if (!$sql_sort) {
$sql_sort = "FIELD(name, $sections)";
}
} else {
$sql[] = '1'.filterFrontPage('name', 'page');
}
if ($exclude === true) {
$sql[] = "searchable";
} elseif ($exclude) {
$exclude = join(',', quote_list(do_list_unique($exclude)));
$sql[] = "name NOT IN ($exclude)";
}
if (!$include_default) {
$sql[] = "name != 'default'";
}
if (!$sql_sort) {
$sql_sort = "name ASC";
}
if ($include_default) {
$sql_sort = "name != 'default', ".$sql_sort;
}
$rs = safe_rows_start(
"name, title, description",
'txp_section',
join(" AND ", $sql)." ORDER BY ".$sql_sort.$sql_limit
);
if ($rs && $last = numRows($rs)) {
$out = array();
$count = 0;
if (isset($thissection)) {
$old_section = $thissection;
}
while ($a = nextRow($rs)) {
++$count;
extract($a);
if ($name == 'default') {
$title = $default_title;
}
if ($form === '' && $thing === null) {
$url = pagelinkurl(array('s' => $name));
$out[] = tag(txpspecialchars($title), 'a',
(($active_class && (0 == strcasecmp($s, $name))) ? ' class="'.txpspecialchars($active_class).'"' : '').
' href="'.$url.'"'
);
} else {
$thissection = array(
'name' => $name,
'title' => $title,
'description' => $description,
'is_first' => ($count == 1),
'is_last' => ($count == $last),
);
if ($thing === null && $form !== '') {
$out[] = parse_form($form);
} else {
$out[] = parse($thing);
}
}
}
$thissection = isset($old_section) ? $old_section : null;
if ($out) {
return doWrap($out, $wraptag, compact('break', 'class', 'html_id'));
}
}
return '';
}
// -------------------------------------------------------------
// Input form for search queries.
function search_input($atts, $thing = null)
{
global $q, $permlink_mode, $doctype;
static $outside = null;
$inside = is_array($outside);
extract(lAtts(array(
'form' => null,
'wraptag' => 'p',
'class' => __FUNCTION__,
'size' => '15',
'html_id' => '',
'label' => gTxt('search'),
'aria_label' => '',
'placeholder' => '',
'button' => '',
'section' => '',
'match' => 'exact',
), $inside ? $atts + $outside : $atts));
unset($atts['form']);
if (!$inside && !isset($form) && !isset($thing) && empty($atts)) {
$form = 'search_input';
}
if ($form && $form = fetch_form($form)) {
$thing = $form;
}
if (isset($thing)) {
$oldatts = $outside;
$outside = $atts;
$out = parse($thing);
$outside = $oldatts;
} else {
$h5 = ($doctype == 'html5');
$out = fInput(
$h5 ? 'search' : 'text',
array(
'name' => 'q',
'aria-label' => $aria_label,
'placeholder' => $placeholder,
'required' => $h5,
'size' => $size,
'class' => $wraptag || empty($atts['class']) ? false : $class
),
$q
);
}
if ($form || $inside) {
empty($atts['wraptag']) or $out = doTag($out, $wraptag, $class);
return $out;
}
$sub = (!empty($button)) ? '' : '';
$id = (!empty($html_id)) ? ' id="'.txpspecialchars($html_id).'"' : '';
$out = (!empty($label)) ? txpspecialchars($label).br.$out.$sub : $out.$sub;
$out = ($match === 'exact') ? $out : hInput('m', txpspecialchars($match)).$out;
$out = ($wraptag) ? doTag($out, $wraptag, $class) : $out;
if (!$section) {
return '';
}
if ($permlink_mode != 'messy') {
return '';
}
return '';
}
// -------------------------------------------------------------
function search_term($atts)
{
global $q;
if (empty($q)) {
return '';
}
return txpspecialchars($q);
}
// -------------------------------------------------------------
// Link to next/prev article, if it exists.
function link_to($atts, $thing = null, $target = 'next')
{
global $thisarticle, $txp_context;
static $lAtts = array(
'form' => '',
'link' => 1,
'showalways' => 0
);
if (!in_array($target, array('next', 'prev')) || !assert_article()) {
return '';
}
$atts += array('context' => empty($txp_context) ? true : null);
extract($atts + $lAtts, EXTR_SKIP);
if (is_array($thisarticle)) {
if (!isset($thisarticle[$target])) {
$thisarticle = $thisarticle + getNextPrev();
}
if ($thisarticle[$target] !== false) {
$oldarticle = $thisarticle;
$thisarticle = $thisarticle[$target];
$url = permlink(array_diff_key($atts, $lAtts));
if ($form || $thing !== null) {
populateArticleData($thisarticle);
$thisarticle['is_first'] = $thisarticle['is_last'] = true;
$thing = $form ? parse_form($form) : parse($thing);
$target_title = escape_title($thisarticle['Title']);
$url = $link ? href(
$thing,
$url,
($target_title != $thing ? ' title="'.$target_title.'"' : '').
' rel="'.$target.'"'
) : $thing;
}
$thisarticle = $oldarticle;
return $url;
}
}
return ($showalways) ? parse($thing) : '';
}
// -------------------------------------------------------------
function next_title()
{
global $thisarticle, $is_article_list;
if (!assert_article()) {
return $is_article_list ? '' : null;
}
if (!isset($thisarticle['next'])) {
$thisarticle = $thisarticle + getNextPrev();
}
if ($thisarticle['next'] !== false) {
return escape_title($thisarticle['next']['Title']);
} else {
return '';
}
}
// -------------------------------------------------------------
function prev_title()
{
global $thisarticle, $is_article_list;
if (!assert_article()) {
return $is_article_list ? '' : null;
}
if (!isset($thisarticle['prev'])) {
$thisarticle = $thisarticle + getNextPrev();
}
if ($thisarticle['prev'] !== false) {
return escape_title($thisarticle['prev']['Title']);
} else {
return '';
}
}
// -------------------------------------------------------------
function site_name()
{
global $sitename;
return txpspecialchars($sitename);
}
// -------------------------------------------------------------
function site_slogan()
{
global $site_slogan;
return txpspecialchars($site_slogan);
}
// -------------------------------------------------------------
function link_to_home($atts, $thing = null)
{
extract(lAtts(array('class' => false), $atts));
if ($thing) {
$class = ($class) ? ' class="'.txpspecialchars($class).'"' : '';
return href(
parse($thing),
hu,
$class.
' rel="home"'
);
}
return hu;
}
// -------------------------------------------------------------
function txp_pager($atts, $thing = null, $newer = null)
{
global $thispage, $is_article_list, $txp_context, $txp_item;
static $pg = true, $numPages = null, $linkall = false, $top = 1, $shown = array();
static $items = array('page' => null, 'total' => null, 'url' => null);
$get = isset($atts['total']) && $atts['total'] === true;
$set = $newer === null && (isset($atts['pg']) || isset($atts['total']) && !$get);
$oldPages = $numPages;
$oldpg = $pg;
extract(lAtts($set ? array(
'pg' => $pg,
'total' => $numPages,
'shift' => 1,
'showalways' => true,
'link' => false,
) : array(
'showalways' => false,
'title' => '',
'link' => $linkall,
'escape' => 'html',
'rel' => '',
'shift' => false,
'limit' => 0,
'break' => '',) +
($get ? array(
'total' => true,
) : array()), $atts));
if ($set) {
if (isset($total) && $total !== true) {
$numPages = (int)$total;
} elseif ($pg === true) {
$numPages = isset($thispage['numPages']) ? (int)$thispage['numPages'] : null;
}
}
if (!isset($numPages)) {
if (isset($thispage['numPages'])) {
$numPages = (int)$thispage['numPages'];
} else {
return $is_article_list ? postpone_process() : '';
}
}
if ($set) {
$oldtop = $top;
$top = $shift === true ? 0 : ((int)$shift < 0 ? $numPages + $shift + 1 : $shift);
$oldshown = $shown;
$oldlink = $linkall;
$linkall = $link;
$shown = array();
if ($thing !== null) {
$thing = $numPages >= ($showalways ? (int)$showalways : 2) ? parse($thing) : '';
$numPages = $oldPages;
$pg = $oldpg;
$top = $oldtop;
$linkall = $oldlink;
$shown = $oldshown;
}
return $thing;
}
$pgc = $pg === true ? 'pg' : $pg;
$thispg = $pg === true && isset($thispage['pg']) ? $thispage['pg'] : intval(gps($pgc, $top));
$thepg = max(1, min($thispg, $numPages));
if ($get) {
if ($thing === null && $shift === false) {
return $newer === null ? $numPages : ($newer ? $thepg - 1 : $numPages - $thepg);
} elseif ($shift === true || $shift === false) {
if ($newer !== null) {
$range = $newer ? $thepg - 1 : $numPages - $thepg;
}
} else {
$range = (int)$shift;
}
}
if (isset($range)) {
if (!$range) {
$pages = array();
} elseif ($range > 0) {
$pages = $newer === null ? range(-max($range, 2*$range + $thepg - $numPages), max($range, 2*$range - $thepg + 1)) :
range($newer ? max($range, 2*$range + $thepg - $numPages) : 1, $newer ? 1 : max($range, 2*$range - $thepg + 1));
} else {
$pages = $newer !== null ? ($newer ? range(-1, -max(-$range, -2*$range + $thepg - $numPages)) : range(-max(-$range, -2*$range - $thepg + 1), -1)) :
range(min(max(1 - $range - $thepg, 1 - 2*$range - $numPages), 0), max(0, min($numPages + $range - $thepg, $numPages + 2*$range - 1)));
}
} elseif (is_bool($shift)) {
$pages = $newer === null ? ($shift ? range(1 - $thepg, $numPages - $thepg) : array(0)) : array($shift ? true : 1);
$range = !$shift;
} else {
$pages = array_map('intval', do_list($shift, array(',', '-')));
$range = false;
}
foreach ($items as $item => $val) {
$items[$item] = isset($txp_item[$item]) ? $txp_item[$item] : null;
}
$txp_item['total'] = $numPages;
$limit = $limit ? (int)$limit : -1;
$old_context = $txp_context;
$txp_context += get_context();
$out = array();
foreach ($pages as $page) {
if ($newer === null) {
$nextpg = $thepg + $page;
} elseif ($newer) {
$nextpg = $page === true ? 1 : ((int)$page < 0 ? -$page : $thepg - $page);
} else {
$nextpg = $page === true ? $numPages : ((int)$page < 0 ? $numPages + $page + 1 : $thepg + $page);
}
if (
$nextpg >= ($newer === false && $range !== false ? $thepg + 1 : 1) &&
$nextpg <= ($newer === true && $range !== false ? $thepg - 1 : $numPages)
) {
if (empty($shown[$nextpg]) || $showalways) {
$txp_context[$pgc] = $nextpg == $top ? null : $nextpg;
$url = pagelinkurl($txp_context);
$txp_item['page'] = $nextpg;
$txp_item['url'] = $url;
if ($shift !== false || $newer === null || !is_bool($range)) {
$shown[$nextpg] = true;
$limit--;
}
if (isset($thing)) {
if ($escape == 'html') {
$title = escape_title($title);
} elseif ($escape) {
$title = txp_escape(array('escape' => $escape), $title);
}
$url = $link || $link === false && $nextpg != $thispg ? href(
parse($thing),
$url,
(empty($title) ? '' : ' title="'.$title.'"').
(empty($rel) ? '' : ' rel="'.txpspecialchars($rel).'"')
) : parse($thing);
}
} else {
$url = false;
}
} else {
$url = isset($thing) ? parse($thing, false) : false;
}
empty($url) or $out[] = $url;
if (!$limit) {
break;
}
}
foreach ($items as $item => $val) {
$txp_item[$item] = $val;
}
$txp_context = $old_context;
return doWrap($out, '', $break);
}
// -------------------------------------------------------------
function text($atts)
{
extract(lAtts(array(
'item' => '',
'escape' => 'html',
), $atts, false));
if (!$item) {
return '';
}
unset(
$atts['item'],
$atts['escape']
);
$tags = array();
foreach ($atts as $name => $value) {
$tags['{'.$name.'}'] = $value;
}
return gTxt($item, $tags, $escape);
}
// -------------------------------------------------------------
function article_id()
{
global $thisarticle;
assert_article();
return $thisarticle['thisid'];
}
// -------------------------------------------------------------
function article_url_title()
{
global $thisarticle;
assert_article();
return $thisarticle['url_title'];
}
// -------------------------------------------------------------
function if_article_id($atts, $thing = null)
{
global $thisarticle, $pretext;
assert_article();
extract(lAtts(array('id' => $pretext['id']), $atts));
$x = $id && in_list($thisarticle['thisid'], $id);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function posted($atts, $thing = null, $time = 'posted')
{
global $thisarticle, $id, $c, $pg, $dateformat, $archive_dateformat;
assert_article();
if (empty($thisarticle[$time])) {
return '';
}
extract(lAtts(array(
'format' => '',
'gmt' => '',
'lang' => '',
), $atts));
if ($format) {
$out = safe_strftime($format, $thisarticle[$time], $gmt, $lang);
} else {
if ($id || $c || $pg) {
$out = safe_strftime($archive_dateformat, $thisarticle[$time], $gmt, $lang);
} else {
$out = safe_strftime($dateformat, $thisarticle[$time], $gmt, $lang);
}
}
return $out;
}
// -------------------------------------------------------------
function if_expires($atts, $thing = null)
{
global $thisarticle;
assert_article();
$x = !empty($thisarticle['expires']);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_expired($atts, $thing = null)
{
global $thisarticle;
assert_article();
$x = !empty($thisarticle['expires']) && ($thisarticle['expires'] <= time());
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function comments_count()
{
global $thisarticle;
assert_article();
return $thisarticle['comments_count'];
}
// -------------------------------------------------------------
function comments_invite($atts)
{
global $thisarticle, $is_article_list;
assert_article();
extract($thisarticle);
global $comments_mode;
if (!$comments_invite) {
$comments_invite = get_pref('comments_default_invite');
}
extract(lAtts(array(
'class' => __FUNCTION__,
'showcount' => true,
'textonly' => false,
'showalways' => false, // FIXME in crockery. This is only for BC.
'wraptag' => '',
), $atts));
$invite_return = '';
if (($annotate || $comments_count) && ($showalways || $is_article_list)) {
$comments_invite = txpspecialchars($comments_invite);
$ccount = ($comments_count && $showcount) ? ' ['.$comments_count.']' : '';
if ($textonly) {
$invite_return = $comments_invite.$ccount;
} else {
if (!$comments_mode) {
$invite_return = doTag($comments_invite, 'a', $class, ' href="'.permlinkurl($thisarticle).'#'.gTxt('comment').'" ').$ccount;
} else {
$invite_return = "'.$comments_invite.' '.$ccount;
}
}
if ($wraptag) {
$invite_return = doTag($invite_return, $wraptag, $class);
}
}
return $invite_return;
}
// -------------------------------------------------------------
function popup_comments($atts, $thing = null)
{
extract(lAtts(array('form' => 'comments_display'), $atts));
$rs = safe_row(
"*, UNIX_TIMESTAMP(Posted) AS uPosted, UNIX_TIMESTAMP(LastMod) AS uLastMod, UNIX_TIMESTAMP(Expires) AS uExpires",
'textpattern',
"ID=".intval(gps('parentid'))." AND Status >= 4"
);
if ($rs) {
populateArticleData($rs);
return ($thing === null ? parse_form($form) : parse($thing));
}
return '';
}
// -------------------------------------------------------------
function comments_form($atts, $thing = null)
{
global $thisarticle, $has_comments_preview;
global $thiscommentsform; // TODO: Remove any uses of $thiscommentsform when removing deprecated attributes from below.
// deprecated attributes since TXP 4.6. Most of these (except msgstyle)
// were moved to the tags that occur within a comments_form, although
// some of the names changed.
$deprecated = array('isize', 'msgrows', 'msgcols', 'msgstyle',
'previewlabel', 'submitlabel', 'rememberlabel', 'forgetlabel');
foreach ($deprecated as $att) {
if (isset($atts[$att])) {
trigger_error(gTxt('deprecated_attribute', array('{name}' => $att)), E_USER_NOTICE);
}
}
$atts = lAtts(array(
'class' => __FUNCTION__,
'form' => 'comment_form',
'isize' => '25',
'msgcols' => '25',
'msgrows' => '5',
'msgstyle' => '',
'show_preview' => empty($has_comments_preview),
'wraptag' => '',
'previewlabel' => gTxt('preview'),
'submitlabel' => gTxt('submit'),
'rememberlabel' => gTxt('remember'),
'forgetlabel' => gTxt('forget'),
), $atts);
extract($atts);
$thiscommentsform = array_intersect_key($atts, array_flip($deprecated));
assert_article();
extract($thisarticle);
$out = '';
$ip = serverSet('REMOTE_ADDR');
$blacklisted = is_blacklisted($ip);
if (!checkCommentsAllowed($thisid)) {
$out = graf(gTxt('comments_closed'), ' id="comments_closed"');
} elseif ($blacklisted) {
$out = graf(gTxt('your_ip_is_blacklisted_by'.' '.$blacklisted), ' id="comments_blocklisted"');
} elseif (gps('commented') !== '') {
$out = gTxt('comment_posted');
if (gps('commented') === '0') {
$out .= " ".gTxt('comment_moderated');
}
$out = graf($out, ' id="txpCommentInputForm"');
} else {
// Display a comment preview if required.
if (ps('preview') && $show_preview) {
$out = comments_preview(array());
}
extract(doDeEnt(psa(array('parentid', 'backpage'))));
// If the form fields are filled (anything other than blank), pages really
// should not be saved by a public cache (rfc2616/14.9.1).
if (pcs('name') || pcs('email') || pcs('web')) {
header('Cache-Control: private');
}
$url = $GLOBALS['pretext']['request_uri'];
// Experimental clean URLs with only 404-error-document on Apache possibly
// requires messy URLs for POST requests.
if (defined('PARTLY_MESSY') && (PARTLY_MESSY)) {
$url = hu.'?id='.intval($parentid);
}
$out .= '';
}
return (!$wraptag ? $out : doTag($out, $wraptag, $class));
}
// -------------------------------------------------------------
function comment_input($atts, $thing = null, $field = 'name', $clean = false)
{
global $prefs, $thiscommentsform;
extract(lAtts(array(
'class' => '',
'size' => $thiscommentsform['isize'],
'aria_label' => '',
'placeholder' => '',
), $atts));
$warn = false;
$val = is_callable($clean) ? $clean(pcs($field)) : pcs($field);
$h5 = ($prefs['doctype'] == 'html5');
$required = get_pref('comments_require_'.$field);
if (!empty($class)) {
$class = ' '.txpspecialchars($class);
}
if (ps('preview')) {
$comment = getComment();
$val = $comment[$field];
$warn = $required && !$val;
}
return fInput('text', array(
'name' => $field,
'aria-label' => $aria_label,
'autocomplete' => $field == 'web' ? 'url' : $field,
'placeholder' => $placeholder,
'required' => $h5 && $required
), $val, 'comment_'.$field.'_input'.$class.($warn ? ' comments_error' : ''), '', '', $size, '', $field);
}
// -------------------------------------------------------------
function comment_message_input($atts)
{
global $prefs, $thiscommentsform;
extract(lAtts(array(
'class' => '',
'rows' => $thiscommentsform['msgrows'],
'cols' => $thiscommentsform['msgcols'],
'aria_label' => '',
'placeholder' => ''
), $atts));
$style = $thiscommentsform['msgstyle'];
$commentwarn = false;
$n_message = 'message';
$formnonce = '';
$message = '';
if (!empty($class)) {
$class = ' '.txpspecialchars($class);
}
if (ps('preview')) {
$comment = getComment();
$message = $comment['message'];
$split = rand(1, 31);
$nonce = getNextNonce();
$secret = getNextSecret();
safe_insert('txp_discuss_nonce', "issue_time = NOW(), nonce = '".doSlash($nonce)."', secret = '".doSlash($secret)."'");
$n_message = md5('message'.$secret);
$formnonce = n.hInput(substr($nonce, 0, $split), substr($nonce, $split));
$commentwarn = (!trim($message));
}
$attr = join_atts(array(
'cols' => intval($cols),
'rows' => intval($rows),
'required' => $prefs['doctype'] == 'html5',
'style' => $style,
'aria-label' => $aria_label,
'placeholder' => $placeholder
));
return ''.
callback_event('comment.form').
$formnonce;
}
// -------------------------------------------------------------
function comment_remember($atts)
{
global $thiscommentsform;
extract(lAtts(array(
'class' => '',
'rememberlabel' => $thiscommentsform['rememberlabel'],
'forgetlabel' => $thiscommentsform['forgetlabel']
), $atts));
if (!empty($class)) {
$class = ' class="'.txpspecialchars($class).'"';
}
extract(doDeEnt(psa(array('checkbox_type', 'remember', 'forget'))));
if (!ps('preview')) {
$rememberCookie = cs('txp_remember');
if (!$rememberCookie) {
$checkbox_type = 'remember';
} else {
$checkbox_type = 'forget';
}
// Inhibit default remember.
if ($forget == 1 || (string) $rememberCookie === '0') {
destroyCookies();
}
}
if ($checkbox_type == 'forget') {
$checkbox = checkbox('forget', 1, $forget, '', 'forget').' '.tag(txpspecialchars($forgetlabel), 'label', ' for="forget"'.$class);
} else {
$checkbox = checkbox('remember', 1, $remember, '', 'remember').' '.tag(txpspecialchars($rememberlabel), 'label', ' for="remember"'.$class);
}
$checkbox .= ' '.hInput('checkbox_type', $checkbox_type);
return $checkbox;
}
// -------------------------------------------------------------
function comment_preview($atts)
{
global $thiscommentsform;
extract(lAtts(array(
'class' => '',
'label' => $thiscommentsform['previewlabel']
), $atts));
if (!empty($class)) {
$class = ' '.txpspecialchars($class);
}
return fInput('submit', 'preview', $label, 'button'.$class, '', '', '', '', 'txpCommentPreview', false);
}
// -------------------------------------------------------------
function comment_submit($atts)
{
global $thiscommentsform;
extract(lAtts(array(
'class' => '',
'label' => $thiscommentsform['submitlabel']
), $atts));
if (!empty($class)) {
$class = ' '.txpspecialchars($class);
}
// If all fields check out, the submit button is active/clickable.
if (ps('preview')) {
return fInput('submit', 'submit', $label, 'button'.$class, '', '', '', '', 'txpCommentSubmit', false);
} else {
return fInput('submit', 'submit', $label, 'button disabled'.$class, '', '', '', '', 'txpCommentSubmit', true);
}
}
// -------------------------------------------------------------
function comments_error($atts)
{
extract(lAtts(array(
'break' => 'br',
'class' => __FUNCTION__,
'wraptag' => 'div',
), $atts));
$evaluator = & get_comment_evaluator();
$errors = $evaluator->get_result_message();
if ($errors) {
return doWrap($errors, $wraptag, $break, $class);
}
}
// -------------------------------------------------------------
function if_comments_error($atts, $thing = null)
{
$evaluator = & get_comment_evaluator();
$x = (count($evaluator->get_result_message()) > 0);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function comments($atts, $thing = null)
{
global $thisarticle, $prefs;
extract($prefs);
extract(lAtts(array(
'form' => 'comments',
'wraptag' => ($comments_are_ol ? 'ol' : ''),
'break' => ($comments_are_ol ? 'li' : 'div'),
'class' => __FUNCTION__,
'limit' => 0,
'offset' => 0,
'sort' => 'posted ASC',
), $atts));
assert_article();
extract($thisarticle);
if (!$comments_count) {
return '';
}
$qparts = array(
"parentid = ".intval($thisid)." AND visible = ".VISIBLE,
"ORDER BY ".sanitizeForSort($sort),
($limit) ? "LIMIT ".intval($offset).", ".intval($limit) : '',
);
$rs = safe_rows_start("*, UNIX_TIMESTAMP(posted) AS time", 'txp_discuss', join(' ', $qparts));
$out = '';
if ($rs) {
$comments = array();
while ($vars = nextRow($rs)) {
$GLOBALS['thiscomment'] = $vars;
$comments[] = ($thing === null ? parse_form($form) : parse($thing)).n;
unset($GLOBALS['thiscomment']);
}
$out .= doWrap($comments, $wraptag, $break, $class);
}
return $out;
}
// -------------------------------------------------------------
function comments_preview($atts, $thing = null)
{
global $has_comments_preview;
if (!ps('preview')) {
return '';
}
extract(lAtts(array(
'form' => 'comments',
'wraptag' => '',
'class' => __FUNCTION__,
), $atts));
assert_article();
$preview = psa(array('name', 'email', 'web', 'message', 'parentid', 'remember'));
$preview['time'] = time();
$preview['discussid'] = 0;
$preview['name'] = strip_tags($preview['name']);
$preview['email'] = clean_url($preview['email']);
if ($preview['message'] == '') {
$in = getComment();
$preview['message'] = $in['message'];
}
// It is called 'message', not 'novel'!
$preview['message'] = markup_comment(substr(trim($preview['message']), 0, 65535));
$preview['web'] = clean_url($preview['web']);
$GLOBALS['thiscomment'] = $preview;
$comments = ($thing === null ? parse_form($form) : parse($thing)).n;
unset($GLOBALS['thiscomment']);
$out = doTag($comments, $wraptag, $class);
// Set a flag to tell the comments_form tag that it doesn't have to show
// a preview.
$has_comments_preview = true;
return $out;
}
// -------------------------------------------------------------
function if_comments_preview($atts, $thing = null)
{
$x = ps('preview') && checkCommentsAllowed(gps('parentid'));
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function comment_permlink($atts, $thing)
{
global $thisarticle, $thiscomment;
assert_article();
assert_comment();
extract($thiscomment);
extract(lAtts(array('anchor' => empty($thiscomment['has_anchor_tag'])), $atts));
$dlink = permlinkurl($thisarticle).'#c'.$discussid;
$thing = parse($thing);
$name = ($anchor ? ' id="c'.$discussid.'"' : '');
return tag($thing, 'a', ' href="'.$dlink.'"'.$name);
}
// -------------------------------------------------------------
function comment_id()
{
global $thiscomment;
assert_comment();
return $thiscomment['discussid'];
}
// -------------------------------------------------------------
function comment_name($atts)
{
global $thiscomment, $prefs;
static $encoder = null;
assert_comment();
isset($encoder) or $encoder = Txp::get('\Textpattern\Mail\Encode');
extract($prefs);
extract($thiscomment);
extract(lAtts(array('link' => 1), $atts));
$name = txpspecialchars($name);
if ($link) {
$web = comment_web();
$nofollow = (@$comment_nofollow ? ' rel="nofollow"' : '');
if (!empty($web)) {
return href($name, $web, $nofollow);
}
if ($email && !$never_display_email) {
return href($name, $encoder->entityObfuscateAddress('mailto:'.$email), $nofollow);
}
}
return $name;
}
// -------------------------------------------------------------
function comment_email()
{
global $thiscomment;
assert_comment();
return txpspecialchars($thiscomment['email']);
}
// -------------------------------------------------------------
function comment_web()
{
global $thiscomment;
assert_comment();
if (preg_match('/^\S/', $thiscomment['web'])) {
// Prepend default protocol 'http' for all non-local URLs.
if (!preg_match('!^https?://|^#|^/[^/]!', $thiscomment['web'])) {
$thiscomment['web'] = 'http://'.$thiscomment['web'];
}
return txpspecialchars($thiscomment['web']);
}
return '';
}
// -------------------------------------------------------------
function comment_time($atts)
{
global $thiscomment, $comments_dateformat;
assert_comment();
extract(lAtts(array(
'format' => $comments_dateformat,
'gmt' => '',
'lang' => '',
), $atts));
return safe_strftime($format, $thiscomment['time'], $gmt, $lang);
}
// -------------------------------------------------------------
function comment_message()
{
global $thiscomment;
assert_comment();
return $thiscomment['message'];
}
// -------------------------------------------------------------
function comment_anchor()
{
global $thiscomment;
assert_comment();
$thiscomment['has_anchor_tag'] = 1;
return '';
}
// -------------------------------------------------------------
function author($atts)
{
global $thisarticle, $thisauthor, $s, $author;
extract(lAtts(array(
'escape' => 'html',
'link' => 0,
'title' => 1,
'section' => '',
'this_section' => 0,
'format' => '', // empty, link, or url
), $atts));
// Synonym.
if ($format === 'link') {
$link = 1;
}
$fetchRealName = $link || $title || $format === 'url';
if ($thisauthor) {
$realname = $thisauthor['realname'];
$name = $thisauthor['name'];
} elseif ($author) {
$name = $author;
} else {
assert_article();
$name = $thisarticle['authorid'];
}
isset($realname) or $realname = $fetchRealName ? get_author_name($name) : $name;
if ($title) {
$display_name = $realname;
} else {
$display_name = $name;
}
if ($escape === 'html') {
$display_name = txpspecialchars($display_name);
} elseif ($escape) {
$display_name = txp_escape(array('escape' => $escape), $display_name);
}
if (!$link && $format !== 'url') {
return $display_name;
}
if ($this_section && $s != 'default') {
$section = $s;
}
$href = pagelinkurl(array(
's' => $section,
'author' => $realname,
));
return $format === 'url' ? $href : href($display_name, $href, ' rel="author"');
}
// -------------------------------------------------------------
function author_email($atts)
{
global $thisarticle, $thisauthor;
extract(lAtts(array(
'escape' => 'html',
'link' => '',
), $atts));
if ($thisauthor) {
$email = get_author_email($thisauthor['name']);
} else {
assert_article();
$email = get_author_email($thisarticle['authorid']);
}
if ($escape == 'html') {
$display_email = txpspecialchars($email);
} else {
$display_email = $escape ? txp_escape(array('escape' => $escape), $email) : $email;
}
if ($link) {
return email(array(
'email' => $email,
'linktext' => $display_email,
));
}
return $display_email;
}
// -------------------------------------------------------------
function if_author($atts, $thing = null)
{
global $author, $context, $thisauthor;
extract(lAtts(array(
'type' => 'article',
'name' => '',
), $atts));
$theType = ($type) ? $type == $context : true;
if ($thisauthor) {
$x = $name === '' || in_list($thisauthor['name'], $name);
} elseif ($name) {
$x = ($theType && in_list($author, $name));
} else {
$x = ($theType && (string) $author !== '');
}
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_article_author($atts, $thing = null)
{
global $thisarticle;
assert_article();
extract(lAtts(array('name' => ''), $atts));
$author = $thisarticle['authorid'];
$x = $name ? in_list($author, $name) : (string) $author !== '';
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_logged_in($atts, $thing = null)
{
global $txp_groups;
static $cache = array();
extract(lAtts(array(
'group' => '',
'name' => '',
), $atts));
$user = isset($cache[$name]) ? $cache[$name] : ($cache[$name] = is_logged_in($name));
$x = false;
if ($user && $group !== '') {
$privs = do_list($group);
$groups = array_flip($txp_groups);
foreach ($privs as &$priv) {
if (!is_numeric($priv) && isset($groups[$priv])) {
$priv = $groups[$priv];
} else {
$priv = intval($priv);
}
}
$privs = array_unique($privs);
if (in_array($user['privs'], $privs)) {
$x = true;
}
} else {
$x = (bool) $user;
}
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function txp_sandbox($atts = array(), $thing = null, $parse = true)
{
static $articles = array(), $uniqid = null, $stack = array(), $depth = null;
global $thisarticle, $is_article_body;
isset($depth) or $depth = get_pref('form_circular_depth', 15);
extract($atts + array('field' => ''));
unset($atts['field']);
if (empty($id)) {
assert_article();
$id = $thisarticle['thisid'];
} elseif (!isset($articles[$id])) {
return;
}
if ($field) {
if (!isset($stack[$id])) {
$stack[$id] = 1;
} elseif ($stack[$id] >= $depth) {
trigger_error(gTxt('form_circular_reference', array(
'{name}' => ''
)));
return '';
} else {
$stack[$id]++;
}
}
if ($parse) {
$oldarticle = $thisarticle;
isset($articles[$id]) and $thisarticle = $articles[$id];
$was_article_body = $is_article_body;
!$field or $is_article_body = 1;
$thing = parse(isset($thing) ? $thing : $thisarticle[$field]);
$is_article_body = $was_article_body;
$thisarticle = $oldarticle;
}
!$field or $stack[$id]--;
if (!preg_match('@<(?:'.TXP_PATTERN.'):@', $thing)) {
return $thing;
}
if (!isset($uniqid)) {
$uniqid = 'sandbox_'.strtr(uniqid('', true), '.', '_');
Txp::get('\Textpattern\Tag\Registry')->register('txp_sandbox', $uniqid);
}
if ($field) {
$tag = $field;
unset($atts['id']);
} else {
$tag = $uniqid;
$atts['id'] = $id;
}
isset($articles[$id]) or $articles[$id] = $thisarticle;
return "{$thing}";
}
// -------------------------------------------------------------
function body($atts = array(), $thing = null)
{
return txp_sandbox(array('field' => 'body'), $thing);
}
// -------------------------------------------------------------
function title($atts)
{
global $thisarticle, $prefs;
assert_article();
extract(lAtts(array(
'escape' => null,
'no_widow' => '',
), $atts));
$t = $escape === null ? escape_title($thisarticle['title']) : $thisarticle['title'];
if ($no_widow && $escape === null) {
$t = noWidow($t);
}
return $t;
}
// -------------------------------------------------------------
function excerpt($atts = array(), $thing = null)
{
return txp_sandbox(array('field' => 'excerpt'), $thing);
}
// -------------------------------------------------------------
function article_category($atts, $thing = null)
{
global $thisarticle, $s, $permlink_mode;
assert_article();
extract(lAtts(array(
'number' => 1,
'class' => '',
'link' => 0,
'title' => 0,
'escape' => true,
'section' => '',
'this_section' => 0,
'wraptag' => '',
), $atts));
$cat = 'category'.intval($number);
if (!empty($thisarticle[$cat])) {
$section = ($this_section) ? ($s == 'default' ? '' : $s) : $section;
$category = $thisarticle[$cat];
$label = $title ? fetch_category_title($category) : $category;
if ($thing) {
$out = href(
parse($thing),
pagelinkurl(array(
's' => $section,
'c' => $category,
)),
(($class && !$wraptag) ? ' class="'.txpspecialchars($class).'"' : '').
($title ? ' title="'.txpspecialchars($label).'"' : '').
($permlink_mode != 'messy' ? ' rel="tag"' : '')
);
} else {
if ($escape) {
$label = txp_escape(array('escape' => $escape), $label);
}
if ($link) {
$out = href(
$label,
pagelinkurl(array(
's' => $section,
'c' => $category,
)),
($permlink_mode != 'messy' ? ' rel="tag"' : '')
);
} else {
$out = $label;
}
}
return doTag($out, $wraptag, $class);
}
}
// -------------------------------------------------------------
function category($atts, $thing = null)
{
global $s, $c, $thiscategory, $context;
extract(lAtts(array(
'class' => '',
'link' => 0,
'name' => '',
'section' => $s,
'this_section' => 0,
'title' => 0,
'type' => 'article',
'url' => 0,
'wraptag' => '',
), $atts));
if ($name) {
$category = $name;
$type = validContext($type);
} elseif (!empty($thiscategory['name'])) {
$category = $thiscategory['name'];
$type = $thiscategory['type'];
} else {
$category = $c;
$type = $context;
}
if ($category) {
if ($this_section) {
$section = ($s == 'default' ? '' : $s);
} elseif (isset($thiscategory['section'])) {
$section = $thiscategory['section'];
}
$label = txpspecialchars(($title) ? fetch_category_title($category, $type) : $category);
$href = pagelinkurl(array(
's' => $section,
'c' => $category,
'context' => $type,
));
if ($thing) {
$out = href(
parse($thing),
$href,
(($class && !$wraptag) ? ' class="'.txpspecialchars($class).'"' : '').
($title ? ' title="'.$label.'"' : '')
);
} elseif ($link) {
$out = href(
$label,
$href,
($class && !$wraptag) ? ' class="'.txpspecialchars($class).'"' : ''
);
} elseif ($url) {
$out = $href;
} else {
$out = $label;
}
return doTag($out, $wraptag, $class);
}
}
// -------------------------------------------------------------
function section($atts, $thing = null)
{
global $thisarticle, $s, $thissection;
extract(lAtts(array(
'class' => '',
'link' => 0,
'name' => '',
'title' => 0,
'url' => 0,
'wraptag' => '',
), $atts));
if ($name) {
$sec = $name;
} elseif (!empty($thissection['name'])) {
$sec = $thissection['name'];
} elseif (!empty($thisarticle['section'])) {
$sec = $thisarticle['section'];
} else {
$sec = $s;
}
if ($sec) {
$label = txpspecialchars(($title) ? fetch_section_title($sec) : $sec);
$href = pagelinkurl(array('s' => $sec));
if ($thing) {
$out = href(
parse($thing),
$href,
(($class && !$wraptag) ? ' class="'.txpspecialchars($class).'"' : '').
($title ? ' title="'.$label.'"' : '')
);
} elseif ($link) {
$out = href(
$label,
$href,
($class && !$wraptag) ? ' class="'.txpspecialchars($class).'"' : ''
);
} elseif ($url) {
$out = $href;
} else {
$out = $label;
}
return doTag($out, $wraptag, $class);
}
}
// -------------------------------------------------------------
function keywords($atts)
{
global $thisarticle;
assert_article();
extract(lAtts(array(
'class' => '',
'break' => ',',
'wraptag' => '',
), $atts));
$out = do_list_unique(txpspecialchars($thisarticle['keywords']));
return doWrap($out, $wraptag, $break, $class);
}
// -------------------------------------------------------------
function if_keywords($atts, $thing = null)
{
global $thisarticle;
assert_article();
extract(lAtts(array('keywords' => ''), $atts));
$condition = empty($keywords)
? $thisarticle['keywords']
: array_intersect(do_list($keywords), do_list($thisarticle['keywords']));
$x = !empty($condition);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_article_image($atts, $thing = null)
{
global $thisarticle;
assert_article();
$x = !empty($thisarticle['article_image']);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function article_image($atts)
{
global $doctype, $thisarticle;
assert_article();
extract(lAtts(array(
'escape' => true,
'title' => '',
'class' => '',
'html_id' => '',
'style' => '',
'width' => '',
'height' => '',
'thumbnail' => 0,
'wraptag' => '',
'loading' => null,
), $atts));
if ($thisarticle['article_image']) {
$image = $thisarticle['article_image'];
} else {
return '';
}
if (intval($image)) {
$rs = safe_row("*", 'txp_image', "id = ".intval($image));
if (empty($rs)) {
trigger_error(gTxt('unknown_image'));
return '';
}
if ($thumbnail && empty($rs['thumbnail'])) {
return '';
}
$width = ($width == '') ? (($thumbnail) ? $rs['thumb_w'] : $rs['w']) : $width;
$height = ($height == '') ? (($thumbnail) ? $rs['thumb_h'] : $rs['h']) : $height;
extract($rs);
if ($title === true) {
$title = $caption;
}
$out = '';
return ($wraptag) ? doTag($out, $wraptag, $class, '', $html_id) : $out;
}
// -------------------------------------------------------------
function search_result_title($atts)
{
return permlink($atts, '');
}
// -------------------------------------------------------------
function search_result_excerpt($atts)
{
global $thisarticle, $pretext;
assert_article();
extract(lAtts(array(
'break' => ' …', // Deprecated in 4.7.0.
'hilight' => 'strong',
'limit' => 5,
'separator' => ' …',
), $atts));
if (isset($atts['break'])) {
trigger_error(gTxt('deprecated_attribute_with', array(
'{name}' => 'break',
'{with}' => 'separator',
)), E_USER_NOTICE);
if (!isset($atts['separator'])) {
$separator = $break;
}
}
$m = $pretext['m'];
$q = $pretext['q'];
$quoted = ($q[0] === '"') && ($q[strlen($q) - 1] === '"');
$q = $quoted ? trim(trim($q, '"')) : trim($q);
$result = preg_replace('/\s+/', ' ', strip_tags(str_replace('><', '> <', $thisarticle['body'])));
if ($quoted || empty($m) || $m === 'exact') {
$regex_search = '/(?:\G|\s).{0,50}'.preg_quote($q, '/').'.{0,50}(?:\s|$)/iu';
$regex_hilite = '/('.preg_quote($q, '/').')/i';
} else {
$regex_search = '/(?:\G|\s).{0,50}('.preg_replace('/\s+/', '|', preg_quote($q, '/')).').{0,50}(?:\s|$)/iu';
$regex_hilite = '/('.preg_replace('/\s+/', '|', preg_quote($q, '/')).')/i';
}
preg_match_all($regex_search, $result, $concat);
$concat = $concat[0];
for ($i = 0, $r = array(); $i < min($limit, count($concat)); $i++) {
$r[] = trim($concat[$i]);
}
$concat = join($separator.n, $r);
$concat = preg_replace('/^[^>]+>/U', '', $concat);
$concat = preg_replace($regex_hilite, "<$hilight>$1$hilight>", $concat);
return ($concat) ? trim($separator.$concat.$separator) : '';
}
// -------------------------------------------------------------
function search_result_url($atts)
{
global $thisarticle;
assert_article();
$l = permlinkurl($thisarticle);
return permlink($atts, $l);
}
// -------------------------------------------------------------
function search_result_date($atts)
{
assert_article();
return posted($atts);
}
// -------------------------------------------------------------
function search_result_count($atts)
{
global $thispage;
if (empty($thispage)) {
return postpone_process();
}
extract(lAtts(array(
'text' => null,
'pageby' => 1,
), $atts));
$by = (int)$pageby or $by = 1;
$t = ceil(@$thispage[$pageby === true ? 'numPages' : 'grand_total']/$by);
if (!isset($text)) {
$text = $pageby === true || $by > 1 ? gTxt($t == 1 ? 'page' : 'pages') : gTxt($t == 1 ? 'article_found' : 'articles_found');
}
return $t.($text ? ' '.$text : '');
}
// -------------------------------------------------------------
function image_index($atts)
{
trigger_error(gTxt('deprecated_tag'), E_USER_NOTICE);
global $c;
lAtts(array(
'break' => br,
'wraptag' => '',
'class' => __FUNCTION__,
'category' => $c,
'limit' => 0,
'offset' => 0,
'sort' => 'name ASC',
), $atts);
if (!isset($atts['category'])) {
$atts['category'] = $c;
}
if (!isset($atts['class'])) {
$atts['class'] = __FUNCTION__;
}
if ($atts['category']) {
return images($atts);
}
return '';
}
// -------------------------------------------------------------
function image_display($atts)
{
trigger_error(gTxt('deprecated_tag'), E_USER_NOTICE);
global $p;
if ($p) {
return image(array('id' => $p));
}
}
// -------------------------------------------------------------
function images($atts, $thing = null)
{
global $s, $c, $context, $thisimage, $thisarticle, $thispage, $pretext;
extract(lAtts(array(
'name' => '',
'id' => '',
'category' => '',
'author' => '',
'realname' => '',
'extension' => '',
'thumbnail' => '',
'size' => '',
'auto_detect' => 'article, category, author',
'break' => br,
'wraptag' => '',
'class' => __FUNCTION__,
'html_id' => '',
'form' => '',
'pageby' => '',
'limit' => 0,
'offset' => 0,
'sort' => 'name ASC',
), $atts));
$safe_sort = sanitizeForSort($sort);
$where = array();
$has_content = $thing || $form;
$filters = isset($atts['id']) || isset($atts['name']) || isset($atts['category']) || isset($atts['author']) || isset($atts['realname']) || isset($atts['extension']) || isset($atts['size']) || $thumbnail === '1' || $thumbnail === '0';
$context_list = (empty($auto_detect) || $filters) ? array() : do_list_unique($auto_detect);
$pageby = ($pageby == 'limit') ? $limit : $pageby;
if ($name) {
$where[] = "name IN ('".join("','", doSlash(do_list_unique($name)))."')";
}
if ($category) {
$where[] = "category IN ('".join("','", doSlash(do_list_unique($category)))."')";
}
if ($id) {
$id = join(',', array_map('intval', do_list_unique($id, array(',', '-'))));
$where[] = "id IN ($id)";
}
if ($author) {
$where[] = "author IN ('".join("','", doSlash(do_list_unique($author)))."')";
}
if ($realname) {
$authorlist = safe_column("name", 'txp_users', "RealName IN ('".join("','", doArray(doSlash(do_list_unique($realname)), 'urldecode'))."')");
if ($authorlist) {
$where[] = "author IN ('".join("','", doSlash($authorlist))."')";
}
}
if ($extension) {
$where[] = "ext IN ('".join("','", doSlash(do_list_unique($extension)))."')";
}
if ($thumbnail === '0' || $thumbnail === '1') {
$where[] = "thumbnail = $thumbnail";
}
// Handle aspect ratio filtering.
if ($size === 'portrait') {
$where[] = "h > w";
} elseif ($size === 'landscape') {
$where[] = "w > h";
} elseif ($size === 'square') {
$where[] = "w = h";
} elseif (is_numeric($size)) {
$where[] = "ROUND(w/h, 2) = $size";
} elseif (strpos($size, ':') !== false) {
$ratio = explode(':', $size);
$ratiow = $ratio[0];
$ratioh = !empty($ratio[1]) ? $ratio[1] : '';
if (is_numeric($ratiow) && is_numeric($ratioh)) {
$where[] = "ROUND(w/h, 2) = ".round($ratiow/$ratioh, 2);
} elseif (is_numeric($ratiow)) {
$where[] = "w = $ratiow";
} elseif (is_numeric($ratioh)) {
$where[] = "h = $ratioh";
}
}
// If no images are selected, try...
if (!$where && !$filters) {
foreach ($context_list as $ctxt) {
switch ($ctxt) {
case 'article':
// ...the article image field.
if ($thisarticle && !empty($thisarticle['article_image'])) {
if (!is_numeric(str_replace(array(',', '-', ' '), '', $thisarticle['article_image']))) {
return article_image(compact('class', 'html_id', 'wraptag'));
}
$id = join(",", array_map('intval', do_list_unique($thisarticle['article_image'], array(',', '-'))));
// Note: This clause will squash duplicate ids.
$where[] = "id IN ($id)";
}
break;
case 'category':
// ...the global category in the URL.
if ($context == 'image' && !empty($c)) {
$where[] = "category = '".doSlash($c)."'";
}
break;
case 'author':
// ...the global author in the URL.
if ($context == 'image' && !empty($pretext['author'])) {
$where[] = "author = '".doSlash($pretext['author'])."'";
}
break;
}
// Only one context can be processed.
if ($where) {
break;
}
}
}
// Order of ids in 'id' attribute overrides default 'sort' attribute.
if (empty($atts['sort']) && $id) {
$safe_sort = "FIELD(id, $id)";
}
// If nothing matches from the filterable attributes, output nothing.
if (!$where && $filters) {
return '';
}
// If no images are filtered, start with all images.
if (!$where) {
$where[] = "1 = 1";
}
$where = join(" AND ", $where);
// Set up paging if required.
if ($limit && $pageby) {
$pg = (!$pretext['pg']) ? 1 : $pretext['pg'];
$pgoffset = $offset + (($pg - 1) * $pageby);
if (empty($thispage)) {
$grand_total = safe_count('txp_image', $where);
$total = $grand_total - $offset;
$numPages = ($pageby > 0) ? ceil($total / $pageby) : 1;
// Send paging info to txp:newer and txp:older.
$pageout['pg'] = $pg;
$pageout['numPages'] = $numPages;
$pageout['s'] = $s;
$pageout['c'] = $c;
$pageout['context'] = 'image';
$pageout['grand_total'] = $grand_total;
$pageout['total'] = $total;
$thispage = $pageout;
}
} else {
$pgoffset = $offset;
}
$qparts = array(
$where,
"ORDER BY ".$safe_sort,
($limit) ? "LIMIT ".intval($pgoffset).", ".intval($limit) : '',
);
$rs = safe_rows_start("*", 'txp_image', join(' ', $qparts));
if ($rs) {
$out = array();
$count = 0;
$last = numRows($rs);
if (isset($thisimage)) {
$old_image = $thisimage;
}
while ($a = nextRow($rs)) {
++$count;
$thisimage = image_format_info($a);
$thisimage['is_first'] = ($count == 1);
$thisimage['is_last'] = ($count == $last);
if (!$has_content) {
$url = pagelinkurl(array(
'c' => $thisimage['category'],
'context' => 'image',
's' => $s,
'p' => $thisimage['id'],
));
$src = image_url(array('thumbnail' => '1'));
$thing = href(
'',
$url
);
}
$out[] = ($thing) ? parse($thing) : parse_form($form);
}
$thisimage = (isset($old_image) ? $old_image : null);
if ($out) {
return doWrap($out, $wraptag, compact('break', 'class', 'html_id'));
}
}
return '';
}
// -------------------------------------------------------------
function image_info($atts)
{
extract(lAtts(array(
'name' => '',
'id' => '',
'type' => 'caption',
'escape' => true,
'wraptag' => '',
'class' => '',
'break' => '',
), $atts));
$validItems = array('id', 'name', 'category', 'category_title', 'alt', 'caption', 'ext', 'author', 'w', 'h', 'thumb_w', 'thumb_h', 'date');
$type = do_list($type);
$out = array();
empty($escape) or $escape = compact('escape');
if ($imageData = imageFetchInfo($id, $name)) {
$imageData['category_title'] = fetch_category_title($imageData['category'], 'image');
foreach ($type as $item) {
if (in_array($item, $validItems)) {
if (isset($imageData[$item])) {
$out[] = $escape ?
txp_escape($escape, $imageData[$item]) : $imageData[$item];
}
} else {
trigger_error(gTxt('invalid_attribute_value', array('{name}' => $item)), E_USER_NOTICE);
}
}
}
return doWrap($out, $wraptag, $break, $class);
}
// -------------------------------------------------------------
function image_url($atts, $thing = null)
{
extract(lAtts(array(
'name' => '',
'id' => '',
'thumbnail' => 0,
'link' => 'auto',
), $atts));
if (($name || $id) && $thing) {
global $thisimage;
$stash = $thisimage;
}
if ($thisimage = imageFetchInfo($id, $name)) {
$url = imagesrcurl($thisimage['id'], $thisimage['ext'], $thumbnail);
$link = ($link == 'auto') ? (($thing) ? 1 : 0) : $link;
$out = ($thing) ? parse($thing) : $url;
$out = ($link) ? href($out, $url) : $out;
}
if (isset($stash)) {
$thisimage = $stash;
}
return isset($out) ? $out : '';
}
// -------------------------------------------------------------
function image_author($atts)
{
global $s;
extract(lAtts(array(
'name' => '',
'id' => '',
'link' => 0,
'title' => 1,
'section' => '',
'this_section' => '',
), $atts));
if ($imageData = imageFetchInfo($id, $name)) {
$author_name = get_author_name($imageData['author']);
$display_name = txpspecialchars(($title) ? $author_name : $imageData['author']);
$section = ($this_section) ? ($s == 'default' ? '' : $s) : $section;
$author = ($link)
? href($display_name, pagelinkurl(array(
's' => $section,
'author' => $author_name,
'context' => 'image',
)))
: $display_name;
return $author;
}
}
// -------------------------------------------------------------
function image_date($atts)
{
extract(lAtts(array(
'name' => '',
'id' => '',
'format' => '',
), $atts));
if ($imageData = imageFetchInfo($id, $name)) {
// Not a typo: use fileDownloadFormatTime() since it's fit for purpose.
$out = fileDownloadFormatTime(array(
'ftime' => $imageData['date'],
'format' => $format,
));
return $out;
}
}
// -------------------------------------------------------------
function if_thumbnail($atts, $thing = null)
{
global $thisimage;
assert_image();
$x = ($thisimage['thumbnail'] == 1);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_comments($atts, $thing = null)
{
global $thisarticle;
assert_article();
$x = ($thisarticle['comments_count'] > 0);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_comments_allowed($atts, $thing = null)
{
global $thisarticle;
assert_article();
$x = checkCommentsAllowed($thisarticle['thisid']);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_comments_disallowed($atts, $thing = null)
{
global $thisarticle;
assert_article();
$x = !checkCommentsAllowed($thisarticle['thisid']);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_individual_article($atts, $thing = null)
{
global $is_article_list;
$x = ($is_article_list == false);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_article_list($atts, $thing = null)
{
global $is_article_list, $pretext;
static $defaults = array('s', 'c', 'q', 'month', 'author');
$x = ($is_article_list == true);
if ($x && !empty($atts)) {
extract(lAtts(array('type' => ''), $atts));
foreach ($type === true ? $defaults : do_list_unique($type) as $q) {
switch ($q) {
case 's':
$x = !empty($pretext['s']) && $pretext['s'] != 'default';
break;
default:
$x = !empty($pretext[$q]) || !isset($pretext[$q]) && gps($q);
}
if ($x) {
break;
}
}
}
return isset($thing) ? parse($thing, $x) : $x;
}
/**
* Returns article keywords.
*
* @param array $atts Tag attributes
* @return string
*/
function meta_keywords($atts)
{
global $id_keywords;
extract(lAtts(array(
'escape' => null,
'format' => 'meta', // or empty for raw value
'separator' => null,
), $atts));
$out = '';
if ($id_keywords) {
$content = ($escape === null) ? txpspecialchars($id_keywords) : $id_keywords;
if ($separator !== null) {
$content = implode($separator, do_list($content));
}
if ($format === 'meta') {
// Can't use tag_void() since it escapes its content.
$out = '';
} else {
$out = $content;
}
}
return $out;
}
/**
* Returns article, section or category meta description info.
*
* @param array $atts Tag attributes
* @return string
*/
function meta_description($atts)
{
extract(lAtts(array(
'escape' => null,
'format' => 'meta', // or empty for raw value
'type' => null,
), $atts));
$out = '';
$content = getMetaDescription($type);
if ($content) {
$content = ($escape === null ? txpspecialchars($content) : $content);
if ($format === 'meta') {
$out = '';
} else {
$out = $content;
}
}
return $out;
}
/**
* Determines if there is meta description content in the given context.
*
* @param array $atts Tag attributes
* @param string $thing Tag container content
* @return string
*/
function if_description($atts, $thing = null)
{
extract(lAtts(array('type' => null), $atts));
$content = getMetaDescription($type);
$x = !empty($content);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function meta_author($atts)
{
global $id_author;
extract(lAtts(array(
'escape' => null,
'format' => 'meta', // or empty for raw value
'title' => 0,
), $atts));
$out = '';
if ($id_author) {
$display_name = ($title) ? get_author_name($id_author) : $id_author;
$display_name = ($escape === null) ? txpspecialchars($display_name) : $display_name;
if ($format === 'meta') {
// Can't use tag_void() since it escapes its content.
$out = '';
} else {
$out = $display_name;
}
}
return $out;
}
// -------------------------------------------------------------
function permlink($atts, $thing = null)
{
global $pretext, $thisarticle, $txp_context;
static $lAtts = array(
'class' => '',
'id' => '',
'style' => '',
'title' => '',
'context' => null,
);
$old_context = $txp_context;
if (!isset($atts['context'])) {
if (empty($txp_context)) {
$atts = lAtts($lAtts, $atts);
} else {
$atts = lAtts($lAtts + $txp_context, $atts);
$txp_context = array_intersect_key($atts, $txp_context);
}
} elseif ($atts['context'] === true) {
$atts = lAtts($lAtts, $atts);
} else {
$extralAtts = array_fill_keys(do_list_unique($atts['context']), null);
$atts = lAtts($lAtts + $extralAtts, $atts);
$extralAtts = array_intersect_key($atts, $extralAtts);
}
$id = $atts['id'];
if (!$id && !assert_article()) {
return;
}
$txp_context = get_context(isset($extralAtts) ? $extralAtts : $atts['context']);
$url = $id ? permlinkurl_id($id) : permlinkurl($thisarticle);
$txp_context = $old_context;
if ($url) {
if ($thing === null) {
return $url;
}
return tag(parse($thing), 'a', array(
'rel' => 'bookmark',
'href' => $url,
'title' => $atts['title'],
'style' => $atts['style'],
'class' => $atts['class'],
));
}
}
// -------------------------------------------------------------
function lang()
{
return txpspecialchars(LANG);
}
// -------------------------------------------------------------
function breadcrumb($atts, $thing = null)
{
global $c, $s, $sitename, $thiscategory, $context;
extract(lAtts(array(
'type' => $context,
'category' => $c,
'section' => $s,
'wraptag' => 'p',
'separator' => ' » ',
'limit' => null,
'offset' => 0,
'link' => 1,
'label' => $sitename,
'title' => '',
'class' => '',
'linkclass' => '',
), $atts));
$content = array();
$label = txpspecialchars($label);
$type = $type === true ? $context : validContext($type);
$section != 'default' or $section = '';
if ($link && $label) {
$label = doTag($label, 'a', $linkclass, ' href="'.hu.'"');
}
if (!empty($section)) {
$section_title = ($title) ? fetch_section_title($section) : $section;
$section_title_html = escape_title($section_title);
$content[] = ($link)
? (doTag($section_title_html, 'a', $linkclass, ' href="'.pagelinkurl(array('s' => $s)).'"'))
: $section_title_html;
}
if (!$category) {
$catpath = array();
} else {
$catpath = array_reverse(getRootPath($category, $type));
}
if ($limit || $offset) {
$offset = (int)$offset < 0 ? (int)$offset - 1 : (int)$offset;
$catpath = array_slice($catpath, $offset, isset($limit) ? (int)$limit : null);
}
$oldcategory = isset($thiscategory) ? $thiscategory : null;
foreach ($catpath as $thiscategory) {
$category_title_html = isset($thing) ? parse($thing) : ($title ? escape_title($thiscategory['title']) : $thiscategory['name']);
$content[] = ($link)
? doTag($category_title_html, 'a', $linkclass, ' href="'.pagelinkurl(array(
'c' => $thiscategory['name'],
'context' => $type,
's' => $section
)).'"')
: $category_title_html;
}
$thiscategory = isset($oldcategory) ? $oldcategory : null;
// Add the label at the end, to prevent breadcrumb for homepage.
if ($content) {
return doWrap($label ? array_merge(array($label), $content) : $content, $wraptag, $separator, $class);
}
}
//------------------------------------------------------------------------
function if_excerpt($atts, $thing = null)
{
global $thisarticle;
assert_article();
$x = trim($thisarticle['excerpt']) !== '';
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
// Searches use default page. This tag allows you to use different templates if searching
// -------------------------------------------------------------
function if_search($atts, $thing = null)
{
global $pretext;
$x = !empty($pretext['q']);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_search_results($atts, $thing = null)
{
global $pretext, $thispage, $is_article_list;
if (empty($pretext['q']) || empty($thispage)) {
return $is_article_list ? postpone_process() : '';
}
extract(lAtts(array(
'min' => 1,
'max' => 0,
), $atts));
$results = (int) $thispage['grand_total'];
$x = $results >= $min && (!$max || $results <= $max);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_category($atts, $thing = null)
{
global $c, $context, $thiscategory;
extract(lAtts(array(
'category' => false,
'type' => false,
'name' => false,
'parent' => 0,
), $atts));
if ($category === false) {
$category = $c;
$theType = $context;
} elseif ($category === true) {
$category = empty($thiscategory['name']) ? $c : $thiscategory['name'];
$theType = empty($thiscategory['type']) ? $context : $thiscategory['type'];
} else {
$theType = $type && $type !== true ? validContext($type) : $context;
($parent || $type === false) or $parent = true;
$category = trim($category);
}
if ($type && $type !== true && $theType !== $type) {
$x = false;
} else {
$parentname = $parent && is_numeric((string)$parent);
$x = $name === false ? !empty($category) : $parentname || in_list($category, $name);
}
if ($x && $parent && $category) {
$path = array_column(getRootPath($category, $theType), 'name');
if (!$parentname) {
$name = $parent;
$parent = true;
}
$names = do_list_unique($name);
if ($parent === true) {
$x = $path && ($name === false || array_intersect($path, $names));
} else {
($parent = (int)$parent) >= 0 or $parent = count($path) + $parent - 1;
$x = isset($path[$parent]) && ($name === false || in_array($path[$parent], $names));
}
}
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_article_category($atts, $thing = null)
{
global $thisarticle;
assert_article();
extract(lAtts(array(
'name' => '',
'number' => '',
), $atts));
$cats = array();
if ($number) {
if (!empty($thisarticle['category'.$number])) {
$cats = array($thisarticle['category'.$number]);
}
} else {
if (!empty($thisarticle['category1'])) {
$cats[] = $thisarticle['category1'];
}
if (!empty($thisarticle['category2'])) {
$cats[] = $thisarticle['category2'];
}
$cats = array_unique($cats);
}
if ($name) {
$cats = array_intersect(do_list($name), $cats);
}
$x = !empty($cats);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_section($atts, $thing = null)
{
global $s, $thissection;
extract(lAtts(array('name' => false, 'section' => false), $atts));
switch ($section) {
case true: $section = isset($thissection) ? $thissection['name'] : $s; break;
case false: $section = $s; break;
}
$section !== 'default' or $section = '';
$name === false or $name = do_list($name);
if ($section) {
$x = $name === false || in_array($section, $name);
} else {
$x = $name !== false && (in_array('', $name) || in_array('default', $name));
}
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_article_section($atts, $thing = null)
{
global $thisarticle, $txp_sections;
assert_article();
extract(lAtts(array('name' => ''), $atts));
$section = $thisarticle['section'];
$x = $name === true ? !empty($txp_sections[$section]['page']) : in_list($section, $name);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function php($atts = null, $thing = null)
{
global $is_article_body, $thisarticle, $prefs, $pretext;
$error = null;
if (empty($is_article_body)) {
if (empty($prefs['allow_page_php_scripting'])) {
$error = 'php_code_disabled_page';
}
} else {
if (!empty($prefs['allow_article_php_scripting'])) {
if (!has_privs('article.php', $thisarticle['authorid'])) {
$error = 'php_code_forbidden_user';
}
} else {
$error = 'php_code_disabled_article';
}
}
if ($thing !== null) {
ob_start();
if ($error) {
trigger_error(gTxt($error));
} else {
eval($thing);
}
return ob_get_clean();
}
return empty($error);
}
// -------------------------------------------------------------
function txp_header($atts)
{
extract(lAtts(array(
'name' => 'Content-Type',
'replace' => 1,
'value' => isset($atts['name']) ? true : 'text/html; charset=utf-8',
'break' => ''
), $atts));
$out = set_headers(array($name => $value), $replace);
return $out ? doWrap($out, null, $break) : null;
}
// -------------------------------------------------------------
function custom_field($atts, $thing = null)
{
global $thisarticle;
assert_article();
extract(lAtts(array(
'name' => get_pref('custom_1_set'),
'escape' => null,
'default' => '',
), $atts));
$name = strtolower($name);
if (!isset($thisarticle[$name])) {
trigger_error(gTxt('field_not_found', array('{name}' => $name)), E_USER_NOTICE);
return '';
}
if (!isset($thing)) {
$thing = $thisarticle[$name] !== '' ? $thisarticle[$name] : $default;
}
$thing = ($escape === null ? txpspecialchars($thing) : parse($thing));
return txp_sandbox(array('field' => 'custom_field') + $atts, $thing, false);
}
// -------------------------------------------------------------
function if_custom_field($atts, $thing = null)
{
global $thisarticle;
assert_article();
extract($atts = lAtts(array(
'name' => get_pref('custom_1_set'),
'value' => null,
'match' => 'exact',
'separator' => '',
), $atts));
$name = strtolower($name);
if (!isset($thisarticle[$name])) {
trigger_error(gTxt('field_not_found', array('{name}' => $name)), E_USER_NOTICE);
return '';
}
if ($value !== null) {
$cond = txp_match($atts, $thisarticle[$name]);
} else {
$cond = ($thisarticle[$name] !== '');
}
return isset($thing) ? parse($thing, !empty($cond)) : !empty($cond);
}
// -------------------------------------------------------------
function site_url($atts)
{
extract(lAtts(array(
'type' => '',
), $atts));
return $type === 'admin' ? ahu : hu;
}
// -------------------------------------------------------------
function error_message()
{
global $txp_error_message;
return $txp_error_message;
}
// -------------------------------------------------------------
function error_status()
{
global $txp_error_status;
return $txp_error_status;
}
// -------------------------------------------------------------
function if_status($atts, $thing = null)
{
global $pretext, $txp_error_code;
extract(lAtts(array('status' => '200'), $atts));
$page_status = $txp_error_code
? $txp_error_code
: $pretext['status'];
$x = $status == $page_status;
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function page_url($atts, $thing = null)
{
global $pretext, $txp_context;
static $specials = null, $internals = array('id', 's', 'c', 'context', 'q', 'm', 'p', 'month', 'author', 'f'),
$lAtts = array(
'type' => null,
'default' => false,
'escape' => null,
'context' => null
);
isset($specials) or $specials = array(
'admin_root' => ahu,
'images_root' => ihu.get_pref('img_dir'),
'themes_root' => hu.get_pref('skin_dir'),
'theme_path' => hu.get_pref('skin_dir').'/'.$pretext['skin'],
'theme' => $pretext['skin'],
);
$old_context = $txp_context;
if (!isset($atts['context'])) {
if (empty($txp_context)) {
$atts = lAtts($lAtts, $atts);
} else {
$atts = lAtts($lAtts + $txp_context, $atts);
$txp_context = array_intersect_key($atts, $txp_context);
}
} elseif ($atts['context'] === true) {
$atts = lAtts($lAtts, $atts);
} else {
$extralAtts = array_fill_keys(do_list_unique($atts['context']), null);
$atts = lAtts($lAtts + $extralAtts, $atts);
$extralAtts = array_intersect_key($atts, $extralAtts);
}
extract($atts, EXTR_SKIP);
$txp_context = get_context(isset($extralAtts) ? $extralAtts : $context, $internals);
if ($default !== false) {
if ($default === true) {
if (isset($type)) {
unset($txp_context[$type]);
} else {
$txp_context = array();
}
} elseif (in_array($type, $internals)) {
$txp_context[$type] = $default;
}
}
if (!isset($type)) {
$type = 'request_uri';
}
if (isset($thing)) {
$out = parse($thing);
} elseif (isset($context)) {
$out = pagelinkurl($txp_context);
$escape === null or $out = str_replace('&', '&', $out);
} elseif (isset($specials[$type])) {
$out = $specials[$type];
} elseif ($type == 'pg' && $pretext['pg'] == '') {
$out = '1';
} elseif (isset($pretext[$type]) && is_bool($default)) {
$out = $escape === null ? txpspecialchars($pretext[$type]) : $pretext[$type];
} else {
$out = gps($type, $default);
!is_array($out) or $out = implode(',', $out);
$escape !== null or $out = txpspecialchars($out);
}
$txp_context = $old_context;
return $out;
}
// -------------------------------------------------------------
function if_different($atts, $thing = null)
{
static $last, $tested;
extract(lAtts(array(
'test' => null,
'not' => ''
), $atts));
$key = md5($thing);
$out = isset($test) ? $test : parse($thing);
if (isset($test)) {
if ($different = !isset($tested[$key]) || $out != $tested[$key]) {
$tested[$key] = $out;
}
} else {
if ($different = !isset($last[$key]) || $out != $last[$key]) {
$last[$key] = $out;
}
}
$condition = $not ? !$different : $different;
return isset($test) ?
parse($thing, $condition) :
($condition ? $out : parse($thing, false));
}
// -------------------------------------------------------------
function if_first($atts, $thing = null, $type = 'article')
{
global ${"this$type"};
$assert = 'assert_'.$type;
$assert();
$x = !empty(${"this$type"}['is_first']);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_last($atts, $thing = null, $type = 'article')
{
global ${"this$type"};
$assert = 'assert_'.$type;
$assert();
$x = !empty(${"this$type"}['is_last']);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_plugin($atts, $thing = null)
{
global $plugins, $plugins_ver;
extract(lAtts(array(
'name' => '',
'version' => '',
), $atts));
$x = @in_array($name, $plugins) && (!$version || version_compare($plugins_ver[$name], $version) >= 0);
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function file_download_list($atts, $thing = null)
{
global $s, $c, $context, $thisfile, $thispage, $pretext;
extract(lAtts(array(
'break' => br,
'category' => '',
'author' => '',
'realname' => '',
'auto_detect' => 'category, author',
'class' => __FUNCTION__,
'form' => 'files',
'id' => '',
'pageby' => '',
'limit' => 10,
'offset' => 0,
'month' => '',
'time' => null,
'sort' => 'filename asc',
'wraptag' => '',
'status' => STATUS_LIVE,
), $atts));
if (!is_numeric($status)) {
$status = getStatusNum($status);
}
// Note: status treated slightly differently.
$where = array();
$filters = isset($atts['id']) || isset($atts['category']) || isset($atts['author']) || isset($atts['realname']) || isset($atts['status']);
$context_list = (empty($auto_detect) || $filters) ? array() : do_list_unique($auto_detect);
$pageby = ($pageby == 'limit') ? $limit : $pageby;
if ($category) {
$where[] = "category IN ('".join("','", doSlash(do_list_unique($category)))."')";
}
$ids = $id ? array_map('intval', do_list_unique($id, array(',', '-'))) : array();
if ($ids) {
$where[] = "id IN ('".join("','", $ids)."')";
}
if ($author) {
$where[] = "author IN ('".join("','", doSlash(do_list_unique($author)))."')";
}
if ($realname) {
$authorlist = safe_column("name", 'txp_users', "RealName IN ('".join("','", doArray(doSlash(do_list_unique($realname)), 'urldecode'))."')");
if ($authorlist) {
$where[] = "author IN ('".join("','", doSlash($authorlist))."')";
}
}
// If no files are selected, try...
if (!$where && !$filters) {
foreach ($context_list as $ctxt) {
switch ($ctxt) {
case 'category':
// ...the global category in the URL.
if ($context == 'file' && !empty($c)) {
$where[] = "category = '".doSlash($c)."'";
}
break;
case 'author':
// ...the global author in the URL.
if ($context == 'file' && !empty($pretext['author'])) {
$where[] = "author = '".doSlash($pretext['author'])."'";
}
break;
}
// Only one context can be processed.
if ($where) {
break;
}
}
}
if ($status) {
$where[] = "status = '".doSlash($status)."'";
} elseif (!$where && $filters) {
// If nothing matches, output nothing.
return '';
}
if ($time === null || $time || $month) {
$where[] = buildTimeSql($month, $time === null ? 'past' : $time, 'created');
}
$where = join(" AND ", $where);
// Set up paging if required.
if ($limit && $pageby) {
$pg = (!$pretext['pg']) ? 1 : $pretext['pg'];
$pgoffset = $offset + (($pg - 1) * $pageby);
if (empty($thispage)) {
$grand_total = safe_count('txp_file', $where);
$total = $grand_total - $offset;
$numPages = ($pageby > 0) ? ceil($total/$pageby) : 1;
// Send paging info to txp:newer and txp:older.
$pageout['pg'] = $pg;
$pageout['numPages'] = $numPages;
$pageout['s'] = $s;
$pageout['c'] = $c;
$pageout['context'] = 'file';
$pageout['grand_total'] = $grand_total;
$pageout['total'] = $total;
$thispage = $pageout;
}
} else {
$pgoffset = $offset;
}
// Preserve order of custom file ids unless 'sort' attribute is set.
if (!empty($ids) && empty($atts['sort'])) {
$safe_sort = "FIELD(id, ".join(',', $ids).")";
} else {
$safe_sort = sanitizeForSort($sort);
}
$qparts = array(
"ORDER BY ".$safe_sort,
($limit) ? "LIMIT ".intval($pgoffset).", ".intval($limit) : '',
);
$rs = safe_rows_start("*", 'txp_file', $where.' '.join(' ', $qparts));
if ($rs) {
$count = 0;
$last = numRows($rs);
$out = array();
while ($a = nextRow($rs)) {
++$count;
$thisfile = file_download_format_info($a);
$thisfile['is_first'] = ($count == 1);
$thisfile['is_last'] = ($count == $last);
$out[] = ($thing) ? parse($thing) : parse_form($form);
$thisfile = '';
}
if ($out) {
return doWrap($out, $wraptag, $break, $class);
}
}
return '';
}
// -------------------------------------------------------------
function file_download($atts, $thing = null)
{
global $thisfile;
extract(lAtts(array(
'filename' => '',
'form' => 'files',
'id' => '',
), $atts));
$from_form = false;
if ($id) {
$thisfile = fileDownloadFetchInfo('id = '.intval($id).' and created <= '.now('created'));
} elseif ($filename) {
$thisfile = fileDownloadFetchInfo("filename = '".doSlash($filename)."' and created <= ".now('created'));
} else {
assert_file();
$from_form = true;
}
if ($thisfile) {
$out = ($thing) ? parse($thing) : parse_form($form);
// Cleanup: this wasn't called from a form, so we don't want this
// value remaining.
if (!$from_form) {
$thisfile = '';
}
return $out;
}
}
// -------------------------------------------------------------
function file_download_link($atts, $thing = null)
{
global $thisfile;
extract(lAtts(array(
'filename' => '',
'id' => '',
), $atts));
$from_form = false;
if ($id) {
$thisfile = fileDownloadFetchInfo('id = '.intval($id).' and created <= '.now('created'));
} elseif ($filename) {
$thisfile = fileDownloadFetchInfo("filename = '".doSlash($filename)."' and created <= ".now('created'));
} else {
assert_file();
$from_form = true;
}
if ($thisfile) {
$url = filedownloadurl($thisfile['id'], $thisfile['filename']);
$out = ($thing) ? href(parse($thing), $url) : $url;
// Cleanup: this wasn't called from a form, so we don't want this
// value remaining
if (!$from_form) {
$thisfile = '';
}
return $out;
}
}
// -------------------------------------------------------------
function file_download_size($atts)
{
global $thisfile;
assert_file();
extract(lAtts(array(
'decimals' => 2,
'format' => '',
), $atts));
if (is_numeric($decimals) && $decimals >= 0) {
$decimals = intval($decimals);
} else {
$decimals = 2;
}
if (isset($thisfile['size'])) {
$format_unit = strtolower(substr($format, 0, 1));
return format_filesize($thisfile['size'], $decimals, $format_unit);
} else {
return '';
}
}
// -------------------------------------------------------------
function file_download_time($atts, $thing = null, $time = 'created')
{
global $thisfile;
assert_file();
extract(lAtts(array('format' => ''), $atts));
if (!empty($thisfile[$time])) {
return fileDownloadFormatTime(array(
'ftime' => $thisfile[$time],
'format' => $format,
));
}
}
// -------------------------------------------------------------
function file_download_id()
{
global $thisfile;
assert_file();
return $thisfile['id'];
}
// -------------------------------------------------------------
function file_download_name($atts)
{
global $thisfile;
assert_file();
extract(lAtts(array('title' => 0), $atts));
return ($title) ? $thisfile['title'] : $thisfile['filename'];
}
// -------------------------------------------------------------
function file_download_category($atts)
{
global $thisfile;
assert_file();
extract(lAtts(array('title' => 0), $atts));
if ($thisfile['category']) {
$category = ($title)
? fetch_category_title($thisfile['category'], 'file')
: $thisfile['category'];
return $category;
}
}
// -------------------------------------------------------------
function file_download_author($atts)
{
global $thisfile, $s;
assert_file();
extract(lAtts(array(
'link' => 0,
'title' => 1,
'section' => '',
'this_section' => '',
), $atts));
if ($thisfile['author']) {
$author_name = get_author_name($thisfile['author']);
$display_name = txpspecialchars(($title) ? $author_name : $thisfile['author']);
$section = ($this_section) ? ($s == 'default' ? '' : $s) : $section;
$author = ($link)
? href($display_name, pagelinkurl(array(
's' => $section,
'author' => $author_name,
'context' => 'file',
)))
: $display_name;
return $author;
}
}
// -------------------------------------------------------------
function file_download_downloads()
{
global $thisfile;
assert_file();
return $thisfile['downloads'];
}
// -------------------------------------------------------------
function file_download_description($atts)
{
global $thisfile;
assert_file();
extract(lAtts(array('escape' => null), $atts));
if ($thisfile['description']) {
return ($escape === null)
? txpspecialchars($thisfile['description'])
: $thisfile['description'];
}
}
// -------------------------------------------------------------
function hide($atts = array(), $thing = null)
{
if (!isset($atts['process'])) {
return '';
}
global $pretext;
extract(lAtts(array('process' => null), $atts));
if (!$process) {
return $pretext['secondpass'] < get_pref('secondpass', 1) ? postpone_process() : $thing;
} elseif (is_numeric($process)) {
return abs($process) > $pretext['secondpass'] + 1 ?
postpone_process($process) :
($process > 0 ? parse($thing) : ''.parse($thing).'');
} elseif ($process) {
parse($thing);
}
return '';
}
// -------------------------------------------------------------
function rsd()
{
global $prefs;
trigger_error(gTxt('deprecated_tag'), E_USER_NOTICE);
return ($prefs['enable_xmlrpc_server']) ? '' : '';
}
// -------------------------------------------------------------
function variable($atts, $thing = null)
{
global $variable, $trace;
$set = isset($thing) || isset($atts['value']) || isset($atts['add']) || isset($atts['reset']) ? '' : null;
extract(lAtts(array(
'escape' => $set,
'name' => '',
'value' => null,
'add' => null,
'reset' => null,
'separator' => null,
'output' => null
), $atts));
$var = isset($variable[$name]) ? $variable[$name] : null;
if (empty($name)) {
trigger_error(gTxt('variable_name_empty'));
} elseif ($set === null && !isset($var)) {
$trace->log("[: Unknown variable '$name']");
} else {
if ($add === true) {
empty($thing) or $thing = parse($thing);
if (!isset($value)) {
$add = isset($thing) ? $thing : 1;
} elseif ($value === true) {
$add = $var;
!isset($thing) or $var = $thing;
} else {
$add = isset($thing) ? $thing : $var;
$var = $value;
}
} elseif ($value === true) {
isset($var) or $var = (isset($thing) ? parse($thing) : null);
} else {
$var = isset($value) ?
$value :
(isset($thing) ? parse($thing) : $var);
}
if (isset($add)) {
if (!isset($separator) && is_numeric($add) && (empty($var) || is_numeric($var))) {
$var += $add;
} else {
$var .= ($var ? $separator : '').$add;
}
}
}
if ($set !== null) {
$var = $escape ? txp_escape(array('escape' => $escape), $var) : $var;
if (isset($reset)) {
$variable[$name] = $reset === true ? null : $reset;
isset($output) or $output = 1;
} else {
$variable[$name] = $var;
}
} else {
isset($output) or $output = 1;
}
return !$output ? '' : ((int)$output ? $var : txp_escape(array('escape' => $output), $var));
}
// -------------------------------------------------------------
function if_variable($atts, $thing = null)
{
global $variable;
extract($atts = lAtts(array(
'name' => '',
'value' => false,
'match' => 'exact',
'separator' => '',
), $atts));
if (empty($name)) {
trigger_error(gTxt('variable_name_empty'));
return '';
}
if (isset($variable[$name])) {
$x = $value === false ? true : txp_match($atts, $variable[$name]);
} else {
$x = false;
}
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function if_request($atts, $thing = null)
{
extract($atts = lAtts(array(
'name' => '',
'type' => 'request',
'value' => null,
'match' => 'exact',
'separator' => '',
), $atts));
switch ($type = strtoupper($type)) {
case 'REQUEST':
case 'GET':
case 'POST':
case 'COOKIE':
case 'SERVER':
global ${'_'.$type};
$what = isset(${'_'.$type}[$name]) ? ${'_'.$type}[$name] : null;
$x = txp_match($atts, $what);
break;
case 'NAME':
$x = txp_match($atts, $name);
break;
default:
$x = false;
trigger_error(gTxt('invalid_attribute_value', array('{name}' => 'type')), E_USER_NOTICE);
}
return isset($thing) ? parse($thing, $x) : $x;
}
// -------------------------------------------------------------
function txp_eval($atts, $thing = null)
{
global $prefs, $txp_tag, $txp_atts;
static $xpath = null, $functions = null;
unset($txp_atts['evaluate']);
$staged = null;
extract(lAtts(array(
'query' => null,
'test' => !isset($atts['query']),
), $atts));
if (!isset($thing) && isset($atts['test']) && $atts['test'] !== true) {
$thing = $atts['test'];
$test = null;
}
if (!isset($query) || $query === true) {
$x = true;
} elseif (!($query = trim($query))) {
$x = $query;
} elseif (class_exists('DOMDocument')) {
if (!isset($xpath)) {
$xpath = new DOMXpath(new DOMDocument);
$functions = do_list_unique(get_pref('txp_evaluate_functions'));
$_functions = array();
foreach ($functions as $function) {
list($key, $val) = do_list($function, '=') + array(null, $function);
if (function_exists($val)) {
$_functions[$key] = $val;
}
}
if ($_functions) {
$functions = implode('|', array_keys($_functions));
$xpath->registerNamespace('php', 'http://php.net/xpath');
$xpath->registerPHPFunctions($_functions);
} else {
$functions = false;
}
$prefs['_txp_evaluate_functions'] = $_functions;
}
if ($functions) {
$query = preg_replace_callback('/\b('.$functions.')\s*\(\s*(\)?)/',
function ($match) {
global $prefs;
$function = empty($prefs['_txp_evaluate_functions'][$match[1]]) ? $match[1] : $prefs['_txp_evaluate_functions'][$match[1]];
return "php:function('$function'".($match[2] ? ')' : ',');
},
$query
);
}
if (strpos($query, '<+>') !== false) {
$staged = $x = true;
} else {
$x = $xpath->evaluate($query);
if ($x instanceof DOMNodeList) {
$x = $x->length;
}
}
} else {
trigger_error(gTxt('missing_dom_extension'));
return '';
}
if (!isset($thing)) {
return $test === true ? !empty($x) : $x;
} elseif (empty($x)) {
return parse($thing, false);
}
$txp_atts['evaluate'] = $test;
$x = parse($thing);
unset($txp_atts['evaluate']);
if ($txp_tag) {
if ($staged) {
$quoted = txp_escape(array('escape' => 'quote'), $x);
$query = str_replace('<+>', $quoted, $query);
$query = $xpath->evaluate($query);
$query = $query instanceof DOMNodeList ? $query->length : $query;
if (empty($query)) {
return parse($thing, false);
} else {
return $test === true ? $x : $query;
}
}
} else {
$txp_atts = null;
$x = parse($thing, false);
}
return $test === null && $query !== true ? !empty($x) : $x;
}
// -------------------------------------------------------------
function txp_escape($atts, $thing = '')
{
global $prefs;
static $textile = null, $decimal = null, $spellout = null, $ordinal = null,
$mb = null, $LocaleInfo = null, $tr = array("'" => "',\"'\",'");
if (empty($atts['escape'])) {
return $thing;
}
extract(lAtts(array('escape' => true), $atts, false));
$escape = $escape === true ? array('html') : do_list(strtolower($escape));
$filter = $tidy = false;
isset($mb) or $mb = extension_loaded('mbstring') ? 'mb_' : '';
foreach ($escape as $attr) {
switch ($attr) {
case 'html':
$thing = txpspecialchars($thing);
break;
case 'url':
$thing = $tidy ? rawurlencode($thing) : urlencode($thing);
break;
case 'js':
$thing = escape_js($thing);
break;
case 'json':
$thing = substr(json_encode($thing, JSON_UNESCAPED_UNICODE), 1, -1);
break;
case 'integer':
!$filter or $thing = do_list($thing);
// no break
case 'number': case 'float': case 'spell': case 'ordinal':
isset($LocaleInfo) or $LocaleInfo = localeconv();
$dec_point = $LocaleInfo['decimal_point'];
$thousands_sep = utf8_encode($LocaleInfo['thousands_sep']);
!$thousands_sep or $thing = str_replace($thousands_sep, '', $thing);
$dec_point == '.' or $thing = str_replace($dec_point, '.', $thing);
if (is_array($thing)) {// integer mode
$value = $tidy ?
array_map(function ($str) {
return filter_var($str, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
}, $thing) :
$thing;
} else {
$value = floatval($tidy ?
filter_var($thing, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION) :
$thing
);
}
switch ($attr) {
case 'integer':
$thing = $filter ? implode(',', array_filter(array_map('intval', $value))) : intval($value);
break;
case 'number':
isset($decimal)
or !($decimal = class_exists('NumberFormatter'))
or $decimal = new NumberFormatter(LANG, NumberFormatter::DECIMAL);
if ($decimal) {
$thing = $decimal->format($value);
} else {
$thing = number_format($value, 3, $dec_point, $thousands_sep);
$thing = rtrim(rtrim($thing, '0'), $dec_point);
}
break;
case 'spell':
isset($spellout)
or !($spellout = class_exists('NumberFormatter'))
or $spellout = new NumberFormatter(LANG, NumberFormatter::SPELLOUT);
if ($spellout && ($tidy || is_numeric($thing))) {
$thing = $spellout->format($value);
}
break;
case 'ordinal':
isset($ordinal)
or !($ordinal = class_exists('NumberFormatter'))
or $ordinal = new NumberFormatter(LANG, NumberFormatter::ORDINAL);
if ($ordinal && ($tidy || is_numeric($thing))) {
$thing = $ordinal->format($value);
}
break;
default:
$thing = $dec_point != '.' ? str_replace($dec_point, '.', $value) : $value;
}
break;
case 'tags':
$thing = strip_tags($thing);
break;
case 'upper': case 'lower':
$function = ($mb && mb_detect_encoding($thing) != 'ASCII' ? 'mb_strto' : 'strto').$attr;
$thing = $function($thing);
break;
case 'title':
$thing = $mb && mb_detect_encoding($thing) != 'ASCII' ?
mb_convert_case($thing, MB_CASE_TITLE) : ucwords($thing);
break;
case 'trim': case 'ltrim': case 'rtrim':
$filter = true;
$thing = is_int($thing) ? ($thing ? $thing : '') : $attr($thing);
break;
case 'tidy':
$thing = preg_replace('/\s+/', ' ', trim($thing));
$tidy = true;
break;
case 'textile':
if ($textile === null) {
$textile = Txp::get('\Textpattern\Textile\Parser');
}
$thing = $textile->parse($tidy ? ' '.$thing : $thing);
!$tidy or $thing = ltrim($thing);
break;
case 'quote':
$thing = strpos($thing, "'") === false ? "'$thing'" : "concat('".strtr($thing, $tr)."')";
break;
default:
$thing = preg_replace('@?'.($tidy ? preg_quote($attr) : $attr).'\b[^<>]*>@Usi', '', $thing);
}
}
return $thing;
}
// -------------------------------------------------------------
function txp_wraptag($atts, $thing = '')
{
extract(lAtts(array(
'label' => '',
'labeltag' => '',
'wraptag' => '',
'class' => '',
'html_id' => '',
'trim' => null,
'replace' => null,
'default' => null,
), $atts, false));
!isset($default) or trim($thing) !== '' or $thing = $default;
if ($replace === true) {
$sep = isset($trim) && $trim !== true ? $trim : ',';
$thing = isset($trim) ? do_list_unique($thing, $sep, $trim === true ? TEXTPATTERN_STRIP_EMPTY : TEXTPATTERN_STRIP_EMPTY_STRING) : array_unique(explode($sep, $thing));
$thing = implode($sep, $thing);
} elseif (isset($trim)) {
if ($trim === true) {
$thing = isset($replace) ? preg_replace('/\s+/', $replace, trim($thing)) : trim($thing);
} elseif (strlen($trim) > 2 && preg_match('/([^\\\w\s]).+\1[UsiAmuS]*$/As', $trim)) {
$thing = preg_replace($trim, $replace, $thing);
} else {
$thing = isset($replace) ? str_replace($trim, $replace, $thing) : trim($thing, $trim);
}
}
$thing = $wraptag && trim($thing) !== '' ? doTag($thing, $wraptag, $class, '', '', $html_id) : $thing;
return $label && trim($thing) !== '' ? doLabel($label, $labeltag).n.$thing : $thing;
}