array('number', ''), 'except' => array('string', ''), 'filter' => array('string', ''), 'title' => array('enum', 'on', array('on', 'off', 'nolink', 'basename')), // obsolete 'titlestr' => array('enum', 'title', array('name', 'off', 'basename', 'title', 'relname')), 'titlelink' => array('bool', true), 'section' => array('array', array()), 'permalink' => array('string', false), 'head' => array('bool', true), ); static $default_section_options = array( 'num' => array('number', ''), 'depth' => array('number', ''), 'except' => array('string', ''), 'filter' => array('string', ''), 'cache' => array('enum', 'on', array('on', 'off', 'reset')), 'inclsub' => array('bool', false), // not yet ); $this->default_options = &$default_options; $this->default_section_options = &$default_section_options; // init static $visited = array(); $this->visited = &$visited; $this->options = $this->default_options; $this->section_options = $this->default_section_options; } function PluginIncludex() { $this->__construct(); } // static var $default_options; var $default_section_options; var $visited; // var var $error = ""; var $plugin = "includex"; var $options; var $section_options; var $inclpage; var $lines; var $headlines; var $narrowed_headlines; function convert() { $args = func_get_args(); $body = $this->body($args); if ($this->error != "" ) { return "
#$this->plugin(): $this->error
"; } return $body; } function body($args) { global $vars, $get, $post; $this->visited[$vars['page']] = TRUE; $this->inclpage = array_shift($args); $this->check_page(); if ($this->error != "") { return; } $parser = new PluginIncludexOptionParser(); $this->options = $parser->parse_options($args, $this->options); if ($parser->error != "") { $this->error = $parser->error; return; } $this->check_options(); if ($this->error != "") { return; } $this->init_lines(); if ($this->error !== "") { return; } $this->narrow_lines(); if ($this->error !== "") { return; } $body = $this->frontend(); if ($this->error !== "") { return; } $this->visited[$this->inclpage] = TRUE; return $body; } function check_options() { // support lower version if ($this->options['title'][1] != 'on') { if ($this->options['title'][1] == 'nolink') { $this->options['titlelink'][1] = false; $this->options['titlestr'][1] = 'name'; } else { $this->options['titlestr'][1] = $this->options['title'][1]; } } if ($this->options['permalink'][1] === '') { $this->options['permalink'][1] = _('Permalink'); } } function check_page() { global $vars; if (empty($this->inclpage)) { $this->error = "No page is specified."; return; } $current = $vars['page']; $this->inclpage = get_fullname($this->inclpage, $current); if (! $this->is_page($this->inclpage)) { $this->error = "$this->inclpage does not eixst."; return; } if (! $this->check_readable($this->inclpage, false, false)) { $this->error = "$this->inclpage is not readable."; return; } if (isset($this->visited[$this->inclpage])) { $this->error = "$this->inclpage is already included."; return; } } function frontend() { global $vars, $get, $post; $titlestr = PluginIncludex::get_titlestr($this->inclpage, $this->options['titlestr'][1]); $title = PluginIncludex::get_title($this->inclpage, $titlestr, $this->options['title'][1]); if ($this->error != "") { return; } // because included page would use these variables. $tmp = $vars['page']; $get['page'] = $post['page'] = $vars['page'] = $this->inclpage; if (function_exists('convert_filter')) { $this->lines = convert_filter($this->lines); // plus } $body = convert_html($this->lines); $get['page'] = $post['page'] = $vars['page'] = $tmp; if ($this->error != "") { return; } $footer = ''; if ($this->options['permalink'][1] !== false) { $linkstr = $this->make_inline($this->options['permalink'][1]); $footer = '' . make_pagelink($this->inclpage, $linkstr) . '
'; } return $title . "\n" . $body . $footer; } // static function get_titlestr($inclpage, $option = null, $current = null) { switch ($option) { case 'off': $titlestr = ''; break; case 'name': $titlestr = htmlsc($inclpage); break; case 'basename': $titlestr = htmlsc(basename($inclpage)); break; case 'relname': if (! isset($current)) $current = $GLOBALS['vars']['page']; if (($i = strpos($inclpage, $current . '/')) === 0) { $titlestr = htmlsc(substr($inclpage, strlen($current)+1)); } else { $titlestr = htmlsc($inclpage); } break; case 'on': case 'title': default: if (exist_plugin('contentsx')) { $contentsx = new PluginContentsx(); if (method_exists($contentsx, 'get_title')) { $titlestr = $contentsx->get_title($inclpage); $titlestr = strip_htmltag(make_link($titlestr)); } } if ($titlestr == '') $titlestr = htmlsc($inclpage); break; } return $titlestr; } // static function get_title($inclpage, $titlestr, $option = true) { global $fixed_heading_edited; $anchorlink = ' ' . PluginIncludex::get_page_anchorlink($inclpage); $editlink = $fixed_heading_edited ? ' ' . PluginIncludex::get_page_editlink($inclpage) : ''; if ($titlestr == '') { //return $ret = '
';
$link .= '';
return $link;
}
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);
}
}
///////////////////////////////////////
class PluginIncludexOptionParser
{
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];
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)));
}
}
// php extension
if (! function_exists('_')) {
function &_($str)
{
return $str;
}
}
////////////////////////////////////////////
function plugin_includex_common_init()
{
global $plugin_includex;
if (class_exists('PluginIncludexUnitTest')) {
$plugin_includex = new PluginIncludexUnitTest();
} elseif (class_exists('PluginIncludexUser')) {
$plugin_includex = new PluginIncludexUser();
} else {
$plugin_includex = new PluginIncludex();
}
}
function plugin_includex_convert()
{
global $plugin_includex;
plugin_includex_common_init();
$args = func_get_args();
return call_user_func_array(array(&$plugin_includex, 'convert'), $args);
}
if (! defined('INIT_DIR')) // if not Plus!
if (file_exists(DATA_HOME . 'init/includex.ini.php'))
include_once(DATA_HOME . 'init/includex.ini.php');
?>