Файловый менеджер - Редактировать - /var/www/html/mediawiki-1.43.1/extensions/Quiz/includes/Quiz.php
Ðазад
<?php namespace MediaWiki\Extension\Quiz; use MediaWiki\Extension\Quiz\Hooks\HookRunner; use MediaWiki\Html\TemplateParser; use MediaWiki\MediaWikiServices; use MediaWiki\Parser\Parser; use MediaWiki\Request\WebRequest; use MediaWiki\Title\Title; use StringUtils; /** * Processes quiz markup */ class Quiz { /** @var int */ private static $sQuizId = 0; /** @var Parser */ private $mParser; /** @var WebRequest */ private $mRequest; /** @var int */ private $mQuizId; /** @var int */ private $mQuestionId; /** @var int */ private $mShuffleDiv; /** @var bool */ private $mBeingCorrected; /** @var string */ private $mState; /** @var int */ private $numberQuestions; /** @var int */ private $mTotal; /** @var int */ private $mScore; /** @var int */ private $mAddedPoints; /** @var int */ private $mCutoffPoints; /** @var bool */ private $mIgnoringCoef; /** @var bool */ private $mDisplaySimple; /** @var bool */ private $shuffleAnswers; /** @var bool */ private $mShuffle; /** @var bool */ private $mCaseSensitive; /** @var string */ private $mIncludePattern; /** * @param array $argv * @param Parser $parser */ public function __construct( $argv, Parser $parser ) { global $wgRequest; $this->mParser = $parser; $this->mRequest = $wgRequest; // Allot a unique identifier to the quiz. $this->mQuizId = $this->getQuizId(); self::$sQuizId++; // Reset the unique identifier of the questions. $this->mQuestionId = 0; // Reset the counter of div "shuffle" or "noshuffle" inside the quiz. $this->mShuffleDiv = 0; // Determine if this quiz is being corrected or not, according to the quizId $this->mBeingCorrected = ( $wgRequest->getVal( 'quizId' ) == strval( $this->mQuizId ) ); // Initialize various parameters used for the score calculation $this->mState = 'NA'; $this->numberQuestions = 0; $this->mTotal = $this->mScore = 0; $this->mAddedPoints = 1; $this->mCutoffPoints = 0; $this->mIgnoringCoef = false; $this->mDisplaySimple = ( array_key_exists( 'display', $argv ) && $argv['display'] == 'simple' ); $this->shuffleAnswers = ( array_key_exists( 'shuffleanswers', $argv ) && $argv['shuffleanswers'] == 'true' ); if ( $this->mBeingCorrected ) { $lAddedPoints = str_replace( ',', '.', $this->mRequest->getVal( 'addedPoints', '' ) ); if ( is_numeric( $lAddedPoints ) ) { $this->mAddedPoints = (int)$lAddedPoints; } $lCutoffPoints = str_replace( ',', '.', $this->mRequest->getVal( 'cutoffPoints', '' ) ); if ( is_numeric( $lCutoffPoints ) ) { $this->mCutoffPoints = (int)$lCutoffPoints; } if ( $this->mRequest->getVal( 'ignoringCoef' ) == 'on' ) { $this->mIgnoringCoef = true; } } if ( array_key_exists( 'points', $argv ) && ( !$this->mBeingCorrected || $this->mDisplaySimple ) && preg_match( '`([\d\.]*)/?([\d\.]*)(!)?`', str_replace( ',', '.', $argv['points'] ), $matches ) ) { if ( is_numeric( $matches[1] ) ) { $this->mAddedPoints = (int)$matches[1]; } if ( is_numeric( $matches[2] ) ) { $this->mCutoffPoints = (int)$matches[2]; } if ( array_key_exists( 3, $matches ) ) { $this->mIgnoringCoef = true; } } $this->mShuffle = !( array_key_exists( 'shuffle', $argv ) && $argv['shuffle'] == 'none' ); $this->mCaseSensitive = !( array_key_exists( 'case', $argv ) && $argv['case'] == '(i)' ); // Patterns used in several places $this->mIncludePattern = '`^\{\{:?(.*)\}\}[ \t]*`m'; } public static function resetQuizID() { self::$sQuizId = 0; } /** * @return int Quiz Id */ public function getQuizId() { return self::$sQuizId; } /** * Get HTML from template using TemplateParser * * @param TemplateParser $templateParser * @return string */ public function getSettingsTable( $templateParser ) { $checked = $this->mIgnoringCoef ? 'checked="checked"' : ''; $settingsTable = $templateParser->processTemplate( 'Setting', [ 'isSettingFirstRow' => ( !$this->mDisplaySimple || $this->mBeingCorrected || $this->mState === 'error' ), 'isSettingOtherRow' => ( !$this->mDisplaySimple || $this->mBeingCorrected ), 'notSimple' => !$this->mDisplaySimple, /** @phan-suppress-next-line PhanPluginDuplicateExpressionBinaryOp FIXME */ 'corrected' => ( $this->mBeingCorrected && $this->mBeingCorrected ), 'shuffle' => $this->mShuffle, 'shuffleOrError' => ( $this->mShuffle && $this->numberQuestions > 1 ) || $this->mState === 'error', 'error' => $this->mState === 'error', 'wfMessage' => [ 'quiz_added' => wfMessage( 'quiz_addedPoints', $this->mAddedPoints )->text(), 'quiz_cutoff' => wfMessage( 'quiz_cutoffPoints', $this->mCutoffPoints )->text(), 'quiz_ignoreCoef' => wfMessage( 'quiz_ignoreCoef' )->text(), 'quiz_legend_correct' => wfMessage( 'quiz_legend_correct' )->text(), 'quiz_legend_incorrect' => wfMessage( 'quiz_legend_incorrect' )->text(), 'quiz_legend_unanswered' => wfMessage( 'quiz_legend_unanswered' )->text(), 'quiz_legend_error' => wfMessage( 'quiz_legend_error' )->text(), 'quiz_shuffle' => wfMessage( 'quiz_shuffle' )->text() ], 'mAddedPoints' => $this->mAddedPoints, 'mCutoffPoints' => $this->mCutoffPoints, 'checked' => $checked, 'shuffleDisplay' => $this->numberQuestions > 1 ] ); return $settingsTable; } /** * Convert the input text to an HTML output. * * @param string $input text between <quiz> and </quiz> tags, in quiz syntax. * @return string */ public function parseQuiz( $input ) { // Ouput the style and the script to the header once for all. if ( $this->mQuizId == 0 ) { $this->mParser->getOutput()->addModules( [ 'ext.quiz' ] ); $this->mParser->getOutput()->addModuleStyles( [ 'ext.quiz.styles' ] ); } // Process the input $input = $this->parseQuestions( $this->parseIncludes( $input ) ); // Generates the output. $templateParser = new TemplateParser( __DIR__ . '/../templates' ); // Determine the content of the settings table. $settingsTable = $this->getSettingsTable( $templateParser ); $quiz_score = wfMessage( 'quiz_score' )->rawParams( '<span class="score">' . $this->mScore . '</span>', '<span class="total">' . $this->mTotal . '</span>' )->escaped(); return $templateParser->processTemplate( 'Quiz', [ 'quiz' => [ 'id' => $this->mQuizId, 'beingCorrected' => $this->mBeingCorrected, 'questions' => $input ], 'settingsTable' => $settingsTable, 'wfMessage' => [ 'quiz_correction' => wfMessage( 'quiz_correction' )->escaped(), 'quiz_reset' => wfMessage( 'quiz_reset' )->escaped(), 'quiz_score' => $quiz_score ] ] ); } /** * Replace inclusions from other quizzes. * * @param string $input text between <quiz> and </quiz> tags, in quiz syntax. * @return string */ private function parseIncludes( $input ) { return preg_replace_callback( $this->mIncludePattern, [ $this, 'parseInclude' ], $input ); } /** * Include text between <quiz> and <quiz> from another page to this quiz. * * @param array $matches elements matching $includePattern * $matches[1] is the page title. * @return mixed|string */ private function parseInclude( $matches ) { $title = Title::makeTitleSafe( NS_MAIN, $matches[1] ); if ( $title === null ) { // Not a valid title for this include; replace w/ empty string. return ''; } $text = $this->mParser->fetchTemplateAndTitle( $title )[0]; $output = ''; if ( preg_match( '`<quiz[^>]*>(.*?)</quiz>`sU', $text, $unparsedQuiz ) ) { // Remove inclusions from included quiz. $output = preg_replace( $this->mIncludePattern, '', StringUtils::escapeRegexReplacement( $unparsedQuiz[1] ) ); $output .= "\n"; } return $output; } /** * Replace questions from quiz syntax to HTML. * * @param string $input a question in quiz syntax. * @return string */ private function parseQuestions( $input ) { $splitPattern = '`(^|\n[ \t]*)\n\{`'; $unparsedQuestions = preg_split( $splitPattern, $input, -1, PREG_SPLIT_NO_EMPTY ); $output = ''; $questionPattern = '`(.*?[^|\}])\}[ \t]*(\n(.*)|$)`s'; $this->numberQuestions = count( $unparsedQuestions ); $numDisplay = $this->numberQuestions > 1; foreach ( $unparsedQuestions as $unparsedQuestion ) { // If this "unparsedQuestion" is not a full question, // we put the text into a buffer to add it at the beginning of the next question. if ( !empty( $buffer ) ) { $unparsedQuestion = $buffer . "\n\n" . '{' . $unparsedQuestion; } if ( preg_match( $questionPattern, $unparsedQuestion, $matches ) ) { $buffer = ''; $output .= $this->parseQuestion( $matches, $numDisplay ); } else { $buffer = $unparsedQuestion; } } // Close unclosed "shuffle" or "noshuffle" tags. while ( $this->mShuffleDiv > 0 ) { $output .= '</div>'; $this->mShuffleDiv--; } return $output; } /** * Convert a question from quiz syntax to HTML * * @param array $matches elements matching $questionPattern * $matches[1] is the question header. * $matches[3] is the question object. * @param bool $numDisplay specifies whether to display question number. * @return string */ public function parseQuestion( $matches, $numDisplay ) { $question = new Question( $this->mBeingCorrected, $this->mCaseSensitive, $this->mQuestionId, $this->shuffleAnswers, $this->mParser ); ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) ) ->onQuizQuestionCreated( $this, $question ); // gets the question text $questionText = $question->parseHeader( $matches[1] ); /* What is this block of code? The only place X !X and /X are spoken about is here https://en.wikiversity.org/wiki/Help:Quiz "A few exotic features are not yet covered, such as shuffle control using {X} {!X} {/X} tags." These were added in commit fb53a3b0 back in 2007, without any explanation and/or documentation. The commit message is actually unrelated. */ if ( !array_key_exists( 3, $matches ) || trim( $matches[3] ) == '' ) { switch ( $matches[1] ) { case 'X': $this->mShuffleDiv++; return '<div class="shuffle">' . "\n"; case '!X': $this->mShuffleDiv++; return '<div class="noshuffle">' . "\n"; case '/X': // Prevent closing of other tags. if ( $this->mShuffleDiv == 0 ) { return ''; } else { $this->mShuffleDiv--; return '</div>' . "\n"; } default: return '<div class="quizText">' . $questionText . '<br /></div>' . "\n"; } } $templateParser = new TemplateParser( __DIR__ . '/../templates' ); $this->mQuestionId++; // This will generate the answers HTML code $answers = call_user_func( // Calling singleChoiceParseObject, multipleChoiceParseObject and textFieldParseObject [ $question, $question->mType . 'ParseObject' ], $matches[3] ); // Set default table title and style $tableTitle = ""; $lState = $question->getState(); if ( $lState != '' ) { // if the question is of type=simple if ( $this->mIgnoringCoef ) { $question->mCoef = 1; } switch ( $lState ) { case 'correct': $this->mTotal += $this->mAddedPoints * $question->mCoef; $this->mScore += $this->mAddedPoints * $question->mCoef; $tableTitle = wfMessage( 'quiz_points', wfMessage( 'quiz_legend_correct' )->text(), $this->mAddedPoints * $question->mCoef )->escaped(); break; case 'incorrect': $this->mTotal += $this->mAddedPoints * $question->mCoef; $this->mScore -= $this->mCutoffPoints * $question->mCoef; $tableTitle = wfMessage( 'quiz_points', wfMessage( 'quiz_legend_incorrect' )->text(), -$this->mCutoffPoints * $question->mCoef )->escaped(); break; case 'NA': $this->mTotal += $this->mAddedPoints * $question->mCoef; $tableTitle = wfMessage( 'quiz_points', wfMessage( 'quiz_legend_unanswered' )->text(), 0 )->escaped(); break; case 'error': $this->mState = 'error'; break; } } $stateObject = [ 'state' => $lState, 'tableTitle' => $tableTitle ]; return $templateParser->processTemplate( 'Question', [ 'question' => [ 'id' => $this->mQuestionId, 'numdis' => $numDisplay, 'text' => $questionText, 'answers' => $answers ], 'state' => $stateObject ] ); } }
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка