User:Nx/Extensions/wigo3/wigo3.php
From RationalWiki
< User:Nx | Extensions
<?php # This extension requires a table in the database, create it with the following mysql command: # replace varbinary with varchar depending on wiki setup # create table /*$wgDBprefix*/wigovote (id varbinary(255) NOT NULL, voter_name varbinary(255) NOT NULL, vote int NOT NULL default 0, timestamp varbinary(14), PRIMARY KEY (id,voter_name)) /*$wgDBTableOptions*/; if ( !defined( 'MEDIAWIKI' ) ) { exit; } # store ips instead of usernames for logged in users too $wgWigo3ConfigStoreIPs = true; $wgExtensionCredits['parserhook'][] = array( 'name' => 'WIGO Voting Extension', 'author' => '[http://rationalwiki.com/wiki/User:Nx Nx]', 'url' => 'http://rationalwiki.com/', 'description' => 'Up/down voting system.', 'version' => '3.5' ); $wgWigoIP = dirname( __FILE__ ); $wgExtensionMessagesFiles['wigo3'] = "$wgWigoIP/wigo3.i18n.php"; //Avoid unstubbing $wgParser on setHook() too early on modern (1.12+) MW versions, as per r35980 if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) { $wgHooks['ParserFirstCallInit'][] = 'wigo3init'; } else { // Otherwise do things the old fashioned way $wgExtensionFunctions[] = 'wigo3init'; } $wgHooks['AjaxAddScript'][] = 'wigo3addjs'; global $wgUseAjax; if ($wgUseAjax) { $wgAjaxExportList[] = "wigovote"; $wgAjaxExportList[] = "wigovote2"; $wgAjaxExportList[] = "wigoinvalidate"; } function wigo3init() { global $wgParser; wfLoadExtensionMessages('wigo3'); $wgParser->setHook('vote','wigo3render'); $wgParser->setHook('votecp','wigo3rendercp'); $wgParser->setHook('capture','wigo3rendercapture'); return true; } function wigo3addjs($out) { global $wgJsMimeType, $wgScriptPath; $out->addScript("<script type=\"{$wgJsMimeType}\" src=\"{$wgScriptPath}/extensions/wigo3/js/wigo3.js\"></script>"); return true; } function wigoinvalidate($pagename) { //$pagename is wgPageName from javascript $title = Title::newFromText($pagename); if ($title->invalidateCache() === true) { $dbw = wfGetDB(DB_MASTER); $dbw->commit(); return "ok"; } else { return "notok"; } } /* kept for compatibility */ function wigovote($pollid, $vote, $min=-1, $max=1) { $dbw = wfGetDB(DB_MASTER); global $wgUser, $wgWigo3ConfigStoreIPs; $voter = $wgWigo3ConfigStoreIPs ? getenv ("REMOTE_ADDR") : $wgUser->getName(); $result = $dbw->replace('wigovote',array('id','voter_name'),array('id' => $pollid, 'voter_name' => $voter, 'vote' => $vote, 'timestamp' => wfTimestampNow()),'wigovote'); $res = $dbw->select('wigovote',array('sum(vote)','count(vote)'),array('id' => $pollid, "vote >= {$min}", "vote <= {$max}"),'wigovote',array('GROUP BY' => 'id')); $row = $res->fetchRow(); $vote = $row['sum(vote)']; $countvotes = $row['count(vote)']; wfLoadExtensionMessages('wigo3'); $totalvotes = wfMsgExt('wigovotestotal',array('parsemag'),array($countvotes)); $res->free(); $dbw->commit(); $dbw->close(); return "$pollid:$vote:$countvotes:$totalvotes:$result"; } /* voting function for up-down wigo only */ function wigovote2($pollid, $vote) { /*store the vote*/ $dbw = wfGetDB(DB_MASTER); global $wgUser, $wgWigo3ConfigStoreIPs; $voter = $wgWigo3ConfigStoreIPs ? getenv ("REMOTE_ADDR") : $wgUser->getName(); $result = $dbw->replace('wigovote',array('id','voter_name'),array('id' => $pollid, 'voter_name' => $voter, 'vote' => $vote, 'timestamp' => wfTimestampNow()),'wigovote'); $dbw->commit(); /*get updated data to update page*/ $plus = 0; $minus = 0; $zero = 0; $myvote = -2; wigo3getvotes($pollid, $plus, $minus, $zero,$voter,$myvote); wfLoadExtensionMessages('wigo3'); $totalvotes = $plus + $minus + $zero; $totaltooltip = wfMsgExt('wigovotestotald',array('parsemag'),array($totalvotes,$plus,$zero,$minus)); /* $totalup = wfMsgExt('wigovotestotal',array('parsemag'),array($plus)); $totaldown = wfMsgExt('wigovotestotal',array('parsemag'),array($minus)); $totalneutral = wfMsgExt('wigovotestotal',array('parsemag'),array($zero));*/ $distribtitle = wfMsgExt('wigovotedistrib',array('parsemag'),array($plus,$zero,$minus)); return "$pollid:$plus:$minus:$zero:$totalvotes:$totaltooltip:$distribtitle:$myvote:$result"; } function wigo3getvotes($voteid, &$plus, &$minus, &$zero, $voter, &$myvote) { $dbr = wfGetDB(DB_SLAVE); $res = $dbr->select('wigovote', array('sum(case vote when 1 then 1 else 0 end) as plus', 'sum(case vote when -1 then 1 else 0 end) as minus', 'sum(case vote when 0 then 1 else 0 end) as zero'), array('id' => $voteid),__FUNCTION__); if ($row = $res->fetchRow()) { $plus = $row['plus']; $minus = $row['minus']; $zero = $row['zero']; } if ($plus == null) { $plus = 0; } if ($minus == null) { $minus = 0; } if ($zero == null) { $zero = 0; } $res->free(); //myvote does not work with caching /* $myvote = $dbr->selectField('wigovote','vote',array('id' => $voteid, 'voter_name' => $voter),__FUNCTION__); if ($myvote === false) { $myvote = -2; }*/ $myvote = -2; } function wigo3rendercp($input, $args, $parser) { return wigo3render($input, $args, $parser,true); } function wigo3render($input, $args, $parser, $cp = false) { //disabled to improve performance //$parser->disableCache(); $voteid = $args['poll']; if (!$voteid) { static $err = null; if (is_null($err)) { wfLoadExtensionMessages('wigo3'); $err = wfMsg('wigoerror'); } $output = $parser->recursiveTagParse($input); return "<p><span style='color:red;'>{$err}</span> {$output}</p>"; } $plus = 0; $minus = 0; $zero = 0; $myvote = -2; global $wgUser, $wgWigo3ConfigStoreIPs; $voter = $wgWigo3ConfigStoreIPs ? getenv ("REMOTE_ADDR") : $wgUser->getName(); wigo3getvotes($voteid,$plus,$minus,$zero,$voter,$myvote); $votes = $plus - $minus; $countvotes = $plus + $minus + $zero; //backwards compatible img tag handling if (!$cp && array_key_exists('img',$args) && (!strcmp($args['img'],'on') || !strcmp($args['img'],'expanded'))) { $input = preg_replace('/\[[^\]]*conservapedia\.com[^\]]*\]/i', "$0<sup>[[:Image:{$args['poll']}_x.png|img]]</sup>",$input); $x = 0; do { $input = preg_replace('/(<sup>\[\[:Image:' . $args['poll'] . '_)x(\.png\|img\]\]<\/sup>)/', "$1 {$x}$2", $input,1,$count); ++$x; } while ($count); } $output = $parser->recursiveTagParse($input); //votecp img tag handling if ($cp) { $matchi = preg_match_all('/(<a[^>]*href="([^"]*conservapedia\.com[^"]*)"[^>]*>(?:[^<]|<[^\/]|<\/[^a]|<\/a[^>])*<\/a>)(?!<span class="wigocapture">)/i', $output,$matches,PREG_OFFSET_CAPTURE); if ($matchi > 0) $newoutput = substr($output,0,$matches[1][0][1]); for ($i=0; $i<$matchi;++$i) { //performance impact of sha1 is 1.2x $imgname = 'capture_' /*. $args['poll'] . '_'*/ . /*crc32*/ /*md5*/ sha1($matches[2][$i][0]) . '.png'; $text = $matches[1][$i][0]; $img = $parser->recursiveTagParse("<span class=\"wigocapture\"><sup>[[:Image:$imgname|img]]</sup></span>"); $nextlength = (($i == $matchi-1) ? (strlen($output) - ($matches[1][$i][1] + strlen($text))) : ($matches[1][$i+1][1] - ($matches[1][$i][1] + strlen($text)))); $newoutput .= substr($output,$matches[1][$i][1],strlen($text)) . $img . substr($output,$matches[1][$i][1]+strlen($text),$nextlength); } if ($matchi > 0) $output = $newoutput; } //wfMsgExt resets the parser state if the message contains a parser function, breaking for example references. recursiveTagParse doesn't. wfLoadExtensionMessages('wigo3'); //$totalvotes = wfMsgExt('wigovotestotald',array('parsemag'),array($countvotes,$plus,$zero,$minus)); $totalvotes = htmlspecialchars($parser->recursiveTagParse(wfMsgNoTrans('wigovotestotald',array($countvotes,$plus,$zero,$minus)))); /* $totalup = wfMsgExt('wigovotestotal',array('parsemag'),array($plus)); $totaldown = wfMsgExt('wigovotestotal',array('parsemag'),array($minus)); $totalneutral = wfMsgExt('wigovotestotal',array('parsemag'),array($zero));*/ //$distribtitle = wfMsgExt('wigovotedistrib',array('parsemag'),array($plus,$zero,$minus)); $distribtitle = htmlspecialchars($parser->recursiveTagParse(wfMsgNoTrans('wigovotedistrib',array($plus,$zero,$minus)))); if ($countvotes != 0) { $uppercent = ($plus / $countvotes) * 100; $downpercent = ($minus / $countvotes) * 100; $neutralpercent = ($zero / $countvotes) * 100; } else { $uppercent = 0; $downpercent = 0; $neutralpercent = 0; } if ($uppercent != 0) { $uppercent .= "%"; } if ($neutralpercent != 0) { $neutralpercent .= "%"; } if ($downpercent != 0) { $downpercent .= "%"; } if (array_key_exists('closed',$args) && strcasecmp($args['closed'],"yes") === 0) { return "<table class=\"vote\" cellspacing=\"2\" cellpadding=\"2\" border=\"0\">" . "<tr>" . "<td style=\"white-space:nowrap;\">" . "<table id=\"{$voteid}-dist\" class=\"wigodistribution\" style=\"width:48px; height:6px; border:1px solid grey; margin:0; padding:0; border-spacing:0;\" title=\"{$distribtitle}\">" . "<tr>" . "<td class=\"wigodist-up\" style=\"border:none; background-color:limegreen; margin:0; padding:0; width:{$uppercent}; height:100%; " . ($totalvotes == 0 ? "display:none;" : "") . "\"></td>" . "<td class=\"wigodist-neutral\" style=\"border:none; background-color:orange; margin:0; padding:0; width:{$neutralpercent}; height:100%; " . ($totalvotes == 0 ? "display:none;" : "") . "\"></td>" . "<td class=\"wigodist-down\" style=\"border:none; background-color:red; margin:0; padding:0; width:{$downpercent}; height:100%; " . ($totalvotes == 0 ? "display:none;" : "") . "\"></td>" . "</tr></table>" . "</td>" . "<td style=\"min-width:25px; text-align:center;\">" . "<span id=\"{$voteid}\" title=\"{$totalvotes}\">{$votes}</span>" . "</td>" . "<td style=\"vertical-align:middle;\">" . "<!--$voteid-->$output" . "</td>" . "</tr>" . "</table>"; } else { //get up-down images //static improves performance a bit static $up = null; static $down = null; static $reset = null; static $altup = null; static $altdown = null; static $altreset = null; static $titleup = null; static $titledown = null; static $titlereset = null; if ( is_null($up) || is_null($down) || is_null($reset) || is_null($altup) || is_null($altdown) || is_null($altreset) || is_null($titleup) || is_null($titledown) || is_null($titlereset) ) { wfLoadExtensionMessages('wigo3'); $up = wfFindFile(wfMsg('wigouparrow')); $up = $up ? $up->getFullUrl() : ''; $down = wfFindFile(wfMsg('wigodownarrow')); $down = $down ? $down->getFullUrl() : ''; $reset = wfFindFile(wfMsg('wigoresetvote')); $reset = $reset ? $reset->getFullUrl() : ''; $altup = wfMsgHtml('wigoaltup'); $altdown = wfMsgHtml('wigoaltdown'); $altreset = wfMsgHtml('wigoaltreset'); $titleup = wfMsgHtml('wigotitleup'); $titledown = wfMsgHtml('wigotitledown'); $titlereset = wfMsgHtml('wigotitlereset'); } return "<table class=\"vote\" cellspacing=\"2\" cellpadding=\"2\" border=\"0\">" . "<tr>" . "<td style=\"white-space:nowrap;\">" . "<a " . "href=\"javascript:wigovoteup('{$voteid}')\" id=\"{$voteid}-up\" class=\"wigobutton wigoupbutton " . ($myvote == 1 ? "myvotebutton" : "") . " \">" . "<img alt=\"{$altup}\" title=\"{$titleup}\" src=\"$up\"></img></a>" . "<a " . "href=\"javascript:wigovotereset('{$voteid}')\" id=\"{$voteid}-neutral\" class=\"wigobutton wigoneutralbutton " . ($myvote == 0 ? "myvotebutton" : "") . " \">" . "<img alt=\"{$altreset}\" title=\"{$titlereset}\" src=\"$reset\"></img></a>" . "<a " . "href=\"javascript:wigovotedown('{$voteid}')\" id=\"{$voteid}-down\" class=\"wigobutton wigodownbutton " . ($myvote == -1 ? "myvotebutton" : "") . " \">" . "<img alt=\"{$altdown}\" title=\"{$titledown}\" src=\"$down\"></img></a>" . "<table id=\"{$voteid}-dist\" class=\"wigodistribution\" style=\"width:100%; height:6px; border:1px solid grey; margin:0; padding:0; border-spacing:0;\" title=\"{$distribtitle}\">" . "<tr>" . "<td class=\"wigodist-up\" style=\"border:none; background-color:limegreen; margin:0; padding:0; width:{$uppercent}; height:100%; " . ($totalvotes == 0 ? "display:none;" : "") . "\"></td>" . "<td class=\"wigodist-neutral\" style=\"border:none; background-color:orange; margin:0; padding:0; width:{$neutralpercent}; height:100%; " . ($totalvotes == 0 ? "display:none;" : "") . "\"></td>" . "<td class=\"wigodist-down\" style=\"border:none; background-color:red; margin:0; padding:0; width:{$downpercent}; height:100%; " . ($totalvotes == 0 ? "display:none;" : "") . "\"></td>" . "</tr></table>" . "</td>" . "<td style=\"min-width:25px; text-align:center;\">" . "<span id=\"{$voteid}\" title=\"{$totalvotes}\">{$votes}</span>" . "</td>" . "<td style=\"vertical-align:middle;\">" . "<!--$voteid-->$output" . "</td>" . "</tr>" . "</table>"; } } function wigo3rendercapture($input, $args, $parser) { $output = $parser->recursiveTagParse($input); $matchi = preg_match_all('/(<a[^>]*href="([^"]*)"[^>]*>(?:[^<]|<[^\/]|<\/[^a]|<\/a[^>])*<\/a>)(?!<span class="wigocapture">)/i', $output,$matches,PREG_OFFSET_CAPTURE); if ($matchi > 0) $newoutput = substr($output,0,$matches[1][0][1]); for ($i=0; $i<$matchi;++$i) { $imgname = 'capture_' /*. $args['poll'] . '_'*/ . /*crc32*/ /*md5*/ sha1($matches[2][$i][0]) . '.png'; $text = $matches[1][$i][0]; $img = $parser->recursiveTagParse("<span class=\"wigocapture\"><sup>[[:Image:$imgname|img]]</sup></span>"); $nextlength = (($i == $matchi-1) ? (strlen($output) - ($matches[1][$i][1] + strlen($text))) : ($matches[1][$i+1][1] - ($matches[1][$i][1] + strlen($text)))); $newoutput .= substr($output,$matches[1][$i][1],strlen($text)) . $img . substr($output,$matches[1][$i][1]+strlen($text),$nextlength); } if ($matchi > 0) $output = $newoutput; return $output; }