diff --git a/mod/lesson/backup/moodle2/backup_lesson_stepslib.php b/mod/lesson/backup/moodle2/backup_lesson_stepslib.php index cfb746d0b0539..c95f6a0b4ec7a 100644 --- a/mod/lesson/backup/moodle2/backup_lesson_stepslib.php +++ b/mod/lesson/backup/moodle2/backup_lesson_stepslib.php @@ -193,6 +193,7 @@ protected function define_structure() { $page->annotate_files('mod_lesson', 'page_contents', 'id'); $answer->annotate_files('mod_lesson', 'page_answers', 'id'); $answer->annotate_files('mod_lesson', 'page_responses', 'id'); + $attempt->annotate_files('mod_lesson', 'essay_responses', 'id'); // Prepare and return the structure we have just created for the lesson module. return $this->prepare_activity_structure($lesson); diff --git a/mod/lesson/backup/moodle2/restore_lesson_stepslib.php b/mod/lesson/backup/moodle2/restore_lesson_stepslib.php index 8be645e9bf06b..815e255005146 100644 --- a/mod/lesson/backup/moodle2/restore_lesson_stepslib.php +++ b/mod/lesson/backup/moodle2/restore_lesson_stepslib.php @@ -131,6 +131,7 @@ protected function process_lesson_attempt($data) { $data->timeseen = $this->apply_date_offset($data->timeseen); $newitemid = $DB->insert_record('lesson_attempts', $data); + $this->set_mapping('lesson_attempt', $oldid, $newitemid, true); // Has related fileareas. } protected function process_lesson_grade($data) { @@ -209,6 +210,7 @@ protected function after_execute() { $this->add_related_files('mod_lesson', 'page_contents', 'lesson_page'); $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'); // 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()), diff --git a/mod/lesson/essay.php b/mod/lesson/essay.php index 2625fc054fff0..2610b4a8c779a 100644 --- a/mod/lesson/essay.php +++ b/mod/lesson/essay.php @@ -25,6 +25,7 @@ require_once('../../config.php'); require_once($CFG->dirroot.'/mod/lesson/locallib.php'); +require_once($CFG->dirroot.'/mod/lesson/pagetypes/essay.php'); require_once($CFG->dirroot.'/mod/lesson/essay_form.php'); require_once($CFG->libdir.'/eventslib.php'); @@ -99,7 +100,13 @@ print_error('cannotfinduser', 'lesson'); } - $mform = new essay_grading_form(null, array('scoreoptions'=>$scoreoptions, 'user'=>$user)); + $editoroptions = array('noclean' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES, + 'maxbytes' => $CFG->maxbytes, 'context' => $context); + $essayinfo = lesson_page_type_essay::extract_useranswer($attempt->useranswer); + $essayinfo = file_prepare_standard_editor($essayinfo, 'response', $editoroptions, $context, + 'mod_lesson', 'essay_responses', $attempt->id); + $mform = new essay_grading_form(null, array('scoreoptions' => $scoreoptions, 'user' => $user)); + $mform->set_data($essayinfo); if ($mform->is_cancelled()) { redirect("$CFG->wwwroot/mod/lesson/essay.php?id=$cm->id"); } @@ -108,12 +115,12 @@ print_error('cannotfindgrade', 'lesson'); } - $essayinfo = new stdClass; - $essayinfo = unserialize($attempt->useranswer); - $essayinfo->graded = 1; $essayinfo->score = $form->score; - $essayinfo->response = clean_param($form->response, PARAM_RAW); + $form = file_postupdate_standard_editor($form, 'response', $editoroptions, $context, + 'mod_lesson', 'essay_responses', $attempt->id); + $essayinfo->response = $form->response; + $essayinfo->responseformat = $form->responseformat; $essayinfo->sent = 0; if (!$lesson->custom && $essayinfo->score == 1) { $attempt->correct = 1; @@ -208,7 +215,7 @@ } foreach ($attempts as $attempt) { - $essayinfo = unserialize($attempt->useranswer); + $essayinfo = lesson_page_type_essay::extract_useranswer($attempt->useranswer); if ($essayinfo->graded && !$essayinfo->sent) { // Holds values for the essayemailsubject string for the email message $a = new stdClass; @@ -232,7 +239,10 @@ $a->question = format_text($currentpage->contents, $currentpage->contentsformat, $formattextdefoptions); $a->response = format_text($essayinfo->answer, $essayinfo->answerformat, array('context' => $context, 'para' => true)); - $a->comment = s($essayinfo->response); + $a->comment = $essayinfo->response; + $a->comment = file_rewrite_pluginfile_urls($a->comment, 'pluginfile.php', $context->id, + 'mod_lesson', 'essay_responses', $attempt->id); + $a->comment = format_text($a->comment, $essayinfo->responseformat, $formattextdefoptions); // Fetch message HTML and plain text formats $message = get_string('essayemailmessage2', 'lesson', $a); @@ -353,7 +363,7 @@ } // Start processing the attempt - $essayinfo = unserialize($essay->useranswer); + $essayinfo = lesson_page_type_essay::extract_useranswer($essay->useranswer); // link for each essay $url = new moodle_url('/mod/lesson/essay.php', array('id'=>$cm->id,'mode'=>'grade','attemptid'=>$essay->id,'sesskey'=>sesskey())); @@ -397,7 +407,7 @@ // Grading form // Expects the following to be set: $attemptid, $answer, $user, $page, $attempt - $essayinfo = unserialize($attempt->useranswer); + $essayinfo = lesson_page_type_essay::extract_useranswer($attempt->useranswer); $currentpage = $lesson->load_page($attempt->pageid); $mform = new essay_grading_form(null, array('scoreoptions'=>$scoreoptions, 'user'=>$user)); @@ -409,6 +419,11 @@ $data->studentanswer = format_text($essayinfo->answer, $essayinfo->answerformat, array('context' => $context, 'para' => true)); $data->response = $essayinfo->response; + $data->responseformat = $essayinfo->responseformat; + $editoroptions = array('noclean' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES, + 'maxbytes' => $CFG->maxbytes, 'context' => $context); + $data = file_prepare_standard_editor($data, 'response', $editoroptions, $context, + 'mod_lesson', 'essay_responses', $attempt->id); $mform->set_data($data); $mform->display(); diff --git a/mod/lesson/essay_form.php b/mod/lesson/essay_form.php index 883c4e66d424c..a1ab40c5cff78 100644 --- a/mod/lesson/essay_form.php +++ b/mod/lesson/essay_form.php @@ -39,6 +39,8 @@ class essay_grading_form extends moodleform { public function definition() { + global $CFG; + $mform = $this->_form; $mform->addElement('header', 'formheader', get_string('question', 'lesson')); @@ -55,8 +57,9 @@ public function definition() { $mform->addElement('static', 'question', get_string('question', 'lesson')); $mform->addElement('static', 'studentanswer', get_string('studentresponse', 'lesson', fullname($this->_customdata['user'], true))); - $mform->addElement('textarea', 'response', get_string('comments', 'lesson'), array('rows'=>'15', 'cols'=>'60')); - $mform->setType('response', PARAM_TEXT); + $editoroptions = array('noclean' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES, 'maxbytes' => $CFG->maxbytes); + $mform->addElement('editor', 'response_editor', get_string('comments', 'lesson'), null, $editoroptions); + $mform->setType('response', PARAM_RAW); $mform->addElement('select', 'score', get_string('essayscore', 'lesson'), $this->_customdata['scoreoptions']); $mform->setType('score', PARAM_INT); diff --git a/mod/lesson/lang/en/lesson.php b/mod/lesson/lang/en/lesson.php index 32e448932a20d..500d025cc65bf 100644 --- a/mod/lesson/lang/en/lesson.php +++ b/mod/lesson/lang/en/lesson.php @@ -171,6 +171,7 @@ $string['essayemailmessage'] = '
Essay prompt:
{$a->question}
Your response:
{$a->response}
{$a->teacher}\'s comments:
{$a->comment}
You have received {$a->earned} out of {$a->outof} for this essay question.
Your grade for the lesson has been changed to {$a->newgrade}%.
'; $string['essayemailmessage2'] = 'Essay prompt:
{$a->question}
Your response:
{$a->response}
Grader\'s comments:
{$a->comment}
You have received {$a->earned} out of {$a->outof} for this essay question.
Your grade for the lesson has been changed to {$a->newgrade}%.
'; $string['essayemailsubject'] = 'Your grade for {$a} question'; +$string['essayresponses'] = 'Essay responses'; $string['essays'] = 'Essays'; $string['essayscore'] = 'Essay score'; $string['eventessayassessed'] = 'Essay assessed'; diff --git a/mod/lesson/lib.php b/mod/lesson/lib.php index 088967d407e5d..138d41c0ed30f 100644 --- a/mod/lesson/lib.php +++ b/mod/lesson/lib.php @@ -682,6 +682,20 @@ function lesson_reset_userdata($data) { WHERE l.course=:course"; $params = array ("course" => $data->courseid); + $lessons = $DB->get_records_sql($lessonssql, $params); + + // Get rid of attempts files. + $fs = get_file_storage(); + if ($lessons) { + foreach ($lessons as $lessonid => $unused) { + if (!$cm = get_coursemodule_from_instance('lesson', $lessonid)) { + continue; + } + $context = context_module::instance($cm->id); + $fs->delete_area_files($context->id, 'mod_lesson', 'essay_responses'); + } + } + $DB->delete_records_select('lesson_timer', "lessonid IN ($lessonssql)", $params); $DB->delete_records_select('lesson_high_scores', "lessonid IN ($lessonssql)", $params); $DB->delete_records_select('lesson_grades', "lessonid IN ($lessonssql)", $params); @@ -897,6 +911,13 @@ function lesson_pluginfile($course, $cm, $context, $filearea, $args, $forcedownl } $fullpath = "/$context->id/mod_lesson/$filearea/$itemid/".implode('/', $args); + } else if ($filearea === 'essay_responses') { + $itemid = (int)array_shift($args); + if (!$attempt = $DB->get_record('lesson_attempts', array('id' => $itemid))) { + return false; + } + $fullpath = "/$context->id/mod_lesson/$filearea/$itemid/".implode('/', $args); + } else if ($filearea === 'mediafile') { if (count($args) > 1) { // Remove the itemid when it appears to be part of the arguments. If there is only one argument @@ -931,6 +952,7 @@ function lesson_get_file_areas() { $areas['mediafile'] = get_string('mediafile', 'mod_lesson'); $areas['page_answers'] = get_string('pageanswers', 'mod_lesson'); $areas['page_responses'] = get_string('pageresponses', 'mod_lesson'); + $areas['essay_responses'] = get_string('essayresponses', 'mod_lesson'); return $areas; } diff --git a/mod/lesson/locallib.php b/mod/lesson/locallib.php index 1a3ba153b847c..9cf7cc2281534 100644 --- a/mod/lesson/locallib.php +++ b/mod/lesson/locallib.php @@ -1870,7 +1870,19 @@ final public static function load($id, lesson $lesson) { */ final public function delete() { global $DB; - // first delete all the associated records... + + $cm = get_coursemodule_from_instance('lesson', $this->lesson->id, $this->lesson->course); + $context = context_module::instance($cm->id); + + // Delete files associated with attempts. + $fs = get_file_storage(); + 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); + } + } + + // Then delete all the associated records... $DB->delete_records("lesson_attempts", array("pageid" => $this->properties->id)); // ...now delete the answers... $DB->delete_records("lesson_answers", array("pageid" => $this->properties->id)); @@ -1878,9 +1890,6 @@ final public function delete() { $DB->delete_records("lesson_pages", array("id" => $this->properties->id)); // Delete files associated with this page. - $cm = get_coursemodule_from_instance('lesson', $this->lesson->id, $this->lesson->course); - $context = context_module::instance($cm->id); - $fs = get_file_storage(); $fs->delete_area_files($context->id, 'mod_lesson', 'page_contents', $this->properties->id); $fs->delete_area_files($context->id, 'mod_lesson', 'page_answers', $this->properties->id); $fs->delete_area_files($context->id, 'mod_lesson', 'page_responses', $this->properties->id); @@ -2088,8 +2097,7 @@ final public function record_attempt($context) { $options->para = true; $options->overflowdiv = true; $options->context = $context; - $result->response = file_rewrite_pluginfile_urls($result->response, 'pluginfile.php', $context->id, - 'mod_lesson', 'page_responses', $result->answerid); + $result->feedback = $OUTPUT->box(format_text($this->get_contents(), $this->properties->contentsformat, $options), 'generalbox boxaligncenter'); if (isset($result->studentanswerformat)) { // This is the student's answer so it should be cleaned. @@ -2100,7 +2108,14 @@ final public function record_attempt($context) { } $result->feedback .= 'Well done.
| | Essay score | 1 | And I press "Save changes" And I should see "Changes saved" + And I follow "Reports" + And I should see "Student 1" + And I click on ".lesson-attempt-link" "css_element" in the "Student 1" "table_row" + And I should see "Essay: Essay question" + And I should see "Please write a story about a frog." + And I should see "Once upon a time there was a little green frog." + And I should see "Well done." + And I should not see "<b>" diff --git a/mod/lesson/tests/pagetypes_test.php b/mod/lesson/tests/pagetypes_test.php new file mode 100644 index 0000000000000..28eab4cb70eb4 --- /dev/null +++ b/mod/lesson/tests/pagetypes_test.php @@ -0,0 +1,70 @@ +. + +/** + * Unit tests for page types classes + * + * @package mod_lesson + * @category test + * @copyright 2015 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU Public License + */ + + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/mod/lesson/locallib.php'); +require_once($CFG->dirroot . '/mod/lesson/pagetypes/essay.php'); + + +/** + * This class contains the test cases for some of the functions in the lesson essay page type class. + * + * @copyright 2015 Jean-Michel Vedrine + * @license http://www.gnu.org/copyleft/gpl.html GNU Public License + */ +class mod_lesson_essay_page_type_test extends advanced_testcase { + public function test_lesson_essay_extract_useranswer() { + // Test that reponseformat is added when not present. + $answer = 'O:8:"stdClass":6:{s:4:"sent";i:1;s:6:"graded";i:1;s:5:"score";s:1:"1";' + . 's:6:"answer";s:64:"This is my answer with bold and italics
This is my answer with bold and italics
This is my answer with bold and italics
This is my answer with bold and italics