http://www.mediawiki.org/wiki/Special:Code/MediaWiki/92857
Revision: 92857 Author: questpc Date: 2011-07-22 10:53:38 +0000 (Fri, 22 Jul 2011) Log Message: ----------- Additional question randomizer fixes Modified Paths: -------------- trunk/extensions/QPoll/ctrl/qp_abstractpoll.php trunk/extensions/QPoll/ctrl/qp_poll.php trunk/extensions/QPoll/ctrl/qp_question.php trunk/extensions/QPoll/qp_eval.php trunk/extensions/QPoll/qp_interpret.php trunk/extensions/QPoll/qp_pollstore.php trunk/extensions/QPoll/qp_results.php trunk/extensions/QPoll/qp_user.php trunk/extensions/QPoll/view/qp_pollview.php Modified: trunk/extensions/QPoll/ctrl/qp_abstractpoll.php =================================================================== --- trunk/extensions/QPoll/ctrl/qp_abstractpoll.php 2011-07-22 10:48:16 UTC (rev 92856) +++ trunk/extensions/QPoll/ctrl/qp_abstractpoll.php 2011-07-22 10:53:38 UTC (rev 92857) @@ -86,8 +86,9 @@ qp_Setup::onLoadAllMessages(); # *** get visual style poll attributes *** $perRow = intval( array_key_exists( 'perrow', $argv ) ? $argv['perrow'] : 1 ); - if ( $perRow < 1 ) + if ( $perRow < 1 ) { $perRow = 1; + } $view->setController( $this, $perRow ); $this->view = $view; # reset the unique index number of the question in the current poll (used to instantiate the questions) @@ -101,12 +102,6 @@ } $this->view->showResults = self::parseShowResults( $argv['showresults'] ); } - # check whether current user has rights for showresults - $user = User::newFromName( $this->username ); - if ( !$user->isAllowed( 'showresults' ) ) { - $this->view->showResults = false; - } - unset( $user ); # every poll on the page should have unique poll id, to minimize the risk of collisions # it is required to be set manually via id="value" parameter Modified: trunk/extensions/QPoll/ctrl/qp_poll.php =================================================================== --- trunk/extensions/QPoll/ctrl/qp_poll.php 2011-07-22 10:48:16 UTC (rev 92856) +++ trunk/extensions/QPoll/ctrl/qp_poll.php 2011-07-22 10:53:38 UTC (rev 92857) @@ -228,7 +228,7 @@ $this->pollStore->setLastUser( $this->username ); $this->pollStore->setUserVote(); } - if ( $this->pollStore->interpAnswer->isError() ) { + if ( $this->pollStore->interpResult->isError() ) { # no redirect when there are script-generated proposal errors (quiz mode) return false; } Modified: trunk/extensions/QPoll/ctrl/qp_question.php =================================================================== --- trunk/extensions/QPoll/ctrl/qp_question.php 2011-07-22 10:48:16 UTC (rev 92856) +++ trunk/extensions/QPoll/ctrl/qp_question.php 2011-07-22 10:53:38 UTC (rev 92857) @@ -623,12 +623,12 @@ * false, when there are no script-generated error messages */ function getProposalsErrors() { - $interpAnswer = &$this->poll->pollStore->interpAnswer; - if ( !is_array( $interpAnswer->qpErrors ) || - !isset( $interpAnswer->qpErrors[$this->mQuestionId] ) ) { + $interpResult = &$this->poll->pollStore->interpResult; + if ( !is_array( $interpResult->qpErrors ) || + !isset( $interpResult->qpErrors[$this->mQuestionId] ) ) { return false; } - return $interpAnswer->qpErrors[$this->mQuestionId]; + return $interpResult->qpErrors[$this->mQuestionId]; } } /* end of qp_Question class */ Modified: trunk/extensions/QPoll/qp_eval.php =================================================================== --- trunk/extensions/QPoll/qp_eval.php 2011-07-22 10:48:16 UTC (rev 92856) +++ trunk/extensions/QPoll/qp_eval.php 2011-07-22 10:53:38 UTC (rev 92857) @@ -328,25 +328,33 @@ /** * Interpretates the answer with selected script * @param $interpretScript string source code of interpretation script - * @param $answers array of user selected categories for every proposal & question of the poll - * @param $interpAnswer instance of qp_InterpAnswer class - * @modifies $interpAnswer + * @param $injectVars array of PHP data to inject into interpretation script; + * key of element will become variable name + * in the interpretation script; + * value of element will become variable value + * in the interpretation script; + * @param $interpResult instance of qp_InterpResult class + * @modifies $interpResult * @return array script result to check, or - * qpInterpAnswer $interpAnswer (in case of error) + * qp_InterpResult $interpResult (in case of error) */ - function interpretAnswer( $interpretScript, $answers, qp_InterpAnswer $interpAnswer ) { + function interpretAnswer( $interpretScript, $injectVars, qp_InterpResult $interpResult ) { # template page evaluation if ( ( $check = self::selfCheck() ) !== true ) { # self-check error - return $interpAnswer->setError( wfMsg( 'qp_error_eval_self_check', $check ) ); + return $interpResult->setError( wfMsg( 'qp_error_eval_self_check', $check ) ); } $evalScript = ''; if ( ( $check = self::checkAndTransformCode( $interpretScript, $evalScript ) ) !== true ) { # possible malicious code - return $interpAnswer->setError( $check ); + return $interpResult->setError( $check ); } # inject poll answer into the interpretation script - $evalScript = "\$" . self::$pseudoNamespace . "a = unserialize( base64_decode( '" . base64_encode( serialize( $answers ) ) . "' ) ); /* */ " . $evalScript; + $evalInject = ''; + foreach ( $injectVars as $varname => $var ) { + $evalInject .= "\$" . self::$pseudoNamespace . "{$varname} = unserialize( base64_decode( '" . base64_encode( serialize( $var ) ) . "' ) ); "; + } + $evalScript = "{$evalInject}/* */ {$evalScript}"; $result = eval( $evalScript ); return $result; } Modified: trunk/extensions/QPoll/qp_interpret.php =================================================================== --- trunk/extensions/QPoll/qp_interpret.php 2011-07-22 10:48:16 UTC (rev 92856) +++ trunk/extensions/QPoll/qp_interpret.php 2011-07-22 10:53:38 UTC (rev 92857) @@ -43,16 +43,20 @@ * Glues the content of <qpinterpret> tags together, checks "lang" attribute * and calls appropriate interpretator to evaluate the user answer * - * @param $interpArticle _existing_ article with interpretation script enclosed in <qpinterp> tags - * @param $answers array of user selected categories for every proposal & question of the poll - * @return instance of qp_InterpAnswer class + * @param $interpArticle _existing_ Article with interpretation script enclosed in <qpinterp> tags + * @param $injectVars array with the following possible keys: + * key 'answer' array of user selected categories for + * every proposal & question of the poll; + * key 'usedQuestions' array of used questions for randomized polls + * or false, when the poll questions were not randomized + * @return instance of qp_InterpResult class (interpretation result) */ - static function getAnswer( $interpArticle, $answers ) { + static function getResult( $interpArticle, $injectVars ) { global $wgParser; $matches = array(); # extract <qpinterpret> tags from the article content $wgParser->extractTagsAndParams( array( qp_Setup::$interpTag ), $interpArticle->getRawText(), $matches ); - $interpAnswer = new qp_InterpAnswer(); + $interpResult = new qp_InterpResult(); # glue content of all <qpinterpret> tags at the page together $interpretScript = ''; $lang = ''; @@ -62,12 +66,12 @@ # however we do not want to limit interpretation language, # so the attribute is enforced to use if ( !isset( $attrs['lang'] ) ) { - return $interpAnswer->setError( wfMsg( 'qp_error_eval_missed_lang_attr' ) ); + return $interpResult->setError( wfMsg( 'qp_error_eval_missed_lang_attr' ) ); } if ( $lang == '' ) { $lang = $attrs['lang']; } elseif ( $attrs['lang'] != $lang ) { - return $interpAnswer->setError( wfMsg( 'qp_error_eval_mix_languages', $lang, $attrs['lang'] ) ); + return $interpResult->setError( wfMsg( 'qp_error_eval_mix_languages', $lang, $attrs['lang'] ) ); } if ( $tagName == qp_Setup::$interpTag ) { $interpretScript .= $content; @@ -75,43 +79,43 @@ } switch ( $lang ) { case 'php' : - $result = qp_Eval::interpretAnswer( $interpretScript, $answers, $interpAnswer ); - if ( $result instanceof qp_InterpAnswer ) { + $result = qp_Eval::interpretAnswer( $interpretScript, $injectVars, $interpResult ); + if ( $result instanceof qp_InterpResult ) { # evaluation error (environment error) , return it; - return $interpAnswer; + return $interpResult; } break; default : - return $interpAnswer->setError( wfMsg( 'qp_error_eval_unsupported_language', $lang ) ); + return $interpResult->setError( wfMsg( 'qp_error_eval_unsupported_language', $lang ) ); } /*** process the result ***/ if ( !is_array( $result ) ) { - return $interpAnswer->setError( wfMsg( 'qp_error_interpretation_no_return' ) ); + return $interpResult->setError( wfMsg( 'qp_error_interpretation_no_return' ) ); } - # initialize $interpAnswer->qpError[] member array + # initialize $interpResult->qpError[] member array foreach ( $result as $qidx => $question ) { if ( is_int( $qidx ) && is_array( $question ) ) { foreach ( $question as $pidx => $error ) { if ( is_int( $pidx ) ) { - $interpAnswer->setQPerror( $qidx, $pidx, $error ); + $interpResult->setQPerror( $qidx, $pidx, $error ); } } } } if ( isset( $result['error'] ) && trim( $result['error'] ) != '' ) { # script-generated error for the whole answer - return $interpAnswer->setError( (string) $result['error'] ); + return $interpResult->setError( (string) $result['error'] ); } # if there were question/proposal errors, return them; - if ( $interpAnswer->isError() ) { - return $interpAnswer->setDefaultErrorMessage(); + if ( $interpResult->isError() ) { + return $interpResult->setDefaultErrorMessage(); } if ( !isset( $result['short'] ) || !isset( $result['long'] ) ) { - return $interpAnswer->setError( wfMsg( 'qp_error_interpretation_no_return' ) ); + return $interpResult->setError( wfMsg( 'qp_error_interpretation_no_return' ) ); } - $interpAnswer->short = (string) $result['short']; - $interpAnswer->long = (string) $result['long']; - return $interpAnswer; + $interpResult->short = (string) $result['short']; + $interpResult->long = (string) $result['long']; + return $interpResult; } } /* end of qp_Interpret class */ Modified: trunk/extensions/QPoll/qp_pollstore.php =================================================================== --- trunk/extensions/QPoll/qp_pollstore.php 2011-07-22 10:48:16 UTC (rev 92856) +++ trunk/extensions/QPoll/qp_pollstore.php 2011-07-22 10:53:38 UTC (rev 92857) @@ -108,7 +108,10 @@ } /* end of qp_QuestionData class */ -class qp_InterpAnswer { +/** + * An interpretation result of user answer to the quiz + */ +class qp_InterpResult { # short answer. it is supposed to be sortable and accountable in statistics # blank value means short answer is unavailable var $short = ''; @@ -172,7 +175,7 @@ return $this->error != '' || is_array( $this->qpErrors ); } -} /* end of qp_InterpAnswer class */ +} /* end of qp_InterpResult class */ /** * poll storage and retrieval using DB @@ -205,7 +208,7 @@ var $interpNS = 0; var $interpDBkey = null; # interpretation of user answer - var $interpAnswer; + var $interpResult; # array of QuestionData instances (data from/to DB) var $Questions = null; @@ -238,7 +241,7 @@ if ( self::$db == null ) { self::$db = & wfGetDB( DB_MASTER ); } - $this->interpAnswer = new qp_InterpAnswer(); + $this->interpResult = new qp_InterpResult(); if ( is_array($argv) && array_key_exists( "from", $argv ) ) { $this->Questions = Array(); $this->mCompletedPostData = 'NA'; @@ -770,9 +773,9 @@ if ( self::$db->numRows( $res ) != 0 ) { $row = self::$db->fetchObject( $res ); $this->attempts = $row->attempts; - $this->interpAnswer = new qp_InterpAnswer(); - $this->interpAnswer->short = $row->short_interpretation; - $this->interpAnswer->long = $row->long_interpretation; + $this->interpResult = new qp_InterpResult(); + $this->interpResult->short = $row->short_interpretation; + $this->interpResult->long = $row->long_interpretation; } // todo: change to "insert ... on duplicate key update ..." when last_insert_id() bugs will be fixed } @@ -891,10 +894,10 @@ /** * Prepares an array of user answer to the current poll and interprets these - * Stores the result in $this->interpAnswer + * Stores the result in $this->interpResult */ private function interpretVote() { - $this->interpAnswer = new qp_InterpAnswer(); + $this->interpResult = new qp_InterpResult(); $interpTitle = $this->getInterpTitle(); if ( $interpTitle === null ) { return; @@ -903,8 +906,9 @@ if ( !$interpArticle->exists() ) { return; } + # prepare array of user answers that will be passed to the interpreter - $poll_answer = array( false ); + $poll_answer = array(); foreach ( $this->Questions as $qkey => &$qdata ) { $questions = array(); foreach( $qdata->ProposalText as $propkey => &$proposal_text ) { @@ -916,14 +920,13 @@ $proposals[$catkey] = $qdata->ProposalCategoryText[ $propkey ][ $id_key ]; } } - $questions[] = $proposals; + $questions[$propkey] = $proposals; } - $poll_answer[] = $questions; + $poll_answer[$qkey] = $questions; } - # only the questions are numbered from 1; - unset( $poll_answer[0] ); + # interpret the poll answer to get interpretation answer - $this->interpAnswer = qp_Interpret::getAnswer( $interpArticle, $poll_answer ); + $this->interpResult = qp_Interpret::getResult( $interpArticle, array( 'answer' => $poll_answer ) ); } // warning: requires qp_PollStorage::last_uid to be set @@ -951,8 +954,8 @@ $this->interpretVote(); # update interpretation result and number of syntax-valid resubmit attempts $qp_users_polls = self::$db->tableName( 'qp_users_polls' ); - $short = self::$db->addQuotes( $this->interpAnswer->short ); - $long = self::$db->addQuotes( $this->interpAnswer->long ); + $short = self::$db->addQuotes( $this->interpResult->short ); + $long = self::$db->addQuotes( $this->interpResult->long ); $this->attempts++; $stmt = "INSERT INTO {$qp_users_polls} (uid,pid,short_interpretation,long_interpretation)\n VALUES ( " . intval( $this->last_uid ) . ", " . intval( $this->pid ) . ", {$short}, {$long} )\n ON DUPLICATE KEY UPDATE attempts = " . intval( $this->attempts ) . ", short_interpretation = {$short} , long_interpretation = {$long}"; self::$db->query( $stmt, __METHOD__ ); Modified: trunk/extensions/QPoll/qp_results.php =================================================================== --- trunk/extensions/QPoll/qp_results.php 2011-07-22 10:48:16 UTC (rev 92856) +++ trunk/extensions/QPoll/qp_results.php 2011-07-22 10:53:38 UTC (rev 92857) @@ -321,13 +321,13 @@ /* # currently, error is not stored in DB, only the vote and long / short interpretations # todo: is it worth to store it? - if ( $pollStore->interpAnswer->error != '' ) { - return '<strong class="error">' . qp_Setup::specialchars( $pollStore->interpAnswer->error ) . '</strong>'; + if ( $pollStore->interpResult->error != '' ) { + return '<strong class="error">' . qp_Setup::specialchars( $pollStore->interpResult->error ) . '</strong>'; } */ $out .= '<div class="interp_answer">' . wfMsg( 'qp_results_interpretation_header' ) . - '<div class="interp_answer_body">' . nl2br( wfMsg( 'qp_results_short_interpretation', qp_Setup::specialChars( $pollStore->interpAnswer->short ) ) ) . '</div>' . - '<div class="interp_answer_body">' . nl2br( wfMsg( 'qp_results_long_interpretation', qp_Setup::specialChars( $pollStore->interpAnswer->long ) ) ) . '</div>' . + '<div class="interp_answer_body">' . nl2br( wfMsg( 'qp_results_short_interpretation', qp_Setup::specialChars( $pollStore->interpResult->short ) ) ) . '</div>' . + '<div class="interp_answer_body">' . nl2br( wfMsg( 'qp_results_long_interpretation', qp_Setup::specialChars( $pollStore->interpResult->long ) ) ) . '</div>' . '</div>'; return $out; } Modified: trunk/extensions/QPoll/qp_user.php =================================================================== --- trunk/extensions/QPoll/qp_user.php 2011-07-22 10:48:16 UTC (rev 92856) +++ trunk/extensions/QPoll/qp_user.php 2011-07-22 10:53:38 UTC (rev 92857) @@ -98,8 +98,8 @@ static $messagesLoaded = false; // check whether the extension's localized messages are loaded static $article; // Article instance we got from hook parameter static $user; // User instance we got from hook parameter - # extension's namespaces with their canonical names - static $namespaces = array( + # interpretation script namespaces with their canonical names + static $interpNamespaces = array( NS_QP_INTERPRETATION => 'Interpretation', NS_QP_INTERPRETATION_TALK => 'Interpretation_talk' ); @@ -225,7 +225,7 @@ 'view/qp_pollstatsview.php' => 'qp_PollStatsView', # storage - 'qp_pollstore.php' => array( 'qp_QuestionData', 'qp_InterpAnswer', 'qp_PollStore' ), + 'qp_pollstore.php' => array( 'qp_QuestionData', 'qp_InterpResult', 'qp_PollStore' ), # results page 'qp_results.php' => array( 'qp_SpecialPage', 'qp_QueryPage', 'PollResults' ), @@ -247,21 +247,26 @@ $wgHooks['CanonicalNamespaces'][] = new qp_Setup; - # define namespaces for the interpretation scripts and their talk pages - foreach ( self::$namespaces as $ns_idx => $canonical_name ) { - if ( isset( $wgExtraNamespaces[$ns_idx] ) ) { - die( "QPoll requires namespace index {$ns_idx} which is already used by another extension. Either disable another extension or change the namespace index." ); + if ( self::mediaWikiVersionCompare( '1.17' ) ) { + # define namespaces for the interpretation scripts and their talk pages + # used only for non-localized namespace names in MW < 1.17 + if ( !is_array( $wgExtraNamespaces ) ) { + $wgExtraNamespaces = array(); } - $wgNamespaceProtection[$ns_idx] = array( 'editinterpretation' ); - } - if ( self::mediaWikiVersionCompare( '1.17' ) ) { - foreach ( self::$namespaces as $ns_idx => $canonical_name ) { + foreach ( self::$interpNamespaces as $ns_idx => $canonical_name ) { + if ( isset( $wgExtraNamespaces[$ns_idx] ) ) { + die( "QPoll requires namespace index {$ns_idx} which is already used by another extension. Either disable another extension or change the namespace index." ); + } + } + foreach ( self::$interpNamespaces as $ns_idx => $canonical_name ) { $wgExtraNamespaces[$ns_idx] = $canonical_name; } } - + + foreach ( self::$interpNamespaces as $ns_idx => $canonical_name ) { + $wgNamespaceProtection[$ns_idx] = array( 'editinterpretation' ); + } # groups which has permission to access poll results by default - $wgGroupPermissions['user']['showresults'] = true; $wgGroupPermissions['sysop']['pollresults'] = true; $wgGroupPermissions['bureaucrat']['pollresults'] = true; $wgGroupPermissions['polladmin']['pollresults'] = true; @@ -510,7 +515,7 @@ public static function onCanonicalNamespaces( &$list ) { # do not use array_merge() as it will destroy negative indexes in $list # thus completely ruining the namespaces list - foreach ( self::$namespaces as $ns_idx => $canonical_name ) { + foreach ( self::$interpNamespaces as $ns_idx => $canonical_name ) { $list[$ns_idx] = $canonical_name; } return true; Modified: trunk/extensions/QPoll/view/qp_pollview.php =================================================================== --- trunk/extensions/QPoll/view/qp_pollview.php 2011-07-22 10:48:16 UTC (rev 92856) +++ trunk/extensions/QPoll/view/qp_pollview.php 2011-07-22 10:53:38 UTC (rev 92857) @@ -104,11 +104,11 @@ $qpoll_div = array( '__tag'=>'div', 'class'=>'qpoll' ); $qpoll_div[] = array( '__tag'=>'a', 'name'=>$this->ctrl->getPollTitleFragment( null, '' ), 0=>'' ); # output script-generated error, when available - if ( ( $scriptError = $this->ctrl->pollStore->interpAnswer->error ) != '' ) { + if ( ( $scriptError = $this->ctrl->pollStore->interpResult->error ) != '' ) { $qpoll_div[] = array( '__tag'=>'div', 'class'=>'interp_error', qp_Setup::specialchars( $scriptError ) ); } # output long result, when available - if ( ( $longAnswer = $this->ctrl->pollStore->interpAnswer->long ) != '' ) { + if ( ( $longAnswer = $this->ctrl->pollStore->interpResult->long ) != '' ) { $qpoll_div[] = array( '__tag'=>'div', 'class'=>'interp_answer', qp_Setup::specialchars( $longAnswer ) ); } # create voting form and fill it with messages and inputs _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs