Merge branch 'MDL-40054_master' of https://github.com/markn86/moodle
[moodle.git] / mod / lesson / view.php
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.
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/>.
18 /**
19  * This page prints a particular instance of lesson
20  *
21  * @package    mod
22  * @subpackage lesson
23  * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
24  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late
25  **/
27 require_once(dirname(__FILE__) . '/../../config.php');
28 require_once($CFG->dirroot.'/mod/lesson/locallib.php');
29 require_once($CFG->dirroot.'/mod/lesson/view_form.php');
30 require_once($CFG->libdir . '/completionlib.php');
32 $id      = required_param('id', PARAM_INT);             // Course Module ID
33 $pageid  = optional_param('pageid', null, PARAM_INT);   // Lesson Page ID
34 $edit    = optional_param('edit', -1, PARAM_BOOL);
35 $userpassword = optional_param('userpassword','',PARAM_RAW);
36 $backtocourse = optional_param('backtocourse', false, PARAM_RAW);
38 $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);
39 $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
40 $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST));
42 require_login($course, false, $cm);
44 if ($backtocourse) {
45     redirect(new moodle_url('/course/view.php', array('id'=>$course->id)));
46 }
48 // Mark as viewed
49 $completion = new completion_info($course);
50 $completion->set_module_viewed($cm);
52 $url = new moodle_url('/mod/lesson/view.php', array('id'=>$id));
53 if ($pageid !== null) {
54     $url->param('pageid', $pageid);
55 }
56 $PAGE->set_url($url);
58 $context = context_module::instance($cm->id);
59 $canmanage = has_capability('mod/lesson:manage', $context);
61 $lessonoutput = $PAGE->get_renderer('mod_lesson');
63 $reviewmode = false;
64 $userhasgrade = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id));
65 if ($userhasgrade && !$lesson->retake) {
66     $reviewmode = true;
67 }
69 /// Check these for students only TODO: Find a better method for doing this!
70 ///     Check lesson availability
71 ///     Check for password
72 ///     Check dependencies
73 ///     Check for high scores
74 if (!$canmanage) {
75     if (!$lesson->is_accessible()) {  // Deadline restrictions
76         echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('notavailable'));
77         if ($lesson->deadline != 0 && time() > $lesson->deadline) {
78             echo $lessonoutput->lesson_inaccessible(get_string('lessonclosed', 'lesson', userdate($lesson->deadline)));
79         } else {
80             echo $lessonoutput->lesson_inaccessible(get_string('lessonopen', 'lesson', userdate($lesson->available)));
81         }
82         echo $lessonoutput->footer();
83         exit();
84     } else if ($lesson->usepassword && empty($USER->lessonloggedin[$lesson->id])) { // Password protected lesson code
85         $correctpass = false;
86         if (!empty($userpassword) && (($lesson->password == md5(trim($userpassword))) || ($lesson->password == trim($userpassword)))) {
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");
92             }
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();
98         }
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;
115                         }
116                     }
117                 }
118                 if (!$timespent) {
119                     $errors[] = get_string('timespenterror', 'lesson', $conditions->timespent);
120                 }
121             }
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;
131                         }
132                     }
133                 }
134                 if (!$gradebetterthan) {
135                     $errors[] = get_string('gradebetterthanerror', 'lesson', $conditions->gradebetterthan);
136                 }
137             }
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');
143                 }
144             }
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();
151             }
152         }
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)));
156     }
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
178             }
179         }
180     }
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;
186     }
188     if (isset($USER->modattempts[$lesson->id])) {
189         unset($USER->modattempts[$lesson->id]);  // if no pageid, then student is NOT reviewing
190     }
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;
206             }
207         } elseif ($jumpto == LESSON_NEXTPAGE) {
208             $lastpageseen = $lesson->get_next_page($attemptpage->nextpageid);
209         } else {
210             $lastpageseen = $jumpto;
211         }
212     }
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             foreach($allattempts as $attempt) {
219                 if ($lastbranchtable->timeseen > $attempt->timeseen) {
220                     // branch table was viewed later than the last attempt
221                     $lastpageseen = $lastbranchtable->pageid;
222                 }
223                 break;
224             }
225         } else {
226             // hasnt answered any questions but has viewed a branch table
227             $lastpageseen = $lastbranchtable->pageid;
228         }
229     }
230     if (isset($lastpageseen) && $DB->count_records('lesson_attempts', array('lessonid'=>$lesson->id, 'userid'=>$USER->id, 'retry'=>$retries)) > 0) {
231         echo $lessonoutput->header($lesson, $cm, '', false, null, get_string('leftduringtimedsession', 'lesson'));
232         if ($lesson->timed) {
233             if ($lesson->retake) {
234                 $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');
235                 echo '<div class="center leftduring">'.$lessonoutput->message(get_string('leftduringtimed', 'lesson'), $continuelink).'</div>';
236             } else {
237                 $courselink = new single_button(new moodle_url('/course/view.php', array('id'=>$PAGE->course->id)), get_string('returntocourse', 'lesson'), 'get');
238                 echo '<div class="center leftduring">'.$lessonoutput->message(get_string('leftduringtimednoretake', 'lesson'), $courselink).'</div>';
239             }
240         } else {
241             echo $lessonoutput->continue_links($lesson, $lastpageseen);
242         }
243         echo $lessonoutput->footer();
244         exit();
245     }
247     if ($attemptflag) {
248         if (!$lesson->retake) {
249             echo $lessonoutput->header($lesson, $cm, 'view', '', null, get_string("noretake", "lesson"));
250             $courselink = new single_button(new moodle_url('/course/view.php', array('id'=>$PAGE->course->id)), get_string('returntocourse', 'lesson'), 'get');
251             echo $lessonoutput->message(get_string("noretake", "lesson"), $courselink);
252             echo $lessonoutput->footer();
253             exit();
254         }
255     }
256     // start at the first page
257     if (!$pageid = $DB->get_field('lesson_pages', 'id', array('lessonid' => $lesson->id, 'prevpageid' => 0))) {
258             print_error('cannotfindfirstpage', 'lesson');
259     }
260     /// This is the code for starting a timed test
261     if(!isset($USER->startlesson[$lesson->id]) && !$canmanage) {
262         $lesson->start_timer();
263     }
266 $currenttab = 'view';
267 $extraeditbuttons = false;
268 $lessonpageid = null;
269 $timer = null;
271 if ($pageid != LESSON_EOL) {
272     /// This is the code updates the lessontime for a timed test
273     $startlastseen = optional_param('startlastseen', '', PARAM_ALPHA);
274     if ($startlastseen == 'no') {
275         // this deletes old records  not totally sure if this is necessary anymore
276         $retries = $DB->count_records('lesson_grades', array('lessonid'=>$lesson->id, 'userid'=>$USER->id));
277         $DB->delete_records('lesson_attempts', array('userid' => $USER->id, 'lessonid' => $lesson->id, 'retry' => $retries));
278         $DB->delete_records('lesson_branch', array('userid' => $USER->id, 'lessonid' => $lesson->id, 'retry' => $retries));
279     }
281     $page = $lesson->load_page($pageid);
282     // Check if the page is of a special type and if so take any nessecary action
283     $newpageid = $page->callback_on_view($canmanage);
284     if (is_numeric($newpageid)) {
285         $page = $lesson->load_page($newpageid);
286     }
288     // Trigger module viewed event.
289     $event = \mod_lesson\event\course_module_viewed::create(array(
290         'objectid' => $lesson->id,
291         'context' => $context,
292         'courseid' => $course->id
293     ));
294     $event->trigger();
296     // This is where several messages (usually warnings) are displayed
297     // all of this is displayed above the actual page
299     // check to see if the user can see the left menu
300     if (!$canmanage) {
301         $lesson->displayleft = lesson_displayleftif($lesson);
303         $continue = ($startlastseen !== '');
304         $restart  = ($continue && $startlastseen == 'yes');
305         $timer = $lesson->update_timer($continue, $restart);
307         if ($lesson->timed) {
308             $timeleft = ($timer->starttime + $lesson->maxtime * 60) - time();
309             if ($timeleft <= 0) {
310                 // Out of time
311                 $lesson->add_message(get_string('eolstudentoutoftime', 'lesson'));
312                 redirect(new moodle_url('/mod/lesson/view.php', array('id'=>$cm->id,'pageid'=>LESSON_EOL, 'outoftime'=>'normal')));
313                 die; // Shouldn't be reached, but make sure
314             } else if ($timeleft < 60) {
315                 // One minute warning
316                 $lesson->add_message(get_string('studentoneminwarning', 'lesson'));
317             }
318         }
320         if ($page->qtype == LESSON_PAGE_BRANCHTABLE && $lesson->minquestions) {
321             // tell student how many questions they have seen, how many are required and their grade
322             $ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id));
323             $gradeinfo = lesson_grade($lesson, $ntries);
324             if ($gradeinfo->attempts) {
325                 if ($gradeinfo->nquestions < $lesson->minquestions) {
326                     $a = new stdClass;
327                     $a->nquestions   = $gradeinfo->nquestions;
328                     $a->minquestions = $lesson->minquestions;
329                     $lesson->add_message(get_string('numberofpagesviewednotice', 'lesson', $a));
330                 }
332                 $a = new stdClass;
333                 $a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1);
334                 $a->total = $lesson->grade;
335                 if (!$reviewmode && !$lesson->retake){
336                     $lesson->add_message(get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned), 'notify');
337                     $lesson->add_message(get_string('yourcurrentgradeisoutof', 'lesson', $a), 'notify');
338                 }
339             }
340         }
341     } else {
342         $timer = null;
343         if ($lesson->timed) {
344             $lesson->add_message(get_string('teachertimerwarning', 'lesson'));
345         }
346         if (lesson_display_teacher_warning($lesson)) {
347             // This is the warning msg for teachers to inform them that cluster
348             // and unseen does not work while logged in as a teacher
349             $warningvars = new stdClass();
350             $warningvars->cluster = get_string('clusterjump', 'lesson');
351             $warningvars->unseen = get_string('unseenpageinbranch', 'lesson');
352             $lesson->add_message(get_string('teacherjumpwarning', 'lesson', $warningvars));
353         }
354     }
356     $PAGE->set_url('/mod/lesson/view.php', array('id' => $cm->id, 'pageid' => $page->id));
357     $PAGE->set_subpage($page->id);
358     $currenttab = 'view';
359     $extraeditbuttons = true;
360     $lessonpageid = $page->id;
361     $extrapagetitle = $page->title;
363     if (($edit != -1) && $PAGE->user_allowed_editing()) {
364         $USER->editing = $edit;
365     }
367     if (is_array($page->answers) && count($page->answers)>0) {
368         // this is for modattempts option.  Find the users previous answer to this page,
369         //   and then display it below in answer processing
370         if (isset($USER->modattempts[$lesson->id])) {
371             $retries = $DB->count_records('lesson_grades', array("lessonid"=>$lesson->id, "userid"=>$USER->id));
372             if (!$attempts = $lesson->get_attempts($retries-1, false, $page->id)) {
373                 print_error('cannotfindpreattempt', 'lesson');
374             }
375             $attempt = end($attempts);
376             $USER->modattempts[$lesson->id] = $attempt;
377         } else {
378             $attempt = false;
379         }
380         $lessoncontent = $lessonoutput->display_page($lesson, $page, $attempt);
381     } else {
382         $data = new stdClass;
383         $data->id = $PAGE->cm->id;
384         $data->pageid = $page->id;
385         $data->newpageid = $lesson->get_next_page($page->nextpageid);
387         $customdata = array(
388             'title'     => $page->title,
389             'contents'  => $page->get_contents()
390         );
391         $mform = new lesson_page_without_answers($CFG->wwwroot.'/mod/lesson/continue.php', $customdata);
392         $mform->set_data($data);
393         ob_start();
394         $mform->display();
395         $lessoncontent = ob_get_contents();
396         ob_end_clean();
397     }
399     lesson_add_fake_blocks($PAGE, $cm, $lesson, $timer);
400     echo $lessonoutput->header($lesson, $cm, $currenttab, $extraeditbuttons, $lessonpageid, $extrapagetitle);
401     if ($attemptflag) {
402         // We are using level 3 header because attempt heading is a sub-heading of lesson title (MDL-30911).
403         echo $OUTPUT->heading(get_string('attempt', 'lesson', $retries), 3);
404     }
405     /// This calculates and prints the ongoing score
406     if ($lesson->ongoing && !empty($pageid) && !$reviewmode) {
407         echo $lessonoutput->ongoing_score($lesson);
408     }
409     if ($lesson->displayleft) {
410         echo '<a name="maincontent" id="maincontent" title="' . get_string('anchortitle', 'lesson') . '"></a>';
411     }
412     echo $lessoncontent;
413     echo $lessonoutput->slideshow_end();
414     echo $lessonoutput->progress_bar($lesson);
415     echo $lessonoutput->footer();
417 } else {
419     $lessoncontent = '';
420     // end of lesson reached work out grade
421     // Used to check to see if the student ran out of time
422     $outoftime = optional_param('outoftime', '', PARAM_ALPHA);
424     // We are using level 3 header because the page title is a sub-heading of lesson title (MDL-30911).
425     $lessoncontent .= $OUTPUT->heading(get_string("congratulations", "lesson"), 3);
426     $lessoncontent .= $OUTPUT->box_start('generalbox boxaligncenter');
427     $ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id));
428     if (isset($USER->modattempts[$lesson->id])) {
429         $ntries--;  // need to look at the old attempts :)
430     }
431     if (!$canmanage) {
432         // Update the clock / get time information for this user.
433         $lesson->stop_timer();
434         $gradeinfo = lesson_grade($lesson, $ntries);
436         if ($gradeinfo->attempts) {
437             if (!$lesson->custom) {
438                 $lessoncontent .= $lessonoutput->paragraph(get_string("numberofpagesviewed", "lesson", $gradeinfo->nquestions), 'center');
439                 if ($lesson->minquestions) {
440                     if ($gradeinfo->nquestions < $lesson->minquestions) {
441                         // print a warning and set nviewed to minquestions
442                         $lessoncontent .= $lessonoutput->paragraph(get_string("youshouldview", "lesson", $lesson->minquestions), 'center');
443                     }
444                 }
445                 $lessoncontent .= $lessonoutput->paragraph(get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned), 'center');
446             }
447             $a = new stdClass;
448             $a->score = $gradeinfo->earned;
449             $a->grade = $gradeinfo->total;
450             if ($gradeinfo->nmanual) {
451                 $a->tempmaxgrade = $gradeinfo->total - $gradeinfo->manualpoints;
452                 $a->essayquestions = $gradeinfo->nmanual;
453                 $lessoncontent .= $OUTPUT->box(get_string("displayscorewithessays", "lesson", $a), 'center');
454             } else {
455                 $lessoncontent .= $OUTPUT->box(get_string("displayscorewithoutessays", "lesson", $a), 'center');
456             }
457             $a = new stdClass;
458             $a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1);
459             $a->total = $lesson->grade;
460             $lessoncontent .= $lessonoutput->paragraph(get_string("yourcurrentgradeisoutof", "lesson", $a), 'center');
462             $grade = new stdClass();
463             $grade->lessonid = $lesson->id;
464             $grade->userid = $USER->id;
465             $grade->grade = $gradeinfo->grade;
466             $grade->completed = time();
467             if (!$lesson->practice) {
468                 if (isset($USER->modattempts[$lesson->id])) { // if reviewing, make sure update old grade record
469                     if (!$grades = $DB->get_records("lesson_grades", array("lessonid" => $lesson->id, "userid" => $USER->id), "completed DESC", '*', 0, 1)) {
470                         print_error('cannotfindgrade', 'lesson');
471                     }
472                     $oldgrade = array_shift($grades);
473                     $grade->id = $oldgrade->id;
474                     $DB->update_record("lesson_grades", $grade);
475                 } else {
476                     $newgradeid = $DB->insert_record("lesson_grades", $grade);
477                 }
478             } else {
479                 $DB->delete_records("lesson_attempts", array("lessonid" => $lesson->id, "userid" => $USER->id, "retry" => $ntries));
480             }
481         } else {
482             if ($lesson->timed) {
483                 if ($outoftime == 'normal') {
484                     $grade = new stdClass();
485                     $grade->lessonid = $lesson->id;
486                     $grade->userid = $USER->id;
487                     $grade->grade = 0;
488                     $grade->completed = time();
489                     if (!$lesson->practice) {
490                         $newgradeid = $DB->insert_record("lesson_grades", $grade);
491                     }
492                     $lessoncontent .= get_string("eolstudentoutoftimenoanswers", "lesson");
493                 }
494             } else {
495                 $lessoncontent .= get_string("welldone", "lesson");
496             }
497         }
499         // update central gradebook
500         lesson_update_grades($lesson, $USER->id);
502     } else {
503         // display for teacher
504         $lessoncontent .= $lessonoutput->paragraph(get_string("displayofgrade", "lesson"), 'center');
505     }
506     $lessoncontent .= $OUTPUT->box_end(); //End of Lesson button to Continue.
508     // after all the grade processing, check to see if "Show Grades" is off for the course
509     // if yes, redirect to the course page
510     if (!$course->showgrades) {
511         redirect(new moodle_url('/course/view.php', array('id'=>$course->id)));
512     }
514     // high scores code
515     if ($lesson->highscores && !$canmanage && !$lesson->practice) {
516         $lessoncontent .= $OUTPUT->box_start('center');
517         if ($grades = $DB->get_records("lesson_grades", array("lessonid" => $lesson->id), "completed")) {
518             $madeit = false;
519             if ($highscores = $DB->get_records("lesson_high_scores", array("lessonid" => $lesson->id))) {
520                 // get all the high scores into an array
521                 $topscores = array();
522                 $uniquescores = array();
523                 foreach ($highscores as $highscore) {
524                     $grade = $grades[$highscore->gradeid]->grade;
525                     $topscores[] = $grade;
526                     $uniquescores[$grade] = 1;
527                 }
528                 // sort to find the lowest score
529                 sort($topscores);
530                 $lowscore = $topscores[0];
532                 if ($gradeinfo->grade >= $lowscore || count($uniquescores) <= $lesson->maxhighscores) {
533                     $madeit = true;
534                 }
535             }
536             if (!$highscores or $madeit) {
537                 $lessoncontent .= $lessonoutput->paragraph(get_string("youmadehighscore", "lesson", $lesson->maxhighscores), 'center');
538                 $aurl = new moodle_url('/mod/lesson/highscores.php', array('id'=>$PAGE->cm->id, 'sesskey'=>sesskey()));
539                 $lessoncontent .= $OUTPUT->single_button($aurl, get_string('clicktopost', 'lesson'));
540             } else {
541                 $lessoncontent .= get_string("nothighscore", "lesson", $lesson->maxhighscores)."<br />";
542             }
543         }
544         $url = new moodle_url('/mod/lesson/highscores.php', array('id'=>$PAGE->cm->id, 'link'=>'1'));
545         $lessoncontent .= html_writer::link($url, get_string('viewhighscores', 'lesson'), array('class'=>'centerpadded lessonbutton standardbutton'));
546         $lessoncontent .= $OUTPUT->box_end();
547     }
549     if ($lesson->modattempts && !$canmanage) {
550         // make sure if the student is reviewing, that he/she sees the same pages/page path that he/she saw the first time
551         // look at the attempt records to find the first QUESTION page that the user answered, then use that page id
552         // to pass to view again.  This is slick cause it wont call the empty($pageid) code
553         // $ntries is decremented above
554         if (!$attempts = $lesson->get_attempts($ntries)) {
555             $attempts = array();
556             $url = new moodle_url('/mod/lesson/view.php', array('id'=>$PAGE->cm->id));
557         } else {
558             $firstattempt = current($attempts);
559             $pageid = $firstattempt->pageid;
560             // IF the student wishes to review, need to know the last question page that the student answered.  This will help to make
561             // sure that the student can leave the lesson via pushing the continue button.
562             $lastattempt = end($attempts);
563             $USER->modattempts[$lesson->id] = $lastattempt->pageid;
565             $url = new moodle_url('/mod/lesson/view.php', array('id'=>$PAGE->cm->id, 'pageid'=>$pageid));
566         }
567         $lessoncontent .= html_writer::link($url, get_string('reviewlesson', 'lesson'), array('class' => 'centerpadded lessonbutton standardbutton'));
568     } elseif ($lesson->modattempts && $canmanage) {
569         $lessoncontent .= $lessonoutput->paragraph(get_string("modattemptsnoteacher", "lesson"), 'centerpadded');
570     }
572     if ($lesson->activitylink) {
573         $lessoncontent .= $lesson->link_for_activitylink();
574     }
576     $url = new moodle_url('/course/view.php', array('id'=>$course->id));
577     $lessoncontent .= html_writer::link($url, get_string('returnto', 'lesson', format_string($course->fullname, true)), array('class'=>'centerpadded lessonbutton standardbutton'));
579     $url = new moodle_url('/grade/index.php', array('id'=>$course->id));
580     $lessoncontent .= html_writer::link($url, get_string('viewgrades', 'lesson'), array('class'=>'centerpadded lessonbutton standardbutton'));
582     lesson_add_fake_blocks($PAGE, $cm, $lesson, $timer);
583     echo $lessonoutput->header($lesson, $cm, $currenttab, $extraeditbuttons, $lessonpageid, get_string("congratulations", "lesson"));
584     echo $lessoncontent;
585     echo $lessonoutput->footer();