* @license http://www.gnu.org/licenses/gpl.html GPL
* @link http://lsx.sourceforge.jp/?Plugin%2Flsx.inc.php
* @version $Id: lsx.inc.php,v 1.17 2007-06-16 11:14:46 sonots $
* @package plugin
*/
// v1.18 PHP8.0対応 2021-12-15 byはいふん
class PluginLsx
{
function __construct()
{
// Configure external plugins
static $conf = array(
'plugin_contents' => 'contentsx',
'plugin_include' => 'includex',
'plugin_new' => 'new',
'plugin_tag' => 'tag',
);
// Modify here for default option values
static $default_options = array(
'hierarchy' => array('bool', true),
'non_list' => array('bool', true),
'reverse' => array('bool', false),
'basename' => array('bool', false), // obsolete
'sort' => array('enum', 'name', array('name', 'reading', 'date')),
'tree' => array('enum', false, array(false, 'leaf', 'dir')),
'depth' => array('number', ''),
'num' => array('number', ''),
'next' => array('bool', false),
'except' => array('string', ''),
'filter' => array('string', ''),
'prefix' => array('string', ''),
'contents' => array('array', ''),
'include' => array('array', ''),
'info' => array('enumarray', array(), array('date', 'new')),
'date' => array('bool', false), // will be obsolete
'new' => array('bool', false),
'tag' => array('string', ''),
'linkstr' => array('enum', 'relative', array('relative', 'absolute', 'basename', 'title', 'headline')),
'link' => array('enum', 'page', array('page', 'anchor', 'off')),
'newpage' => array('enum', false, array('on', 'except')),
'popular' => array('enum', false, array('total', 'today', 'yesterday', 'recent')), // alpha
);
$this->conf = &$conf;
$this->default_options = &$default_options;
// init
$this->options = $this->default_options;
if (function_exists('mb_ereg')) { // extension_loaded('mbstring')
mb_regex_encoding(SOURCE_ENCODING);
$this->ereg = 'mb_ereg';
} else {
$this->ereg = 'ereg';
}
}
function PluginLsx() {
$this->__construct();
}
// static
var $conf;
var $default_options;
// var
var $options;
var $error = "";
var $plugin = "lsx";
var $metapages;
function convert()
{
$args = func_get_args();
$body = $this->body($args);
if ($this->error != "") {
$body = "
$this->plugin(): $this->error
";
}
return $body;
}
function action()
{
global $vars;
$args = $vars;
$body = $this->body($args);
if ($this->error != "") {
$body = "$this->plugin(): $this->error
";
}
if (! isset($body)) $body = 'no result.
';
if ($this->options['tag'][1] != '') {
$msg = htmlsc($this->options['tag'][1]);
} elseif ($this->options['prefix'][1] != '') {
$msg = htmlsc($this->options['prefix'][1]);
} else {
$msg = $this->plugin;
}
return array('msg'=>$msg, 'body'=>$body);
}
function body($args)
{
$parser = new PluginLsxOptionParser();
$this->options = $parser->parse_options($args, $this->options);
if ($parser->error != "") { $this->error = $parser->error; return; }
$this->validate_options();
if ($this->error !== "") { return $this->error; }
$this->init_metapages();
if ($this->error !== "") { return $this->error; }
$this->prefix_filter_metapages();
if ($this->error !== "") { return $this->error; }
$this->nonlist_filter_metapages();
if ($this->error !== "") { return $this->error; }
$this->relative_metapages(); // before filter, except
if ($this->error !== "") { return $this->error; }
$this->filter_filter_metapages();
if ($this->error !== "") { return $this->error; }
$this->except_filter_metapages();
if ($this->error !== "") { return $this->error; }
$this->newpage_filter_metapages();
if ($this->error !== "") { return $this->error; }
$parser = new PluginLsxOptionParser();
$this->maxdepth = $this->depth_metapages();
$this->options['depth'][1] = $parser->parse_numoption($this->options['depth'][1], 1, $this->maxdepth);
if ($parser->error != "") { $this->error = $parser->error; return; }
$this->depth_filter_metapages();
if ($this->error !== "") { return $this->error; }
$this->tree_filter_metapages();
if ($this->error !== "") { return $this->error; }
$this->popular_metapages(); // before sort
if ($this->error !== "") { return $this->error; }
$this->timestamp_metapages(); // before sort
if ($this->error !== "") { return $this->error; }
$this->sort_metapages(); // before num_filter
if ($this->error !== "") { return $this->error; }
$this->maxnum = sizeof($this->metapages); // after all filters
$this->options['num'][1] = $parser->parse_numoption($this->options['num'][1], 1, $this->maxnum);
if ($parser->error != "") { $this->error = $parser->error; return; }
$this->num_filter_metapages();
if ($this->error !== "") { return $this->error; }
$this->hierarchy_metapages();
if ($this->error !== "") { return $this->error; }
$this->info_metapages();
if ($this->error !== "") { return $this->error; }
$this->linkstr_metapages();
if ($this->error !== "") { return $this->error; }
$this->link_metapages();
if ($this->error !== "") { return $this->error; }
$body = $this->list_pages();
$body .= $this->next_pages();
return $body;
}
function validate_options()
{
global $vars;
if ($this->options['tag'][1] != '') {
if(! exist_plugin($this->conf['plugin_tag'])) {
$this->error .= "The option, tag, requires #{$this->conf['plugin_tag']} plugin, but it does not exist. ";
return;
}
$this->options['hierarchy'][1] = false;
// best is to turn off the default only so that 'hierarchy' can be configured by option.
} else {
if ($this->options['prefix'][1] == '') {
$this->options['prefix'][1] = $vars['page'] != '' ? $vars['page'] . '/' : '';
}
}
if ($this->options['prefix'][1] == '/') {
$this->options['prefix'][1] = '';
} elseif ($this->options['prefix'][1] != '') {
$this->options['prefix'][1] = $this->get_fullname($this->options['prefix'][1], $vars['page']);
}
$this->options['prefix'][4] = $this->options['prefix'][1];
if ($this->options['sort'][1] == 'date') {
$this->options['hierarchy'][1] = false;
}
// alpha func
if ($this->options['popular'][1] != false) {
$this->options['sort'][1] = 'popular';
$this->options['hierarchy'][1] = false;
// Future Work: info_popular. hmmm
}
// Another Idea
// sort=popular>today,popular>total,popular>yesterday,popular>recent
// if (strpos($this->options['sort'][1], 'popular>') !== false) {
// list($this->optiions['sort'][1], $this->options['popular'][1]) = explode('>', $this->options['sort'][1]);
// $this->options['hierarchy'][1] = false;
// }
if ($this->options['contents'][1] != '') {
if(! exist_plugin_convert($this->conf['plugin_contents'])) {
$this->error .= "The option, contents, requires {$this->conf['plugin_contents']} plugin, but it does not exist. ";
return;
}
}
if ($this->options['include'][1] != '') {
if(! exist_plugin_convert($this->conf['plugin_include'])) {
$this->error .= "The option, include, requires {$this->conf['plugin_include']} plugin, but it does not exist. ";
return;
}
$this->options['hierarchy'][1] = false; // hierarchy + include => XHTML invalid
$this->options['date'][1] = false; // include does not use definitely
$this->options['new'][1] = false; // include does not use definitely
$this->options['contents'][1] = ''; // include does not use definitely
}
if ($this->options['linkstr'][1] === 'title' || $this->options['linkstr'][1] === 'headline') {
if(! exist_plugin_convert($this->conf['plugin_contents'])) {
$this->error .= "The option, linkstr, requires {$this->conf['plugin_contents']} plugin, but it does not exist. ";
return;
}
}
// to support lower versions
// basename -> linkstr
if ($this->options['basename'][1] === true) {
$this->options['linkstr'][1] = 'basename';
}
// new,date -> info
foreach ($this->options['info'][2] as $key) {
if ($this->options[$key][1]) {
array_push($this->options['info'][1], $key);
}
}
$this->options['info'][1] = array_unique($this->options['info'][1]);
// to save time (to avoid in_array everytime)
foreach ($this->options['info'][1] as $key) {
$this->options[$key][1] = true;
}
if ($this->options['new'][1] && ! exist_plugin_inline($this->conf['plugin_new'])) {
$this->error .= "The option, new, requires {$this->conf['plugin_new']} plugin, but it does not exist. ";
return;
}
}
function next_pages()
{
if (! $this->options['next'][1] || $this->options['num'][1] == '') return;
$options = $this->options;
unset($options['num']);
$href = get_script_uri() . '?' . 'cmd=lsx';
foreach ($options as $key => $val) {
if (isset($val[4])) {
$href .= '&' . htmlsc($key) . '=' . htmlsc(rawurlencode($val[4]));
}
}
$count = count($this->options['num'][1]);
$min = reset($this->options['num'][1]);
$max = end($this->options['num'][1]);
$maxnum = $this->maxnum;
$prevmin = max($min - $count, 0);
$prevmax = min($min - 1, $maxnum);
$prevlink = '';
if ($prevmax > 0) {
$prevhref = $href . '&num=' . $prevmin . ':' . $prevmax;
$prevlink = '' . _('Prev ') . $count . '';
}
$nextmin = max($max + 1, 0);
$nextmax = min($max + $count, $maxnum);
$nextlink = '';
if ($nextmin < $maxnum) {
$nexthref = $href . '&num=' . $nextmin . ':' . $nextmax;
$nextlink = '' . _('Next ') . $count . '';
}
$ret = '';
$ret .= '' . $prevlink . $nextlink . '
';
return $ret;
}
function list_pages()
{
global $script;
if (sizeof($this->metapages) == 0) {
return;
}
/* HTML validate (without - , we have to do as
- as pukiwiki standard. I did not like it)
- 1
- 1
- 1
- 2
- 1
=>
1
1
*/
$html = "";
$ul = $pdepth = 0;
foreach ($this->metapages as $i => $metapage) {
$page = $metapage['page'];
$exist = $metapage['exist'];
$depth = $metapage['listdepth'];
$info = $metapage['info'];
$link = $metapage['link'];
if ($exist && $this->options['include'][1] != '') {
$option = '"' . $page . '"';
if (! empty($this->options['include'][1])) {
$option .= ',' . csv_implode(',', $this->options['include'][1]);
}
$html .= do_plugin_convert($this->conf['plugin_include'], $option);
continue;
}
if ($depth > $pdepth) {
$diff = $depth - $pdepth;
$html .= str_repeat('- ', $diff - 1);
if ($depth == 1) { // or $first flag
$html .= '
- ';
} else {
$html .= '
- ';
}
$ul += $diff;
} elseif ($depth == $pdepth) {
$html .= '
- ';
} elseif ($depth < $pdepth) {
$diff = $pdepth - $depth;
$html .= str_repeat('
', $diff);
$html .= ' - ';
$ul -= $diff;
}
$pdepth = $depth;
$html .= $link;
if (isset($info) && $info != '') {
$html .= '' . $info . '' . "\n";
}
if ($exist && $this->options['contents'][1] != '') {
$args = $this->options['contents'][1];
$pagearg = 'page=' . $page ;
array_unshift($args, $pagearg);
$contentsx = new PluginContentsx();
$html .= call_user_func(array($contentsx, 'body'), $args);
}
}
$html .= str_repeat('
', $ul);
return $html;
}
function link_metapages()
{
switch ($this->options['link'][1]) {
case 'page':
foreach ($this->metapages as $i => $metapage) {
if ($metapage['exist']) {
$this->metapages[$i]['link'] =
$this->make_pagelink($metapage['page'], $metapage['linkstr']);
} else {
$this->metapages[$i]['link'] = $metapage['linkstr'];
}
}
break;
case 'anchor':
foreach ($this->metapages as $i => $metapage) {
// PluginIncludex::get_page_anchor($metapage['page'])
$anchor = 'z' . md5($metapage['page']);
$anchor = '#' . htmlsc($anchor);
if ($metapage['exist']) {
$this->metapages[$i]['link'] =
$this->make_pagelink('', $metapage['linkstr'], $anchor);
} else {
$this->metapages[$i]['link'] = $metapage['linkstr'];
}
}
break;
case 'off':
foreach ($this->metapages as $i => $metapage) {
$this->metapages[$i]['link'] = $metapage['linkstr'];
}
break;
}
}
function linkstr_metapages()
{
switch ($this->options['linkstr'][1]) {
case 'absolute':
foreach ($this->metapages as $i => $metapage) {
$this->metapages[$i]['linkstr'] =
htmlsc($metapage['page']);
}
break;
case 'basename':
foreach ($this->metapages as $i => $metapage) {
$this->metapages[$i]['linkstr'] =
htmlsc($this->my_basename($metapage['page']));
}
break;
case 'title':
$contentsx = new PluginContentsx();
foreach ($this->metapages as $i => $metapage) {
$title = $contentsx->get_title($metapage['page']);
$title = strip_htmltag(make_link($title));
$this->metapages[$i]['linkstr'] = $title;
}
break;
case 'headline':
$contentsx = new PluginContentsx();
foreach ($this->metapages as $i => $metapage) {
$metalines = $contentsx->get_metalines($metapage['page']);
$title = $metalines[0]['headline'];
$title = strip_htmltag(make_link($title));
$this->metapages[$i]['linkstr'] = $title;
}
break;
}
// default: relative
if ($this->options['hierarchy'][1] === true) {
foreach ($this->metapages as $i => $metapage) {
if (! isset($metapage['linkstr']) || $metapage['linkstr'] === '') {
$this->metapages[$i]['linkstr'] =
htmlsc($this->my_basename($metapage['page']));
}
}
} else {
foreach ($this->metapages as $i => $metapage) {
if (! isset($metapage['linkstr']) || $metapage['linkstr'] === '') {
$this->metapages[$i]['linkstr'] =
htmlsc($metapage['relative']);
}
}
}
}
function popular_metapages()
{
if ($this->options['popular'][1] === false) {
return;
}
if (function_exists('set_timezone')) { // plus
list($zone, $zonetime) = set_timezone(DEFAULT_LANG);
$localtime = UTIME + $zonetime;
$today = gmdate('Y/m/d', $localtime);
$yesterday = gmdate('Y/m/d',gmmktime(0,0,0, gmdate('m',$localtime), gmdate('d',$localtime)-1, gmdate('Y',$localtime)));
} else {
$localtime = ZONETIME + UTIME;
$today = get_date('Y/m/d'); // == get_date('Y/m/d', UTIME) == date('Y/m/d, ZONETIME + UTIME);
$yesterday = get_date('Y/m/d', mktime(0,0,0, date('m',$localtime), date('d',$localtime)-1, date('Y',$localtime)));
}
foreach ($this->metapages as $i => $metapage) {
$page = $metapage['page'];
$lines = file(COUNTER_DIR . encode($page) . '.count');
$lines = array_map('rtrim', $lines);
list($total_count, $date, $today_count, $yesterday_count, $ip) = $lines;
$popular = 0;
switch ($this->options['popular'][1]) {
case 'total':
$popular = $total_count;
break;
case 'today':
if ($date == $today) {
$popular = $today_count;
}
break;
case 'yesterday':
if ($date == $today) {
$popular = $yesterday_count;
} elseif ($date == $yesterday) {
$popular = $today_count;
}
break;
case 'recent':
if ($date == $today) {
$popular = $today_count + $yesterday_count;
} elseif ($date == $yesterday) {
$popular = $today_count;
}
break;
}
if ($popular > 0) {
$this->metapages[$i]['popular'] = $popular;
} else {
unset($this->metapages[$i]); // like popular plugin
}
}
}
function timestamp_metapages()
{
if (! $this->options['date'][1] && ! $this->options['new'][1] &&
$this->options['sort'][1] !== 'date') {
return;
}
foreach ($this->metapages as $i => $metapage) {
$page = $metapage['page'];
$timestamp = $this->get_filetime($page);
$this->metapages[$i]['timestamp'] = $timestamp;
}
}
function date_metapages()
{
if (! $this->options['date'][1] && ! $this->options['new'][1]) {
return;
}
foreach ($this->metapages as $i => $metapage) {
$timestamp = $metapage['timestamp'];
$date = format_date($timestamp);
$this->metapages[$i]['date'] = $date;
}
}
function info_date_metapages()
{
if (! $this->options['date'][1]) {
return;
}
foreach ($this->metapages as $i => $metapage) {
$this->metapages[$i]['info_date'] =
'';
}
}
function info_new_metapages()
{
if (! $this->options['new'][1]) {
return;
}
foreach ($this->metapages as $i => $metapage) {
$date = $this->metapages[$i]['date'];
// burdonsome, but to use configuration of new plugin
$new = do_plugin_inline($this->conf['plugin_new'], 'nodate', $date);
$this->metapages[$i]['info_new'] = $new;
}
}
function info_metapages()
{
if (empty($this->options['info'][1])) {
return;
}
$this->date_metapages();
$this->info_date_metapages();
$this->info_new_metapages();
//foreach ($this->options['info'][2] as $key) {
// call_user_func(array($this, $key . '_metapages'));
//}
foreach ($this->metapages as $i => $metapage) {
$info = '';
foreach ($this->options['info'][1] as $key) {
$info .= ' ' . $metapage['info_' . $key];
}
$this->metapages[$i]['info'] = $info;
}
}
function tree_filter_metapages()
{
if ($this->options['tree'][1] === false) {
return;
}
$allpages = get_existpages();
$this->sort_pages($allpages);
$current = current($allpages);
while ($next = next($allpages)) {
if (strpos($next, $current . '/') === FALSE) {
$leafs[$current] = TRUE;
} else {
$leafs[$current] = FALSE;
}
$current = $next;
}
$leafs[$current] = TRUE;
switch ($this->options['tree'][1]) {
case 'dir':
foreach ($this->metapages as $i => $metapage) {
$page = $metapage['page'];
if ($leafs[$page]) {
unset($this->metapages[$i]);
}
}
break;
case 'leaf':
foreach ($this->metapages as $i => $metapage) {
$page = $metapage['page'];
if (! $leafs[$page]) {
unset($this->metapages[$i]);
}
}
break;
}
}
function hierarchy_metapages()
{
if ($this->options['hierarchy'][1] === false) {
return;
}
$pdepth = substr_count($this->options['prefix'][1], '/') - 1;
$pdir = $this->my_dirname($this->options['prefix'][1]);
$pdirlen = ($pdir == '') ? 0 : strlen($pdir) + 1; // Add '/'
$num = count($this->metapages);
foreach ($this->metapages as $i => $metapage) {
$page = $metapage['page'];
$depth = $metapage['depth']; // depth_metapages()
if ($this->options['hierarchy'][1] === true) {
$this->metapages[$i]['listdepth'] = $depth;
}
while ($depth > 1) {
$page = $this->my_dirname($page);
if ($page == '') break;
$depth = substr_count($page, '/') - $pdepth;
// if parent dir does not exist, complement
if (($j = $this->array_search_by($page, $this->metapages, 'page')) === false) {
if ($this->options['hierarchy'][1] === true) {
$relative = substr($page, $pdirlen);
$listdepth = $depth;
$this->metapages[] = array('reading'=>$page,'page'=>$page, 'relative'=>$relative, 'exist'=>false, 'depth'=>$depth, 'listdepth'=>$listdepth, 'timestamp'=>1, 'date'=>'', 'leaf'=>false);
// PHP: new item is ignored on this loop
}
}
}
}
if (count($this->metapages) != $num) {
$this->sort_metapages();
}
}
function sort_metapages($sort = 'natcasesort', $sortflag = SORT_REGULAR)
{
switch ($this->options['sort'][1]) {
case 'name':
$this->sort_by($this->metapages, 'page', 'sort', SORT_STRING);
break;
case 'date':
$this->sort_by($this->metapages, 'timestamp', 'rsort', SORT_NUMERIC);
break;
case 'reading':
$this->sort_by($this->metapages, 'reading', 'sort', SORT_STRING);
break;
case 'popular':
$this->sort_by($this->metapages, 'popular', 'rsort', SORT_NUMERIC);
break;
default:
$this->sort_by($this->metapages, $this->options['sort'][1], $sort, $sortflag);
break;
}
if ($this->options['reverse'][1]) {
$this->metapages = array_reverse($this->metapages);
}
}
function depth_metapages()
{
if ($this->options['depth'][1] === '' && $this->options['hierarchy'][1] === false &&
$this->options['tree'][1] === false ) {
return;
}
$pdepth = substr_count($this->options['prefix'][1], '/') - 1;
foreach ($this->metapages as $i => $metapage) {
$page = $metapage['page'];
$depth = substr_count($page, '/');
$this->metapages[$i]['depth'] = $depth - $pdepth;
}
return $this->max_by($this->metapages, 'depth');
}
function relative_metapages()
{
$pdir = $this->my_dirname($this->options['prefix'][1]);
if ($pdir == '') {
foreach ($this->metapages as $i => $metapage) {
$this->metapages[$i]['relative'] = $metapage['page'];
}
} else {
$pdirlen = strlen($pdir) + 1; // Add strlen('/')
foreach ($this->metapages as $i => $metapage) {
$this->metapages[$i]['relative'] = substr($metapage['page'], $pdirlen);
}
}
}
function init_metapages()
{
if ($this->options['sort'][1] === 'reading') {
// Beta Function
if ($this->options['tag'][1] == '') {
$readings = $this->get_readings();
} else {
$plugin_tag = new PluginTag();
$pages = $plugin_tag->get_taggedpages($this->options['tag'][1]);
if ($pages === FALSE) {
$this->error = 'The tag token, ' . htmlsc($this->options['tag'][1]) . ', is invalid. ';
$this->error .= 'Perhaps, the tag does not exist. ';
}
$readings = $this->get_readings(); // why can not set pages...
foreach ($pages as $page)
$tagged_readings[$page] = '';
// array_intersect_key >= PHP 5.1.0 RC1
// $readings = array_intersect_key($readings, $tagged_readings);
foreach ($readings as $page => $reading) {
if (! isset($tagged_readings[$page])) unset($readings[$page]);
}
}
$metapages = array();
foreach ($readings as $page => $reading) {
unset($readings[$page]);
$metapages[] = array('reading'=>$reading,'page'=>$page, 'exist'=>true, 'depth'=>1, 'listdepth'=>1, 'timestamp'=>1, 'date'=>'');
}
$this->metapages = $metapages;
} else {
if ($this->options['tag'][1] == '') {
$pages = get_existpages();
} else {
$plugin_tag = new PluginTag();
$pages = $plugin_tag->get_taggedpages($this->options['tag'][1]);
if ($pages === FALSE) {
$this->error = 'The tag token, ' . htmlsc($this->options['tag'][1]) . ', is invalid. ';
$this->error .= 'Perhaps, the tag does not exist. ';
}
}
$metapages = array();
foreach ($pages as $i => $page) {
unset($pages[$i]);
$metapages[] = array('page'=>$page, 'exist'=>true, 'depth'=>1, 'listdepth'=>1, 'timestamp'=>1, 'date'=>'');
}
$this->metapages = $metapages;
}
}
function depth_filter_metapages()
{
if ($this->options['depth'][1] === '') {
return;
}
$metapages = array();
foreach ($this->metapages as $i => $metapage) {
unset($this->metapages[$i]);
if (in_array($metapage['depth'], $this->options['depth'][1])) {
$metapages[] = $metapage;
}
}
$this->metapages = $metapages;
}
// sort before this ($this->sort_by)
function num_filter_metapages()
{
if ($this->options['num'][1] === '') {
return;
}
$metapages = array();
// $num < count($this->metapages) is assured.
foreach ($this->options['num'][1] as $num) {
$metapages[] = $this->metapages[$num - 1];
}
$this->metapages = $metapages;
}
function newpage_filter_metapages()
{
if ($this->options['newpage'][1] === false) {
return;
}
if ($this->options['newpage'][1] == 'on') {
$new = true;
} elseif ($this->options['newpage'][1] == 'except') {
$new = false;
}
$metapages = array();
foreach ($this->metapages as $i => $metapage) {
unset($this->metapages[$i]);
if ($new == $this->is_newpage($metapage['page'])) {
$metapages[] = $metapage;
}
}
$this->metapages = $metapages;
}
function prefix_filter_metapages()
{
if ($this->options['prefix'][1] === "") {
return;
}
$metapages = array();
foreach ($this->metapages as $i => $metapage) {
unset($this->metapages[$i]);
if (strpos($metapage['page'], $this->options['prefix'][1]) !== 0) {
continue;
}
$metapages[] = $metapage;
}
$this->metapages = $metapages;
}
function nonlist_filter_metapages()
{
if ($this->options['non_list'][1] === false) {
return;
}
global $non_list;
$metapages = array();
foreach ($this->metapages as $i => $metapage) {
unset($this->metapages[$i]);
if (preg_match("/$non_list/", $metapage['page'])) {
continue;
}
$metapages[] = $metapage;
}
$this->metapages = $metapages;
}
function except_filter_metapages()
{
if ($this->options['except'][1] === "") {
return;
}
$metapages = array();
foreach ($this->metapages as $i => $metapage) {
unset($this->metapages[$i]);
if (call_user_func($this->ereg, $this->options['except'][1], $metapage['relative'])) {
continue;
}
$metapages[] = $metapage;
}
$this->metapages = $metapages;
}
function filter_filter_metapages()
{
if ($this->options['filter'][1] === "") {
return;
}
$metapages = array();
foreach ($this->metapages as $i => $metapage) {
unset($this->metapages[$i]);
if (! call_user_func($this->ereg, $this->options['filter'][1], $metapage['relative'])) {
continue;
}
$metapages[] = $metapage;
}
$this->metapages = $metapages;
}
// PukiWiki API Extension
function sort_pages(&$pages)
{
$pages = str_replace('/', "\0", $pages);
sort($pages, SORT_STRING);
$pages = str_replace("\0", '/', $pages);
}
// No PREG_SPLIT_NO_EMPTY version
// copy from lib/make_link.php#get_fullname
function get_fullname($name, $refer)
{
global $defaultpage;
// 'Here'
if ($name == '' || $name == './') return $refer;
// Absolute path
if ($name[0] == '/') {
$name = substr($name, 1);
return ($name == '') ? $defaultpage : $name;
}
// Relative path from 'Here'
if (substr($name, 0, 2) == './') {
$arrn = preg_split('#/#', $name, -1); //, PREG_SPLIT_NO_EMPTY);
$arrn[0] = $refer;
return join('/', $arrn);
}
// Relative path from dirname()
if (substr($name, 0, 3) == '../') {
$arrn = preg_split('#/#', $name, -1); //, PREG_SPLIT_NO_EMPTY);
$arrp = preg_split('#/#', $refer, -1, PREG_SPLIT_NO_EMPTY);
while (! empty($arrn) && $arrn[0] == '..') {
array_shift($arrn);
array_pop($arrp);
}
$name = ! empty($arrp) ? join('/', array_merge($arrp, $arrn)) :
(! empty($arrn) ? $defaultpage . '/' . join('/', $arrn) : $defaultpage);
}
return $name;
}
function is_newpage($page)
{
// pukiwiki trick
return ! _backup_file_exists($page);
}
function make_pagelink($page, $alias = '', $anchor = '', $refer = '', $isautolink = FALSE)
{
// no passage
global $show_passage;
$tmp = $show_passage; $show_passage = 0;
$link = make_pagelink($page, $alias, $anchor, $refer, $isautolink);
$show_passage = $tmp;
return $link;
}
function get_readings()
{
return get_readings();
}
function get_filetime($page)
{
return get_filetime($page);
}
// PHP Extension
// dirname(Page/) => '.' , dirname(Page/a) => Page, dirname(Page) => '.'
// But, want Page/ => Page, Page/a => Page, Page => ''
function my_dirname($page)
{
if (($pos = strrpos($page, '/')) !== false) {
return substr($page, 0, $pos);
} else {
return '';
}
}
// basename(Page/) => Page , basename(Page/a) => a, basename(Page) => Page
// But, want Page/ => '', Page/a => a, Page => Page
function my_basename($page)
{
if (($pos = strrpos($page, '/')) !== false) {
return substr($page, $pos + 1);
} else {
return $page;
}
}
function array_search_by($value, $array, $fieldname = null)
{
foreach ($array as $i => $val) {
if ($value == $val[$fieldname]) {
return $i;
}
}
return false;
}
function in_array_by($value, $array, $fieldname = null)
{
//foreach ($array as $i => $befree) {
// $field_array[$i] = $array[$i][$fieldname];
//}
//return in_array($value, $field_array);
foreach ($array as $i => $val) {
if ($value == $val[$fieldname]) {
return true;
}
}
return false;
}
# sort arrays by a specific field without maintaining key association
function sort_by(&$array, $fieldname, $sort, $sortflag)
{
$field_array = $inarray = array();
# store the keyvalues in a seperate array
foreach ($array as $i => $befree) {
$field_array[$i] = $array[$i][$fieldname];
}
$field_array = str_replace('/', "\0", $field_array); // must not be here. Refactor me.
switch ($sort) {
case 'sort':
# sort an array and maintain index association...
asort($field_array, $sortflag);
break;
case 'rsort':
# sort an array in reverse order and maintain index association
arsort($field_array, $sortflag);
break;
case 'natsort':
natsort($field_array);
case 'natcasesort':
# sort an array using a case insensitive "natural order" algorithm
natcasesort($field_array);
break;
}
# rebuild the array
$outarray = array();
foreach ( $field_array as $i=> $befree) {
$outarray[] = $array[$i];
unset($array[$i]);
}
$array = $outarray;
}
function max_by($array, $fieldname = null)
{
$field_array = $inarray = array();
# store the keyvalues in a seperate array
foreach ($array as $i => $befree) {
$field_array[$i] = $array[$i][$fieldname];
}
return empty($field_array) ? 0 : max($field_array);
}
}
///////////////////////////////////////
class PluginLsxOptionParser
{
var $error = "";
function parse_options($args, $options)
{
if (! $this->is_associative_array($args)) {
$args = $this->associative_args($args, $options);
if ($this->error != "") { return; }
}
foreach ($args as $key => $val) {
if ( !isset($options[$key]) ) { continue; } // for action ($vars)
$type = $options[$key][0];
$options[$key][4] = $val;
switch ($type) {
case 'bool':
if($val == "" || $val == "on" || $val == "true") {
$options[$key][1] = true;
} elseif ($val == "off" || $val == "false" ) {
$options[$key][1] = false;
} else {
$this->error = htmlsc("$key=$val") . " is invalid. ";
$this->error .= "The option, $key, accepts only a boolean value.";
$this->error .= "#$this->plugin($key) or #$this->plugin($key=on) or #$this->plugin($key=true) for true. ";
$this->error .= "#$this->plugin($key=off) or #$this->plugin($key=false) for false. ";
return;
}
break;
case 'string':
$options[$key][1] = $val;
break;
case 'sanitize':
$options[$key][1] = htmlsc($val);
break;
case 'number':
// Do not parse yet, parse after getting min and max. Here, just format checking
if ($val === '') {
$options[$key][1] = '';
break;
}
if ($val[0] === '(' && $val[strlen($val) - 1] == ')') {
$val = substr($val, 1, strlen($val) - 2);
}
foreach (explode(",", $val) as $range) {
if (preg_match('/^-?\d+$/', $range)) {
} elseif (preg_match('/^-?\d*\:-?\d*$/', $range)) {
} elseif (preg_match('/^-?\d+\+-?\d+$/', $range)) {
} else {
$this->error = htmlsc("$key=$val") . " is invalid. ";
$this->error .= "The option, " . $key . ", accepts number values such as 1, 1:3, 1+3, 1,2,4. ";
$this->error .= "Specify options as \"$key=1,2,4\" or $key=(1,2,3) when you want to use \",\". ";
$this->error .= "In more details, a style like (1:3,5:7,9:) is also possible. 9: means from 9 to the last. ";
$this->error .= "Furtermore, - means backward. -1:-3 means 1,2,3 from the tail. ";
return;
}
}
$options[$key][1] = $val;
break;
case 'enum':
if($val == "") {
$options[$key][1] = $options[$key][2][0];
} elseif (in_array($val, $options[$key][2])) {
$options[$key][1] = $val;
} else {
$this->error = htmlsc("$key=$val") . " is invalid. ";
$this->error .= "The option, " . $key . ", accepts values from one of (" . join(",", $options[$key][2]) . "). ";
$this->error .= "By the way, #$this->plugin($key) equals to #$this->plugin($key=" . $options[$key][2][0] . "). ";
return;
}
break;
case 'array':
if ($val == '') {
$options[$key][1] = array();
break;
}
if ($val[0] === '(' && $val[strlen($val) - 1] == ')') {
$val = substr($val, 1, strlen($val) - 2);
}
$val = explode(',', $val);
//$val = $this->support_paren($val);
$options[$key][1] = $val;
break;
case 'enumarray':
if ($val == '') {
$options[$key][1] = $options[$key][2];
break;
}
if ($val[0] === '(' && $val[strlen($val) - 1] == ')') {
$val = substr($val, 1, strlen($val) - 2);
}
$val = explode(',', $val);
//$val = $this->support_paren($val);
$options[$key][1] = $val;
foreach ($options[$key][1] as $each) {
if (! in_array($each, $options[$key][2])) {
$this->error = "$key=" . htmlsc(join(",", $options[$key][1])) . " is invalid. ";
$this->error .= "The option, " . $key . ", accepts sets of values from (" . join(",", $options[$key][2]) . "). ";
$this->error .= "By the way, #$this->plugin($key) equals to #$this->plugin($key=(" . join(',',$options[$key][2]) . ")). ";
return;
}
}
break;
default:
}
}
return $options;
}
/**
* Handle associative type option arguments as
* ["prefix=Hoge/", "contents=(hoge", "hoge", "hoge)"] => ["prefix"=>"hoge/", "contents"=>"(hoge,hoge,hoge)"]
* This has special supports for parentheses type arguments (number, array, enumarray)
* Check option in along with.
* @access public
* @param Array $args Original option arguments
* @return Array $result Converted associative option arguments
*/
function associative_args($args, $options)
{
$result = array();
while (($arg = current($args)) !== false) {
list($key, $val) = array_pad(explode("=", $arg, 2), 2, '');
if (! isset($options[$key])) {
$this->error = 'No such a option, ' . htmlsc($key);
return;
}
// paren support
if ($val[0] === '(' && ($options[$key][0] == 'number' ||
$options[$key][0] == 'array' || $options[$key][0] == 'enumarray')) {
while(true) {
if ($val[strlen($val)-1] === ')' && substr_count($val, '(') == substr_count($val, ')')) {
break;
}
$arg = next($args);
if ($arg === false) {
$this->error = "The # of open and close parentheses of one of your arguments did not match. ";
return;
}
$val .= ',' . $arg;
}
}
$result[$key] = $val;
next($args);
}
return $result;
}
function parse_numoption($optionval, $min, $max)
{
if ($optionval === '') {
return '';
}
$result = array();
foreach (explode(",", $optionval) as $range) {
if (preg_match('/^-?\d+$/', $range)) {
$left = $right = $range;
} elseif (preg_match('/^-?\d*\:-?\d*$/', $range)) {
list($left, $right) = explode(":", $range, 2);
if ($left == "" && $right == "") {
$left = $min;
$right = $max;
} elseif($left == "") {
$left = $min;
} elseif ($right == "") {
$right = $max;
}
} elseif (preg_match('/^-?\d+\+-?\d+$/', $range)) {
list($left, $right) = explode("+", $range, 2);
$right += $left;
}
if ($left < 0) {
$left += $max + 1;
}
if ($right < 0) {
$right += $max + 1;
}
$result = array_merge($result, range($left, $right));
// range allows like range(5, 3) also
}
// filter
foreach (array_keys($result) as $i) {
if ($result[$i] < $min || $result[$i] > $max) {
unset($result[$i]);
}
}
sort($result);
$result = array_unique($result);
return $result;
}
function option_debug_print($options) {
foreach ($options as $key => $val) {
$type = $val[0];
$val = $val[1];
if(is_array($val)) {
$val=join(',', $val);
}
$body .= "$key=>($type, $val),";
}
return $body;
}
// php extension
function is_associative_array($array)
{
if (!is_array($array) || empty($array))
return false;
$keys = array_keys($array);
return array_keys($keys) !== $keys;
// or
//return is_array($array) && !is_numeric(implode(array_keys($array)));
}
}
//////////////////////////////////
function plugin_lsx_common_init()
{
global $plugin_lsx;
if (class_exists('PluginLsxUnitTest')) {
$plugin_lsx = new PluginLsxUnitTest();
} elseif (class_exists('PluginLsxUser')) {
$plugin_lsx = new PluginLsxUser();
} else {
$plugin_lsx = new PluginLsx();
}
}
function plugin_lsx_convert()
{
global $plugin_lsx; plugin_lsx_common_init();
$args = func_get_args();
return call_user_func_array(array(&$plugin_lsx, 'convert'), $args);
}
function plugin_lsx_action()
{
global $plugin_lsx; plugin_lsx_common_init();
return call_user_func(array(&$plugin_lsx, 'action'));
}
?>