User:Nx/Extensions/bestof/bestof.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*/wigotext (vote_id varbinary(255) NOT NULL, text mediumblob, is_cp boolean default false, PRIMARY KEY (vote_id)) /*$wgDBTableOptions*/; //version 3.5 database addition: //alter table wigotext add column is_cp boolean default false; // Extension credits that show up on Special:Version $wgExtensionCredits['parserhook'][] = array( 'name' => 'Best of display system', 'author' => '[http://rationalwiki.com/wiki/User:Tmtoulouse Trent Toulouse], [http://rationalwiki.com/wiki/User:Nx Nx]', 'url' => 'http://rationalwiki.com/', 'description' => 'Displays WIGO items sorted by votes, with custom settings.', 'version' => '3.5' ); $wgBestofIP = dirname( __FILE__ ); $wgExtensionMessagesFiles['bestof'] = "$wgBestofIP/bestof.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'][] = 'bestofinit'; } else { // Otherwise do things the old fashioned way $wgExtensionFunctions[] = 'bestofinit'; } $wgHooks['ArticleSaveComplete'][] = 'bestofharvest'; global $wgUseAjax; if ($wgUseAjax) { $wgAjaxExportList[] = "bestofget"; } function bestofinit() { global $wgParser; wfLoadExtensionMessages('bestof'); $wgParser->setHook('bestof','bestofrender'); return true; } function image(&$input,$pollid) { $input = preg_replace('/\[[^\]]*conservapedia\.com[^\]]*\]/i', "$0<sup>[[:Image:{$pollid}_x.png|img]]</sup>",$input); $x = 0; do { $input = preg_replace('/(<sup>\[\[:Image:' . $pollid . '_)x(\.png\|img\]\]<\/sup>)/', "$1 {$x}$2", $input,1,$count); ++$x; } while ($count); } function imagecp(&$output, $parser) { $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) { $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; } function bestofharvest( &$article, &$user, $text, $summary, &$minoredit, $watchthis, $sectionanchor, &$flags ) { Sanitizer::removeHTMLcomments($text); $matchnum = preg_match_all('/<vote(cp|)[^>]*poll=([^ >]*|"[^"]*")[^>]*>(.*?)<\/vote(?:cp|)>/',$text,$matches,PREG_SET_ORDER); $dbw = wfGetDB(DB_MASTER); foreach ($matches as $match) { $hasimg = ( (strpos($match[0],'img="on"') !== false) || (strpos($match[0],'img="expanded"') !== false) ); $hasimgcp = ( $match[1] == "cp" ); $voteid = $match[2]; $wtext = $match[3]; if ($hasimg) { image($wtext,$voteid); } $dbw->replace('wigotext','vote_id',array('vote_id' => $voteid, 'text' => $wtext, 'is_cp' => $hasimgcp),__METHOD__); } $dbw->commit(); return true; } function bestofrender($input, $args, $parser) { $parser->disableCache(); if ($args['dynamic']) { global $wgRequest; global $wgTitle; $cutoff = $wgRequest->getVal('bfcutoff', array_key_exists('cutoff',$args) ? $args['cutoff'] : null); $year = $wgRequest->getVal('bfyear', array_key_exists('year',$args) ? $args['yar'] : null); $month = $wgRequest->getVal('bfmonth', array_key_exists('month',$args) ? $args['month'] : null); $keyword = $wgRequest->getVal('bfsearch', array_key_exists('keyword',$args) ? $args['keyword'] : null); wfLoadExtensionMessages('bestof'); global $wgLang; $selected = $month === null ? 'all' : intval($month); $monthopts[] = Xml::option(wfMsg('monthsall'),'all',$selected === 'all'); for ($i = 1; $i < 13; ++$i) { $monthopts[] = Xml::option($wgLang->getMonthName($i),$i, $selected === $i); } $forminside = Xml::openElement('table',array('cellpadding' => 8)) . Xml::openElement('tr') . Xml::openElement('td') . Xml::label(wfMsg('bestof-cutoff'),'bfcutoff') . Xml::closeElement('td') . Xml::openElement('td') . Xml::label(wfMsg('bestof-month'),'bfmonth') . Xml::closeElement('td') . Xml::openElement('td') . Xml::label(wfMsg('bestof-filter'),'bfsearch') . Xml::closeElement('td') . Xml::closeElement('tr') . "\n" . Xml::openElement('tr') . Xml::openElement('td') . Xml::input( 'bfcutoff', 3, $cutoff, array('maxlength' => 3) ) . ' '. Xml::closeElement('td') . Xml::openElement('td') . Xml::input( 'bfyear', 4, $year, array('maxlength' => 4) ) . ' '. Xml::openElement('select',array('name' => 'bfmonth','class' => 'mw-month-selector')) . implode("\n",$monthopts) . Xml::closeElement('select') . Xml::closeElement('td') . Xml::openElement('td') . Xml::input( 'bfsearch', 25, $keyword ) . ' '. Xml::closeElement('td') . Xml::openElement('td') . Xml::submitButton(wfMsg('bestof-submit')) . Xml::closeElement('td') . Xml::closeElement('tr') . Xml::closeElement('table'); foreach ($wgRequest->getValues() as $key => $value) { if ($key != 'bfcutoff' && $key != 'bfyear' && $key != 'bfmonth' && $key != 'bfsearch') { $forminside .= "\n" . Xml::hidden($key,$value); } } $form = Xml::openElement('form', array( 'id' => 'bestofoption', 'action' => '', 'method' => $wgRequest->wasPosted() ? 'POST' : 'GET' ) ) . Xml::fieldset(wfMsg('bestof-legend'),$forminside) . Xml::closeElement('form'); $output = $form; } else { $cutoff = $args['cutoff']; $year = $args['year']; $month = $args['month']; $keyword = $args['keyword']; } $list = bestofget($args['poll'],$cutoff,$month === 'all' ? null : $month,$year,$keyword,$parser); $output .= $list; return $output; } function bestofget($pollid, $cutoff, $month, $year, $keyword, $parser) { $dbr = wfGetDB(DB_SLAVE); $conds = array("vote_id LIKE \"$pollid%\""); $options = array('GROUP BY' => 'vote_id','ORDER BY' => 'total DESC'); if ($cutoff != null) { $options['HAVING'] = "total >= {$cutoff}"; } if ($month != null && $year != null) { $month = str_pad($month,2,'0',STR_PAD_LEFT); $conds[] = "timestamp LIKE \"{$year}{$month}%\""; } elseif ($month == null && $year != null) { $conds[] = "timestamp LIKE \"{$year}%\""; } elseif ($month != null && $year == null) { $month = str_pad($month,2,'0',STR_PAD_LEFT); $conds[] = "timestamp LIKE \"____{$month}%\""; } if ($keyword != null) { $conds[] = "text LIKE \"%{$keyword}%\""; } $res = $dbr->select(array('wigovote','wigotext'), 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', 'ifnull(sum(vote),0) as total', 'vote_id', 'text','is_cp'), $conds, __METHOD__, $options, array('wigotext' => array('RIGHT JOIN','id=vote_id'))); $output="<table cellspacing=\"2\" cellpadding=\"2\" border=\"0\">"; wfLoadExtensionMessages('wigo3'); static $sep = null; if (is_null($sep)) $sep = wfMsg('bestof-tooltipseparator'); while ($row = $res->fetchRow()) { $plus = $row['plus']; $minus = $row['minus']; $zero = $row['zero']; $numvotes = $plus+$minus+$zero; $total = $plus - $minus; //wfMsgExt resets the parser state if the message contains a parser function, breaking for example references. recursiveTagParse doesn't. //$totalvotes = htmlspecialchars($row['vote_id']) . " • " . wfMsgExt('wigovotestotald',array('parsemag'),array($numvotes,$plus,$zero,$minus)); $totalvotes = htmlspecialchars($row['vote_id']) . $sep . $parser->recursiveTagParse(wfMsgNoTrans('wigovotestotald',array($numvotes,$plus,$zero,$minus))); $text = $parser->recursiveTagParse($row['text']); if ($row['is_cp']) { imagecp($text,$parser); } $output .= "<tr><td width=20px valign=top title=\"{$totalvotes}\">{$total}</td><td>{$text}</td></tr>"; } $output.="</table>"; $res->free(); return "$output"; }