MDL-51569 mod_choice: Prevent users from updating choices with curl
[moodle.git] / mod / lesson / view.php
blob6ec49df4f9ebd6cc780eda62cc7728b1d37ed5a7
1 <?php
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.
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/>.
18 /**
19 * This page prints a particular instance of lesson
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 late
24 **/
26 require_once(dirname(__FILE__) . '/../../config.php');
27 require_once($CFG->dirroot.'/mod/lesson/locallib.php');
28 require_once($CFG->dirroot.'/mod/lesson/view_form.php');
29 require_once($CFG->libdir . '/completionlib.php');
31 $id = required_param('id', PARAM_INT); // Course Module ID
32 $pageid = optional_param('pageid', null, PARAM_INT); // Lesson Page ID
33 $edit = optional_param('edit', -1, PARAM_BOOL);
34 $userpassword = optional_param('userpassword','',PARAM_RAW);
35 $backtocourse = optional_param('backtocourse', false, PARAM_RAW);
37 $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);
38 $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
39 $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST));
41 require_login($course, false, $cm);
43 if ($backtocourse) {
44 redirect(new moodle_url('/course/view.php', array('id'=>$course->id)));
47 // Mark as viewed
48 $completion = new completion_info($course);
49 $completion->set_module_viewed($cm);
51 $url = new moodle_url('/mod/lesson/view.php', array('id'=>$id));
52 if ($pageid !== null) {
53 $url->param('pageid', $pageid);
55 $PAGE->set_url($url);
57 $context = context_module::instance($cm->id);
58 $canmanage = has_capability('mod/lesson:manage', $context);
60 $lessonoutput = $PAGE->get_renderer('mod_lesson');
62 $reviewmode = false;
63 $userhasgrade = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id));
64 if ($userhasgrade && !$lesson->retake) {
65 $reviewmode = true;
68 /// Check these for students only TODO: Find a better method for doing this!
69 /// Check lesson availability
70 /// Check for password
71 /// Check dependencies
72 /// Check for high scores
73 if (!$canmanage) {
74 if (!$lesson->is_accessible()) { // Deadline restrictions
75 echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('notavailable'));
76 if ($lesson->deadline != 0 && time() > $lesson->deadline) {
77 echo $lessonoutput->lesson_inaccessible(get_string('lessonclosed', 'lesson', userdate($lesson->deadline)));
78 } else {
79 echo $lessonoutput->lesson_inaccessible(get_string('lessonopen', 'lesson', userdate($lesson->available)));
81 echo $lessonoutput->footer();
82 exit();
83 } else if ($lesson->usepassword && empty($USER->lessonloggedin[$lesson->id])) { // Password protected lesson code
84 $correctpass = false;
85 if (!empty($userpassword) && (($lesson->password == md5(trim($userpassword))) || ($lesson->password == trim($userpassword)))) {
86 require_sesskey();
87 // with or without md5 for backward compatibility (MDL-11090)
88 $USER->lessonloggedin[$lesson->id] = true;
89 if ($lesson->highscores) {
90 // Logged in - redirect so we go through all of these checks before starting the lesson.
91 redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id");
93 } else {
94 echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('passwordprotectedlesson', 'lesson', format_string($lesson->name)));
95 echo $lessonoutput->login_prompt($lesson, $userpassword !== '');
96 echo $lessonoutput->footer();
97 exit();
99 } else if ($lesson->dependency) { // check for dependencies
100 if ($dependentlesson = $DB->get_record('lesson', array('id' => $lesson->dependency))) {
101 // lesson exists, so we can proceed
102 $conditions = unserialize($lesson->conditions);
103 // assume false for all
104 $errors = array();
106 // check for the timespent condition
107 if ($conditions->timespent) {
108 $timespent = false;
109 if ($attempttimes = $DB->get_records('lesson_timer', array("userid"=>$USER->id, "lessonid"=>$dependentlesson->id))) {
110 // go through all the times and test to see if any of them satisfy the condition
111 foreach($attempttimes as $attempttime) {
112 $duration = $attempttime->lessontime - $attempttime->starttime;
113 if ($conditions->timespent < $duration/60) {
114 $timespent = true;
118 if (!$timespent) {
119 $errors[] = get_string('timespenterror', 'lesson', $conditions->timespent);
123 // check for the gradebetterthan condition
124 if($conditions->gradebetterthan) {
125 $gradebetterthan = false;
126 if ($studentgrades = $DB->get_records('lesson_grades', array("userid"=>$USER->id, "lessonid"=>$dependentlesson->id))) {
127 // go through all the grades and test to see if any of them satisfy the condition
128 foreach($studentgrades as $studentgrade) {
129 if ($studentgrade->grade >= $conditions->gradebetterthan) {
130 $gradebetterthan = true;
134 if (!$gradebetterthan) {
135 $errors[] = get_string('gradebetterthanerror', 'lesson', $conditions->gradebetterthan);
139 // check for the completed condition
140 if ($conditions->completed) {
141 if (!$DB->count_records('lesson_grades', array('userid'=>$USER->id, 'lessonid'=>$dependentlesson->id))) {
142 $errors[] = get_string('completederror', 'lesson');
146 if (!empty($errors)) { // print out the errors if any
147 echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('completethefollowingconditions', 'lesson', format_string($lesson->name)));
148 echo $lessonoutput->dependancy_errors($dependentlesson, $errors);
149 echo $lessonoutput->footer();
150 exit();
153 } else if ($lesson->highscores && !$lesson->practice && !optional_param('viewed', 0, PARAM_INT) && empty($pageid)) {
154 // Display high scores before starting lesson
155 redirect(new moodle_url('/mod/lesson/highscores.php', array("id"=>$cm->id)));
159 // this is called if a student leaves during a lesson
160 if ($pageid == LESSON_UNSEENBRANCHPAGE) {
161 $pageid = lesson_unseen_question_jump($lesson, $USER->id, $pageid);
164 // display individual pages and their sets of answers
165 // if pageid is EOL then the end of the lesson has been reached
166 // for flow, changed to simple echo for flow styles, michaelp, moved lesson name and page title down
167 $attemptflag = false;
168 if (empty($pageid)) {
169 // make sure there are pages to view
170 if (!$DB->get_field('lesson_pages', 'id', array('lessonid' => $lesson->id, 'prevpageid' => 0))) {
171 if (!$canmanage) {
172 $lesson->add_message(get_string('lessonnotready2', 'lesson')); // a nice message to the student
173 } else {
174 if (!$DB->count_records('lesson_pages', array('lessonid'=>$lesson->id))) {
175 redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); // no pages - redirect to add pages
176 } else {
177 $lesson->add_message(get_string('lessonpagelinkingbroken', 'lesson')); // ok, bad mojo
182 // if no pageid given see if the lesson has been started
183 $retries = $DB->count_records('lesson_grades', array("lessonid" => $lesson->id, "userid" => $USER->id));
184 if ($retries > 0) {
185 $attemptflag = true;
188 if (isset($USER->modattempts[$lesson->id])) {
189 unset($USER->modattempts[$lesson->id]); // if no pageid, then student is NOT reviewing
192 // If there are any questions that have been answered correctly (or not) in this attempt.
193 $allattempts = $lesson->get_attempts($retries);
194 if (!empty($allattempts)) {
195 $attempt = end($allattempts);
196 $attemptpage = $lesson->load_page($attempt->pageid);
197 $jumpto = $DB->get_field('lesson_answers', 'jumpto', array('id' => $attempt->answerid));
198 // convert the jumpto to a proper page id
199 if ($jumpto == 0) {
200 // Check if a question has been incorrectly answered AND no more attempts at it are left.
201 $nattempts = $lesson->get_attempts($attempt->retry, false, $attempt->pageid, $USER->id);
202 if (count($nattempts) >= $lesson->maxattempts) {
203 $lastpageseen = $lesson->get_next_page($attemptpage->nextpageid);
204 } else {
205 $lastpageseen = $attempt->pageid;
207 } elseif ($jumpto == LESSON_NEXTPAGE) {
208 $lastpageseen = $lesson->get_next_page($attemptpage->nextpageid);
209 } else {
210 $lastpageseen = $jumpto;
214 if ($branchtables = $DB->get_records('lesson_branch', array("lessonid" => $lesson->id, "userid" => $USER->id, "retry" => $retries), 'timeseen DESC')) {
215 // in here, user has viewed a branch table
216 $lastbranchtable = current($branchtables);
217 if (count($allattempts) > 0) {
218 if ($lastbranchtable->timeseen > $attempt->timeseen) {
219 // This branch table was viewed more recently than the question page.
220 $lastpageseen = $lastbranchtable->pageid;
222 } else {
223 // hasnt answered any questions but has viewed a branch table
224 $lastpageseen = $lastbranchtable->pageid;
227 if (isset($lastpageseen) && $DB->count_records('lesson_attempts', array('lessonid'=>$lesson->id, 'userid'=>$USER->id, 'retry'=>$retries)) > 0) {
228 echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('leftduringtimedsession', 'lesson'));
229 if ($lesson->timed) {
230 if ($lesson->retake) {
231 $continuelink = new single_button(new moodle_url('/mod/lesson/view.php', array('id'=>$cm->id, 'pageid'=>$lesson->firstpageid, 'startlastseen'=>'no')), get_string('continue', 'lesson'), 'get');
232 echo '<div class="center leftduring">'.$lessonoutput->message(get_string('leftduringtimed', 'lesson'), $continuelink).'</div>';
233 } else {
234 $courselink = new single_button(new moodle_url('/course/view.php', array('id'=>$PAGE->course->id)), get_string('returntocourse', 'lesson'), 'get');
235 echo '<div class="center leftduring">'.$lessonoutput->message(get_string('leftduringtimednoretake', 'lesson'), $courselink).'</div>';
237 } else {
238 echo $lessonoutput->continue_links($lesson, $lastpageseen);
240 echo $lessonoutput->footer();
241 exit();
244 if ($attemptflag) {
245 if (!$lesson->retake) {
246 echo $lessonoutput->header($lesson, $cm, 'view', '', null, get_string("noretake", "lesson"));
247 $courselink = new single_button(new moodle_url('/course/view.php', array('id'=>$PAGE->course->id)), get_string('returntocourse', 'lesson'), 'get');
248 echo $lessonoutput->message(get_string("noretake", "lesson"), $courselink);
249 echo $lessonoutput->footer();
250 exit();
253 // start at the first page
254 if (!$pageid = $DB->get_field('lesson_pages', 'id', array('lessonid' => $lesson->id, 'prevpageid' => 0))) {
255 print_error('cannotfindfirstpage', 'lesson');
257 /// This is the code for starting a timed test
258 if(!isset($USER->startlesson[$lesson->id]) && !$canmanage) {
259 $lesson->start_timer();
263 $currenttab = 'view';
264 $extraeditbuttons = false;
265 $lessonpageid = null;
266 $timer = null;
268 if ($pageid != LESSON_EOL) {
269 /// This is the code updates the lessontime for a timed test
270 $startlastseen = optional_param('startlastseen', '', PARAM_ALPHA);
272 $page = $lesson->load_page($pageid);
273 // Check if the page is of a special type and if so take any nessecary action
274 $newpageid = $page->callback_on_view($canmanage);
275 if (is_numeric($newpageid)) {
276 $page = $lesson->load_page($newpageid);
279 // Trigger module viewed event.
280 $event = \mod_lesson\event\course_module_viewed::create(array(
281 'objectid' => $lesson->id,
282 'context' => $context
284 $event->add_record_snapshot('course_modules', $cm);
285 $event->add_record_snapshot('course', $course);
286 $event->trigger();
288 // This is where several messages (usually warnings) are displayed
289 // all of this is displayed above the actual page
291 // check to see if the user can see the left menu
292 if (!$canmanage) {
293 $lesson->displayleft = lesson_displayleftif($lesson);
295 $continue = ($startlastseen !== '');
296 $restart = ($continue && $startlastseen == 'yes');
297 $timer = $lesson->update_timer($continue, $restart);
299 if ($lesson->timed) {
300 $timeleft = ($timer->starttime + $lesson->maxtime * 60) - time();
301 if ($timeleft <= 0) {
302 // Out of time
303 $lesson->add_message(get_string('eolstudentoutoftime', 'lesson'));
304 redirect(new moodle_url('/mod/lesson/view.php', array('id'=>$cm->id,'pageid'=>LESSON_EOL, 'outoftime'=>'normal')));
305 die; // Shouldn't be reached, but make sure
306 } else if ($timeleft < 60) {
307 // One minute warning
308 $lesson->add_message(get_string('studentoneminwarning', 'lesson'));
312 if ($page->qtype == LESSON_PAGE_BRANCHTABLE && $lesson->minquestions) {
313 // tell student how many questions they have seen, how many are required and their grade
314 $ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id));
315 $gradeinfo = lesson_grade($lesson, $ntries);
316 if ($gradeinfo->attempts) {
317 if ($gradeinfo->nquestions < $lesson->minquestions) {
318 $a = new stdClass;
319 $a->nquestions = $gradeinfo->nquestions;
320 $a->minquestions = $lesson->minquestions;
321 $lesson->add_message(get_string('numberofpagesviewednotice', 'lesson', $a));
324 $a = new stdClass;
325 $a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1);
326 $a->total = $lesson->grade;
327 if (!$reviewmode && !$lesson->retake){
328 $lesson->add_message(get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned), 'notify');
329 $lesson->add_message(get_string('yourcurrentgradeisoutof', 'lesson', $a), 'notify');
333 } else {
334 $timer = null;
335 if ($lesson->timed) {
336 $lesson->add_message(get_string('teachertimerwarning', 'lesson'));
338 if (lesson_display_teacher_warning($lesson)) {
339 // This is the warning msg for teachers to inform them that cluster
340 // and unseen does not work while logged in as a teacher
341 $warningvars = new stdClass();
342 $warningvars->cluster = get_string('clusterjump', 'lesson');
343 $warningvars->unseen = get_string('unseenpageinbranch', 'lesson');
344 $lesson->add_message(get_string('teacherjumpwarning', 'lesson', $warningvars));
348 $PAGE->set_subpage($page->id);
349 $currenttab = 'view';
350 $extraeditbuttons = true;
351 $lessonpageid = $page->id;
352 $extrapagetitle = $page->title;
354 if (($edit != -1) && $PAGE->user_allowed_editing()) {
355 $USER->editing = $edit;
358 if (is_array($page->answers) && count($page->answers)>0) {
359 // this is for modattempts option. Find the users previous answer to this page,
360 // and then display it below in answer processing
361 if (isset($USER->modattempts[$lesson->id])) {
362 $retries = $DB->count_records('lesson_grades', array("lessonid"=>$lesson->id, "userid"=>$USER->id));
363 if (!$attempts = $lesson->get_attempts($retries-1, false, $page->id)) {
364 print_error('cannotfindpreattempt', 'lesson');
366 $attempt = end($attempts);
367 $USER->modattempts[$lesson->id] = $attempt;
368 } else {
369 $attempt = false;
371 $lessoncontent = $lessonoutput->display_page($lesson, $page, $attempt);
372 } else {
373 $data = new stdClass;
374 $data->id = $PAGE->cm->id;
375 $data->pageid = $page->id;
376 $data->newpageid = $lesson->get_next_page($page->nextpageid);
378 $customdata = array(
379 'title' => $page->title,
380 'contents' => $page->get_contents()
382 $mform = new lesson_page_without_answers($CFG->wwwroot.'/mod/lesson/continue.php', $customdata);
383 $mform->set_data($data);
384 ob_start();
385 $mform->display();
386 $lessoncontent = ob_get_contents();
387 ob_end_clean();
390 lesson_add_fake_blocks($PAGE, $cm, $lesson, $timer);
391 echo $lessonoutput->header($lesson, $cm, $currenttab, $extraeditbuttons, $lessonpageid, $extrapagetitle);
392 if ($attemptflag) {
393 // We are using level 3 header because attempt heading is a sub-heading of lesson title (MDL-30911).
394 echo $OUTPUT->heading(get_string('attempt', 'lesson', $retries), 3);
396 /// This calculates and prints the ongoing score
397 if ($lesson->ongoing && !empty($pageid) && !$reviewmode) {
398 echo $lessonoutput->ongoing_score($lesson);
400 if ($lesson->displayleft) {
401 echo '<a name="maincontent" id="maincontent" title="' . get_string('anchortitle', 'lesson') . '"></a>';
403 echo $lessoncontent;
404 echo $lessonoutput->progress_bar($lesson);
405 echo $lessonoutput->footer();
407 } else {
409 $lessoncontent = '';
410 // end of lesson reached work out grade
411 // Used to check to see if the student ran out of time
412 $outoftime = optional_param('outoftime', '', PARAM_ALPHA);
414 $ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id));
415 if (isset($USER->modattempts[$lesson->id])) {
416 $ntries--; // need to look at the old attempts :)
419 $gradelesson = true;
420 $gradeinfo = lesson_grade($lesson, $ntries);
421 if ($lesson->custom && !$canmanage) {
422 // Before we calculate the custom score make sure they answered the minimum
423 // number of questions. We only need to do this for custom scoring as we can
424 // not get the miniumum score the user should achieve. If we are not using
425 // custom scoring (so all questions are valued as 1) then we simply check if
426 // they answered more than the minimum questions, if not, we mark it out of the
427 // number specified in the minimum questions setting - which is done in lesson_grade().
428 // Get the number of answers given.
429 if ($gradeinfo->nquestions < $lesson->minquestions) {
430 $gradelesson = false;
431 $a = new stdClass;
432 $a->nquestions = $gradeinfo->nquestions;
433 $a->minquestions = $lesson->minquestions;
434 $lessoncontent .= $OUTPUT->box_start('generalbox boxaligncenter');
435 $lesson->add_message(get_string('numberofpagesviewednotice', 'lesson', $a));
438 if ($gradelesson) {
439 // We are using level 3 header because the page title is a sub-heading of lesson title (MDL-30911).
440 $lessoncontent .= $OUTPUT->heading(get_string("congratulations", "lesson"), 3);
441 $lessoncontent .= $OUTPUT->box_start('generalbox boxaligncenter');
443 if (!$canmanage) {
444 if ($gradelesson) {
445 // Update the clock / get time information for this user.
446 $lesson->stop_timer();
447 $gradeinfo = lesson_grade($lesson, $ntries);
449 if ($gradeinfo->attempts) {
450 if (!$lesson->custom) {
451 $lessoncontent .= $lessonoutput->paragraph(get_string("numberofpagesviewed", "lesson", $gradeinfo->nquestions), 'center');
452 if ($lesson->minquestions) {
453 if ($gradeinfo->nquestions < $lesson->minquestions) {
454 // print a warning and set nviewed to minquestions
455 $lessoncontent .= $lessonoutput->paragraph(get_string("youshouldview", "lesson", $lesson->minquestions), 'center');
458 $lessoncontent .= $lessonoutput->paragraph(get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned), 'center');
460 $a = new stdClass;
461 $a->score = $gradeinfo->earned;
462 $a->grade = $gradeinfo->total;
463 if ($gradeinfo->nmanual) {
464 $a->tempmaxgrade = $gradeinfo->total - $gradeinfo->manualpoints;
465 $a->essayquestions = $gradeinfo->nmanual;
466 $lessoncontent .= $OUTPUT->box(get_string("displayscorewithessays", "lesson", $a), 'center');
467 } else {
468 $lessoncontent .= $OUTPUT->box(get_string("displayscorewithoutessays", "lesson", $a), 'center');
470 $a = new stdClass;
471 $a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1);
472 $a->total = $lesson->grade;
473 $lessoncontent .= $lessonoutput->paragraph(get_string("yourcurrentgradeisoutof", "lesson", $a), 'center');
475 $grade = new stdClass();
476 $grade->lessonid = $lesson->id;
477 $grade->userid = $USER->id;
478 $grade->grade = $gradeinfo->grade;
479 $grade->completed = time();
480 if (!$lesson->practice) {
481 if (isset($USER->modattempts[$lesson->id])) { // if reviewing, make sure update old grade record
482 if (!$grades = $DB->get_records("lesson_grades", array("lessonid" => $lesson->id, "userid" => $USER->id), "completed DESC", '*', 0, 1)) {
483 print_error('cannotfindgrade', 'lesson');
485 $oldgrade = array_shift($grades);
486 $grade->id = $oldgrade->id;
487 $DB->update_record("lesson_grades", $grade);
488 } else {
489 $newgradeid = $DB->insert_record("lesson_grades", $grade);
491 } else {
492 $DB->delete_records("lesson_attempts", array("lessonid" => $lesson->id, "userid" => $USER->id, "retry" => $ntries));
494 } else {
495 if ($lesson->timed) {
496 if ($outoftime == 'normal') {
497 $grade = new stdClass();
498 $grade->lessonid = $lesson->id;
499 $grade->userid = $USER->id;
500 $grade->grade = 0;
501 $grade->completed = time();
502 if (!$lesson->practice) {
503 $newgradeid = $DB->insert_record("lesson_grades", $grade);
505 $lessoncontent .= get_string("eolstudentoutoftimenoanswers", "lesson");
507 } else {
508 $lessoncontent .= get_string("welldone", "lesson");
512 // update central gradebook
513 lesson_update_grades($lesson, $USER->id);
515 } else {
516 // display for teacher
517 $lessoncontent .= $lessonoutput->paragraph(get_string("displayofgrade", "lesson"), 'center');
519 $lessoncontent .= $OUTPUT->box_end(); //End of Lesson button to Continue.
521 // high scores code
522 if ($lesson->highscores && !$canmanage && !$lesson->practice) {
523 $lessoncontent .= $OUTPUT->box_start('center');
524 if ($grades = $DB->get_records("lesson_grades", array("lessonid" => $lesson->id), "completed")) {
525 $madeit = false;
526 if ($highscores = $DB->get_records("lesson_high_scores", array("lessonid" => $lesson->id))) {
527 // get all the high scores into an array
528 $topscores = array();
529 $uniquescores = array();
530 foreach ($highscores as $highscore) {
531 $grade = $grades[$highscore->gradeid]->grade;
532 $topscores[] = $grade;
533 $uniquescores[$grade] = 1;
535 // sort to find the lowest score
536 sort($topscores);
537 $lowscore = $topscores[0];
539 if ($gradeinfo->grade >= $lowscore || count($uniquescores) <= $lesson->maxhighscores) {
540 $madeit = true;
543 if (!$highscores or $madeit) {
544 $lessoncontent .= $lessonoutput->paragraph(get_string("youmadehighscore", "lesson", $lesson->maxhighscores), 'center');
545 $aurl = new moodle_url('/mod/lesson/highscores.php', array('id'=>$PAGE->cm->id, 'sesskey'=>sesskey()));
546 $lessoncontent .= $OUTPUT->single_button($aurl, get_string('clicktopost', 'lesson'));
547 } else {
548 $lessoncontent .= get_string("nothighscore", "lesson", $lesson->maxhighscores)."<br />";
551 $url = new moodle_url('/mod/lesson/highscores.php', array('id'=>$PAGE->cm->id, 'link'=>'1'));
552 $lessoncontent .= html_writer::link($url, get_string('viewhighscores', 'lesson'), array('class'=>'centerpadded lessonbutton standardbutton'));
553 $lessoncontent .= $OUTPUT->box_end();
556 if ($lesson->modattempts && !$canmanage) {
557 // make sure if the student is reviewing, that he/she sees the same pages/page path that he/she saw the first time
558 // look at the attempt records to find the first QUESTION page that the user answered, then use that page id
559 // to pass to view again. This is slick cause it wont call the empty($pageid) code
560 // $ntries is decremented above
561 if (!$attempts = $lesson->get_attempts($ntries)) {
562 $attempts = array();
563 $url = new moodle_url('/mod/lesson/view.php', array('id'=>$PAGE->cm->id));
564 } else {
565 $firstattempt = current($attempts);
566 $pageid = $firstattempt->pageid;
567 // IF the student wishes to review, need to know the last question page that the student answered. This will help to make
568 // sure that the student can leave the lesson via pushing the continue button.
569 $lastattempt = end($attempts);
570 $USER->modattempts[$lesson->id] = $lastattempt->pageid;
572 $url = new moodle_url('/mod/lesson/view.php', array('id'=>$PAGE->cm->id, 'pageid'=>$pageid));
574 $lessoncontent .= html_writer::link($url, get_string('reviewlesson', 'lesson'), array('class' => 'centerpadded lessonbutton standardbutton'));
575 } elseif ($lesson->modattempts && $canmanage) {
576 $lessoncontent .= $lessonoutput->paragraph(get_string("modattemptsnoteacher", "lesson"), 'centerpadded');
579 if ($lesson->activitylink) {
580 $lessoncontent .= $lesson->link_for_activitylink();
583 $url = new moodle_url('/course/view.php', array('id'=>$course->id));
584 $lessoncontent .= html_writer::link($url, get_string('returnto', 'lesson', format_string($course->fullname, true)), array('class'=>'centerpadded lessonbutton standardbutton'));
586 if (has_capability('gradereport/user:view', context_course::instance($course->id))
587 && $course->showgrades && $lesson->grade != 0 && !$lesson->practice) {
588 $url = new moodle_url('/grade/index.php', array('id' => $course->id));
589 $lessoncontent .= html_writer::link($url, get_string('viewgrades', 'lesson'),
590 array('class' => 'centerpadded lessonbutton standardbutton'));
593 lesson_add_fake_blocks($PAGE, $cm, $lesson, $timer);
594 echo $lessonoutput->header($lesson, $cm, $currenttab, $extraeditbuttons, $lessonpageid, get_string("congratulations", "lesson"));
595 echo $lessoncontent;
596 echo $lessonoutput->footer();