/** * Add interpretation results to tagarray of poll view */ function showInterpResults( array &$tagarray, qp_InterpResult $ctrl, $showDescriptions = false ) { if ( $ctrl->hasVisibleProperties() ) { return; } $interp = array(); if ( $showDescriptions ) { $interp[] = array( '__tag' => 'div', wfMsg( 'qp_results_interpretation_header' ) ); } # currently, error is not stored in DB, only the vote and long / short interpretations # todo: is it worth to store it? if ( ( $scriptError = $ctrl->error ) != '' ) { $interp[] = array( '__tag' => 'div', 'class' => 'interp_error', qp_Setup::specialchars( $scriptError ) ); } # output long result, when permitted and available if ( $this->showInterpretation['long'] && ( $answer = $ctrl->long ) !== '' ) { if ( $showDescriptions ) { $interp[] = array( '__tag' => 'div', 'class' => 'interp_header', wfMsg( 'qp_results_long_interpretation' ) ); } $interp[] = array( '__tag' => 'div', 'class' => 'interp_answer_body', is_null( $this->pview ) ? nl2br( qp_Setup::specialchars( $answer ) ) : $this->pview->rtp( $answer ) ); } # output short result, when permitted and available if ( $this->showInterpretation['short'] && ( $answer = $ctrl->short ) !== '' ) { if ( $showDescriptions ) { $interp[] = array( '__tag' => 'div', 'class' => 'interp_header', wfMsg( 'qp_results_short_interpretation' ) ); } $interp[] = array( '__tag' => 'div', 'class' => 'interp_answer_body', nl2br( qp_Setup::specialchars( $answer ) ) ); } if ( $this->showInterpretation['structured'] && ( $answer = $ctrl->structured ) !== '' ) { if ( $showDescriptions ) { $interp[] = array( '__tag' => 'div', 'class' => 'interp_header', wfMsg( 'qp_results_structured_interpretation' ) ); } $strucTable = $ctrl->getStructuredAnswerTable(); $rows = array(); foreach ( $strucTable as &$line ) { if ( isset( $line['keys'] ) ) { # current node is associative array qp_Renderer::addRow( $rows, $line['keys'], array(), 'th' ); qp_Renderer::addRow( $rows, $line['vals'] ); } else { # current node is scalar value qp_Renderer::addRow( $rows, array( $line['vals'] ) ); } } $interp[] = array( '__tag' => 'table', 'class' => 'structured_answer', $rows ); unset( $strucTable ); } $tagarray[] = array( '__tag' => 'div', 'class' => 'interp_answer', $interp ); }
/** * Interpretates the answer with selected script * @param $interpretScript * string source code of interpretation script * @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 qp_InterpResult * @modifies $interpResult * @return mixed * array script result to check * qp_InterpResult $interpResult (in case of error) */ static function interpretAnswer( $interpretScript, array $injectVars, qp_InterpResult $interpResult ) { # template page evaluation if ( ( $check = self::selfCheck() ) !== true ) { # self-check error return $interpResult->setError( wfMsg( 'qp_error_eval_self_check', $check ) ); } $evalScript = ''; if ( ( $check = self::checkAndTransformCode( $interpretScript, $evalScript ) ) !== true ) { # possible malicious code return $interpResult->setError( $check ); } # inject poll answer into the interpretation script $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; }
/** * 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 $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 getResult( Article $interpArticle, array $injectVars ) { global $wgParser, $wgContLang; $matches = array(); # extract <qpinterpret> tags from the article content $wgParser->extractTagsAndParams( array( qp_Setup::$interpTag ), $interpArticle->getRawText(), $matches ); $interpResult = new qp_InterpResult(); # glue content of all <qpinterpret> tags at the page together $interpretScript = ''; $lang = ''; foreach ( $matches as &$match ) { list( $tagName, $content, $attrs ) = $match; # basic checks for lang attribute (only lang="php" is implemented yet) # however we do not want to limit interpretation language, # so the attribute is enforced to use if ( !isset( $attrs['lang'] ) ) { return $interpResult->setError( wfMsg( 'qp_error_eval_missed_lang_attr' ) ); } if ( $lang == '' ) { $lang = $attrs['lang']; } elseif ( $attrs['lang'] != $lang ) { return $interpResult->setError( wfMsg( 'qp_error_eval_mix_languages', $lang, $attrs['lang'] ) ); } if ( $tagName == qp_Setup::$interpTag ) { $interpretScript .= $content; } } switch ( $lang ) { case 'php' : $result = qp_Eval::interpretAnswer( $interpretScript, $injectVars, $interpResult ); if ( $result instanceof qp_InterpResult ) { # evaluation error (environment error) , return it; return $interpResult; } break; default : return $interpResult->setError( wfMsg( 'qp_error_eval_unsupported_language', $lang ) ); } /*** process the result ***/ if ( !is_array( $result ) ) { return $interpResult->setError( wfMsg( 'qp_error_interpretation_no_return' ) ); } if ( isset( $result['options'] ) && is_array( $result['options'] ) && array_key_exists( 'store_erroneous', $result['options'] ) ) { $interpResult->storeErroneous = (boolean) $result['options']['store_erroneous']; } if ( isset( $result['error'] ) && is_array( $result['error'] ) ) { # initialize $interpResult->qpcErrors[] member array foreach ( $result['error'] as $qidx => $question ) { if ( is_array( $question ) ) { foreach ( $question as $pidx => $prop_error ) { # integer indicates proposal id; string - proposal name if ( is_array( $prop_error ) ) { # separate error messages list for proposal categories foreach ( $prop_error as $cidx => $cat_error ) { $interpResult->setQPCerror( $cat_error, $qidx, $pidx, $cidx ); } } else { # error message for the whole proposal line $interpResult->setQPCerror( $prop_error, $qidx, $pidx ); } } } } } if ( isset( $result['errmsg'] ) && trim( strval( $result['errmsg'] ) ) != '' ) { # script-generated error message for the whole answer return $interpResult->setError( (string) $result['errmsg'] ); } # if there were question/proposal errors, return them; if ( $interpResult->isError() ) { return $interpResult->setDefaultErrorMessage(); } $interpCount = 0; foreach ( qp_Setup::$show_interpretation as $interpType => $show ) { if ( isset( $result[$interpType] ) ) { $interpCount++; } } if ( $interpCount == 0 ) { return $interpResult->setError( wfMsg( 'qp_error_interpretation_no_return' ) ); } $interpResult->structured = isset( $result['structured'] ) ? serialize( $result['structured'] ) : ''; if ( strlen( $interpResult->structured ) > qp_Setup::$field_max_len['serialized_interpretation'] ) { # serialized structured interpretation is too long and # this type of interpretation cannot be truncated unset( $interpResult->structured ); return $interpResult->setError( wfMsg( 'qp_error_structured_interpretation_is_too_long' ) ); } $interpResult->short = isset( $result['short'] ) ? strval( $result['short'] ) : ''; $interpResult->long = isset( $result['long'] ) ? strval( $result['long'] ) : ''; if ( strlen( $interpResult->long ) > qp_Setup::$field_max_len['long_interpretation'] ) { $interpResult->long = $wgContLang->truncate( $interpResult->long, qp_Setup::$field_max_len['long_interpretation'] , '' ); } return $interpResult; }