Merge branch 'MDL-39261-master' of git://github.com/peterRd/moodle

This commit is contained in:
Adrian Greeve 2019-04-12 10:52:16 +08:00
commit 7ff3919dc2
8 changed files with 166 additions and 21 deletions

View File

@ -197,6 +197,7 @@ class backup_lesson_activity_structure_step extends backup_activity_structure_st
$answer->annotate_files('mod_lesson', 'page_answers', 'id');
$answer->annotate_files('mod_lesson', 'page_responses', 'id');
$attempt->annotate_files('mod_lesson', 'essay_responses', 'id');
$attempt->annotate_files('mod_lesson', 'essay_answers', 'id');
// Prepare and return the structure we have just created for the lesson module.
return $this->prepare_activity_structure($lesson);

View File

@ -253,6 +253,7 @@ class restore_lesson_activity_structure_step extends restore_activity_structure_
$this->add_related_files('mod_lesson', 'page_answers', 'lesson_answer');
$this->add_related_files('mod_lesson', 'page_responses', 'lesson_answer');
$this->add_related_files('mod_lesson', 'essay_responses', 'lesson_attempt');
$this->add_related_files('mod_lesson', 'essay_answers', 'lesson_attempt');
// Remap all the restored prevpageid and nextpageid now that we have all the pages and their mappings
$rs = $DB->get_recordset('lesson_pages', array('lessonid' => $this->task->get_activityid()),

View File

@ -445,6 +445,7 @@ class provider implements
$fs = get_file_storage();
$fs->delete_area_files($context->id, 'mod_lesson', 'essay_responses');
$fs->delete_area_files($context->id, 'mod_lesson', 'essay_answers');
}
/**
@ -485,6 +486,7 @@ class provider implements
$cmid = $lessonidstocmids[$record->lessonid];
$context = context_module::instance($cmid);
$fs->delete_area_files($context->id, 'mod_lesson', 'essay_responses', $record->id);
$fs->delete_area_files($context->id, 'mod_lesson', 'essay_answers', $record->id);
}
$recordset->close();
@ -522,6 +524,7 @@ class provider implements
$recordset = $DB->get_recordset_select('lesson_attempts', $sql, $params, '', 'id, lessonid');
foreach ($recordset as $record) {
$fs->delete_area_files($context->id, 'mod_lesson', 'essay_responses', $record->id);
$fs->delete_area_files($context->id, 'mod_lesson', 'essay_answers', $record->id);
}
$recordset->close();
@ -616,7 +619,21 @@ class provider implements
if ($data->page_qtype == LESSON_PAGE_ESSAY) {
// Essay questions serialise data in the answer field.
$info = \lesson_page_type_essay::extract_useranswer($answer);
$answer = format_text($info->answer, $info->answerformat, $options);
$answerfilespath = [get_string('privacy:path:essayanswers', 'mod_lesson'), $data->attempt_id];
$answer = format_text(
writer::with_context($context)->rewrite_pluginfile_urls(
$answerfilespath,
'mod_lesson',
'essay_answers',
$data->attempt_id,
$info->answer
),
$info->answerformat,
$options
);
writer::with_context($context)->export_area_files($answerfilespath, 'mod_lesson',
'essay_answers', $data->page_id);
if ($info->response !== null) {
// We export the files in a subfolder to avoid conflicting files, and tell the user
// where those files were exported. That is because we are not using a subfolder for
@ -636,6 +653,7 @@ class provider implements
);
writer::with_context($context)->export_area_files($responsefilespath, 'mod_lesson',
'essay_responses', $data->page_id);
}
} else if ($data->page_qtype == LESSON_PAGE_MULTICHOICE && $data->page_qoption) {

View File

@ -247,7 +247,9 @@ switch ($mode) {
// Set rest of the message values
$currentpage = $lesson->load_page($attempt->pageid);
$a->question = format_text($currentpage->contents, $currentpage->contentsformat, $formattextdefoptions);
$a->response = format_text($essayinfo->answer, $essayinfo->answerformat,
$answer = file_rewrite_pluginfile_urls($essayinfo->answer, 'pluginfile.php', $context->id,
'mod_lesson', 'essay_answers', $attempt->id);
$a->response = format_text($answer, $essayinfo->answerformat,
array('context' => $context, 'para' => true));
$a->comment = $essayinfo->response;
$a->comment = file_rewrite_pluginfile_urls($a->comment, 'pluginfile.php', $context->id,
@ -454,6 +456,8 @@ switch ($mode) {
// Grading form
// Expects the following to be set: $attemptid, $answer, $user, $page, $attempt
$essayinfo = lesson_page_type_essay::extract_useranswer($attempt->useranswer);
$answer = file_rewrite_pluginfile_urls($essayinfo->answer, 'pluginfile.php', $context->id,
'mod_lesson', 'essay_answers', $attempt->id);
$currentpage = $lesson->load_page($attempt->pageid);
$mform = new essay_grading_form(null, array('scoreoptions'=>$scoreoptions, 'user'=>$user));
@ -462,7 +466,7 @@ switch ($mode) {
$data->attemptid = $attemptid;
$data->score = $essayinfo->score;
$data->question = format_text($currentpage->contents, $currentpage->contentsformat, $formattextdefoptions);
$data->studentanswer = format_text($essayinfo->answer, $essayinfo->answerformat,
$data->studentanswer = format_text($answer, $essayinfo->answerformat,
array('context' => $context, 'para' => true));
$data->response = $essayinfo->response;
$data->responseformat = $essayinfo->responseformat;

View File

@ -477,6 +477,7 @@ $string['privacy:metadata:overrides:password'] = 'The password to access the les
$string['privacy:metadata:overrides'] = 'A record of overrides per lesson';
$string['privacy:metadata:userpref:lessonview'] = 'The preferred display mode when editing lessons';
$string['privacy:path:essayresponses'] = 'Essay responses';
$string['privacy:path:essayanswers'] = 'Essay answers';
$string['privacy:path:pages'] = 'Pages';
$string['processerror'] = 'Error occurred during processing!';
$string['progressbar'] = 'Progress bar';

View File

@ -1088,6 +1088,7 @@ function lesson_reset_userdata($data) {
}
$context = context_module::instance($cm->id);
$fs->delete_area_files($context->id, 'mod_lesson', 'essay_responses');
$fs->delete_area_files($context->id, 'mod_lesson', 'essay_answers');
}
}
@ -1366,7 +1367,7 @@ function lesson_pluginfile($course, $cm, $context, $filearea, $args, $forcedownl
}
$fullpath = "/$context->id/mod_lesson/$filearea/$itemid/".implode('/', $args);
} else if ($filearea === 'essay_responses') {
} else if ($filearea === 'essay_responses' || $filearea === 'essay_answers') {
$itemid = (int)array_shift($args);
if (!$attempt = $DB->get_record('lesson_attempts', array('id' => $itemid))) {
return false;
@ -1408,6 +1409,7 @@ function lesson_get_file_areas() {
$areas['page_answers'] = get_string('pageanswers', 'mod_lesson');
$areas['page_responses'] = get_string('pageresponses', 'mod_lesson');
$areas['essay_responses'] = get_string('essayresponses', 'mod_lesson');
$areas['essay_answers'] = get_string('essayresponses', 'mod_lesson');
return $areas;
}

View File

@ -3926,6 +3926,7 @@ abstract class lesson_page extends lesson_base {
if ($attempts = $DB->get_records('lesson_attempts', array("pageid" => $this->properties->id))) {
foreach ($attempts as $attempt) {
$fs->delete_area_files($context->id, 'mod_lesson', 'essay_responses', $attempt->id);
$fs->delete_area_files($context->id, 'mod_lesson', 'essay_answers', $attempt->id);
}
}
@ -4117,6 +4118,14 @@ abstract class lesson_page extends lesson_base {
if (!$userisreviewing) {
if ($this->lesson->retake || (!$this->lesson->retake && $nretakes == 0)) {
$attempt->id = $DB->insert_record("lesson_attempts", $attempt);
list($updatedattempt, $updatedresult) = $this->on_after_write_attempt($attempt, $result);
if ($updatedattempt) {
$attempt = $updatedattempt;
$result = $updatedresult;
$DB->update_record("lesson_attempts", $attempt);
}
// Trigger an event: question answered.
$eventparams = array(
'context' => context_module::instance($PAGE->cm->id),
@ -4194,6 +4203,7 @@ abstract class lesson_page extends lesson_base {
$options->para = true;
$options->overflowdiv = true;
$options->context = $context;
$options->attemptid = isset($attempt) ? $attempt->id : null;
$result->feedback .= $OUTPUT->box(format_text($this->get_contents(), $this->properties->contentsformat, $options),
'generalbox boxaligncenter p-y-1');
@ -4247,21 +4257,27 @@ abstract class lesson_page extends lesson_base {
}
/**
* Formats the answer
* Formats the answer. Override for custom formatting.
*
* @param string $answer
* @param context $context
* @param int $answerformat
* @return string Returns formatted string
*/
private function format_answer($answer, $context, $answerformat, $options = []) {
public function format_answer($answer, $context, $answerformat, $options = []) {
if (empty($options)) {
$options = [
'context' => $context,
'para' => true
];
if (is_object($options)) {
$options = (array) $options;
}
if (empty($options['context'])) {
$options['context'] = $context;
}
if (empty($options['para'])) {
$options['para'] = true;
}
return format_text($answer, $answerformat, $options);
}
@ -4645,11 +4661,27 @@ abstract class lesson_page extends lesson_base {
$result->studentanswerformat = FORMAT_MOODLE;
$result->userresponse = null;
$result->feedback = '';
// Store data that was POSTd by a form. This is currently used to perform any logic after the 1st write to the db
// of the attempt.
$result->postdata = false;
$result->nodefaultresponse = false; // Flag for redirecting when default feedback is turned off
$result->inmediatejump = false; // Flag to detect when we should do a jump from the page without further processing.
return $result;
}
/**
* Do any post persistence processing logic of an attempt. E.g. in cases where we need update file urls in an editor
* and we need to have the id of the stored attempt. Should be overridden in each individual child
* pagetype on a as required basis
*
* @param object $attempt The attempt corresponding to the db record
* @param object $result The result from the 'check_answer' method
* @return array False if nothing to be modified, updated $attempt and $result if update required.
*/
public function on_after_write_attempt($attempt, $result) {
return [false, false];
}
/**
* True if the page uses a custom option
*

View File

@ -67,7 +67,20 @@ class lesson_page_type_essay extends lesson_page {
public function display($renderer, $attempt) {
global $PAGE, $CFG, $USER;
$mform = new lesson_display_answer_form_essay($CFG->wwwroot.'/mod/lesson/continue.php', array('contents'=>$this->get_contents(), 'lessonid'=>$this->lesson->id));
$context = context_module::instance($PAGE->cm->id);
$options = array(
'contents' => $this->get_contents(),
'lessonid' => $this->lesson->id,
'attemptid' => $attempt ? $attempt->id : null,
'editoroptions' => array(
'maxbytes' => $PAGE->course->maxbytes,
'context' => $context,
'noclean' => true,
'maxfiles' => EDITOR_UNLIMITED_FILES,
'enable_filemanagement' => false
)
);
$mform = new lesson_display_answer_form_essay($CFG->wwwroot.'/mod/lesson/continue.php', $options);
$data = new stdClass;
$data->id = $PAGE->cm->id;
@ -76,6 +89,9 @@ class lesson_page_type_essay extends lesson_page {
$essayinfo = self::extract_useranswer($attempt->useranswer);
$data->answer = $essayinfo->answer;
}
$data = file_prepare_standard_editor($data, 'answer', $options['editoroptions'],
$context, 'mod_lesson', 'essay_answers');
$mform->set_data($data);
// Trigger an event question viewed.
@ -110,12 +126,74 @@ class lesson_page_type_essay extends lesson_page {
$this->answers = $answers;
return $answers;
}
/**
* Overridden function
*
* @param object $attempt
* @param object $result
* @return array
*/
public function on_after_write_attempt($attempt, $result) {
global $PAGE;
if ($formdata = $result->postdata) {
// Save any linked files if we are using an editor.
$editoroptions = array(
'maxbytes' => $PAGE->course->maxbytes,
'context' => context_module::instance($PAGE->cm->id),
'noclean' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES,
'enable_filemanagement' => false,
);
$formdata = file_postupdate_standard_editor($formdata, 'answer', $editoroptions,
$editoroptions['context'], 'mod_lesson', 'essay_answers', $attempt->id);
// Update the student response to have the modified link.
$useranswer = unserialize($attempt->useranswer);
$useranswer->answer = $formdata->answer;
$useranswer->answerformat = $formdata->answerformat;
$attempt->useranswer = serialize($useranswer);
$result->studentanswer = $formdata->answer;
$result->studentanswerformat = $formdata->answerformat;
return [$attempt, $result];
}
return parent::on_after_write_attempt($attempt, $result);
}
/**
* Custom formats the answer to display
*
* @param string $answer
* @param context $context
* @param int $answerformat
* @param array $options Optional param for additional options.
* @return string Returns formatted string
*/
public function format_answer($answer, $context, $answerformat, $options = []) {
$answer = file_rewrite_pluginfile_urls($answer, 'pluginfile.php', $context->id,
'mod_lesson', 'essay_answers', $options->attemptid);
return parent::format_answer($answer, $context, $answerformat, $options);
}
public function check_answer() {
global $PAGE, $CFG;
$result = parent::check_answer();
$result->isessayquestion = true;
$mform = new lesson_display_answer_form_essay($CFG->wwwroot.'/mod/lesson/continue.php', array('contents'=>$this->get_contents()));
$context = context_module::instance($PAGE->cm->id);
$options = array(
'contents' => $this->get_contents(),
'editoroptions' => array(
'maxbytes' => $PAGE->course->maxbytes,
'context' => $context,
'noclean' => true,
'maxfiles' => EDITOR_UNLIMITED_FILES,
'enable_filemanagement' => false,
)
);
$mform = new lesson_display_answer_form_essay($CFG->wwwroot.'/mod/lesson/continue.php', $options);
$data = $mform->get_data();
require_sesskey();
@ -125,11 +203,11 @@ class lesson_page_type_essay extends lesson_page {
return $result;
}
if (is_array($data->answer)) {
$studentanswer = $data->answer['text'];
$studentanswerformat = $data->answer['format'];
if (is_array($data->answer_editor) && strlen($data->answer_editor['text'])) {
$studentanswer = $data->answer_editor['text']; // Will be reset later.
$studentanswerformat = $data->answer_editor['format']; // Will be reset later.
} else {
$studentanswer = $data->answer;
$studentanswer = isset($data->answer) ? $data->answer : '';
$studentanswerformat = FORMAT_HTML;
}
@ -155,6 +233,7 @@ class lesson_page_type_essay extends lesson_page {
$result->userresponse = serialize($userresponse);
$result->studentanswerformat = $studentanswerformat;
$result->studentanswer = $studentanswer;
$result->postdata = $data;
return $result;
}
public function update($properties, $context = null, $maxbytes = null) {
@ -213,15 +292,19 @@ class lesson_page_type_essay extends lesson_page {
return true;
}
public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) {
global $PAGE;
$formattextdefoptions = new stdClass();
$formattextdefoptions->noclean = true;
$formattextdefoptions->para = false;
$formattextdefoptions->context = $answerpage->context;
$answers = $this->get_answers();
$context = context_module::instance($PAGE->cm->id);
foreach ($answers as $answer) {
if ($useranswer != null) {
$essayinfo = self::extract_useranswer($useranswer->useranswer);
$essayinfo->answer = file_rewrite_pluginfile_urls($essayinfo->answer, 'pluginfile.php',
$context->id, 'mod_lesson', 'essay_answers', $useranswer->id);
if ($essayinfo->response == null) {
$answerdata->response = get_string("nocommentyet", "lesson");
} else {
@ -304,6 +387,7 @@ class lesson_display_answer_form_essay extends moodleform {
global $USER, $OUTPUT;
$mform = $this->_form;
$contents = $this->_customdata['contents'];
$editoroptions = $this->_customdata['editoroptions'];
$hasattempt = false;
$attrs = '';
@ -341,11 +425,13 @@ class lesson_display_answer_form_essay extends moodleform {
$mform->addElement('hidden', 'answer', $useranswerraw);
$mform->setType('answer', PARAM_RAW);
$mform->addElement('html', $OUTPUT->container(get_string('youranswer', 'lesson'), 'youranswer'));
$useranswer = file_rewrite_pluginfile_urls($useranswer, 'pluginfile.php', $editoroptions['context']->id,
'mod_lesson', 'essay_answers', $this->_customdata['attemptid']);
$mform->addElement('html', $OUTPUT->container($useranswer, 'reviewessay'));
$this->add_action_buttons(null, get_string("nextpage", "lesson"));
} else {
$mform->addElement('editor', 'answer', get_string('youranswer', 'lesson'), null, null);
$mform->setType('answer', PARAM_RAW);
$mform->addElement('editor', 'answer_editor', get_string('youranswer', 'lesson'), null, $editoroptions);
$mform->setType('answer_editor', PARAM_RAW);
$this->add_action_buttons(null, get_string("submit", "lesson"));
}
}