_('Table of Contents'),
);
// Modify here for default option values
static $default_options = array(
'page' => array('string', ''),
'fromhere' => array('bool', true),
'hierarchy' => array('bool', true),
'compact' => array('bool', true),
'num' => array('number', ''),
'depth' => array('number', ''),
'except' => array('string', ''),
'filter' => array('string', ''),
'include' => array('bool', true),
'cache' => array('enum', 'on', array('on', 'off', 'reset')),
'link' => array('enum', 'on', array('on', 'off', 'anchor', 'page')),
);
// Definitions
static $conf = array(
'def_headline' => '/^(\*{1,3})/',
'max_depth' => 3,
'def_include' => '/^#include.*\((.+)\)/',
'def_title' => '/^TITLE:(.+)/',
'use_session' => TRUE, // action
'through_if_admin' => TRUE, // action
);
$this->msg = &$msg;
$this->default_options = &$default_options;
$this->conf = &$conf;
// init
$this->options = $this->default_options;
}
function PluginContentsx() {
$this->__construct();
}
// static
var $msg;
var $default_options;
var $conf;
// var
var $args;
var $options;
var $error = "";
var $plugin = "contentsx";
var $metalines;
var $visited = array(); // page => title(alias)
function action() // clean cache
{
global $vars;
if (is_admin($vars['pass'], $this->conf['use_session'], $this->conf['through_if_admin']) &&
$vars['pcmd'] == 'clean') {
$body = $this->clean_cache();
} else {
$body = $this->display_password_form();
}
return array('msg'=>'Clean Contentsx Caches', 'body'=>$body);
}
function clean_cache()
{
set_time_limit(0);
global $vars;
$page = isset($vars['page']) ? $vars['page'] : '';
if ($page != '') {
$file = $this->get_cache_filename($page);
@unlink($file);
if (exec_page($page, '/^#contentsx/')) {
$body = 'Recreated a cache of ';
} else {
$body = 'No #contentsx in ';
}
$body .= make_pagelink($page);
} else {
// remove all files
$files = $this->get_cache_filenames();
foreach ($files as $file) {
unlink($file);
}
// execute all pages
$exec_pages = exec_existpages('/^#contentsx/');
if (empty($exec_pages)) {
$body = '';
} else {
$links = array_map('make_pagelink', $exec_pages);
$body = '
Following pages were executed to assure:
'
. '' . implode("
\n", $links) . '
';
}
}
return $body;
}
/**
* Display a password form
*
* @param $msg error message or some messages
* @return string form html
*/
function display_password_form($message = "")
{
$cmd = $this->plugin;
$pcmd = 'clean';
$form = array();
$form[] = '';
$form = implode("\n", $form);
if ($message != '') {
$message = '' . htmlsc($message) . '
';
}
return $message . $form;
}
function convert()
{
$args = func_get_args();
if ($GLOBALS['vars']['cmd'] != 'read') {
return '';
}
$body = $this->body($args);
if ($body != '') {
$body = '' . "\n"
. '' . "\n"
. '' . $this->msg['toctitle'] . "\n"
. " |
\n"
. '' . "\n"
. $body
. " |
\n"
. "
\n";
}
if ($this->error != "" ) {
return "#$this->plugin(): $this->error
";
}
return $body;
}
function body($args)
{
global $vars;
$parser = new PluginContentsxOptionParser();
$this->options = $parser->parse_options($args, $this->options);
if ($parser->error != "") { $this->error = $parser->error; return; }
$this->options['page'][1] = $this->check_page($this->options['page'][1]);
if ($this->error !== "") { return; }
$this->init_metalines($this->options['page'][1]);
if ($this->error !== "") { return; }
$this->narrow_metalines();
if ($this->error !== "") { return; }
$body = $this->frontend();
if ($this->error !== "") { return; }
return $body;
}
function get_title($page)
{
$page = $this->check_page($page);
$this->init_metalines($page);
$title = $this->visited[$page];
// FYI: $title = strip_htmltag(make_link($title));
// $link = make_pagelink($page, $title);
return $title;
}
function get_visited($page)
{
$page = $this->check_page($page);
$this->init_metalines($page);
return array_keys($this->visited);
}
function get_metalines($page)
{
$page = $this->check_page($page);
$this->init_metalines($page);
return $this->metalines;
}
function narrow_metalines()
{
$this->fromhere_metalines();
$this->include_metalines();
$this->filter_metalines();
$this->except_metalines();
$parser = new PluginContentsxOptionParser();
$this->options['depth'][1] = $parser->parse_numoption($this->options['depth'][1], 0, $this->conf['max_depth']);
if ($parser->error != "") { $this->error = $parser->error; return; }
$this->depth_filter_metalines();
$num = sizeof($this->metalines);
$this->options['num'][1] = $parser->parse_numoption($this->options['num'][1], 1, $num);
if ($parser->error != "") { $this->error = $parser->error; return; }
$this->num_filter_metalines();
}
function frontend()
{
$this->hierarchy_metalines();
$this->compact_metalines();
$this->makelink_metalines();
return $this->list_metalines();
}
function list_metalines()
{
if (sizeof($this->metalines) == 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->metalines as $metaline) {
$display = $metaline['display'];
$depth = $metaline['listdepth'];
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;
}
$html .= $display;
$html .= "\n";
$pdepth = $depth;
}
$html .= str_repeat('
', $ul);
return $html;
}
function makelink_metalines()
{
$metalines = array();
foreach ($this->metalines as $metaline) {
$anchor = $metaline['anchor'];
$headline = $metaline['headline'];
$headline = strip_htmltag(make_link($headline)); // convert inline plugin
$metaline['display'] = $this->make_pagelink($this->options['page'][1], $headline, $anchor);
$metalines[] = $metaline;
}
$this->metalines = $metalines;
}
function make_pagelink($page, $alias, $anchor)
{
global $vars;
if ($this->options['link'][1] == 'off' || $anchor =='') {
return htmlsc($alias);
}
if (($this->options['link'][1] == 'on' && $page == $vars['page'])
|| $this->options['link'][1] == 'anchor') {
$page = '';
}
global $show_passage;
$tmp = $show_passage; $show_passage = 0;
$link = make_pagelink($page, $alias, $anchor);
$show_passage = $tmp;
return $link;
}
function compact_metalines()
{
// Hmmmmm, complex
if (!$this->options['compact'][1]) {
return;
}
if (! $this->options['hierarchy'][1]) {
return;
}
// 1) fill in list spaces for each page
// 1 3 1 1 3 3 1 => 1 2 1 1 2 2 1 (2 was none, move 3 to 2)
// 2 2 2 => 1 1 1
$listdepthstack = array();
foreach ($this->metalines as $metaline) {
$page = $metaline['page'];
$listdepth = $metaline['listdepth'];
if (empty($listdepthstack[$page])) {
$listdepthstack[$page][] = $listdepth;
}
else if(! in_array($listdepth, $listdepthstack[$page])) {
$listdepthstack[$page][] = $listdepth;
}
}
foreach (array_keys($listdepthstack) as $page) {
sort($listdepthstack[$page]);
}
// 1 2 4 == (0=>1, 1=>2, 2=>4) -> (1=>1, 1=>2, 3=>4) -exchange keys and values-> (1=>1, 2=>1, 4=>3)
$listdepthfill = array();
foreach ($listdepthstack as $page => $stack) {
foreach($stack as $i => $listdepth) {
$listdepthfill[$page][$listdepth] = $i + 1;
}
}
$metalines = array();
foreach ($this->metalines as $metaline) {
$page = $metaline['page'];
$listdepth = $metaline['listdepth'];
$metaline['listdepth'] = $listdepthfill[$page][$listdepth];
$metalines[] = $metaline;
}
$this->metalines = $metalines;
// 2) fill in previous list space, seperately for each page
// 1 3 2 => 1 2 2
$pdepth = array(); $plistdepth = array();
foreach (array_keys($listdepthstack) as $page) {
$pdepth[$page] = -1;
$plistdepth[$page] = 0;
}
$metalines = array();
$this->hoge = array();
foreach ($this->metalines as $metaline) {
$page = $metaline['page'];
if ($metaline['depth'] > $pdepth[$page]) {
$metaline['listdepth'] = $plistdepth[$page] + 1;
} elseif($metaline['depth'] == $pdepth[$page]) {
$metaline['listdepth'] = $plistdepth[$page];
} else {
$metaline['listdepth'] = ($plistdepth[$page] < $metaline['listdepth']) ? $plistdepth[$page]: $metaline['listdepth'];
}
$pdepth[$page] = $metaline['depth'];
$plistdepth[$page] = $metaline['listdepth'];
$metalines[] = $metaline;
}
$this->metalines = $metalines;
}
function hierarchy_metalines()
{
$include = 0;
if ($this->options['include'][1] && sizeof($this->visited) >= 2) { // include (0,1,2,3...) -> (1,2,3,4...)
$include = 1;
}
$metalines = array();
foreach($this->metalines as $metaline) {
if ($this->options['hierarchy'][1]) {
$metaline['listdepth'] = $metaline['depth'] + $include;
} else {
$metaline['listdepth'] = 1;
}
$metalines[] = $metaline;
}
$this->metalines = $metalines;
}
function num_filter_metalines()
{
if ($this->options['num'][1] === '') {
return;
}
$metalines = array();
foreach ($this->options['num'][1] as $num) {
$metalines[] = $this->metalines[$num - 1];
}
$this->metalines = $metalines;
}
function depth_filter_metalines()
{
if ($this->options['depth'][1] === '') {
return;
}
$metalines = array();
foreach ($this->metalines as $metaline) {
$depth = $metaline['depth'];
if (in_array($depth, $this->options['depth'][1])) {
$metalines[] = $metaline;
}
}
$this->metalines = $metalines;
}
function filter_metalines()
{
if ($this->options['filter'][1] === "") {
return;
}
$metalines = array();
foreach ($this->metalines as $metaline) {
$headline = $metaline['headline'];
if (ereg($this->options['filter'][1], $headline)) {
$metalines[] = $metaline;
}
}
$this->metalines = $metalines;
}
function except_metalines()
{
if ($this->options['except'][1] === "") {
return;
}
$metalines = array();
foreach ($this->metalines as $metaline) {
$headline = $metaline['headline'];
if (!ereg($this->options['except'][1], $headline)) {
$metalines[] = $metaline;
}
}
$this->metalines = $metalines;
}
function include_metalines()
{
if ($this->options['include'][1]) {
return;
}
$metalines = array();
foreach ($this->metalines as $metaline) {
if ($metaline['page'] == $this->options['page'][1]) {
$metalines[] = $metaline;
}
}
$this->metalines = $metalines;
}
function fromhere_metalines()
{
if (! $this->options['fromhere'][1]) {
return;
}
$metalines = array();
foreach ($this->metalines as $metaline) {
if ($metaline['fromhere']) {
$metalines[] = $metaline;
}
}
$this->metalines = $metalines;
}
function init_metalines($page)
{
$this->metalines = array();
$this->visited = array();
if ($this->read_cache($page) !== false) { return; }
$this->metalines = $this->r_metalines($page);
$this->write_cache($page);
}
function get_cache_filename($page)
{
return CACHE_DIR . encode($page) . ".$this->plugin";
}
function get_cache_filenames()
{
return get_existfiles(CACHE_DIR, ".$this->plugin");
}
/**
* Read cache
*
* @param $apage pagename
* @return mixed contents or FALSE if cache should be renewed
*/
function read_cache($apage)
{
if ($this->options['cache'][1] == 'off' || $this->options['cache'][1] == 'reset') {
return false;
}
if (! is_page($apage)) {
return false;
}
$cache = $this->get_cache_filename($apage);
if (! $this->file_exists($cache)) {
return false;
}
if (! $this->is_readable($cache)) {
$this->error = "Cache file, $cache is not readable. ";
return;
}
$lines = file($cache);
$pages = csv_explode(',', rtrim(array_shift($lines)));
foreach ($pages as $page) {
list($page, $title) = csv_explode('=', $page);
$visited[$page] = $title;
}
// renew cache if preview mode
if (isset($vars['preview']) || isset($vars['realview'])) {
return false;
}
// renew cache if page is newer than cache
foreach ($visited as $page => $title) {
if (is_page_newer($page, $cache)) {
return false;
}
}
$this->visited = $visited;
$metalines = array();
foreach ($lines as $line) {
$metas = csv_explode(',', rtrim($line));
$metaline = array();
foreach ($metas as $meta) {
list($key, $val) = explode('=', $meta, 2);
$metaline[$key] = $val;
}
$metalines[] = $metaline;
}
$this->metalines = $metalines;
}
function write_cache($apage)
{
if ($this->options['cache'][1] == 'off') {
return;
}
if (! is_page($apage)) {
return;
}
$cache = $this->get_cache_filename($apage);
if ($this->file_exists($cache) && ! $this->is_writable($cache)) {
$this->error = "Cache file, $cache is not writable. ";
return;
}
$pages = array();
foreach ($this->visited as $page => $title) {
$pages[] = csv_implode('=', array($page, $title));
}
$contents = '';
$contents .= csv_implode(',', $pages) . "\n";
foreach ($this->metalines as $metaline) {
$metas = array();
foreach ($metaline as $key => $val) {
$metas[] = "$key=$val";
}
$contents .= csv_implode(',', $metas) . "\n";
}
// file_put_contents($cache, $contents); // PHP5
if (! $fp = fopen($cache, "w")) {
$this->error = "Can not open $cache. ";
return;
}
if (! fwrite($fp, $contents)) {
$this->error = "Can not write to $cache. ";
return;
}
fclose($fp);
}
function r_metalines($page, $detected = false)
{
if (array_key_exists($page, $this->visited)) {
return array();
}
if (! is_page($page)) {
return array();
}
$this->visited[$page] = '';
$lines = $this->get_source($page);
$multiline = 0;
$metalines = array();
foreach ($lines as $i => $line) {
// multiline plugin. refer lib/convert_html
if(defined('PKWKEXP_DISABLE_MULTILINE_PLUGIN_HACK') && PKWKEXP_DISABLE_MULTILINE_PLUGIN_HACK === 0) {
$matches = array();
if ($multiline < 2) {
if(preg_match('/^#([^\(\{]+)(?:\(([^\r]*)\))?(\{*)/', $line, $matches)) {
$multiline = strlen($matches[3]);
}
} else {
if (preg_match('/^\}{' . $multiline . '}$/', $line, $matches)) {
$multiline = 0;
}
continue;
}
}
// fromhere
if ($this->options['page'][1] == $page && !$detected) {
if (preg_match('/^#' . $this->plugin . '/', $line, $matches)) {
$detected = true;
continue;
}
}
if (preg_match($this->conf['def_headline'], $line, $matches)) {
$depth = strlen($matches[1]);
$anchor = '#' . $this->make_heading($line); // *** [id] is removed from $line
$headline = trim($line);
$metalines[] = array('page'=>$page, 'headline'=>$headline, 'anchor'=>$anchor, 'depth'=>$depth, 'linenum'=>$i, 'fromhere'=>$detected);
continue;
}
if (preg_match($this->conf['def_include'], $line, $matches)) {
$args = csv_explode(',', $matches[1]);
$inclpage = array_shift($args);
$options = array();
foreach ($args as $arg) {
list($key, $val) = array_pad(explode('=', $arg, 2), 2, true);
$options[$key] = $val;
}
$inclpage = get_fullname($inclpage, $page);
if (! $this->is_page($inclpage)) {
continue;
}
// $anchor = PluginIncludex::get_page_anchor($inclpage)
$anchor = 'z' . md5($inclpage);
$anchor = '#' . htmlsc($anchor);
if (exist_plugin('includex') & is_callable(array('PluginIncludex', 'get_titlestr'))) {
$titlestr = PluginIncludex::get_titlestr($inclpage, $options['titlestr']);
} else {
$titlestr = $inclpage;
}
$metalines[] = array('page'=>$inclpage, 'headline'=>$titlestr, 'anchor'=>$anchor, 'depth'=>0, 'linenum'=>$i, 'fromhere'=>$detected);
$metalines = array_merge($metalines, $this->r_metalines($inclpage, $detected));
continue;
}
if (preg_match($this->conf['def_title'], $line, $matches)) {
$title = $matches[1];
$this->visited[$page] = $title;
continue;
}
}
return $metalines;
}
// copy from lib/html.php
function make_heading(& $str, $strip = TRUE)
{
global $NotePattern;
// Cut fixed-heading anchors
$id = '';
$matches = array();
if (preg_match('/^(\*{0,3})(.*?)\[#([A-Za-z][\w-]+)\](.*?)$/m', $str, $matches)) {
$str = $matches[2] . $matches[4];
$id = & $matches[3];
} else {
$str = preg_replace('/^\*{0,3}/', '', $str);
}
// Cut footnotes and tags
if ($strip === TRUE) {
// $str = strip_htmltag(make_link(preg_replace($NotePattern, '', $str))); // sonots
$str = preg_replace($NotePattern, '', $str); // sonots
}
return $id;
}
function check_page($page)
{
global $vars, $defaultpage;
if ($page == "") {
$page = isset($vars['page']) ? $vars['page'] : $defaultpage;
} else {
$page = get_fullname($page, $vars['page']);
$this->options['fromhere'][1] = false;
}
if (! $this->is_page($page)) {
$this->error = "No such a page, " . $page;
return;
}
if (! $this->check_readable($page, FALSE, FALSE)) {
$this->error = "Page, " . $page . ", is not readable.";
}
return $page;
}
// PukiWiki API
function get_source($page)
{
return get_source($page);
}
function is_page($page)
{
return is_page($page);
}
function check_readable($page, $flag, $flag2)
{
return check_readable($page, $flag, $flag2);
}
// PHP API
function file_exists($file)
{
return file_exists($file);
}
function is_readable($file)
{
return is_readable($file);
}
function is_writable($file)
{
return is_writable($file);
}
}
///////////////////////////////////////
class PluginContentsxOptionParser
{
var $error = "";
function parse_options($args, $options)
{
if (! 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];
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)));
}
}
//////////////// PukiWiki API Extension
if (! function_exists('is_admin')) {
/**
* PukiWiki admin login with session
*
* @param string $pass
* @param boolean $use_session Use Session log
* @param boolean $use_basicauth Use BasicAuth log
* @return boolean
*/
function is_admin($pass = null, $use_session = false, $use_basicauth = false)
{
$is_admin = FALSE;
if ($use_basicauth) {
if (is_callable(array('auth', 'check_role'))) { // Plus!
$is_admin = ! auth::check_role('role_adm_contents');
}
}
if (! $is_admin && isset($pass)) {
$is_admin = function_exists('pkwk_login') ? pkwk_login($pass) :
md5($pass) === $GLOBALS['adminpass']; // 1.4.3
}
if ($use_session) {
session_start();
if ($is_admin) $_SESSION['is_admin'] = TRUE;
return isset($_SESSION['is_admin']) && $_SESSION['is_admin'];
} else {
return $is_admin;
}
}
}
if (! function_exists('is_page_newer')) {
/**
* Check if the page timestamp is newer than the file timestamp
*
* PukiWiki API Extension
*
* @param string $page pagename
* @param string $file filename
* @param bool $ignore_notimestamp Ignore notimestamp edit and see the real time editted
* @return boolean
*/
function is_page_newer($page, $file, $ignore_notimestamp = TRUE)
{
$filestamp = file_exists($file) ? filemtime($file) : 0;
if ($ignore_notimestamp) { // See the diff file. PukiWiki Trick.
$pagestamp = is_page($page) ? filemtime(DIFF_DIR . encode($page) . '.txt') : 0;
} else {
$pagestamp = is_page($page) ? filemtime(get_filename($page)) : 0;
}
return $pagestamp > $filestamp;
}
}
if (! function_exists('exec_page')) {
/**
* Execute (convert_html) this page
*
* PukiWiki API Extension
*
* @param string $page
* @param string $regexp execute only matched lines (preg_grep)
* @return boolean executed
*/
function exec_page($page, $regexp = null)
{
global $vars, $get, $post;
$lines = get_source($page);
if (isset($regexp)) {
$lines = preg_grep($regexp, $lines);
}
if (empty($lines)) return FALSE;
$tmp_page = $vars['page'];
$tmp_cmd = $vars['cmd'];
$vars['cmd'] = $get['cmd'] = $post['cmd'] = 'read';
$vars['page'] = $get['page'] = $post['page'] = $page;
convert_html($lines);
$vars['page'] = $get['page'] = $post['page'] = $tmp_page;
$vars['cmd'] = $get['cmd'] = $post['cmd'] = $tmp_cmd;
return TRUE;
}
}
if (! function_exists('exec_existpages')) {
/**
* Execute (convert_html) all pages
*
* PukiWiki API Extension
*
* @param string $regexp execute only matched lines (preg_grep)
* @return array executed pages
*/
function exec_existpages($regexp = null)
{
global $vars, $get, $post;
$pages = get_existpages();
$exec_pages = array();
$tmp_page = $vars['page'];
$tmp_cmd = $vars['cmd'];
$vars['cmd'] = $get['cmd'] = $post['cmd'] = 'read';
foreach ($pages as $page) {
$vars['page'] = $get['page'] = $post['page'] = $page;
$lines = get_source($page);
if (isset($regexp)) {
$lines = preg_grep($regexp, $lines);
}
if (empty($lines)) continue;
convert_html($lines);
$exec_pages[] = $page;
}
$vars['page'] = $get['page'] = $post['page'] = $tmp_page;
$vars['cmd'] = $get['cmd'] = $post['cmd'] = $tmp_cmd;
return $exec_pages;
}
}
////////////// PHP API Extension
if (! function_exists('get_existfiles')) {
/**
* Get list of files in a directory
*
* PHP Extension
*
* @access public
* @param string $dir Directory Name
* @param string $ext File Extension
* @param bool $recursive Traverse Recursively
* @return array array of filenames
* @uses is_dir()
* @uses opendir()
* @uses readdir()
*/
function &get_existfiles($dir, $ext = '', $recursive = FALSE)
{
if (($dp = @opendir($dir)) == FALSE)
return FALSE;
$pattern = '/' . preg_quote($ext, '/') . '$/';
$dir = ($dir[strlen($dir)-1] == '/') ? $dir : $dir . '/';
$dir = ($dir == '.' . '/') ? '' : $dir;
$files = array();
while (($file = readdir($dp)) !== false ) {
if($file != '.' && $file != '..' && is_dir($dir . $file) && $recursive) {
$files = array_merge($files, get_existfiles($dir . $file, $ext, $recursive));
} else {
$matches = array();
if (preg_match($pattern, $file, $matches)) {
$files[] = $dir . $file;
}
}
}
closedir($dp);
return $files;
}
}
if (! function_exists('is_associative_array')) {
/**
* Check if an array is an associative array
*
* PHP Extension
*
* @param array $array
* @return boolean
*/
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)));
}
}
if (! function_exists('_')) {
function &_($str)
{
return $str;
}
}
///////////////////////////////////
function plugin_contentsx_common_init()
{
global $plugin_contentsx;
if (class_exists('PluginContentsxUnitTest')) {
$plugin_contentsx = new PluginContentsxUnitTest();
} elseif (class_exists('PluginContentsxUser')) {
$plugin_contentsx = new PluginContentsxUser();
} else {
$plugin_contentsx = new PluginContentsx();
}
}
function plugin_contentsx_convert()
{
global $plugin_contentsx; plugin_contentsx_common_init();
$args = func_get_args();
return call_user_func_array(array(&$plugin_contentsx, 'convert'), $args);
}
function plugin_contentsx_action()
{
global $plugin_contentsx; plugin_contentsx_common_init();
return call_user_func(array(&$plugin_contentsx, 'action'));
}
?>