CONF = &$CONF;
if (empty($this->CONF)) {
$this->CONF['RECENT_PAGE'] = 'RecentVotes';
$this->CONF['RECENT_LOG'] = CACHE_DIR . 'recentvotes.dat';
$this->CONF['RECENT_LIMIT'] = 100;
$this->CONF['COOKIE_EXPIRED'] = 60*60*24*3;
$this->CONF['BARCHART_LIB_FILE'] = LIB_DIR . 'barchart.cls.php';
$this->CONF['BARCHART_COLOR_BAR'] = ' #0000cc';
$this->CONF['BARCHART_COLOR_BG'] = 'transparent';
$this->CONF['BARCHART_COLOR_BORDER'] = 'transparent';
}
static $default_options = array();
$this->default_options = &$default_options;
if (empty($this->default_options)) {
$this->default_options['readonly'] = FALSE;
$this->default_options['addchoice'] = FALSE;
$this->default_options['barchart'] = FALSE;
}
// init
$this->options = $this->default_options;
if (function_exists('textdomain')) {
textdomain('vote'); // use i18n msgs of vote.inc.php
}
}
function PluginVotex() {
$this->__construct();
}
// static
var $CONF;
var $default_options;
// var
var $options;
/**
* Action Plugin Main Function
* @static
*/
function action()
{
global $vars;
if ($vars['pcmd'] === 'inline') {
return $this->action_inline();
} else {
return $this->action_convert();
}
}
/**
* POST action via inline plugin
*/
function action_inline()
{
global $vars, $defaultpage;
$_title_collided = _('On updating $1, a collision has occurred.');
$_title_updated = _('$1 was updated');
$_msg_collided = _('It seems that someone has already updated this page while you were editing it.
+ is placed at the beginning of a line that was newly added.
! is placed at the beginning of a line that has possibly been updated.
Edit those lines, and submit again.');
if (method_exists('auth', 'check_role')) { // Plus!
if (auth::check_role('readonly')) die_message('PKWK_READONLY prohibits editing');
} else {
if (PKWK_READONLY) die_message('PKWK_READONLY prohibits editing');
}
$page = isset($vars['refer']) ? $vars['refer'] : $defaultpage;
$pcmd = $vars['pcmd'];
$vote_id = $vars['vote_id'];
$vars['page'] = $page;
$choice_id = $vars['choice_id'];
if ($this->is_continuous_vote($page, $pcmd, $vote_id)) {
return array(
'msg' => _('Error in vote'),
'body' => _('Continuation vote cannot be performed.'),
);
}
// parse contents of wiki page and get update
$lines = get_source($page);
list($linenum, $newline, $newtext, $newvotes) = $this->get_update_inline($lines, $vote_id, $choice_id);
if ($linenum === false) {
die_message(_('There was no matching vote. '));
}
$newlines = $lines;
$newlines[$linenum] = $newline;
$newcontents = implode('', $newlines);
// collision check
$contents = implode('', $lines);
if (md5($contents) !== $vars['digest']) {
$msg = $_title_collided;
$body = $this->show_preview_form($_msg_collided, $newline);
return array('msg'=>$msg, 'body'=>$body);
}
page_write($page, $newcontents, TRUE); // notimestamp
$this->update_recent_voted($page, $pcmd, $vote_id, $choice_id, $newvotes);
//static in convert() was somehow wierd if return(msg=>'',body=>'');
//$msg = $_title_updated;
//$body = '';
//return array('msg'=>$msg, 'body'=>$body);
$anchor = $this->get_anchor($pcmd, $vote_id);
header('Location: ' . get_script_uri() . '?' . rawurlencode($page) . '#' . $anchor);
exit;
}
/**
* POST action via convert plugin
*/
function action_convert()
{
global $vars, $defaultpage;
$_title_collided = _('On updating $1, a collision has occurred.');
$_title_updated = _('$1 was updated');
$_msg_collided = _('It seems that someone has already updated this page while you were editing it.
+ is placed at the beginning of a line that was newly added.
! is placed at the beginning of a line that has possibly been updated.
Edit those lines, and submit again.');
if (method_exists('auth', 'check_role')) { // Plus!
if (auth::check_role('readonly')) die_message('PKWK_READONLY prohibits editing');
} else {
if (PKWK_READONLY) die_message('PKWK_READONLY prohibits editing');
}
$page = isset($vars['refer']) ? $vars['refer'] : $defaultpage;
$pcmd = $vars['pcmd'];
$vote_id = $vars['vote_id'];
$vars['page'] = $page;
$choice_id = $this->get_selected_choice_convert();
$addchoice = isset($vars['addchoice']) && $vars['addchoice'] !== ''
? $vars['addchoice'] : null;
if ($this->is_continuous_vote($page, $pcmd, $vote_id)) {
return array(
'msg' => _('Error in vote'),
'body' => _('Continuation vote cannot be performed.'),
);
}
// parse contents of wiki page and get update
$lines = get_source($page);
list($linenum, $newline, $newtext, $newvotes) = $this->get_update_convert($lines, $vote_id, $choice_id, $addchoice);
if ($linenum === false) {
die_message(_('There was no matching vote. '));
}
$newlines = $lines;
$newlines[$linenum] = $newline;
$newcontents = implode('', $newlines);
// collision check
$contents = implode('', $lines);
if (md5($contents) !== $vars['digest']) {
$msg = $_title_collided;
$body = $this->show_preview_form($_msg_collided, $newline);
return array('msg'=>$msg, 'body'=>$body);
}
page_write($page, $newcontents, TRUE); // notimestamp
if (isset($addchoice)) $choice_id = count($newvotes) - 1; // to make sure
$this->update_recent_voted($page, $pcmd, $vote_id, $choice_id, $newvotes);
//static in convert() was somehow wierd if return(msg=>'',body=>'');
//$msg = $_title_updated;
//$body = '';
//return array('msg'=>$msg, 'body'=>$body);
$anchor = $this->get_anchor($pcmd, $vote_id);
header('Location: ' . get_script_uri() . '?' . rawurlencode($page) . '#' . $anchor);
exit;
}
/**
* Update Vote for inline plugin
*
* @param array &$lines
* @param integer $vote_id
* @parram string $choice_id
* @return array array($linenum, $updated_line, $updated_text, $updated_votes)
*/
function get_update_inline(&$lines, $vote_id, $choice_id)
{
$contents = implode('', $lines);
global $vars, $defaultpage;
$page = isset($vars['refer']) ? $vars['refer'] : $defaultpage;
$ic = new InlineConverter(array('plugin'));
$vote_count = 0;
foreach ($lines as $linenum => $line) {
if (strpos($line, ' ') === 0) continue; // skip pre
$inlines = $ic->get_objects($line, $page);
$pos = 0;
foreach ($inlines as $inline) {
if ($inline->name !== 'votex') continue;
$pos = strpos($line, '&votex', $pos);
if ($vote_id > $vote_count++) {
$pos++;
} else {
$l_remain = substr($line, 0, $pos);
$r_remain = substr($line, $pos + strlen($inline->text));
$arg = $inline->param;
$body = $inline->body;
$args = csv_explode(',', $arg);
list($votes, $options) = $this->parse_args_inline($args, $this->default_options);
if ($options['readonly']) return array(false, false, false, false);
foreach ($votes as $i => $vote) {
list($choice, $count) = $vote;
if ($i == $choice_id) {
++$count;
$votes[$i] = array($choice, $count);
}
}
$new_args = $this->restore_args_inline($votes, $options, $this->default_options);
$new_arg = csv_implode(',', $new_args);
$body = ($body != '') ? '{' . $body . '};' : ';';
$newtext = '&votex(' . $new_arg . ')' . $body;
$newline = $l_remain . $newtext . $r_remain;
return array($linenum, $newline, $newtext, $votes);
}
}
}
return array(false, false, false, false);
}
/**
* Update Vote for convert plugin
*
* @param array &$lines
* @param integer $vote_id
* @parram string $choice_id
* @param string $addchoice
* @return array array($linenum, $updated_line, $updated_text, $updated_votes)
*/
function get_update_convert(&$lines, $vote_id, $choice_id, $addchoice = null)
{
$vote_count = 0;
foreach($lines as $linenum => $line) {
$matches = array();
if (preg_match('/^#votex(?:\((.*)\)(.*))?$/i', $line, $matches)
&& $vote_id == $vote_count++) {
$args = csv_explode(',', $matches[1]);
$remain = isset($matches[2]) ? $matches[2] : '';
list($votes, $options) = $this->parse_args_convert($args, $this->default_options);
if ($options['readonly']) return array(false, false, false, false);
if (isset($addchoice)) {
$votes[] = array($addchoice, 1);
} elseif (isset($votes[$choice_id])) {
list($choice, $count) = $votes[$choice_id];
$votes[$choice_id] = array($choice, $count + 1);
}
$new_args = $this->restore_args_convert($votes, $options, $this->default_options);
$new_arg = csv_implode(',', $new_args);
$newtext = '#votex(' . $new_arg . ')';
$newline = $newtext . $remain . "\n";
return array($linenum, $newline, $newtext, $votes);
}
}
return array(false, false, false, false);
}
/**
* Get the selected choice id
*
* @global $vars;
* @return string $choice_id
* @uses decode_choice()
*/
function get_selected_choice_convert()
{
global $vars;
$choice_id = false;
foreach ($vars as $key => $val) {
if (strpos($key, 'choice_') === 0) {
$choice_id = $this->decode_choice($key);
break;
}
}
return $choice_id;
}
/**
* Recent Voted
*
* @param string $page voted page
* @param string $pcmd convert or inline
* @param integer $vote_id
* @param integer $choice_id
* @param array $votes
* @return void
*/
function update_recent_voted($page, $pcmd, $vote_id, $choice_id, $votes)
{
$limit = max(0, $this->CONF['RECENT_LIMIT']);
$time = UTIME;
// RecentVoted
$lines = get_source($this->CONF['RECENT_PAGE']);
$anchor = $this->get_anchor($pcmd, $vote_id);
$args = array();
foreach ($votes as $vote) {
list($choice, $count) = $vote;
$args[] = $choice . '[' . $count . ']';
}
$arg = csv_implode(',', $args);
list($choice, $count) = $votes[$choice_id];
$addline =
'-' . format_date($time) .
' - [[' . $page . '#' . $vote_id . '>' . $page . '#' . $anchor . ']] ' .
$choice .
' (' . $arg . ')' .
"\n";
array_unshift($lines, $addline);
$lines = array_splice($lines, 0, $limit);
page_write($this->CONF['RECENT_PAGE'], implode('', $lines));
// recentvoted.dat (serialization)
if (is_readable($this->CONF['RECENT_LOG'])) {
$log_contents = file_get_contents($this->CONF['RECENT_LOG']);
$logs = unserialize($log_contents);
} else {
$logs = array();
}
$addlog = array($time, $page, $pcmd, $vote_id, $choice_id, $votes);
array_unshift($logs, $addlog);
$logs = array_splice($logs, 0, $limit);
file_put_contents($this->CONF['RECENT_LOG'], serialize($logs));
}
/**
* Check if a continuous vote
*
* @param string $page
* @param string $pcmd convert or inline
* @param integer $vote_id vote form id
* @return boolean true if if is a continuous vote
* @global $_COOKIE
* @global $_SERVER
* @vars $CONF 'COOKIE_EXPIRED'
*/
function is_continuous_vote($page, $pcmd, $vote_id)
{
$cmd = 'votex';
$votedkey = $cmd . '_' . $pcmd . '_' . $page . '_' . $vote_id;
if (isset($_COOKIE[$votedkey])) {
return true;
}
$_COOKIE[$votedkey] = 1;
$matches = array();
preg_match('!(.*/)!', $_SERVER['REQUEST_URI'], $matches);
setcookie($votedkey, 1, time()+$this->CONF['COOKIE_EXPIRED'], $matches[0]);
return false;
}
/**
* Get Preview Form HTML (for when collision occured)
*
* @param string $msg message
* @param string $body
* @return string
*/
function show_preview_form($msg = '', $body = '')
{
global $vars, $rows, $cols;
$s_refer = htmlsc($vars['refer']);
$s_digest = htmlsc($vars['digest']);
$s_body = htmlsc($body);
$form = '';
$form .= $msg . "\n";
$form .= '