<?php /** * Table of Contents Plugin eXtension * * @author sonots * @license http://www.gnu.org/licenses/gpl.html GPL v2 * @link http://lsx.sourceforge.jp/?Plugin%2Fcontentsx.inc.php * @version $Id: contentsx.inc.php,v 1.11 2007-08-03 07:23:17Z sonots $ * @package plugin */ // v1.12 PHP8.0対応 2021-12-15 byã¯ã„ãµã‚“ class PluginContentsx { function __construct() { // Message static $msg = array(); if (empty($msg)) $msg = array( 'toctitle' => _('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 = '<p>Following pages were executed to assure:</p>' . '<p>' . implode("<br />\n", $links) . '</p>'; } } 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 action="' . get_script_uri() . '?cmd=' . $cmd . '" method="post">'; $form[] = '<div>'; $form[] = ' <input type="hidden" name="pcmd" value="' . $pcmd . '" />'; $form[] = ' <input type="text" name="page" size="24" value="" /> ' . _('A Page (Blank if All)') . '<br />'; if (! is_admin(null, $this->conf['use_session'], $this->conf['through_if_admin'])) { $form[] = ' <input type="password" name="pass" size="24" value="" /> ' . _('Admin Password') . '<br />'; } else { $form[] = ' <input type="password" name="pass" size="24" value="" style="background-color:#ddd;" disabled="disabled" /> ' . _('Admin Password') . '<br />'; } $form[] = ' <input type="submit" name="submit" value="Submit" /><br />'; $form[] = '</div>'; $form[] = '</form>'; $form = implode("\n", $form); if ($message != '') { $message = '<p><b>' . htmlsc($message) . '</b></p>'; } return $message . $form; } function convert() { $args = func_get_args(); if ($GLOBALS['vars']['cmd'] != 'read') { return ''; } $body = $this->body($args); if ($body != '') { $body = '<table border="0" class="toc"><tbody>' . "\n" . '<tr><td class="toctitle">' . "\n" . '<span>' . $this->msg['toctitle'] . "</span>\n" . "</td></tr>\n" . '<tr><td class="toclist">' . "\n" . $body . "</td></tr>\n" . "</tbody></table>\n"; } if ($this->error != "" ) { return "<p>#$this->plugin(): $this->error</p>"; } 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 <ul><li style="list-type:none"><ul><li>, we have to do as <ul><li style="padding-left:16*2px;margin-left:16*2px"> as pukiwiki standard. I did not like it) <ul> <ul><li>1 <li>1</li> </li><li>1 <li>1 <ul><li>2 <ul> </li></ul></li><li>1 <li>2</li> </li><li>1 </ul> => <ul><li style="list-type:none"><ul><li>3 </li> </li></ul></li></ul></li></ul> <li>1</li> <li>1</li> <ul><li style="list-type:none"><ul> <li>3</li> </ul></li></ul> </li> </ul> */ $html = ""; $ul = $pdepth = 0; foreach ($this->metalines as $metaline) { $display = $metaline['display']; $depth = $metaline['listdepth']; if ($depth > $pdepth) { $diff = $depth - $pdepth; $html .= str_repeat('<ul><li style="list-style:none">', $diff - 1); if ($depth == 1) { // or $first flag $html .= '<ul class="' . $this->plugin . '"><li>'; } else { $html .= '<ul><li>'; } $ul += $diff; } elseif ($depth == $pdepth) { $html .= '</li><li>'; } elseif ($depth < $pdepth) { $diff = $pdepth - $depth; $html .= str_repeat('</li></ul>', $diff); $html .= '</li><li>'; $ul -= $diff; } $html .= $display; $html .= "\n"; $pdepth = $depth; } $html .= str_repeat('</li></ul>', $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')); } ?>