Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/questiondefaults.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ question:
penalty: '0.1'
hidden: '0'
idnumber: ''
stackversion: '2025102200'
stackversion: ''
questionvariables: 'ta1:1;'
specificfeedback: '<p>[[feedback:prt1]]</p>'
specificfeedbackformat: html
Expand Down
93 changes: 70 additions & 23 deletions api/util/StackQuestionLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,15 @@ public static function loadxml($xml, $includetests = false) {
$question->questionnoteformat =
isset($xmldata->question->questionnote['format']) ? (string) $xmldata->question->questionnote['format'] :
self::get_default('question', 'questionnoteformat', 'html');
$question->specificfeedback =
isset($xmldata->question->specificfeedback->text) ?
(string) $xmldata->question->specificfeedback->text :
self::get_default('question', 'specificfeedback', '[[feedback:prt1]]');
if (isset($xmldata->question->specificfeedback->text)) {
$question->specificfeedback = (string) $xmldata->question->specificfeedback->text;
} else {
if (preg_match("/\[\[input:" . self::get_default('input', 'name', 'ans1') . "\]\]/", $question->questiontext)) {
$question->specificfeedback = self::get_default('question', 'specificfeedback', '[[feedback:prt1]]');
} else {
$question->specificfeedback = '';
}
}
$question->specificfeedbackformat =
isset($xmldata->question->specificfeedback['format']) ?
(string) $xmldata->question->specificfeedback['format'] :
Expand Down Expand Up @@ -295,11 +300,17 @@ public static function loadxml($xml, $includetests = false) {
$inputmap[(string) $input->name] = $input;
}

if (empty($inputmap) && $question->defaultmark) {
$defaultinput = new \SimpleXMLElement('<input></input>');
$defaultinput->addChild('name', self::get_default('input', 'name', 'ans1'));
$defaultinput->addChild('tans', self::get_default('input', 'tans', 'ta1'));
$inputmap[self::get_default('input', 'name', 'ans1')] = $defaultinput;
if (empty($inputmap)) {
$inputname = self::get_default('input', 'name', 'ans1');
if (preg_match("/\[\[input:{$inputname}\]\]/", $question->questiontext)) {
$defaultinput = new \SimpleXMLElement('<input></input>');
$defaultinput->addChild('name', $inputname);
$defaultinput->addChild('tans', self::get_default('input', 'tans', 'ta1'));
$inputmap[$inputname] = $defaultinput;
} else {
// We've not got any inputs. Set default mark to 0.
$question->defaultmark = 0;
}
}

$requiredparams = \stack_input_factory::get_parameters_used();
Expand Down Expand Up @@ -372,16 +383,19 @@ public static function loadxml($xml, $includetests = false) {
$prtmap[(string) $prt->name] = $prt;
}

if (empty($prtmap) && $question->defaultmark) {
$defaultprt = new \SimpleXMLElement('<prt></prt>');
$defaultprt->addChild('name', self::get_default('prt', 'name', 'prt1'));
$defaultnode = $defaultprt->addChild('node');
$defaultnode->addChild('name', self::get_default('node', 'name', '0'));
$defaultnode->addChild('sans', self::get_default('node', 'sans', 'ans1'));
$defaultnode->addChild('tans', self::get_default('node', 'tans', 'ta1'));
$defaultnode->addChild('trueanswernote', self::get_default('node', 'trueanswernote', 'prt1-1-T'));
$defaultnode->addChild('falseanswernote', self::get_default('node', 'falseanswernote', 'prt1-1-F'));
$prtmap[self::get_default('prt', 'name', 'prt1')] = $defaultprt;
if (empty($prtmap)) {
$prtname = self::get_default('prt', 'name', 'prt1');
if (preg_match("/\[\[feedback:{$prtname}\]\]/", $question->questiontext . $question->specificfeedback)) {
$defaultprt = new \SimpleXMLElement('<prt></prt>');
$defaultprt->addChild('name', $prtname);
$defaultnode = $defaultprt->addChild('node');
$defaultnode->addChild('name', self::get_default('node', 'name', '0'));
$defaultnode->addChild('sans', self::get_default('node', 'sans', 'ans1'));
$defaultnode->addChild('tans', self::get_default('node', 'tans', 'ta1'));
$defaultnode->addChild('trueanswernote', self::get_default('node', 'trueanswernote', 'prt1-1-T'));
$defaultnode->addChild('falseanswernote', self::get_default('node', 'falseanswernote', 'prt1-1-F'));
$prtmap[$prtname] = $defaultprt;
}
}

foreach ($prtmap as $prtdata) {
Expand Down Expand Up @@ -749,14 +763,37 @@ public static function detect_differences($xml) {
}
$plaindata = self::xml_to_array($xmldata);
$diff = self::obj_diff(self::$defaults['question'], $plaindata['question']);

$isquestiontext = isset($plaindata['question']['questiontext']);
$isdefaultinput = preg_match(
"/\[\[input:" . self::get_default('input', 'name', 'ans1') . "\]\]/",
self::get_default('question', 'questiontext', '<p>Default question</p><p>[[input:ans1]] [[validation:ans1]]</p>')
);
$isrequesteddefaultinput = isset($plaindata['question']['questiontext']) && preg_match(
"/\[\[input:" . self::get_default('input', 'name', 'ans1') . "\]\]/",
$plaindata['question']['questiontext']
);
$isfeedback = isset($plaindata['question']['specificfeedback']);
$isdefaultprt = preg_match(
"/\[\[feedback:" . self::get_default('prt', 'name', 'prt1') . "\]\]/",
self::get_default('question', 'specificfeedback', '[[feedback:prt1]]')
);
$isrequesteddefaultprt = isset($plaindata['question']['questiontext']) &&
isset($plaindata['question']['specificfeedback']) &&
preg_match(
"/\[\[feedback:{" . self::get_default('prt', 'name', 'prt1') . "}\]\]/",
$plaindata['question']['questiontext'] . $plaindata['question']['specificfeedback']
);
if (!empty($plaindata['question']['input'])) {
$diffinputs = [];
foreach ($plaindata['question']['input'] as $input) {
$diffinput = self::obj_diff(self::$defaults['input'], $input);
$diffinputs[] = $diffinput;
}
$diff['input'] = $diffinputs;
} else if (!isset($plaindata['question']['defaultgrade']) || $plaindata['question']['defaultgrade']) {
// We need to create an input if questiontext contains [[input:ansnamedefault]] or
// questiontext doesn't exist and default contains [[input:ansnamedefault]].
} else if ((!$isquestiontext && $isdefaultinput) || $isrequesteddefaultinput) {
$diff['input'] = [['name' => self::get_default('input', 'name', 'ans1'),
'type' => self::get_default('input', 'type', 'algebraic'),
'tans' => self::get_default('input', 'tans', 'ta1'),
Expand All @@ -767,6 +804,11 @@ public static function detect_differences($xml) {
'showvalidation' => self::get_default('input', 'showvalidation', '1')]];
} else {
$diff['input'] = [];
if (self::get_default('question', 'defaultgrade', 1) !== 0) {
$diff['defaultgrade'] = '0';
} else {
unset($diff['defaultgrade']);
}
}
if (!empty($plaindata['question']['prt'])) {
$diffprts = [];
Expand Down Expand Up @@ -805,12 +847,17 @@ public static function detect_differences($xml) {
$diffprts[] = $diffprt;
}
$diff['prt'] = $diffprts;
} else if (!isset($plaindata['question']['defaultgrade']) || $plaindata['question']['defaultgrade']) {
// We need to create a PRT if questiontext contains [[input:ansnamedefault]] or
// questiontext doesn't exist and default contains [[input:ansnamedefault]].
} else if (
((!$isfeedback && $isdefaultprt) || $isrequesteddefaultprt) &&
((!$isquestiontext && $isdefaultinput) || $isrequesteddefaultinput)
) {
$prtnode = ['name' => self::get_default('node', 'name', '0'),
'answertest' => self::get_default('node', 'answertest', 'AlgEquiv'), ];
if (substr($prtnode['answertest'], 0, 2) !== 'AT') {
$prtnode['sans'] = self::get_default('node', 'sans', 'sans');
$prtnode['tans'] = self::get_default('node', 'tans', 'tans');
$prtnode['sans'] = self::get_default('node', 'sans', 'ans1');
$prtnode['tans'] = self::get_default('node', 'tans', 'ta1');
}
$prtnode['quiet'] = self::get_default('node', 'quiet', '0');
$diff['prt'] = [['name' => self::get_default('prt', 'name', 'prt1'),
Expand Down
21 changes: 17 additions & 4 deletions questiontype.php
Original file line number Diff line number Diff line change
Expand Up @@ -1808,7 +1808,17 @@ public function import_from_xml($xml, $fromform, qformat_xml $format, $notused =
if (isset($fromform->specificfeedbackformat)) {
$fformat = $fromform->specificfeedbackformat;
}
$fromform->specificfeedback = $this->import_xml_text($xml, 'specificfeedback', $format, $fformat, '[[feedback:prt1]]');

$fromform->specificfeedback = $this->import_xml_text($xml, 'specificfeedback', $format, $fformat, 'default_placeholder');
// We need a temporary placeholder to differentiate user-supplied blank feedback (which we leave) from absent
// feedback (which we may need to replace).
if ($fromform->specificfeedback['text'] === 'default_placeholder') {
if (preg_match("/\[\[input:ans1\]\]/", $fromform->questiontext)) {
$fromform->specificfeedback['text'] = '[[feedback:prt1]]';
} else {
$fromform->specificfeedback['text'] = '';
}
}
$fformat = FORMAT_HTML;
if (isset($fromform->questionnoteformat)) {
$fformat = $fromform->questionnoteformat;
Expand Down Expand Up @@ -1875,10 +1885,13 @@ public function import_from_xml($xml, $fromform, qformat_xml $format, $notused =
$this->import_xml_input($inputxml, $fromform, $format);
}
} else {
if ($fromform->defaultmark) {
if (preg_match("/\[\[input:ans1\]\]/", $fromform->questiontext)) {
$defaultinput = [];
$defaultinput['#'] = ['name' => [0 => ['#' => 'ans1']], 'tans' => [0 => ['#' => 'ta1']]];
$this->import_xml_input($defaultinput, $fromform, $format);
} else {
// We've not got any inputs. Set default mark to 0.
$fromform->defaultmark = 0;
}
}

Expand All @@ -1887,7 +1900,7 @@ public function import_from_xml($xml, $fromform, qformat_xml $format, $notused =
$structurerepairs .= $this->import_xml_prt($prtxml, $fromform, $format);
}
} else {
if ($fromform->defaultmark) {
if (preg_match("/\[\[feedback:prt1\]\]/", $fromform->questiontext . $fromform->specificfeedback['text'])) {
$defaultnode = [
'name' => [0 => ['#' => 0]],
'sans' => [0 => ['#' => 'ans1']],
Expand Down Expand Up @@ -2135,7 +2148,7 @@ protected function import_xml_qtest($xml, qformat_xml $format) {
if (isset($xml['#']['testinput'])) {
foreach ($xml['#']['testinput'] as $inputxml) {
$name = $format->getpath($inputxml, ['#', 'name', 0, '#'], 'ans1');
$value = $format->getpath($inputxml, ['#', 'value', 0, '#'], 'ta1');
$value = $format->getpath($inputxml, ['#', 'value', 0, '#'], '');
$inputs[$name] = $value;
}
}
Expand Down
Loading
Loading