Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
1 <?php 2 3 // This file is part of Moodle - http://moodle.org/ 4 // 5 // Moodle is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // Moodle is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 17 18 /** 19 * Provides the interface for grading essay questions 20 * 21 * @package mod_lesson 22 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 **/ 25 26 require_once('../../config.php'); 27 require_once($CFG->dirroot.'/mod/lesson/locallib.php'); 28 require_once($CFG->dirroot.'/mod/lesson/pagetypes/essay.php'); 29 require_once($CFG->dirroot.'/mod/lesson/essay_form.php'); 30 31 $id = required_param('id', PARAM_INT); // Course Module ID 32 $mode = optional_param('mode', 'display', PARAM_ALPHA); 33 34 $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST); 35 $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); 36 $dblesson = $DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST); 37 $lesson = new lesson($dblesson); 38 39 require_login($course, false, $cm); 40 $context = context_module::instance($cm->id); 41 require_capability('mod/lesson:grade', $context); 42 43 $url = new moodle_url('/mod/lesson/essay.php', array('id'=>$id)); 44 if ($mode !== 'display') { 45 $url->param('mode', $mode); 46 } 47 $PAGE->set_url($url); 48 49 $currentgroup = groups_get_activity_group($cm, true); 50 51 $attempt = new stdClass(); 52 $user = new stdClass(); 53 $attemptid = optional_param('attemptid', 0, PARAM_INT); 54 55 $formattextdefoptions = new stdClass(); 56 $formattextdefoptions->noclean = true; 57 $formattextdefoptions->para = false; 58 $formattextdefoptions->context = $context; 59 60 if ($attemptid > 0) { 61 $attempt = $DB->get_record('lesson_attempts', array('id' => $attemptid)); 62 $answer = $DB->get_record('lesson_answers', array('lessonid' => $lesson->id, 'pageid' => $attempt->pageid)); 63 $user = $DB->get_record('user', array('id' => $attempt->userid)); 64 // Apply overrides. 65 $lesson->update_effective_access($user->id); 66 $scoreoptions = array(); 67 if ($lesson->custom) { 68 $i = $answer->score; 69 while ($i >= 0) { 70 $scoreoptions[$i] = (string)$i; 71 $i--; 72 } 73 } else { 74 $scoreoptions[0] = get_string('nocredit', 'lesson'); 75 $scoreoptions[1] = get_string('credit', 'lesson'); 76 } 77 } 78 79 /// Handle any preprocessing before header is printed - based on $mode 80 switch ($mode) { 81 case 'grade': 82 // Grading form - get the necessary data 83 require_sesskey(); 84 85 if (empty($attempt)) { 86 print_error('cannotfindattempt', 'lesson'); 87 } 88 if (empty($user)) { 89 print_error('cannotfinduser', 'lesson'); 90 } 91 if (empty($answer)) { 92 print_error('cannotfindanswer', 'lesson'); 93 } 94 break; 95 96 case 'update': 97 require_sesskey(); 98 99 if (empty($attempt)) { 100 print_error('cannotfindattempt', 'lesson'); 101 } 102 if (empty($user)) { 103 print_error('cannotfinduser', 'lesson'); 104 } 105 106 $editoroptions = array('noclean' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES, 107 'maxbytes' => $CFG->maxbytes, 'context' => $context); 108 $essayinfo = lesson_page_type_essay::extract_useranswer($attempt->useranswer); 109 $essayinfo = file_prepare_standard_editor($essayinfo, 'response', $editoroptions, $context, 110 'mod_lesson', 'essay_responses', $attempt->id); 111 $mform = new essay_grading_form(null, array('scoreoptions' => $scoreoptions, 'user' => $user)); 112 $mform->set_data($essayinfo); 113 if ($mform->is_cancelled()) { 114 redirect("$CFG->wwwroot/mod/lesson/essay.php?id=$cm->id"); 115 } 116 if ($form = $mform->get_data()) { 117 if (!$grades = $DB->get_records('lesson_grades', array("lessonid"=>$lesson->id, "userid"=>$attempt->userid), 'completed', '*', $attempt->retry, 1)) { 118 print_error('cannotfindgrade', 'lesson'); 119 } 120 121 $essayinfo->graded = 1; 122 $essayinfo->score = $form->score; 123 $form = file_postupdate_standard_editor($form, 'response', $editoroptions, $context, 124 'mod_lesson', 'essay_responses', $attempt->id); 125 $essayinfo->response = $form->response; 126 $essayinfo->responseformat = $form->responseformat; 127 $essayinfo->sent = 0; 128 if (!$lesson->custom && $essayinfo->score == 1) { 129 $attempt->correct = 1; 130 } else { 131 $attempt->correct = 0; 132 } 133 134 $attempt->useranswer = serialize($essayinfo); 135 136 $DB->update_record('lesson_attempts', $attempt); 137 138 // Get grade information 139 $grade = current($grades); 140 $gradeinfo = lesson_grade($lesson, $attempt->retry, $attempt->userid); 141 142 // Set and update 143 $updategrade = new stdClass(); 144 $updategrade->id = $grade->id; 145 $updategrade->grade = $gradeinfo->grade; 146 $DB->update_record('lesson_grades', $updategrade); 147 148 $params = array( 149 'context' => $context, 150 'objectid' => $grade->id, 151 'courseid' => $course->id, 152 'relateduserid' => $attempt->userid, 153 'other' => array( 154 'lessonid' => $lesson->id, 155 'attemptid' => $attemptid 156 ) 157 ); 158 $event = \mod_lesson\event\essay_assessed::create($params); 159 $event->add_record_snapshot('lesson', $dblesson); 160 $event->trigger(); 161 162 $lesson->add_message(get_string('changessaved'), 'notifysuccess'); 163 164 // update central gradebook 165 lesson_update_grades($lesson, $grade->userid); 166 167 redirect(new moodle_url('/mod/lesson/essay.php', array('id'=>$cm->id))); 168 } else { 169 print_error('invalidformdata'); 170 } 171 break; 172 case 'email': 173 // Sending an email(s) to a single user or all 174 require_sesskey(); 175 176 // Get our users (could be singular) 177 if ($userid = optional_param('userid', 0, PARAM_INT)) { 178 $queryadd = " AND userid = ?"; 179 if (! $users = $DB->get_records('user', array('id' => $userid))) { 180 print_error('cannotfinduser', 'lesson'); 181 } 182 } else { 183 $queryadd = ''; 184 185 // If group selected, only send to group members. 186 list($esql, $params) = get_enrolled_sql($context, '', $currentgroup, true); 187 list($sort, $sortparams) = users_order_by_sql('u'); 188 $params['lessonid'] = $lesson->id; 189 190 // Need to use inner view to avoid distinct + text 191 if (!$users = $DB->get_records_sql(" 192 SELECT u.* 193 FROM {user} u 194 JOIN ( 195 SELECT DISTINCT userid 196 FROM {lesson_attempts} 197 WHERE lessonid = :lessonid 198 ) ui ON u.id = ui.userid 199 JOIN ($esql) ue ON ue.id = u.id 200 ORDER BY $sort", $params)) { 201 print_error('cannotfinduser', 'lesson'); 202 } 203 } 204 205 $pages = $lesson->load_all_pages(); 206 foreach ($pages as $key=>$page) { 207 if ($page->qtype != LESSON_PAGE_ESSAY) { 208 unset($pages[$key]); 209 } 210 } 211 212 // Get only the attempts that are in response to essay questions 213 list($usql, $params) = $DB->get_in_or_equal(array_keys($pages)); 214 if (!empty($queryadd)) { 215 $params[] = $userid; 216 } 217 if (!$attempts = $DB->get_records_select('lesson_attempts', "pageid $usql".$queryadd, $params)) { 218 print_error('nooneansweredthisquestion', 'lesson'); 219 } 220 // Get the answers 221 list($answerUsql, $parameters) = $DB->get_in_or_equal(array_keys($pages)); 222 array_unshift($parameters, $lesson->id); 223 if (!$answers = $DB->get_records_select('lesson_answers', "lessonid = ? AND pageid $answerUsql", $parameters, '', 'pageid, score')) { 224 print_error('cannotfindanswer', 'lesson'); 225 } 226 227 $userpicture = new user_picture($USER); 228 $userpicture->size = 1; // Use f1 size. 229 foreach ($attempts as $attempt) { 230 $essayinfo = lesson_page_type_essay::extract_useranswer($attempt->useranswer); 231 if ($essayinfo->graded && !$essayinfo->sent) { 232 // Holds values for the essayemailsubject string for the email message 233 $a = new stdClass; 234 235 // Set the grade 236 $grades = $DB->get_records('lesson_grades', array("lessonid"=>$lesson->id, "userid"=>$attempt->userid), 'completed', '*', $attempt->retry, 1); 237 $grade = current($grades); 238 $a->newgrade = $grade->grade; 239 240 // Set the points 241 if ($lesson->custom) { 242 $a->earned = $essayinfo->score; 243 $a->outof = $answers[$attempt->pageid]->score; 244 } else { 245 $a->earned = $essayinfo->score; 246 $a->outof = 1; 247 } 248 249 // Set rest of the message values 250 $currentpage = $lesson->load_page($attempt->pageid); 251 $a->question = format_text($currentpage->contents, $currentpage->contentsformat, $formattextdefoptions); 252 $answer = file_rewrite_pluginfile_urls($essayinfo->answer, 'pluginfile.php', $context->id, 253 'mod_lesson', 'essay_answers', $attempt->id); 254 $a->response = format_text($answer, $essayinfo->answerformat, 255 array('context' => $context, 'para' => true)); 256 $a->comment = $essayinfo->response; 257 $a->comment = file_rewrite_pluginfile_urls($a->comment, 'pluginfile.php', $context->id, 258 'mod_lesson', 'essay_responses', $attempt->id); 259 $a->comment = format_text($a->comment, $essayinfo->responseformat, $formattextdefoptions); 260 $a->lesson = format_string($lesson->name, true); 261 262 // Fetch message HTML and plain text formats 263 $message = get_string('essayemailmessage2', 'lesson', $a); 264 $plaintext = format_text_email($message, FORMAT_HTML); 265 266 $smallmessage = get_string('essayemailmessagesmall', 'lesson', $a); 267 $smallmessage = format_text_email($smallmessage, FORMAT_HTML); 268 269 // Subject 270 $subject = get_string('essayemailsubject', 'lesson'); 271 272 // Context url. 273 $contexturl = new moodle_url('/grade/report/user/index.php', array('id' => $course->id)); 274 275 $eventdata = new \core\message\message(); 276 $eventdata->courseid = $course->id; 277 $eventdata->modulename = 'lesson'; 278 $eventdata->userfrom = $USER; 279 $eventdata->userto = $users[$attempt->userid]; 280 $eventdata->subject = $subject; 281 $eventdata->fullmessage = $plaintext; 282 $eventdata->fullmessageformat = FORMAT_PLAIN; 283 $eventdata->fullmessagehtml = $message; 284 $eventdata->smallmessage = $smallmessage; 285 $eventdata->contexturl = $contexturl->out(false); 286 $userpicture->includetoken = $attempt->userid; // Generate an out-of-session token for the destinatary. 287 $eventdata->customdata = [ 288 'cmid' => $cm->id, 289 'instance' => $lesson->id, 290 'retake' => $lesson->id, 291 'notificationiconurl' => $userpicture->get_url($PAGE)->out(false), 292 ]; 293 294 // Required for messaging framework 295 $eventdata->component = 'mod_lesson'; 296 $eventdata->name = 'graded_essay'; 297 298 message_send($eventdata); 299 $essayinfo->sent = 1; 300 $attempt->useranswer = serialize($essayinfo); 301 $DB->update_record('lesson_attempts', $attempt); 302 } 303 } 304 $lesson->add_message(get_string('emailsuccess', 'lesson'), 'notifysuccess'); 305 redirect(new moodle_url('/mod/lesson/essay.php', array('id'=>$cm->id))); 306 break; 307 case 'display': // Default view - get the necessary data 308 default: 309 // Get lesson pages that are essay 310 $pages = $lesson->load_all_pages(); 311 foreach ($pages as $key=>$page) { 312 if ($page->qtype != LESSON_PAGE_ESSAY) { 313 unset($pages[$key]); 314 } 315 } 316 if (count($pages) > 0) { 317 // Get only the attempts that are in response to essay questions 318 list($usql, $parameters) = $DB->get_in_or_equal(array_keys($pages), SQL_PARAMS_NAMED); 319 // If group selected, only get group members attempts. 320 list($esql, $params) = get_enrolled_sql($context, '', $currentgroup, true); 321 $parameters = array_merge($params, $parameters); 322 323 $sql = "SELECT a.* 324 FROM {lesson_attempts} a 325 JOIN ($esql) ue ON a.userid = ue.id 326 WHERE pageid $usql"; 327 if ($essayattempts = $DB->get_records_sql($sql, $parameters)) { 328 $userfieldsapi = \core_user\fields::for_userpic(); 329 $ufields = $userfieldsapi->get_sql('u', false, '', '', false)->selects; 330 // Get all the users who have taken this lesson. 331 list($sort, $sortparams) = users_order_by_sql('u'); 332 333 $params['lessonid'] = $lesson->id; 334 $sql = "SELECT DISTINCT $ufields 335 FROM {user} u 336 JOIN {lesson_attempts} a ON u.id = a.userid 337 JOIN ($esql) ue ON ue.id = a.userid 338 WHERE a.lessonid = :lessonid 339 ORDER BY $sort"; 340 if (!$users = $DB->get_records_sql($sql, $params)) { 341 $mode = 'none'; // not displaying anything 342 if (!empty($currentgroup)) { 343 $groupname = groups_get_group_name($currentgroup); 344 $lesson->add_message(get_string('noonehasansweredgroup', 'lesson', $groupname)); 345 } else { 346 $lesson->add_message(get_string('noonehasanswered', 'lesson')); 347 } 348 } 349 } else { 350 $mode = 'none'; // not displaying anything 351 if (!empty($currentgroup)) { 352 $groupname = groups_get_group_name($currentgroup); 353 $lesson->add_message(get_string('noonehasansweredgroup', 'lesson', $groupname)); 354 } else { 355 $lesson->add_message(get_string('noonehasanswered', 'lesson')); 356 } 357 } 358 } else { 359 $mode = 'none'; // not displaying anything 360 $lesson->add_message(get_string('noessayquestionsfound', 'lesson')); 361 } 362 break; 363 } 364 365 $lessonoutput = $PAGE->get_renderer('mod_lesson'); 366 echo $lessonoutput->header($lesson, $cm, 'essay', false, null, get_string('manualgrading', 'lesson')); 367 368 switch ($mode) { 369 case 'display': 370 groups_print_activity_menu($cm, $url); 371 // Expects $user, $essayattempts and $pages to be set already 372 373 // Group all the essays by userid 374 $studentessays = array(); 375 foreach ($essayattempts as $essay) { 376 // Not very nice :) but basically 377 // this organizes the essays so we know how many 378 // times a student answered an essay per try and per page 379 $studentessays[$essay->userid][$essay->pageid][$essay->retry][] = $essay; 380 } 381 382 // Setup table 383 $table = new html_table(); 384 $table->head = array(get_string('name'), get_string('essays', 'lesson'), get_string('status'), 385 get_string('email', 'lesson')); 386 $table->attributes['class'] = 'standardtable generaltable'; 387 $table->align = array('left', 'left', 'left'); 388 $table->wrap = array('nowrap', 'nowrap', ''); 389 390 // Cycle through all the students 391 foreach (array_keys($studentessays) as $userid) { 392 $studentname = fullname($users[$userid], true); 393 $essaylinks = array(); 394 $essaystatuses = array(); 395 396 // Number of attempts on the lesson 397 $attempts = $lesson->count_user_retries($userid); 398 399 // Go through each essay page 400 foreach ($studentessays[$userid] as $page => $tries) { 401 $count = 0; 402 403 // Go through each attempt per page 404 foreach($tries as $try) { 405 if ($count == $attempts) { 406 break; // Stop displaying essays (attempt not completed) 407 } 408 $count++; 409 410 // Make sure they didn't answer it more than the max number of attempts. 411 $essay = $lesson->get_last_attempt($try); 412 413 // Start processing the attempt 414 $essayinfo = lesson_page_type_essay::extract_useranswer($essay->useranswer); 415 416 // link for each essay 417 $url = new moodle_url('/mod/lesson/essay.php', array('id'=>$cm->id,'mode'=>'grade','attemptid'=>$essay->id,'sesskey'=>sesskey())); 418 $linktitle = userdate($essay->timeseen, get_string('strftimedatetime')).' '. 419 format_string($pages[$essay->pageid]->title, true); 420 421 // Different colors for all the states of an essay (graded, if sent, not graded) 422 if (!$essayinfo->graded) { 423 $class = "badge badge-warning"; 424 $status = get_string('notgraded', 'lesson'); 425 } elseif (!$essayinfo->sent) { 426 $class = "badge badge-success"; 427 $status = get_string('graded', 'lesson'); 428 } else { 429 $class = "badge badge-success"; 430 $status = get_string('sent', 'lesson'); 431 } 432 $attributes = array('tabindex' => 0); 433 434 $essaylinks[] = html_writer::link($url, $linktitle); 435 $essaystatuses[] = html_writer::span($status, $class, $attributes); 436 } 437 } 438 // email link for this user 439 $url = new moodle_url('/mod/lesson/essay.php', array('id'=>$cm->id,'mode'=>'email','userid'=>$userid,'sesskey'=>sesskey())); 440 $emaillink = html_writer::link($url, get_string('emailgradedessays', 'lesson')); 441 442 $table->data[] = array($OUTPUT->user_picture($users[$userid], array('courseid' => $course->id)) . $studentname, 443 implode("<br />", $essaylinks), implode("<br />", $essaystatuses), $emaillink); 444 } 445 446 // email link for all users 447 $url = new moodle_url('/mod/lesson/essay.php', array('id'=>$cm->id,'mode'=>'email','sesskey'=>sesskey())); 448 $emailalllink = html_writer::link($url, get_string('emailallgradedessays', 'lesson')); 449 450 $table->data[] = array(' ', ' ', ' ', $emailalllink); 451 452 echo html_writer::table($table); 453 break; 454 case 'grade': 455 // Trigger the essay grade viewed event. 456 $event = \mod_lesson\event\essay_attempt_viewed::create(array( 457 'objectid' => $attempt->id, 458 'relateduserid' => $attempt->userid, 459 'context' => $context, 460 'courseid' => $course->id, 461 )); 462 $event->add_record_snapshot('lesson_attempts', $attempt); 463 $event->trigger(); 464 465 // Grading form 466 // Expects the following to be set: $attemptid, $answer, $user, $page, $attempt 467 $essayinfo = lesson_page_type_essay::extract_useranswer($attempt->useranswer); 468 $answer = file_rewrite_pluginfile_urls($essayinfo->answer, 'pluginfile.php', $context->id, 469 'mod_lesson', 'essay_answers', $attempt->id); 470 $currentpage = $lesson->load_page($attempt->pageid); 471 472 $mform = new essay_grading_form(null, array('scoreoptions'=>$scoreoptions, 'user'=>$user)); 473 $data = new stdClass; 474 $data->id = $cm->id; 475 $data->attemptid = $attemptid; 476 $data->score = $essayinfo->score; 477 $data->question = format_text($currentpage->contents, $currentpage->contentsformat, $formattextdefoptions); 478 $data->studentanswer = format_text($answer, $essayinfo->answerformat, 479 array('context' => $context, 'para' => true)); 480 $data->response = $essayinfo->response; 481 $data->responseformat = $essayinfo->responseformat; 482 $editoroptions = array('noclean' => true, 'maxfiles' => EDITOR_UNLIMITED_FILES, 483 'maxbytes' => $CFG->maxbytes, 'context' => $context); 484 $data = file_prepare_standard_editor($data, 'response', $editoroptions, $context, 485 'mod_lesson', 'essay_responses', $attempt->id); 486 $mform->set_data($data); 487 488 $mform->display(); 489 break; 490 default: 491 groups_print_activity_menu($cm, $url); 492 break; 493 } 494 495 echo $OUTPUT->footer();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body