r61048 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r61047‎ | r61048 | r61049 >
Date:10:20, 14 January 2010
Author:questpc
Status:deferred
Tags:
Comment:
Parser and Article cache control for better efficiency. Fixed htmlentities issue with non-utf locales under PHP 5.3.x.
Modified paths:
  • /trunk/extensions/QPoll/Excel/Console_Getopt.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/Excel_BIFFwriter.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/Excel_Format.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/Excel_Parser.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/Excel_Validator.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/Excel_Workbook.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/Excel_Worksheet.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/Excel_Writer.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/OLE.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/OLE_ChainedBlockStream.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/OLE_PPS.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/OLE_PPS_File.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/OLE_PPS_Root.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/PEAR.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/System.php (modified) (history)
  • /trunk/extensions/QPoll/Excel/readme.txt (modified) (history)
  • /trunk/extensions/QPoll/INSTALL (modified) (history)
  • /trunk/extensions/QPoll/README (modified) (history)
  • /trunk/extensions/QPoll/qp_i18n.php (modified) (history)
  • /trunk/extensions/QPoll/qp_question.php (modified) (history)
  • /trunk/extensions/QPoll/qp_results.php (modified) (history)
  • /trunk/extensions/QPoll/qp_user.js (modified) (history)
  • /trunk/extensions/QPoll/qp_user.php (modified) (history)

Diff [purge]

Index: trunk/extensions/QPoll/README
@@ -1,4 +1,4 @@
2 -MediaWiki extension QPoll, version 0.6.3
 2+MediaWiki extension QPoll, version 0.6.4
33
44 This extension allows to create polls embedded into the wikipages. Every poll
55 may contain a set of the questions of various types. The polls can be "chained"
Index: trunk/extensions/QPoll/qp_question.php
@@ -541,7 +541,7 @@
542542 $this->mType = 'mixedChoice';
543543 break;
544544 default :
545 - $this->setState( 'error', wfMsg( 'qp_error_invalid_question_type', htmlentities( $type ) ) );
 545+ $this->setState( 'error', wfMsg( 'qp_error_invalid_question_type', qp_Setup::entities( $type ) ) );
546546 }
547547 }
548548
@@ -810,7 +810,7 @@
811811 $inp[ 'type' ] = $inputType;
812812 $inp[ 'name' ] = $name;
813813 if ( $inputType == 'text' ) {
814 - $inp[ 'value' ] = htmlspecialchars( $text_answer );
 814+ $inp[ 'value' ] = qp_Setup::specialchars( $text_answer );
815815 if ( $this->textInputStyle != '' ) {
816816 $inp[ 'style' ] = $this->textInputStyle;
817817 }
Index: trunk/extensions/QPoll/Excel/Excel_Format.php
@@ -32,7 +32,7 @@
3333 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3434 */
3535
36 -require_once( $qp_ExtDir . '/Excel/PEAR.php' );
 36+require_once( qp_Setup::$ExtDir . '/Excel/PEAR.php' );
3737
3838 /**
3939 * Class for generating Excel XF records (formats)
Index: trunk/extensions/QPoll/Excel/Excel_Parser.php
@@ -93,7 +93,7 @@
9494 define('SPREADSHEET_EXCEL_WRITER_NE', "<>");
9595
9696
97 -require_once( $qp_ExtDir . '/Excel/PEAR.php' );
 97+require_once( qp_Setup::$ExtDir . '/Excel/PEAR.php' );
9898
9999 /**
100100 * Class for parsing Excel formulas
Index: trunk/extensions/QPoll/Excel/Excel_Workbook.php
@@ -32,12 +32,12 @@
3333 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3434 */
3535
36 -require_once( $qp_ExtDir . '/Excel/Excel_Format.php' );
37 -require_once( $qp_ExtDir . '/Excel/Excel_BIFFwriter.php' );
38 -require_once( $qp_ExtDir . '/Excel/Excel_Worksheet.php' );
39 -require_once( $qp_ExtDir . '/Excel/Excel_Parser.php' );
40 -require_once( $qp_ExtDir . '/Excel/OLE_PPS_Root.php' );
41 -require_once( $qp_ExtDir . '/Excel/OLE_PPS_File.php' );
 36+require_once( qp_Setup::$ExtDir . '/Excel/Excel_Format.php' );
 37+require_once( qp_Setup::$ExtDir . '/Excel/Excel_BIFFwriter.php' );
 38+require_once( qp_Setup::$ExtDir . '/Excel/Excel_Worksheet.php' );
 39+require_once( qp_Setup::$ExtDir . '/Excel/Excel_Parser.php' );
 40+require_once( qp_Setup::$ExtDir . '/Excel/OLE_PPS_Root.php' );
 41+require_once( qp_Setup::$ExtDir . '/Excel/OLE_PPS_File.php' );
4242
4343 /**
4444 * Class for generating Excel Spreadsheets
@@ -375,7 +375,7 @@
376376 */
377377 function &addValidator()
378378 {
379 - include_once( $qp_ExtDir . '/Excel/Excel_Validator.php' );
 379+ include_once( qp_Setup::$ExtDir . '/Excel/Excel_Validator.php' );
380380 /* FIXME: check for successful inclusion*/
381381 $valid = new Spreadsheet_Excel_Writer_Validator($this->_parser);
382382 return $valid;
Index: trunk/extensions/QPoll/Excel/OLE.php
@@ -30,7 +30,7 @@
3131 define('OLE_LONG_INT_SIZE', 4);
3232 define('OLE_PPS_SIZE', 0x80);
3333
34 -require_once( $qp_ExtDir . '/Excel/PEAR.php' );
 34+require_once( qp_Setup::$ExtDir . '/Excel/PEAR.php' );
3535
3636 /**
3737 * Array for storing OLE instances that are accessed from
@@ -222,7 +222,7 @@
223223 */
224224 function getStream($blockIdOrPps)
225225 {
226 - require_once( $qp_ExtDir . '/Excel/OLE_ChainedBlockStream.php' );
 226+ require_once( qp_Setup::$ExtDir . '/Excel/OLE_ChainedBlockStream.php' );
227227 static $isRegistered = false;
228228 if (!$isRegistered) {
229229 stream_wrapper_register('ole-chainedblockstream',
Index: trunk/extensions/QPoll/Excel/OLE_ChainedBlockStream.php
@@ -22,8 +22,8 @@
2323 * @since File available since Release 0.6.0
2424 */
2525
26 -require_once( $qp_ExtDir . '/Excel/PEAR.php' );
27 -require_once( $qp_ExtDir . '/Excel/OLE.php' );
 26+require_once( qp_Setup::$ExtDir . '/Excel/PEAR.php' );
 27+require_once( qp_Setup::$ExtDir . '/Excel/OLE.php' );
2828
2929 /**
3030 * Stream wrapper for reading data stored in an OLE file. Implements methods
Index: trunk/extensions/QPoll/Excel/Excel_BIFFwriter.php
@@ -32,7 +32,7 @@
3333 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3434 */
3535
36 -require_once( $qp_ExtDir . '/Excel/PEAR.php' );
 36+require_once( qp_Setup::$ExtDir . '/Excel/PEAR.php' );
3737
3838 /**
3939 * Class for writing Excel BIFF records.
Index: trunk/extensions/QPoll/Excel/Console_Getopt.php
@@ -18,7 +18,7 @@
1919 //
2020 // $Id: Getopt.php,v 1.4 2007/06/12 14:58:56 cellog Exp $
2121
22 -require_once( $qp_ExtDir . '/Excel/PEAR.php' );
 22+require_once( qp_Setup::$ExtDir . '/Excel/PEAR.php' );
2323
2424 /**
2525 * Command-line options parsing class.
Index: trunk/extensions/QPoll/Excel/System.php
@@ -17,8 +17,8 @@
1818 /**
1919 * base class
2020 */
21 -require_once( $qp_ExtDir . '/Excel/PEAR.php' );
22 -require_once( $qp_ExtDir . '/Excel/Console_Getopt.php' );
 21+require_once( qp_Setup::$ExtDir . '/Excel/PEAR.php' );
 22+require_once( qp_Setup::$ExtDir . '/Excel/Console_Getopt.php' );
2323
2424 $GLOBALS['_System_temp_files'] = array();
2525
Index: trunk/extensions/QPoll/Excel/readme.txt
@@ -7,7 +7,7 @@
88 Spreadsheet_Excel_Writer-0.9.1.tgz
99
1010 Nested filename paths are replaced to longer filenames with underscores, because I find deep nesting unhandy.
11 -require_once() and include_once() calls are also corrected relative from $qp_ExtDir extension global variable.
 11+require_once() and include_once() calls are made relative from qp_Setup::$ExtDir extension's property.
1212
1313 Spreadsheet_Excel_Writer-0.9.1 has a bug related to UTF16-LE string cell data encoding.
1414 This bug can cause corruption of exported XLS files when non-ASCII set of codes
Index: trunk/extensions/QPoll/Excel/PEAR.php
@@ -763,7 +763,7 @@
764764 }
765765
766766 if (PEAR_ZE2) {
767 - include_once( $qp_ExtDir . '/Excel/PEAR5.php' );
 767+ include_once( qp_Setup::$ExtDir . '/Excel/PEAR5.php' );
768768 }
769769
770770 // {{{ _PEAR_call_destructors()
Index: trunk/extensions/QPoll/Excel/Excel_Worksheet.php
@@ -32,8 +32,8 @@
3333 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3434 */
3535
36 -require_once( $qp_ExtDir . '/Excel/Excel_Parser.php' );
37 -require_once( $qp_ExtDir . '/Excel/Excel_BIFFwriter.php' );
 36+require_once( qp_Setup::$ExtDir . '/Excel/Excel_Parser.php' );
 37+require_once( qp_Setup::$ExtDir . '/Excel/Excel_BIFFwriter.php' );
3838
3939 /**
4040 * Class for generating Excel Spreadsheets
Index: trunk/extensions/QPoll/Excel/Excel_Writer.php
@@ -31,8 +31,8 @@
3232 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3333 */
3434
35 -require_once( $qp_ExtDir . '/Excel/PEAR.php' );
36 -require_once( $qp_ExtDir . '/Excel/Excel_Workbook.php' );
 35+require_once( qp_Setup::$ExtDir . '/Excel/PEAR.php' );
 36+require_once( qp_Setup::$ExtDir . '/Excel/Excel_Workbook.php' );
3737
3838 /**
3939 * Class for writing Excel Spreadsheets. This class should change COMPLETELY.
Index: trunk/extensions/QPoll/Excel/OLE_PPS_File.php
@@ -20,8 +20,8 @@
2121 // $Id: File.php,v 1.12 2008/02/02 21:00:37 schmidt Exp $
2222
2323
24 -require_once( $qp_ExtDir . '/Excel/OLE_PPS.php' );
25 -require_once( $qp_ExtDir . '/Excel/System.php' );
 24+require_once( qp_Setup::$ExtDir . '/Excel/OLE_PPS.php' );
 25+require_once( qp_Setup::$ExtDir . '/Excel/System.php' );
2626
2727 /**
2828 * Class for creating File PPS's for OLE containers
Index: trunk/extensions/QPoll/Excel/OLE_PPS.php
@@ -20,8 +20,8 @@
2121 // $Id: PPS.php,v 1.7 2007/02/13 21:00:42 schmidt Exp $
2222
2323
24 -require_once( $qp_ExtDir . '/Excel/PEAR.php' );
25 -require_once( $qp_ExtDir . '/Excel/OLE.php' );
 24+require_once( qp_Setup::$ExtDir . '/Excel/PEAR.php' );
 25+require_once( qp_Setup::$ExtDir . '/Excel/OLE.php' );
2626
2727 /**
2828 * Class for creating PPS's for OLE containers
Index: trunk/extensions/QPoll/Excel/OLE_PPS_Root.php
@@ -20,8 +20,8 @@
2121 // $Id: Root.php,v 1.10 2008/02/02 21:00:37 schmidt Exp $
2222
2323
24 -require_once( $qp_ExtDir . '/Excel/OLE_PPS.php' );
25 -require_once( $qp_ExtDir . '/Excel/System.php' );
 24+require_once( qp_Setup::$ExtDir . '/Excel/OLE_PPS.php' );
 25+require_once( qp_Setup::$ExtDir . '/Excel/System.php' );
2626
2727 /**
2828 * Class for creating Root PPS's for OLE containers
Index: trunk/extensions/QPoll/Excel/Excel_Validator.php
@@ -22,7 +22,7 @@
2323 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2424 */
2525
26 -require_once( $qp_ExtDir . '/Excel/PEAR.php' );
 26+require_once( qp_Setup::$ExtDir . '/Excel/PEAR.php' );
2727
2828 // Possible operator types
2929
Index: trunk/extensions/QPoll/qp_user.php
@@ -28,7 +28,7 @@
2929 * * Add this line at the end of your LocalSettings.php file :
3030 * require_once "$IP/extensions/QPoll/qp_user.php";
3131 *
32 - * @version 0.6.3
 32+ * @version 0.6.4
3333 * @link http://www.mediawiki.org/wiki/Extension:QPoll
3434 * @author QuestPC <questpc@rambler.ru>
3535 */
@@ -37,8 +37,6 @@
3838 die( "This file is part of the QPoll extension. It is not a valid entry point.\n" );
3939 }
4040
41 -qp_CheckRequiredClassesAndMethods();
42 -
4341 define( 'QP_CSS_ERROR_COLOR1' , "LightYellow" );
4442 define( 'QP_CSS_ERROR_COLOR2', "#D700D7" );
4543 define( 'QP_CSS_ERROR_STYLE', 'background-color: ' . QP_CSS_ERROR_COLOR1 . ';' );
@@ -48,13 +46,15 @@
4947
5048 define( 'QP_MAX_TEXT_ANSWER_LENGTH', 1024 );
5149
 50+qp_Setup::init();
 51+
5252 /**
5353 * Extension's parameters.
5454 */
5555 $wgExtensionCredits['parserhook'][] = array(
5656 'path' => __FILE__,
5757 'name' => 'QPoll',
58 - 'version' => '0.6.3',
 58+ 'version' => '0.6.4',
5959 'author' => 'QuestPC',
6060 'url' => 'http://www.mediawiki.org/wiki/Extension:QPoll',
6161 'description' => 'Allows creation of polls',
@@ -63,131 +63,196 @@
6464 $wgExtensionCredits['specialpage'][] = array(
6565 'path' => __FILE__,
6666 'name' => 'QPoll results page',
67 - 'version' => '0.6.3',
 67+ 'version' => '0.6.4',
6868 'author' => 'QuestPC',
6969 'url' => 'http://www.mediawiki.org/wiki/Extension:QPoll',
7070 'description' => 'QPoll extension [[Special:PollResults]] page for viewing results of the polls',
7171 'descriptionmsg' => 'qp_desc-sp',
7272 );
7373
74 -/**
75 - * Add this extension to the mediawiki's extensions list.
76 - */
77 -$qp_ExtDir = str_replace( "\\", "/", dirname(__FILE__) ); // filesys path with windows path fix
78 -$dirs = explode( '/', $qp_ExtDir );
79 -$qp_top_dir = array_pop( $dirs );
80 -$qp_ScriptPath = $wgScriptPath . '/extensions' . ( ( $qp_top_dir == 'extensions' ) ? '' : '/' . $qp_top_dir ); // apache virtual path
 74+class qp_Setup {
8175
82 -$wgExtensionMessagesFiles['QPoll'] = $qp_ExtDir . '/qp_i18n.php';
83 -$wgAutoloadClasses['PollResults'] = $qp_ExtDir . '/qp_results.php';
84 -$wgAutoloadClasses['qp_Question'] = $qp_ExtDir . '/qp_question.php';
85 -$wgAutoloadClasses['qp_QuestionStats'] = $qp_ExtDir . '/qp_question.php';
86 -$wgAutoloadClasses['qp_PollStore'] = $qp_ExtDir . '/qp_pollstore.php';
87 -$wgAutoloadClasses['qp_QuestionData'] = $qp_ExtDir . '/qp_pollstore.php';
88 -$wgAutoloadClasses['qp_QueryPage'] = $qp_ExtDir . '/qp_results.php';
89 -// TODO: Use the new technique for i18n of special page aliases
90 -$wgSpecialPages['PollResults'] = array('PollResults');
 76+ static $ExtDir; // filesys path with windows path fix
 77+ static $ScriptPath; // apache virtual path
 78+ static $messagesLoaded = false; // check whether the extension's localized messages are loaded
 79+ static $article; // Article instance we got from hook parameter
 80+ static $user; // User instance we got from hook parameter
9181
92 -if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) {
93 - $wgHooks['ParserFirstCallInit'][] = 'wfQPollExtension';
94 -} else {
95 - die( "QPoll extension requires ParserFirstCallInit hook.\nPlease upgrade your MediaWiki installation first.\n" );
96 - $wgExtensionFunctions[] = 'wfQPollExtension';
97 -}
 82+ static function entities( &$s ) {
 83+ return htmlentities( $s, ENT_COMPAT, 'UTF-8' );
 84+ }
9885
99 -// TODO: Use the new technique for i18n of magic words
100 -$wgHooks['LanguageGetMagic'][] = 'qp_FunctionsHook::languageGetMagic';
101 -$wgHooks['LoadAllMessages'][] = 'qp_AbstractPoll::loadMessages';
 86+ static function specialchars( &$s ) {
 87+ return htmlspecialchars( $s, ENT_COMPAT, 'UTF-8' );
 88+ }
10289
103 -function qp_CheckRequiredClassesAndMethods() {
104 - $required_classes_and_methods = array(
105 - array( "Linker"=>"link" ),
106 - array( "OutputPage"=>"isPrintable" ),
107 - array( "Parser"=>"fetchTemplate" ),
108 - array( "Parser"=>"getTitle" ),
109 - array( "Parser"=>"setHook" ),
110 - array( "Parser"=>"recursiveTagParse" ),
111 - array( "Title"=>"getArticleID" ),
112 - array( "Title"=>"getPrefixedText" ),
113 - array( "Title"=>"makeTitle" ),
114 - array( "Title"=>"makeTitleSafe" ),
115 - array( "Title"=>"newFromID" )
116 - );
117 - foreach ( $required_classes_and_methods as &$check ) {
118 - list( $object, $method ) = each( $check );
119 - if ( !method_exists( $object, $method ) ) {
120 - die( "QPoll extension requires " . $object . "::" . $method . " to be available.<br />\n" .
121 - "Your version of MediaWiki is incompatible with this extension.\n" );
 90+ static function coreRequirements() {
 91+ $required_classes_and_methods = array(
 92+ array( 'Article'=>'doPurge' ),
 93+ array( 'Linker'=>'link' ),
 94+ array( 'OutputPage'=>'isPrintable' ),
 95+ array( 'Parser'=>'getTitle' ),
 96+ array( 'Parser'=>'setHook' ),
 97+ array( 'Parser'=>'recursiveTagParse' ),
 98+ array( 'ParserCache'=>'getKey' ),
 99+ array( 'ParserCache'=>'singleton' ),
 100+ array( 'Title'=>'getArticleID' ),
 101+ array( 'Title'=>'getPrefixedText' ),
 102+ array( 'Title'=>'makeTitle' ),
 103+ array( 'Title'=>'makeTitleSafe' ),
 104+ array( 'Title'=>'newFromID' )
 105+ );
 106+ foreach ( $required_classes_and_methods as &$check ) {
 107+ list( $object, $method ) = each( $check );
 108+ if ( !method_exists( $object, $method ) ) {
 109+ die( "QPoll extension requires " . $object . "::" . $method . " method to be available.<br />\n" .
 110+ "Your version of MediaWiki is incompatible with this extension.\n" );
 111+ }
122112 }
 113+ if ( !defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) {
 114+ die( "QPoll extension requires ParserFirstCallInit hook.\nPlease upgrade your MediaWiki installation first.\n" );
 115+ }
123116 }
124 -}
125117
126 -/**
127 - * Register the extension with the WikiText parser.
128 - */
129 -function wfQPollExtension() {
130 - global $qp_ScriptPath;
131 - global $wgParser;
132 - global $wgExtensionCredits;
133 - global $wgQPollFunctionsHook;
134 - global $wgContLang;
135 - global $wgJsMimeType, $wgOut;
136 - global $qp_enable_showresults;
137 - # setup proper integer global showresults level
138 - if ( isset( $qp_enable_showresults ) ) {
139 - if ( !is_int( $qp_enable_showresults ) ) {
140 - # convert from older v0.5 boolean value
141 - $qp_enable_showresults = (int) (boolean) $qp_enable_showresults;
 118+ /**
 119+ * Add this extension to the mediawiki's extensions list.
 120+ */
 121+ static function init() {
 122+ global $wgScriptPath;
 123+ global $wgAutoloadClasses;
 124+ global $wgExtensionMessagesFiles;
 125+ global $wgSpecialPages;
 126+ global $wgHooks;
 127+ self::coreRequirements();
 128+ self::$ExtDir = str_replace( "\\", "/", dirname(__FILE__) );
 129+ $dirs = explode( '/', self::$ExtDir );
 130+ $top_dir = array_pop( $dirs );
 131+ self::$ScriptPath = $wgScriptPath . '/extensions' . ( ( $top_dir == 'extensions' ) ? '' : '/' . $top_dir );
 132+ $wgExtensionMessagesFiles['QPoll'] = self::$ExtDir . '/qp_i18n.php';
 133+ $wgAutoloadClasses['PollResults'] = self::$ExtDir . '/qp_results.php';
 134+ $wgAutoloadClasses['qp_Question'] = self::$ExtDir . '/qp_question.php';
 135+ $wgAutoloadClasses['qp_QuestionStats'] = self::$ExtDir . '/qp_question.php';
 136+ $wgAutoloadClasses['qp_PollStore'] = self::$ExtDir . '/qp_pollstore.php';
 137+ $wgAutoloadClasses['qp_QuestionData'] = self::$ExtDir . '/qp_pollstore.php';
 138+ $wgAutoloadClasses['qp_QueryPage'] = self::$ExtDir . '/qp_results.php';
 139+ // TODO: Use the new technique for i18n of special page aliases
 140+ $wgSpecialPages['PollResults'] = array('PollResults');
 141+ // TODO: Use the new technique for i18n of magic words
 142+ $wgHooks['LanguageGetMagic'][] = 'qp_Setup::languageGetMagic';
 143+ $wgHooks['MediaWikiPerformAction'][] = 'qp_Setup::mediaWikiPerformAction';
 144+ $wgHooks['ParserFirstCallInit'][] = 'qp_Setup::parserFirstCallInit';
 145+ $wgHooks['LoadAllMessages'][] = 'qp_Setup::loadMessages';
 146+ }
 147+
 148+ static function loadMessages() {
 149+ if ( !self::$messagesLoaded ) {
 150+ self::$messagesLoaded = true;
 151+ wfLoadExtensionMessages('QPoll');
142152 }
143 - if ( $qp_enable_showresults < 0 ) {
 153+ return true;
 154+ }
 155+
 156+ static function ParserFunctionsWords( $lang ) {
 157+ $words = array();
 158+ $words[ 'en' ] = array( 'qpuserchoice'=>array( 0, 'qpuserchoice' ) );
 159+ # English is used as a fallback, and the English synonyms are
 160+ # used if a translation has not been provided for a given word
 161+ return ( $lang == 'en' || !array_key_exists( $lang, $words ) )
 162+ ? $words[ 'en' ]
 163+ : array_merge( $words[ 'en' ], $words[ $lang ] );
 164+ }
 165+
 166+ static function languageGetMagic( &$magicWords, $langCode ) {
 167+ foreach( self::ParserFunctionsWords( $langCode ) as $word => $trans )
 168+ $magicWords [$word ] = $trans;
 169+ return true;
 170+ }
 171+
 172+ static function clearCache() {
 173+ $parserCache = ParserCache::singleton();
 174+ $key = $parserCache->getKey( self::$article, self::$user );
 175+ $parserCache->mMemc->delete( $key );
 176+ self::$article->doPurge();
 177+ }
 178+
 179+ static function mediaWikiPerformAction( $output, $article, $title, $user, $request, $wiki ) {
 180+ global $wgCookiePrefix;
 181+ global $qp_enable_showresults;
 182+ self::$article = $article;
 183+ self::$user = $user;
 184+ # setup proper integer global showresults level
 185+ if ( isset( $qp_enable_showresults ) ) {
 186+ if ( !is_int( $qp_enable_showresults ) ) {
 187+ # convert from older v0.5 boolean value
 188+ $qp_enable_showresults = (int) (boolean) $qp_enable_showresults;
 189+ }
 190+ if ( $qp_enable_showresults < 0 ) {
 191+ $qp_enable_showresults = 0;
 192+ }
 193+ if ( $qp_enable_showresults > 2 ) {
 194+ $qp_enable_showresults = 2;
 195+ }
 196+ } else {
144197 $qp_enable_showresults = 0;
145198 }
146 - if ( $qp_enable_showresults > 2 ) {
147 - $qp_enable_showresults = 2;
 199+ if ( isset( $_COOKIE[$wgCookiePrefix.'QPoll'] ) ) {
 200+ $request->response()->setCookie( 'QPoll', '', time() - 86400 ); // clear cookie
 201+ self::clearCache();
 202+ } elseif ( $request->getVal('pollId') !== null ) {
 203+ self::clearCache();
148204 }
149 - } else {
150 - $qp_enable_showresults = 0;
 205+ return true;
151206 }
152 - # Ouput the style and the script to the header once for all.
153 - $head = '<style type="text/css">' . "\n";
154 - $head .= '.qpoll .fatalerror { border: 1px solid gray; padding: 4px; ' . QP_CSS_ERROR_STYLE . ' }' . "\n";
155 - $head .= '</style>' . "\n";
156 - $head .= '<script type="' . $wgJsMimeType . '" src="' . $qp_ScriptPath . '/qp_user.js"></script>' . "\n";
157 - $wgOut->addScript( $head );
158 - $wgOut->addExtensionStyle( $qp_ScriptPath . '/qp_user.css' );
159 - if ( $wgContLang->isRTL() ) {
160 - $wgOut->addExtensionStyle( $qp_ScriptPath . '/qp_user_rtl.css' );
 207+
 208+ /**
 209+ * Register the extension with the WikiText parser.
 210+ */
 211+ static function parserFirstCallInit() {
 212+ global $wgParser;
 213+ global $wgExtensionCredits;
 214+ global $wgQPollFunctionsHook;
 215+ global $wgContLang;
 216+ global $wgJsMimeType, $wgOut;
 217+ # Ouput the style and the script to the header once for all.
 218+ $head = '<style type="text/css">' . "\n";
 219+ $head .= '.qpoll .fatalerror { border: 1px solid gray; padding: 4px; ' . QP_CSS_ERROR_STYLE . ' }' . "\n";
 220+ $head .= '</style>' . "\n";
 221+ $head .= '<script type="' . $wgJsMimeType . '" src="' . self::$ScriptPath . '/qp_user.js"></script>' . "\n";
 222+ $wgOut->addScript( $head );
 223+ $wgOut->addExtensionStyle( self::$ScriptPath . '/qp_user.css' );
 224+ if ( $wgContLang->isRTL() ) {
 225+ $wgOut->addExtensionStyle( self::$ScriptPath . '/qp_user_rtl.css' );
 226+ }
 227+ # setup tag hook
 228+ $wgParser->setHook("qpoll", "qp_Setup::renderPoll");
 229+ $wgQPollFunctionsHook = new qp_FunctionsHook();
 230+ # setup function hook
 231+ $wgParser->setFunctionHook( 'qpuserchoice', array( &$wgQPollFunctionsHook, 'qpuserchoice' ), SFH_OBJECT_ARGS );
 232+ return true;
161233 }
162 - # setup tag hook
163 - $wgParser->setHook("qpoll", "qp_RenderPoll");
164 - $wgQPollFunctionsHook = new qp_FunctionsHook();
165 - # setup function hook
166 - $wgParser->setFunctionHook( 'qpuserchoice', array( &$wgQPollFunctionsHook, 'qpuserchoice' ), SFH_OBJECT_ARGS );
167 - return true;
168 -}
169234
170 -/**
171 - * Call the poll parser on an input text.
172 - *
173 - * @param $input Text between <qpoll> and </qpoll> tags, in QPoll syntax.
174 - * @param $argv An array containing any arguments passed to the extension
175 - * @param &$parser The wikitext parser.
176 - *
177 - * @return An HTML poll.
178 - */
 235+ /**
 236+ * Call the poll parser on an input text.
 237+ *
 238+ * @param $input Text between <qpoll> and </qpoll> tags, in QPoll syntax.
 239+ * @param $argv An array containing any arguments passed to the extension
 240+ * @param &$parser The wikitext parser.
 241+ *
 242+ * @return An HTML poll.
 243+ */
179244
180 -/* @param $input Text between <qpoll> and </qpoll> tags, in QPoll syntax. */
181 -function qp_RenderPoll( $input, $argv, $parser ) {
182 - $parser->disableCache();
183 - if ( array_key_exists( 'address', $argv ) ) {
184 - $qpoll = new qp_PollStats( $argv, $parser );
185 - } else {
186 - $qpoll = new qp_Poll( $argv, $parser );
 245+ /* @param $input Text between <qpoll> and </qpoll> tags, in QPoll syntax. */
 246+ static function renderPoll( $input, $argv, $parser ) {
 247+ if ( array_key_exists( 'address', $argv ) ) {
 248+ $qpoll = new qp_PollStats( $argv, $parser );
 249+ } else {
 250+ $qpoll = new qp_Poll( $argv, $parser );
 251+ }
 252+ return $qpoll->parsePoll( $input );
187253 }
188 - return $qpoll->parsePoll( $input );
 254+
189255 }
190256
191 -
192257 /***
193258 * a poll stub which cannot process and render itself
194259 * to process and render itself, real Poll should extend this class to implement it's own:
@@ -204,8 +269,6 @@
205270
206271 var $parser; // parser for parsing tags content
207272 var $username;
208 - // params of tag
209 - var $wikiTag = 'qpoll';
210273
211274 # an ID of the poll on current page (used in declaration/voting mode)
212275 var $mPollId = null;
@@ -236,6 +299,7 @@
237300 global $qp_enable_showresults;
238301 $this->parser = &$parser;
239302 $this->mRequest = &$wgRequest;
 303+ $this->mResponse = $wgRequest->response();
240304 # Determine which messages will be used, according to the language.
241305 self::loadMessages();
242306 # load current skin
@@ -671,11 +735,9 @@
672736 $this->pollStore->setUserVote();
673737 }
674738 if ( $this->pollStore->voteDone ) {
675 - # purge itself on successful vote to update the statistics
676 -// $wgArticle->doPurge(); // TODO: does not work. why ?
677 - # redirect to itself, otherwise stats display will not be updated (showresults parameter)
678 - $this->mRequest->response()->header( 'HTTP/1.0 302 Moved Temporarily' );
679 - $this->mRequest->response()->header( 'Location: ' . $wgTitle->getFullURL() . self::getPollTitleFragment( $this->mPollId ) );
 739+ $this->mResponse->setcookie( 'QPoll', 'clearCache', time()+20 );
 740+ $this->mResponse->header( 'HTTP/1.0 302 Found' );
 741+ $this->mResponse->header( 'Location: ' . $wgTitle->getFullURL() . self::getPollTitleFragment( $this->mPollId ) );
680742 return true;
681743 }
682744 return $output;
@@ -891,7 +953,7 @@
892954 if ( $question->getState() != 'error' ) {
893955 # load previous user choice, when it's available and DB header is compatible with parsed header
894956 if ( $body === null || !method_exists( $question, $question->mType . 'ParseBody' ) ) {
895 - $question->setState( 'error', wfMsgHtml( 'qp_error_question_not_implemented', htmlentities( $question->mType ) ) );
 957+ $question->setState( 'error', wfMsgHtml( 'qp_error_question_not_implemented', qp_Setup::entities( $question->mType ) ) );
896958 } else {
897959 # parse the categories and spans (metacategories)
898960 $question->parseBodyHeader( $body );
@@ -1144,7 +1206,7 @@
11451207 var $error_message = 'no_such_poll';
11461208
11471209 function qpuserchoice( &$parser, $frame, $args ) {
1148 - qp_AbstractPoll::loadMessages();
 1210+ qp_Setup::loadMessages();
11491211 $this->frame = &$frame;
11501212 $this->args = &$args;
11511213 if ( isset( $args[ 0 ] ) ) {
@@ -1175,7 +1237,7 @@
11761238 }
11771239 }
11781240 }
1179 - return '<strong class="error">qpuserchoice: ' . wfMsgHTML( 'qp_func_' . $this->error_message, htmlspecialchars( $this->pollAddr ), htmlspecialchars( $this->question_id ), htmlspecialchars( $this->proposal_id ) ) . '</strong>';
 1241+ return '<strong class="error">qpuserchoice: ' . wfMsgHTML( 'qp_func_' . $this->error_message, qp_Setup::specialchars( $this->pollAddr ), qp_Setup::specialchars( $this->question_id ), qp_Setup::specialchars( $this->proposal_id ) ) . '</strong>';
11801242 }
11811243
11821244 function getQuestionData( $qid ) {
@@ -1226,24 +1288,8 @@
12271289 }
12281290 }
12291291 }
1230 - # do not need to use htmlentities because the result is a wikitext (will be escaped by parser)
 1292+ # do not need to use qp_Setup::entities because the result is a wikitext (will be escaped by parser)
12311293 return $result;
12321294 }
12331295
1234 - static function ParserFunctionsWords( $lang ) {
1235 - $words = array();
1236 - $words[ 'en' ] = array( 'qpuserchoice'=>array( 0, 'qpuserchoice' ) );
1237 - # English is used as a fallback, and the English synonyms are
1238 - # used if a translation has not been provided for a given word
1239 - return ( $lang == 'en' || !array_key_exists( $lang, $words ) )
1240 - ? $words[ 'en' ]
1241 - : array_merge( $words[ 'en' ], $words[ $lang ] );
1242 - }
1243 -
1244 - static function languageGetMagic( &$magicWords, $langCode ) {
1245 - foreach( qp_FunctionsHook::ParserFunctionsWords( $langCode ) as $word => $trans )
1246 - $magicWords [$word ] = $trans;
1247 - return true;
1248 - }
1249 -
12501296 }
Index: trunk/extensions/QPoll/qp_i18n.php
@@ -28,7 +28,7 @@
2929 * * Add this line at the end of your LocalSettings.php file :
3030 * require_once "$IP/extensions/QPoll/qp_user.php";
3131 *
32 - * @version 0.6.3
 32+ * @version 0.6.4
3333 * @link http://www.mediawiki.org/wiki/Extension:QPoll
3434 * @author QuestPC <questpc@rambler.ru>
3535 * @addtogroup Extensions
Index: trunk/extensions/QPoll/INSTALL
@@ -1,4 +1,4 @@
2 -MediaWiki extension QPoll, version 0.6.3
 2+MediaWiki extension QPoll, version 0.6.4
33
44 * download the latest available version and extract it to your wiki extension directory.
55 * add the following line to LocalSettings.php
Index: trunk/extensions/QPoll/qp_results.php
@@ -28,7 +28,7 @@
2929 * * Add this line at the end of your LocalSettings.php file :
3030 * require_once "$IP/extensions/QPoll/qp_user.php";
3131 *
32 - * @version 0.6.3
 32+ * @version 0.6.4
3333 * @link http://www.mediawiki.org/wiki/Extension:QPoll
3434 * @author QuestPC <questpc@rambler.ru>
3535 */
@@ -53,12 +53,11 @@
5454 // (should be equal to 'http://'.$_SERVER['SERVER_NAME'])
5555 global $wgScript; // "/subdirectory/of/wiki/index.php"
5656 global $wgUser;
57 - global $qp_ScriptPath;
5857 if ( !$wgUser->isAllowed( 'delete' ) ) {
5958 $wgOut->permissionRequired('delete');
6059 return;
6160 }
62 - $wgOut->addExtensionStyle( $qp_ScriptPath . '/qp_results.css' );
 61+ $wgOut->addExtensionStyle( qp_Setup::$ScriptPath . '/qp_results.css' );
6362 if ( self::$skin == null ) {
6463 self::$skin = $wgUser->getSkin();
6564 }
@@ -157,7 +156,6 @@
158157 # @param $db - MediaWiki database object
159158 # @return true if tables are found, string with error message otherwise
160159 private function checkTables( $db ) {
161 - global $qp_ExtDir;
162160 $sql_tables = array(
163161 "qp_poll_desc",
164162 "qp_question_desc",
@@ -178,7 +176,7 @@
179177 }
180178 if ( $tablesFound == 0 ) {
181179 # no tables were found, initialize the DB completely
182 - $r = $db->sourceFile( $qp_ExtDir . "/qpoll.src" );
 180+ $r = $db->sourceFile( qp_Setup::$ExtDir . "/qpoll.src" );
183181 if ( $r === true ) {
184182 $result = 'Tables were initialized.<br />Please <a href="#" onclick="window.location.reload()">reload</a> this page to view future page edits.';
185183 } else {
@@ -211,7 +209,7 @@
212210 $output .= wfMsg( 'qp_browse_to_user', $user_link ) . "<br />\n";
213211 $output .= wfMsg( 'qp_browse_to_poll', $poll_link ) . "<br />\n";
214212 foreach ( $pollStore->Questions as $qkey => &$qdata ) {
215 - $output .= "<br />\n<b>" . $qkey . ".</b> " . htmlentities( $qdata->CommonQuestion ) . "<br />\n";
 213+ $output .= "<br />\n<b>" . $qkey . ".</b> " . qp_Setup::entities( $qdata->CommonQuestion ) . "<br />\n";
216214 $output .= $this->displayUserQuestionVote( $qdata );
217215 }
218216 }
@@ -222,7 +220,7 @@
223221 }
224222
225223 private function categoryentities( $cat ) {
226 - $cat['name'] = htmlentities( $cat['name'] );
 224+ $cat['name'] = qp_Setup::entities( $cat['name'] );
227225 return $cat;
228226 }
229227
@@ -241,9 +239,9 @@
242240 $text_answer = $qdata->ProposalCategoryText[ $propkey ][ $id_key ];
243241 if ( $text_answer != '' ) {
244242 if ( strlen( $text_answer ) > 20 ) {
245 - $cell[ 0 ] = array( '__tag'=>'div', 'style'=>'width:10em; height:5em; overflow:auto', 0=>htmlentities( $text_answer ) );
 243+ $cell[ 0 ] = array( '__tag'=>'div', 'style'=>'width:10em; height:5em; overflow:auto', 0=>qp_Setup::entities( $text_answer ) );
246244 } else {
247 - $cell[ 0 ] = htmlentities( $text_answer );
 245+ $cell[ 0 ] = qp_Setup::entities( $text_answer );
248246 }
249247 } else {
250248 $cell[ 0 ] = '+';
@@ -260,7 +258,7 @@
261259 }
262260 $row[] = $cell;
263261 }
264 - $row[] = array( 0=>htmlentities( $proposal_text ), "style"=>"text-align:left;" );
 262+ $row[] = array( 0=>qp_Setup::entities( $proposal_text ), "style"=>"text-align:left;" );
265263 $output .= qp_Renderer::displayRow( $row );
266264 }
267265 $output .= "</table>\n" . "</div>\n";
@@ -281,7 +279,7 @@
282280 $output .= wfMsg( 'qp_browse_to_poll', $poll_link ) . "<br />\n";
283281 $output .= self::$skin->link( $this->getTitle(), wfMsg( 'qp_export_to_xls' ), array( "style"=>"font-weight:bold;" ), array( 'action'=>'stats_xls', 'id'=>$pid ) );
284282 foreach ( $pollStore->Questions as $qkey => &$qdata ) {
285 - $output .= "<br />\n<b>" . $qkey . ".</b> " . htmlentities( $qdata->CommonQuestion ) . "<br />\n";
 283+ $output .= "<br />\n<b>" . $qkey . ".</b> " . qp_Setup::entities( $qdata->CommonQuestion ) . "<br />\n";
286284 $output .= $this->displayQuestionStats( $pid, $qdata );
287285 }
288286 }
@@ -290,7 +288,6 @@
291289 }
292290
293291 private function votesToXLS( $pid ) {
294 - global $qp_ExtDir;
295292 $output = "";
296293 if ( $pid !== null ) {
297294 $pollStore = new qp_PollStore( array( 'from'=>'pid', 'pid'=> $pid ) );
@@ -300,7 +297,7 @@
301298 $pollStore->loadTotals();
302299 $pollStore->calculateStatistics();
303300 try {
304 - require_once( $qp_ExtDir . '/Excel/Excel_Writer.php' );
 301+ require_once( qp_Setup::$ExtDir . '/Excel/Excel_Writer.php' );
305302 $xls_fname = tempnam( "", ".xls" );
306303 $xls_workbook = new Spreadsheet_Excel_Writer_Workbook( $xls_fname );
307304 $xls_workbook->setVersion( 8 );
@@ -430,7 +427,7 @@
431428 # this proposal has no statistics (no votes)
432429 $row = array_fill( 0, count( $qdata->Categories ), '' );
433430 }
434 - $row[] = array( 0=>htmlentities( $proposal_text ), "style"=>"text-align:left;" );
 431+ $row[] = array( 0=>qp_Setup::entities( $proposal_text ), "style"=>"text-align:left;" );
435432 $output .= qp_Renderer::displayRow( $row );
436433 }
437434 $output .= "</table>\n" . "</div>\n";
@@ -647,8 +644,8 @@
648645 function formatResult( $skin, $result ) {
649646 global $wgLang, $wgContLang;
650647 $poll_title = Title::makeTitle( $result->ns, $result->title, qp_AbstractPoll::getPollTitleFragment( $result->poll_id, '' ) );
651 - $pagename = htmlspecialchars( $wgContLang->convert( $poll_title->getPrefixedText() ) );
652 - $pollname = htmlspecialchars( $result->poll_id );
 648+ $pagename = qp_Setup::specialchars( $wgContLang->convert( $poll_title->getPrefixedText() ) );
 649+ $pollname = qp_Setup::specialchars( $result->poll_id );
653650 $goto_link = self::$skin->link( $poll_title, wfMsg( 'qp_source_link' ) );
654651 $voice_link = self::$skin->link( $this->getTitle(), wfMsg( 'qp_voice_link' . ($this->inverse ? "_inv" : "") ), array(), array( "id"=>intval( $result->pid), "uid"=>$this->uid, "action"=>"uvote" ) );
655652 $link = wfMsg( 'qp_results_line_qupl', $pagename, $pollname, $voice_link );
@@ -688,8 +685,8 @@
689686 function formatResult( $skin, $result ) {
690687 global $wgLang, $wgContLang;
691688 $poll_title = Title::makeTitle( $result->ns, $result->title, qp_AbstractPoll::getPollTitleFragment( $result->poll_id, '' ) );
692 - $pagename = htmlspecialchars( $wgContLang->convert( $poll_title->getPrefixedText() ) );
693 - $pollname = htmlspecialchars( $result->poll_id );
 689+ $pagename = qp_Setup::specialchars( $wgContLang->convert( $poll_title->getPrefixedText() ) );
 690+ $pollname = qp_Setup::specialchars( $result->poll_id );
694691 $goto_link = self::$skin->link( $poll_title, wfMsg( 'qp_source_link' ) );
695692 $voices_link = self::$skin->link( $this->getTitle(), wfMsg( 'qp_stats_link' ), array(), array( "id"=>intval( $result->pid), "action"=>"stats" ) );
696693 $users_link = self::$skin->link( $this->getTitle(), wfMsg( 'qp_users_link' ), array(), array( "id"=>intval( $result->pid), "action"=>"pulist" ) );
@@ -729,8 +726,8 @@
730727 __METHOD__ );
731728 if ( $row = $db->fetchObject( $res ) ) {
732729 $poll_title = Title::makeTitle( intval( $row->ns ), $row->title, qp_AbstractPoll::getPollTitleFragment( $row->poll_id, '' ) );
733 - $pagename = htmlspecialchars( $wgContLang->convert( $poll_title->getPrefixedText() ) );
734 - $pollname = htmlspecialchars( $row->poll_id );
 730+ $pagename = qp_Setup::specialchars( $wgContLang->convert( $poll_title->getPrefixedText() ) );
 731+ $pollname = qp_Setup::specialchars( $row->poll_id );
735732 $goto_link = self::$skin->link( $poll_title, wfMsg( 'qp_source_link' ) );
736733 $spec = wfMsg( 'qp_header_line_qpul', wfMsg( $this->inverse ? 'qp_not_participated_link' : 'qp_users_link'), $pagename, $pollname );
737734 $head[] = PollResults::getPollsLink();
@@ -822,8 +819,8 @@
823820 if ( $pollStore->pid !== null ) {
824821 $pollStore->loadQuestions();
825822 $poll_title = Title::makeTitle( intval( $this->ns ), $this->title, qp_AbstractPoll::getPollTitleFragment( $this->poll_id, '' ) );
826 - $pagename = htmlspecialchars( $wgContLang->convert( $poll_title->getPrefixedText() ) );
827 - $pollname = htmlspecialchars( $this->poll_id );
 823+ $pagename = qp_Setup::specialchars( $wgContLang->convert( $poll_title->getPrefixedText() ) );
 824+ $pollname = qp_Setup::specialchars( $this->poll_id );
828825 $goto_link = self::$skin->link( $poll_title, wfMsg( 'qp_source_link' ) );
829826 $spec = wfMsg( 'qp_header_line_qpul', wfMsg( 'qp_users_link' ), $pagename, $pollname );
830827 $head[] = PollResults::getPollsLink();
@@ -839,7 +836,7 @@
840837 }
841838 }
842839 if ( $ques_found ) {
843 - $qpa = wfMsg( 'qp_header_line_qucl', $this->question_id, htmlentities( $ques->CommonQuestion ) );
 840+ $qpa = wfMsg( 'qp_header_line_qucl', $this->question_id, qp_Setup::entities( $ques->CommonQuestion ) );
844841 if ( array_key_exists( $this->cat_id, $ques->Categories ) ) {
845842 $categ = &$ques->Categories[ $this->cat_id ];
846843 $proptext = $ques->ProposalText[ $this->proposal_id ];
@@ -847,7 +844,11 @@
848845 if ( array_key_exists( 'spanId', $categ ) ) {
849846 $cat_name = wfMsg( 'qp_full_category_name', $cat_name, $ques->CategorySpans[ $categ['spanId'] ]['name'] );
850847 }
851 - $qpa = wfMsg( 'qp_header_line_qucl', $this->question_id, htmlentities( $ques->CommonQuestion ), htmlentities( $proptext ), htmlentities( $cat_name ) ) . '<br />';
 848+ $qpa = wfMsg( 'qp_header_line_qucl',
 849+ $this->question_id,
 850+ qp_Setup::entities( $ques->CommonQuestion ),
 851+ qp_Setup::entities( $proptext ),
 852+ qp_Setup::entities( $cat_name ) ) . '<br />';
852853 $head[] = array( '__tag'=>'div', 'class'=>'head', 'style'=>'padding-left:2em;', 0=>$qpa );
853854 $link = qp_Renderer::renderHTMLobject( $head );
854855 }
@@ -883,7 +884,7 @@
884885 $userTitle = Title::makeTitleSafe( NS_USER, $userName );
885886 $user_link = self::$skin->link( $userTitle, $userName );
886887 $voice_link = self::$skin->link( $this->getTitle(), wfMsg( 'qp_voice_link' . ($this->inverse ? "_inv" : "" ) ), array(), array( "id"=>intval( $this->pid), "uid"=>$uid, "action"=>"uvote" ) );
887 - $text_answer = ($result->text_answer == '') ? '' : '<i>' . htmlentities( $result->text_answer ) . '</i>';
 888+ $text_answer = ($result->text_answer == '') ? '' : '<i>' . qp_Setup::entities( $result->text_answer ) . '</i>';
888889 $link = wfMsg( 'qp_results_line_qucl', $user_link, $voice_link, $text_answer );
889890 }
890891 return $link;
Index: trunk/extensions/QPoll/qp_user.js
@@ -27,7 +27,7 @@
2828 * * Add this line at the end of your LocalSettings.php file :
2929 * require_once "$IP/extensions/QPoll/qp_user.php";
3030 *
31 - * @version 0.6.3
 31+ * @version 0.6.4
3232 * @link http://www.mediawiki.org/wiki/Extension:QPoll
3333 * @author QuestPC <questpc@rambler.ru>
3434 */

Status & tagging log