diff --git a/backup/restorelib.php b/backup/restorelib.php
index 20e415b1b0d..9d561d9b74b 100644
--- a/backup/restorelib.php
+++ b/backup/restorelib.php
@@ -70,6 +70,8 @@
if (!defined('RESTORE_SILENTLY')) {
echo "
";
}
+
+ // Restore links in modules.
foreach ($restore->mods as $name => $info) {
//If the module is being restored
if (isset($info->restore) && $info->restore == 1) {
@@ -85,12 +87,22 @@
}
}
}
+
+ // TODO: process all html text also in blocks too
+
+ // Restore links in questions.
+ if (!defined('RESTORE_SILENTLY')) {
+ echo '- ' . get_string('from') . ' ' . get_string('questions', 'quiz');
+ }
+ $status = question_decode_content_links_caller($restore);
+ if (!defined('RESTORE_SILENTLY')) {
+ echo '
';
+ }
+
if (!defined('RESTORE_SILENTLY')) {
echo "
";
}
-
- // TODO: process all html text also in blocks too
-
+
return $status;
}
diff --git a/question/restorelib.php b/question/restorelib.php
index acc439f5780..aefa2cf3918 100644
--- a/question/restorelib.php
+++ b/question/restorelib.php
@@ -727,4 +727,105 @@
return $status;
}
+ /**
+ * Recode content links in question texts.
+ * @param object $restore the restore metadata object.
+ * @return boolean whether the operation succeeded.
+ */
+ function question_decode_content_links_caller($restore) {
+ global $CFG, $QTYPES;
+ $status = true;
+ $i = 1; //Counter to send some output to the browser to avoid timeouts
+
+ // Get a list of which question types have custom field that will need decoding.
+ $qtypeswithextrafields = array();
+ $qtypeswithhtmlanswers = array();
+ foreach ($QTYPES as $qtype => $qtypeclass) {
+ $qtypeswithextrafields[$qtype] = method_exists($qtypeclass, 'decode_content_links_caller');
+ $qtypeswithhtmlanswers[$qtype] = $qtypeclass->has_html_answers();
+ }
+ $extraprocessing = array();
+
+ // Decode links in questions.
+ if ($questions = get_records_sql('SELECT q.id, q.qtype, q.questiontext, q.generalfeedback
+ FROM ' . $CFG->prefix . 'question q,
+ ' . $CFG->prefix . 'question_categories qc
+ WHERE q.category = qc.id
+ AND qc.course = ' . $restore->course_id)) {
+
+ foreach ($questions as $question) {
+ $questiontext = restore_decode_content_links_worker($question->questiontext, $restore);
+ $generalfeedback = restore_decode_content_links_worker($question->generalfeedback, $restore);
+ if ($questiontext != $question->questiontext || $generalfeedback != $question->generalfeedback) {
+ $question->questiontext = addslashes($questiontext);
+ $question->generalfeedback = addslashes($generalfeedback);
+ if (!update_record('question', $question)) {
+ $status = false;
+ }
+ }
+
+ // Do some output.
+ if (++$i % 5 == 0 && !defined('RESTORE_SILENTLY')) {
+ echo ".";
+ if ($i % 100 == 0) {
+ echo "
";
+ }
+ backup_flush(300);
+ }
+
+ // Decode any questiontype specific fields.
+ if ($qtypeswithextrafields[$question->qtype]) {
+ if (!array_key_exists($question->qtype, $extraprocessing)) {
+ $extraprocessing[$question->qtype] = array();
+ }
+ $extraprocessing[$question->qtype][] = $question->id;
+ }
+ }
+ }
+
+ // Decode links in answers.
+ if ($answers = get_records_sql('SELECT qa.id, qa.answer, qa.feedback, q.qtype
+ FROM ' . $CFG->prefix . 'question_answers qa,
+ ' . $CFG->prefix . 'question q,
+ ' . $CFG->prefix . 'question_categories qc
+ WHERE qa.question = q.id
+ AND q.category = qc.id
+ AND qc.course = ' . $restore->course_id)) {
+
+ foreach ($answers as $answer) {
+ $feedback = restore_decode_content_links_worker($answer->feedback, $restore);
+ if ($qtypeswithhtmlanswers[$answer->qtype]) {
+ $answertext = restore_decode_content_links_worker($answer->answer, $restore);
+ } else {
+ $answertext = $answer->answer;
+ }
+ if ($feedback != $answer->feedback || $answertext != $answer->answer) {
+ unset($answer->qtype);
+ $answer->feedback = addslashes($feedback);
+ $answer->answer = addslashes($answertext);
+ if (!update_record('question_answers', $answer)) {
+ $status = false;
+ }
+ }
+
+ // Do some output.
+ if (++$i % 5 == 0 && !defined('RESTORE_SILENTLY')) {
+ echo ".";
+ if ($i % 100 == 0) {
+ echo "
";
+ }
+ backup_flush(300);
+ }
+ }
+ }
+
+ // Do extra work for certain question types.
+ foreach ($extraprocessing as $qtype => $questionids) {
+ if (!$QTYPES[$qtype]->decode_content_links_caller($questionids, $restore, $i)) {
+ $status = false;
+ }
+ }
+
+ return $status;
+ }
?>
diff --git a/question/type/match/questiontype.php b/question/type/match/questiontype.php
index 766aa200c29..046fd24ed43 100644
--- a/question/type/match/questiontype.php
+++ b/question/type/match/questiontype.php
@@ -589,6 +589,35 @@ class question_match_qtype extends default_questiontype {
return $answer_field;
}
+ /**
+ * Decode links in question type specific tables.
+ * @return bool success or failure.
+ */
+ function decode_content_links_caller($questionids, $restore, &$i) {
+ // Decode links in the question_match_sub table.
+ if ($subquestions = get_records_list('question_match_sub', 'question',
+ implode(',', $questionids), '', 'id, questiontext')) {
+
+ foreach ($subquestions as $subquestion) {
+ $questiontext = restore_decode_content_links_worker($subquestion->questiontext, $restore);
+ if ($questiontext != $subquestion->questiontext) {
+ $subquestion->questiontext = addslashes($questiontext);
+ if (!update_record('question_match_sub', $subquestion)) {
+ $status = false;
+ }
+ }
+
+ // Do some output.
+ if (++$i % 5 == 0 && !defined('RESTORE_SILENTLY')) {
+ echo ".";
+ if ($i % 100 == 0) {
+ echo "
";
+ }
+ backup_flush(300);
+ }
+ }
+ }
+ }
}
//// END OF CLASS ////
diff --git a/question/type/multichoice/questiontype.php b/question/type/multichoice/questiontype.php
index 241286727bd..0efca329ca1 100644
--- a/question/type/multichoice/questiontype.php
+++ b/question/type/multichoice/questiontype.php
@@ -17,6 +17,10 @@ class question_multichoice_qtype extends default_questiontype {
return 'multichoice';
}
+ function has_html_answers() {
+ return true;
+ }
+
function get_question_options(&$question) {
// Get additional information from database
// and attach it to the question object
@@ -543,6 +547,41 @@ class question_multichoice_qtype extends default_questiontype {
return implode(',', $order).':'.implode(',', $responses);
}
+ /**
+ * Decode links in question type specific tables.
+ * @return bool success or failure.
+ */
+ function decode_content_links_caller($questionids, $restore, &$i) {
+ // Decode links in the question_multichoice table.
+ if ($multichoices = get_records_list('question_multichoice', 'question',
+ implode(',', $questionids), '', 'id, correctfeedback, partiallycorrectfeedback, incorrectfeedback')) {
+
+ foreach ($multichoices as $multichoice) {
+ $correctfeedback = restore_decode_content_links_worker($multichoice->correctfeedback, $restore);
+ $partiallycorrectfeedback = restore_decode_content_links_worker($multichoice->partiallycorrectfeedback, $restore);
+ $incorrectfeedback = restore_decode_content_links_worker($multichoice->incorrectfeedback, $restore);
+ if ($correctfeedback != $multichoice->correctfeedback ||
+ $partiallycorrectfeedback != $multichoice->partiallycorrectfeedback ||
+ $incorrectfeedback != $multichoice->incorrectfeedback) {
+ $subquestion->correctfeedback = addslashes($correctfeedback);
+ $subquestion->partiallycorrectfeedback = addslashes($partiallycorrectfeedback);
+ $subquestion->incorrectfeedback = addslashes($incorrectfeedback);
+ if (!update_record('question_multichoice', $multichoice)) {
+ $status = false;
+ }
+ }
+
+ // Do some output.
+ if (++$i % 5 == 0 && !defined('RESTORE_SILENTLY')) {
+ echo ".";
+ if ($i % 100 == 0) {
+ echo "
";
+ }
+ backup_flush(300);
+ }
+ }
+ }
+ }
}
//// END OF CLASS ////
diff --git a/question/type/questiontype.php b/question/type/questiontype.php
index ad5f221977b..707e435ba0c 100644
--- a/question/type/questiontype.php
+++ b/question/type/questiontype.php
@@ -71,6 +71,14 @@ class default_questiontype {
return true;
}
+ /**
+ * @return whether the question_answers.answer field needs to have
+ * restore_decode_content_links_worker called on it.
+ */
+ function has_html_answers() {
+ return false;
+ }
+
/**
* Saves or updates a question after editing by a teacher
*