MDL-11082 Improved groups upgrade performance 1.8x -> 1.9; thanks Eloy for telling...
[moodle-pu.git] / mod / lesson / view.php
blob5f43117b560b51dcdd304a19836b52406dca195f
1 <?php // $Id$
2 /**
3 * This page prints a particular instance of lesson
5 * @version $Id$
6 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
7 * @package lesson
8 **/
10 require_once('../../config.php');
11 require_once($CFG->dirroot.'/mod/lesson/locallib.php');
12 require_once($CFG->dirroot.'/mod/lesson/lib.php');
13 require_once($CFG->dirroot.'/mod/lesson/pagelib.php');
14 require_once($CFG->libdir.'/blocklib.php');
16 $id = required_param('id', PARAM_INT); // Course Module ID
17 $pageid = optional_param('pageid', NULL, PARAM_INT); // Lesson Page ID
18 $edit = optional_param('edit', -1, PARAM_BOOL);
20 list($cm, $course, $lesson) = lesson_get_basics($id);
22 require_login($course->id, false, $cm);
24 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
26 /// Check these for students only TODO: Find a better method for doing this!
27 /// Check lesson availability
28 /// Check for password
29 /// Check dependencies
30 /// Check for high scores
31 if (!has_capability('mod/lesson:manage', $context)) {
33 if (($lesson->available != 0 and time() < $lesson->available) or
34 ($lesson->deadline != 0 and time() > $lesson->deadline)) { // Deadline restrictions
35 if ($lesson->deadline != 0 and time() > $lesson->deadline) {
36 $message = get_string('lessonclosed', 'lesson', userdate($lesson->deadline));
37 } else {
38 $message = get_string('lessonopen', 'lesson', userdate($lesson->available));
41 lesson_print_header($cm, $course, $lesson);
42 print_simple_box_start('center');
43 echo '<div style="text-align:center;">';
44 echo '<p>'.$message.'</p>';
45 echo '<div class="lessonbutton standardbutton" style="padding: 5px;"><a href="'.$CFG->wwwroot.'/course/view.php?id='. $course->id .'">'. get_string('returnto', 'lesson', format_string($course->fullname, true)) .'</a></div>';
46 echo '</div>';
47 print_simple_box_end();
48 print_footer($course);
49 exit();
51 } else if ($lesson->usepassword and empty($USER->lessonloggedin[$lesson->id])) { // Password protected lesson code
52 $correctpass = false;
53 if ($password = optional_param('userpassword', '', PARAM_CLEAN)) {
54 if ($lesson->password == md5(trim($password))) {
55 $USER->lessonloggedin[$lesson->id] = true;
56 $correctpass = true;
57 if ($lesson->highscores) {
58 // Logged in - redirect so we go through all of these checks before starting the lesson.
59 redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id");
64 if (!$correctpass) {
65 lesson_print_header($cm, $course, $lesson);
66 echo "<div class=\"password-form\">\n";
67 print_simple_box_start('center');
68 echo '<form id="password" method="post" action="'.$CFG->wwwroot.'/mod/lesson/view.php" autocomplete="off">' . "\n";
69 echo '<fieldset class="invisiblefieldset">';
70 echo '<input type="hidden" name="id" value="'. $cm->id .'" />' . "\n";
71 if (optional_param('userpassword', 0, PARAM_CLEAN)) {
72 notify(get_string('loginfail', 'lesson'));
75 echo get_string('passwordprotectedlesson', 'lesson', format_string($lesson->name))."<br /><br />\n".
76 get_string('enterpassword', 'lesson')." <input type=\"password\" name=\"userpassword\" /><br /><br />\n<center>".
77 '<span class="lessonbutton standardbutton"><a href="'.$CFG->wwwroot.'/course/view.php?id='. $course->id .'">'. get_string('cancel', 'lesson') .'</a></span> ';
79 lesson_print_submit_link(get_string('continue', 'lesson'), 'password', 'center', 'standardbutton submitbutton');
80 echo '</fieldset></form>';
81 print_simple_box_end();
82 echo "</div>\n";
83 print_footer($course);
84 exit();
87 } else if ($lesson->dependency) { // check for dependencies
88 if ($dependentlesson = get_record('lesson', 'id', $lesson->dependency)) {
89 // lesson exists, so we can proceed
90 $conditions = unserialize($lesson->conditions);
91 // assume false for all
92 $timespent = false;
93 $completed = false;
94 $gradebetterthan = false;
95 // check for the timespent condition
96 if ($conditions->timespent) {
97 if ($attempttimes = get_records_select('lesson_timer', "userid = $USER->id AND lessonid = $dependentlesson->id")) {
98 // go through all the times and test to see if any of them satisfy the condition
99 foreach($attempttimes as $attempttime) {
100 $duration = $attempttime->lessontime - $attempttime->starttime;
101 if ($conditions->timespent < $duration/60) {
102 $timespent = true;
106 } else {
107 $timespent = true; // there isn't one set
110 // check for the gradebetterthan condition
111 if($conditions->gradebetterthan) {
112 if ($studentgrades = get_records_select('lesson_grades', "userid = $USER->id AND lessonid = $dependentlesson->id")) {
113 // go through all the grades and test to see if any of them satisfy the condition
114 foreach($studentgrades as $studentgrade) {
115 if ($studentgrade->grade >= $conditions->gradebetterthan) {
116 $gradebetterthan = true;
120 } else {
121 $gradebetterthan = true; // there isn't one set
124 // check for the completed condition
125 if ($conditions->completed) {
126 if (count_records('lesson_grades', 'userid', $USER->id, 'lessonid', $dependentlesson->id)) {
127 $completed = true;
129 } else {
130 $completed = true; // not set
133 $errors = array();
134 // collect all of our error statements
135 if (!$timespent) {
136 $errors[] = get_string('timespenterror', 'lesson', $conditions->timespent);
138 if (!$completed) {
139 $errors[] = get_string('completederror', 'lesson');
141 if (!$gradebetterthan) {
142 $errors[] = get_string('gradebetterthanerror', 'lesson', $conditions->gradebetterthan);
144 if (!empty($errors)) { // print out the errors if any
145 lesson_print_header($cm, $course, $lesson);
146 echo '<p>';
147 print_simple_box_start('center');
148 print_string('completethefollowingconditions', 'lesson', $dependentlesson->name);
149 echo '<p style="text-align:center;">'.implode('<br />'.get_string('and', 'lesson').'<br />', $errors).'</p>';
150 print_simple_box_end();
151 echo '</p>';
152 print_footer($course);
153 exit();
157 } else if ($lesson->highscores and !$lesson->practice and !optional_param('viewed', 0) and empty($pageid)) {
158 // Display high scores before starting lesson
159 redirect("$CFG->wwwroot/mod/lesson/highscores.php?id=$cm->id");
163 // set up some general variables
164 $path = $CFG->wwwroot .'/course';
166 // this is called if a student leaves during a lesson
167 if($pageid == LESSON_UNSEENBRANCHPAGE) {
168 $pageid = lesson_unseen_question_jump($lesson->id, $USER->id, $pageid);
171 // display individual pages and their sets of answers
172 // if pageid is EOL then the end of the lesson has been reached
173 // for flow, changed to simple echo for flow styles, michaelp, moved lesson name and page title down
174 $attemptflag = false;
175 if (empty($pageid)) {
176 // make sure there are pages to view
177 if (!get_field('lesson_pages', 'id', 'lessonid', $lesson->id, 'prevpageid', 0)) {
178 if (!has_capability('mod/lesson:manage', $context)) {
179 lesson_set_message(get_string('lessonnotready', 'lesson', $course->teacher)); // a nice message to the student
180 } else {
181 if (!count_records('lesson_pages', 'lessonid', $lesson->id)) {
182 redirect("$CFG->wwwroot/mod/lesson/edit.php?id=$cm->id"); // no pages - redirect to add pages
183 } else {
184 lesson_set_message(get_string('lessonpagelinkingbroken', 'lesson')); // ok, bad mojo
189 add_to_log($course->id, 'lesson', 'start', 'view.php?id='. $cm->id, $lesson->id, $cm->id);
191 // if no pageid given see if the lesson has been started
192 if ($grades = get_records_select('lesson_grades', 'lessonid = '. $lesson->id .' AND userid = '. $USER->id,
193 'grade DESC')) {
194 $retries = count($grades);
195 } else {
196 $retries = 0;
198 if ($retries) {
199 $attemptflag = true;
202 if (isset($USER->modattempts[$lesson->id])) {
203 unset($USER->modattempts[$lesson->id]); // if no pageid, then student is NOT reviewing
206 // if there are any questions have been answered correctly in this attempt
207 if ($attempts = get_records_select('lesson_attempts',
208 "lessonid = $lesson->id AND userid = $USER->id AND retry = $retries AND
209 correct = 1", 'timeseen DESC')) {
211 foreach ($attempts as $attempt) {
212 $jumpto = get_field('lesson_answers', 'jumpto', 'id', $attempt->answerid);
213 // convert the jumpto to a proper page id
214 if ($jumpto == 0) { // unlikely value!
215 $lastpageseen = $attempt->pageid;
216 } elseif ($jumpto == LESSON_NEXTPAGE) {
217 if (!$lastpageseen = get_field('lesson_pages', 'nextpageid', 'id',
218 $attempt->pageid)) {
219 // no nextpage go to end of lesson
220 $lastpageseen = LESSON_EOL;
222 } else {
223 $lastpageseen = $jumpto;
225 break; // only look at the latest correct attempt
227 } else {
228 $attempts = NULL;
231 if ($branchtables = get_records_select('lesson_branch',
232 "lessonid = $lesson->id AND userid = $USER->id AND retry = $retries", 'timeseen DESC')) {
233 // in here, user has viewed a branch table
234 $lastbranchtable = current($branchtables);
235 if ($attempts != NULL) {
236 foreach($attempts as $attempt) {
237 if ($lastbranchtable->timeseen > $attempt->timeseen) {
238 // branch table was viewed later than the last attempt
239 $lastpageseen = $lastbranchtable->pageid;
241 break;
243 } else {
244 // hasnt answered any questions but has viewed a branch table
245 $lastpageseen = $lastbranchtable->pageid;
248 //if ($lastpageseen != $firstpageid) {
249 if (isset($lastpageseen) and count_records('lesson_attempts', 'lessonid', $lesson->id, 'userid', $USER->id, 'retry', $retries) > 0) {
250 // get the first page
251 if (!$firstpageid = get_field('lesson_pages', 'id', 'lessonid', $lesson->id,
252 'prevpageid', 0)) {
253 error('Navigation: first page not found');
255 lesson_print_header($cm, $course, $lesson);
256 if ($lesson->timed) {
257 if ($lesson->retake) {
258 print_simple_box('<p style="text-align:center;">'. get_string('leftduringtimed', 'lesson') .'</p>', 'center');
259 echo '<div style="text-align:center;" class="lessonbutton standardbutton">'.
260 '<a href="view.php?id='.$cm->id.'&amp;pageid='.$firstpageid.'&amp;startlastseen=no">'.
261 get_string('continue', 'lesson').'</a></div>';
262 } else {
263 print_simple_box_start('center');
264 echo '<div style="text-align:center;">';
265 echo get_string('leftduringtimednoretake', 'lesson');
266 echo '<br /><br /><div class="lessonbutton standardbutton"><a href="../../course/view.php?id='. $course->id .'">'. get_string('returntocourse', 'lesson') .'</a></div>';
267 echo '</div>';
268 print_simple_box_end();
271 } else {
272 print_simple_box("<p style=\"text-align:center;\">".get_string('youhaveseen','lesson').'</p>',
273 "center");
275 echo '<div style="text-align:center;">';
276 echo '<span class="lessonbutton standardbutton">'.
277 '<a href="view.php?id='.$cm->id.'&amp;pageid='.$lastpageseen.'&amp;startlastseen=yes">'.
278 get_string('yes').'</a></span>&nbsp;&nbsp;&nbsp;';
279 echo '<span class="lessonbutton standardbutton">'.
280 '<a href="view.php?id='.$cm->id.'&amp;pageid='.$firstpageid.'&amp;startlastseen=no">'.
281 get_string('no').'</a></div>';
282 echo '</span>';
284 print_footer($course);
285 exit();
288 if ($grades) {
289 foreach ($grades as $grade) {
290 $bestgrade = $grade->grade;
291 break;
293 if (!$lesson->retake) {
294 lesson_print_header($cm, $course, $lesson, 'view');
295 print_simple_box_start('center');
296 echo "<div style=\"text-align:center;\">";
297 echo get_string("noretake", "lesson");
298 echo "<br /><br /><div class=\"lessonbutton standardbutton\"><a href=\"../../course/view.php?id=$course->id\">".get_string('returntocourse', 'lesson').'</a></div>';
299 echo "</div>";
300 print_simple_box_end();
301 print_footer($course);
302 exit();
303 //redirect("../../course/view.php?id=$course->id", get_string("alreadytaken", "lesson"));
304 // allow student to retake course even if they have the maximum grade
305 // } elseif ($bestgrade == 100) {
306 // redirect("../../course/view.php?id=$course->id", get_string("maximumgradeachieved",
307 // "lesson"));
310 // start at the first page
311 if (!$pageid = get_field('lesson_pages', 'id', 'lessonid', $lesson->id, 'prevpageid', 0)) {
312 error('Navigation: first page not found');
314 /// This is the code for starting a timed test
315 if(!isset($USER->startlesson[$lesson->id]) && !has_capability('mod/lesson:manage', $context)) {
316 $USER->startlesson[$lesson->id] = true;
317 $startlesson = new stdClass;
318 $startlesson->lessonid = $lesson->id;
319 $startlesson->userid = $USER->id;
320 $startlesson->starttime = time();
321 $startlesson->lessontime = time();
323 if (!insert_record('lesson_timer', $startlesson)) {
324 error('Error: could not insert row into lesson_timer table');
326 if ($lesson->timed) {
327 lesson_set_message(get_string('maxtimewarning', 'lesson', $lesson->maxtime), 'center');
331 if ($pageid != LESSON_EOL) {
332 /// This is the code updates the lessontime for a timed test
333 if ($startlastseen = optional_param('startlastseen', '', PARAM_ALPHA)) { /// this deletes old records not totally sure if this is necessary anymore
334 if ($startlastseen == 'no') {
335 if ($grades = get_records_select('lesson_grades', "lessonid = $lesson->id AND userid = $USER->id",
336 'grade DESC')) {
337 $retries = count($grades);
338 } else {
339 $retries = 0;
341 if (!delete_records('lesson_attempts', 'userid', $USER->id, 'lessonid', $lesson->id, 'retry', $retries)) {
342 error('Error: could not delete old attempts');
344 if (!delete_records('lesson_branch', 'userid', $USER->id, 'lessonid', $lesson->id, 'retry', $retries)) {
345 error('Error: could not delete old seen branches');
350 add_to_log($course->id, 'lesson', 'view', 'view.php?id='. $cm->id, $pageid, $cm->id);
352 if (!$page = get_record('lesson_pages', 'id', $pageid)) {
353 error('Navigation: the page record not found');
356 if ($page->qtype == LESSON_CLUSTER) { //this only gets called when a user starts up a new lesson and the first page is a cluster page
357 if (!has_capability('mod/lesson:manage', $context)) {
358 // get new id
359 $pageid = lesson_cluster_jump($lesson->id, $USER->id, $pageid);
360 // get new page info
361 if (!$page = get_record('lesson_pages', 'id', $pageid)) {
362 error('Navigation: the page record not found');
364 add_to_log($course->id, 'lesson', 'view', 'view.php?id='. $cm->id, $pageid, $cm->id);
365 } else {
366 // get the next page
367 $pageid = $page->nextpageid;
368 if (!$page = get_record('lesson_pages', 'id', $pageid)) {
369 error('Navigation: the page record not found');
372 } elseif ($page->qtype == LESSON_ENDOFCLUSTER) { // Check for endofclusters
373 if ($page->nextpageid == 0) {
374 $nextpageid = LESSON_EOL;
375 } else {
376 $nextpageid = $page->nextpageid;
378 redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id&amp;pageid=$nextpageid");
379 } else if ($page->qtype == LESSON_ENDOFBRANCH) { // Check for endofbranches
380 if ($answers = get_records('lesson_answers', 'pageid', $page->id, 'id')) {
381 // print_heading(get_string('endofbranch', 'lesson'));
382 foreach ($answers as $answer) {
383 // just need the first answer
384 if ($answer->jumpto == LESSON_RANDOMBRANCH) {
385 $answer->jumpto = lesson_unseen_branch_jump($lesson->id, $USER->id);
386 } elseif ($answer->jumpto == LESSON_CLUSTERJUMP) {
387 if (!has_capability('mod/lesson:manage', $context)) {
388 $answer->jumpto = lesson_cluster_jump($lesson->id, $USER->id, $pageid);
389 } else {
390 if ($page->nextpageid == 0) {
391 $answer->jumpto = LESSON_EOL;
392 } else {
393 $answer->jumpto = $page->nextpageid;
396 } else if ($answer->jumpto == LESSON_NEXTPAGE) {
397 if ($page->nextpageid == 0) {
398 $answer->jumpto = LESSON_EOL;
399 } else {
400 $answer->jumpto = $page->nextpageid;
402 } else if ($answer->jumpto == 0) {
403 $answer->jumpto = $page->id;
404 } else if ($answer->jumpto == LESSON_PREVIOUSPAGE) {
405 $answer->jumpto = $page->prevpageid;
407 redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id&amp;pageid=$answer->jumpto");
408 break;
410 } else {
411 error('Navigation: No answers on EOB');
415 // check to see if the user can see the left menu
416 if (!has_capability('mod/lesson:manage', $context)) {
417 $lesson->displayleft = lesson_displayleftif($lesson);
420 // This is where several messages (usually warnings) are displayed
421 // all of this is displayed above the actual page
423 // clock code
424 // get time information for this user
425 $timer = new stdClass;
426 if(!has_capability('mod/lesson:manage', $context)) {
427 if (!$timer = get_records_select('lesson_timer', "lessonid = $lesson->id AND userid = $USER->id", 'starttime')) {
428 error('Error: could not find records');
429 } else {
430 $timer = array_pop($timer); // this will get the latest start time record
434 $startlastseen = optional_param('startlastseen', '', PARAM_ALPHA);
435 if ($startlastseen == 'yes') { // continue a previous test, need to update the clock (think this option is disabled atm)
436 $timer->starttime = time() - ($timer->lessontime - $timer->starttime);
437 $timer->lessontime = time();
438 } else if ($startlastseen == 'no') { // starting over
439 // starting over, so reset the clock
440 $timer->starttime = time();
441 $timer->lessontime = time();
444 // for timed lessons, display clock
445 if ($lesson->timed) {
446 if(has_capability('mod/lesson:manage', $context)) {
447 lesson_set_message(get_string('teachertimerwarning', 'lesson'));
448 } else {
449 if ((($timer->starttime + $lesson->maxtime * 60) - time()) <= 0) {
450 lesson_set_message(get_string('eolstudentoutoftime', 'lesson'));
451 redirect("$CFG->wwwroot/mod/lesson/view.php?id=$cm->id&amp;pageid=".LESSON_EOL."&amp;outoftime=normal", get_string("outoftime", "lesson"));
453 // update clock when viewing a new page... no special treatment
454 if ((($timer->starttime + $lesson->maxtime * 60) - time()) < 60) {
455 lesson_set_message(get_string('studentoneminwarning', 'lesson'));
460 // update the clock
461 if (!has_capability('mod/lesson:manage', $context)) {
462 $timer->lessontime = time();
463 if (!update_record('lesson_timer', $timer)) {
464 error('Error: could not update lesson_timer table');
468 /// This is the warning msg for teachers to inform them that cluster and unseen does not work while logged in as a teacher
469 if(has_capability('mod/lesson:manage', $context)) {
470 if (lesson_display_teacher_warning($lesson->id)) {
471 $warningvars->cluster = get_string('clusterjump', 'lesson');
472 $warningvars->unseen = get_string('unseenpageinbranch', 'lesson');
473 lesson_set_message(get_string('teacherjumpwarning', 'lesson', $warningvars));
477 if ($page->qtype == LESSON_BRANCHTABLE) {
478 if ($lesson->minquestions and !has_capability('mod/lesson:manage', $context)) {
479 // tell student how many questions they have seen, how many are required and their grade
480 $ntries = count_records("lesson_grades", "lessonid", $lesson->id, "userid", $USER->id);
482 $gradeinfo = lesson_grade($lesson, $ntries);
484 if ($gradeinfo->attempts) {
485 if ($gradeinfo->nquestions < $lesson->minquestions) {
486 $a = new stdClass;
487 $a->nquestions = $gradeinfo->nquestions;
488 $a->minquestions = $lesson->minquestions;
489 lesson_set_message(get_string('numberofpagesviewednotice', 'lesson', $a));
491 lesson_set_message(get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned), 'notify');
492 $a = new stdClass;
493 $a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1);
494 $a->total = $lesson->grade;
495 lesson_set_message(get_string('yourcurrentgradeisoutof', 'lesson', $a), 'notify');
500 $PAGE = page_create_instance($lesson->id);
501 $PAGE->set_lessonpageid($page->id);
502 $pageblocks = blocks_setup($PAGE);
504 $leftcolumnwidth = bounded_number(180, blocks_preferred_width($pageblocks[BLOCK_POS_LEFT]), 210);
505 $rightcolumnwidth = bounded_number(180, blocks_preferred_width($pageblocks[BLOCK_POS_RIGHT]), 210);
507 if (($edit != -1) and $PAGE->user_allowed_editing()) {
508 $USER->editing = $edit;
511 /// Print the page header, heading and tabs
512 $PAGE->print_header();
514 if ($attemptflag) {
515 print_heading(get_string('attempt', 'lesson', $retries + 1));
518 /// This calculates and prints the ongoing score
519 if ($lesson->ongoing and !empty($pageid)) {
520 lesson_print_ongoing_score($lesson);
523 require($CFG->dirroot.'/mod/lesson/viewstart.html');
525 // now starting to print the page's contents
526 if ($page->qtype == LESSON_BRANCHTABLE) {
527 print_heading(format_string($page->title));
528 } else {
529 $lesson->slideshow = false; // turn off slide show for all pages other than LESSON_BRANTCHTABLE
532 if (!$lesson->slideshow) {
533 $options = new stdClass;
534 $options->noclean = true;
535 print_simple_box('<div class="contents">'.
536 format_text($page->contents, FORMAT_MOODLE, $options).
537 '</div>', 'center');
540 // this is for modattempts option. Find the users previous answer to this page,
541 // and then display it below in answer processing
542 if (isset($USER->modattempts[$lesson->id])) {
543 $retries = count_records('lesson_grades', "lessonid", $lesson->id, "userid", $USER->id);
544 $retries--;
545 if (! $attempts = get_records_select("lesson_attempts", "lessonid = $lesson->id AND userid = $USER->id AND pageid = $page->id AND retry = $retries", "timeseen")) {
546 error("Previous attempt record could not be found!");
548 $attempt = end($attempts);
551 // get the answers in a set order, the id order
552 if ($answers = get_records("lesson_answers", "pageid", $page->id, "id")) {
553 if ($page->qtype != LESSON_BRANCHTABLE) { // To fix XHTML problem (BT have their own forms)
554 echo "<form id=\"answerform\" method =\"post\" action=\"lesson.php\" autocomplete=\"off\">";
555 echo '<fieldset class="invisiblefieldset">';
556 echo "<input type=\"hidden\" name=\"id\" value=\"$cm->id\" />";
557 echo "<input type=\"hidden\" name=\"action\" value=\"continue\" />";
558 echo "<input type=\"hidden\" name=\"pageid\" value=\"$pageid\" />";
559 echo "<input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />";
560 print_simple_box_start("center");
561 echo '<table width="100%">';
563 // default format text options
564 $options = new stdClass;
565 $options->para = false; // no <p></p>
566 $options->noclean = true;
567 // echo "qtype is $page->qtype"; // debug
568 switch ($page->qtype) {
569 case LESSON_SHORTANSWER :
570 case LESSON_NUMERICAL :
571 if (isset($USER->modattempts[$lesson->id])) {
572 $value = 'value="'.s($attempt->useranswer).'"';
573 } else {
574 $value = "";
576 echo '<tr><td style="text-align:center;"><label for="answer">'.get_string('youranswer', 'lesson').'</label>'.
577 ": <input type=\"text\" id=\"answer\" name=\"answer\" size=\"50\" maxlength=\"200\" $value />\n";
578 echo '</td></tr></table>';
579 print_simple_box_end();
580 lesson_print_submit_link(get_string('pleaseenteryouranswerinthebox', 'lesson'), 'answerform');
581 break;
582 case LESSON_TRUEFALSE :
583 shuffle($answers);
584 $i = 0;
585 foreach ($answers as $answer) {
586 echo '<tr><td valign="top">';
587 if (isset($USER->modattempts[$lesson->id]) && $answer->id == $attempt->answerid) {
588 $checked = 'checked="checked"';
589 } else {
590 $checked = '';
592 echo "<input type=\"radio\" id=\"answerid$i\" name=\"answerid\" value=\"{$answer->id}\" $checked />";
593 echo "</td><td>";
594 echo "<label for=\"answerid$i\">".format_text(trim($answer->answer), FORMAT_MOODLE, $options).'</label>';
595 echo '</td></tr>';
596 if ($answer != end($answers)) {
597 echo "<tr><td><br /></td></tr>";
599 $i++;
601 echo '</table>';
602 print_simple_box_end();
603 lesson_print_submit_link(get_string('pleasecheckoneanswer', 'lesson'), 'answerform');
604 break;
605 case LESSON_MULTICHOICE :
606 $i = 0;
607 shuffle($answers);
609 foreach ($answers as $answer) {
610 echo '<tr><td valign="top">';
611 if ($page->qoption) {
612 $checked = '';
613 if (isset($USER->modattempts[$lesson->id])) {
614 $answerids = explode(",", $attempt->useranswer);
615 if (in_array($answer->id, $answerids)) {
616 $checked = ' checked="checked"';
617 } else {
618 $checked = '';
621 // more than one answer allowed
622 echo "<input type=\"checkbox\" id=\"answerid$i\" name=\"answer[$i]\" value=\"{$answer->id}\"$checked />";
623 } else {
624 if (isset($USER->modattempts[$lesson->id]) && $answer->id == $attempt->answerid) {
625 $checked = ' checked="checked"';
626 } else {
627 $checked = '';
629 // only one answer allowed
630 echo "<input type=\"radio\" id=\"answerid$i\" name=\"answerid\" value=\"{$answer->id}\"$checked />";
632 echo '</td><td>';
633 echo "<label for=\"answerid$i\" >".format_text(trim($answer->answer), FORMAT_MOODLE, $options).'</label>';
634 echo '</td></tr>';
635 if ($answer != end($answers)) {
636 echo '<tr><td><br /></td></tr>';
638 $i++;
640 echo '</table>';
641 print_simple_box_end();
642 if ($page->qoption) {
643 $linkname = get_string('pleasecheckoneormoreanswers', 'lesson');
644 } else {
645 $linkname = get_string('pleasecheckoneanswer', 'lesson');
647 lesson_print_submit_link($linkname, 'answerform');
648 break;
650 case LESSON_MATCHING :
651 echo '<tr><td><table width="100%">';
652 // don't suffle answers (could be an option??)
653 foreach ($answers as $answer) {
654 // get all the response
655 if ($answer->response != NULL) {
656 $responses[] = trim($answer->response);
660 $responseoptions = array();
661 if (!empty($responses)) {
662 shuffle($responses);
663 $responses = array_unique($responses);
664 foreach ($responses as $response) {
665 $responseoptions[htmlspecialchars(trim($response))] = $response;
668 if (isset($USER->modattempts[$lesson->id])) {
669 $useranswers = explode(',', $attempt->useranswer);
670 $t = 0;
672 foreach ($answers as $answer) {
673 if ($answer->response != NULL) {
674 echo '<tr><td align="right">';
675 echo "<b><label for=\"menuresponse[$answer->id]\">".
676 format_text($answer->answer,FORMAT_MOODLE,$options).
677 '</label>: </b></td><td valign="bottom">';
679 if (isset($USER->modattempts[$lesson->id])) {
680 $selected = htmlspecialchars(trim($answers[$useranswers[$t]]->response)); // gets the user's previous answer
681 choose_from_menu ($responseoptions, "response[$answer->id]", $selected);
682 $t++;
683 } else {
684 choose_from_menu ($responseoptions, "response[$answer->id]");
686 echo '</td></tr>';
687 if ($answer != end($answers)) {
688 echo '<tr><td><br /></td></tr>';
692 echo '</table></td></tr></table>';
693 print_simple_box_end();
694 lesson_print_submit_link(get_string('pleasematchtheabovepairs', 'lesson'), 'answerform');
695 break;
696 case LESSON_BRANCHTABLE :
697 $options = new stdClass;
698 $options->para = false;
699 $buttons = array();
700 $i = 0;
701 foreach ($answers as $answer) {
702 // Each button must have its own form inorder for it to work with JavaScript turned off
703 $button = "<form id=\"answerform$i\" method=\"post\" action=\"$CFG->wwwroot/mod/lesson/lesson.php\">\n".
704 '<div>'.
705 "<input type=\"hidden\" name=\"id\" value=\"$cm->id\" />\n".
706 "<input type=\"hidden\" name=\"action\" value=\"continue\" />\n".
707 "<input type=\"hidden\" name=\"pageid\" value=\"$pageid\" />\n".
708 "<input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />\n".
709 "<input type=\"hidden\" name=\"jumpto\" value=\"$answer->jumpto\" />\n".
710 lesson_print_submit_link(strip_tags(format_text($answer->answer, FORMAT_MOODLE, $options)), "answerform$i", '', '', '', '', true).
711 '</div>'.
712 '</form>';
714 $buttons[] = $button;
715 $i++;
718 /// Set the orientation
719 if ($page->layout) {
720 $orientation = 'horizontal';
721 } else {
722 $orientation = 'vertical';
725 $fullbuttonhtml = "\n<div class=\"branchbuttoncontainer $orientation\">\n" .
726 implode("\n", $buttons).
727 "\n</div>\n";
729 if ($lesson->slideshow) {
730 $options = new stdClass;
731 $options->noclean = true;
732 echo '<div class="contents">'.format_text($page->contents, FORMAT_MOODLE, $options)."</div>\n";
733 echo '</div><!--end slideshow div-->';
734 echo $fullbuttonhtml;
735 } else {
736 echo $fullbuttonhtml;
739 break;
740 case LESSON_ESSAY :
741 if (isset($USER->modattempts[$lesson->id])) {
742 $essayinfo = unserialize($attempt->useranswer);
743 $value = s(stripslashes_safe($essayinfo->answer));
744 } else {
745 $value = "";
747 echo '<tr><td style="text-align:center;" valign="top" nowrap="nowrap"><label for="answer">'.get_string("youranswer", "lesson").'</label>:</td><td>'.
748 '<textarea id="answer" name="answer" rows="15" cols="60">'.$value."</textarea>\n";
749 echo '</td></tr></table>';
750 print_simple_box_end();
751 lesson_print_submit_link(get_string('pleaseenteryouranswerinthebox', 'lesson'), 'answerform');
752 break;
753 default: // close the tags MDL-7861
754 echo ('</table>');
755 print_simple_box_end();
756 break;
758 if ($page->qtype != LESSON_BRANCHTABLE) { // To fix XHTML problem (BT have their own forms)
759 echo '</fieldset>';
760 echo "</form>\n";
762 } else {
763 // a page without answers - find the next (logical) page
764 echo "<form id=\"pageform\" method=\"post\" action=\"$CFG->wwwroot/mod/lesson/view.php\">\n";
765 echo '<div>';
766 echo "<input type=\"hidden\" name=\"id\" value=\"$cm->id\" />\n";
767 if ($lesson->nextpagedefault) {
768 // in Flash Card mode...
769 // ...first get number of retakes
770 $nretakes = count_records("lesson_grades", "lessonid", $lesson->id, "userid", $USER->id);
771 // ...then get the page ids (lessonid the 5th param is needed to make get_records play)
772 $allpages = get_records("lesson_pages", "lessonid", $lesson->id, "id", "id,lessonid");
773 shuffle ($allpages);
774 $found = false;
775 if ($lesson->nextpagedefault == LESSON_UNSEENPAGE) {
776 foreach ($allpages as $thispage) {
777 if (!count_records("lesson_attempts", "pageid", $thispage->id, "userid",
778 $USER->id, "retry", $nretakes)) {
779 $found = true;
780 break;
783 } elseif ($lesson->nextpagedefault == LESSON_UNANSWEREDPAGE) {
784 foreach ($allpages as $thispage) {
785 if (!count_records_select("lesson_attempts", "pageid = $thispage->id AND
786 userid = $USER->id AND correct = 1 AND retry = $nretakes")) {
787 $found = true;
788 break;
792 if ($found) {
793 $newpageid = $thispage->id;
794 if ($lesson->maxpages) {
795 // check number of pages viewed (in the lesson)
796 if (count_records("lesson_attempts", "lessonid", $lesson->id, "userid", $USER->id,
797 "retry", $nretakes) >= $lesson->maxpages) {
798 $newpageid = LESSON_EOL;
801 } else {
802 $newpageid = LESSON_EOL;
804 } else {
805 // in normal lesson mode...
806 if (!$newpageid = get_field("lesson_pages", "nextpageid", "id", $pageid)) {
807 // this is the last page - flag end of lesson
808 $newpageid = LESSON_EOL;
811 echo "<input type=\"hidden\" name=\"pageid\" value=\"$newpageid\" />\n";
812 lesson_print_submit_link(get_string('continue', 'lesson'), 'pageform');
813 echo '</div>';
814 echo "</form>\n";
817 // Finish of the page
818 lesson_print_progress_bar($lesson, $course);
819 require($CFG->dirroot.'/mod/lesson/viewend.html');
820 } else {
821 // end of lesson reached work out grade
823 // Used to check to see if the student ran out of time
824 $outoftime = optional_param('outoftime', '', PARAM_ALPHA);
826 // Update the clock / get time information for this user
827 if (!has_capability('mod/lesson:manage', $context)) {
828 unset($USER->startlesson[$lesson->id]);
829 if (!$timer = get_records_select('lesson_timer', "lessonid = $lesson->id AND userid = $USER->id", 'starttime')) {
830 error('Error: could not find records');
831 } else {
832 $timer = array_pop($timer); // this will get the latest start time record
834 $timer->lessontime = time();
836 if (!update_record("lesson_timer", $timer)) {
837 error("Error: could not update lesson_timer table");
841 add_to_log($course->id, "lesson", "end", "view.php?id=$cm->id", "$lesson->id", $cm->id);
843 lesson_print_header($cm, $course, $lesson, 'view');
844 print_heading(get_string("congratulations", "lesson"));
845 print_simple_box_start("center");
846 $ntries = count_records("lesson_grades", "lessonid", $lesson->id, "userid", $USER->id);
847 if (isset($USER->modattempts[$lesson->id])) {
848 $ntries--; // need to look at the old attempts :)
850 if (!has_capability('mod/lesson:manage', $context)) {
852 $gradeinfo = lesson_grade($lesson, $ntries);
854 if ($gradeinfo->attempts) {
855 if (!$lesson->custom) {
856 echo "<p style=\"text-align:center;\">".get_string("numberofpagesviewed", "lesson", $gradeinfo->nquestions).
857 "</p>\n";
858 if ($lesson->minquestions) {
859 if ($gradeinfo->nquestions < $lesson->minquestions) {
860 // print a warning and set nviewed to minquestions
861 echo "<p style=\"text-align:center;\">".get_string("youshouldview", "lesson",
862 $lesson->minquestions)."</p>\n";
865 echo "<p style=\"text-align:center;\">".get_string("numberofcorrectanswers", "lesson", $gradeinfo->earned).
866 "</p>\n";
868 $a = new stdClass;
869 $a->score = $gradeinfo->earned;
870 $a->grade = $gradeinfo->total;
871 if ($gradeinfo->nmanual) {
872 $a->tempmaxgrade = $gradeinfo->total - $gradeinfo->manualpoints;
873 $a->essayquestions = $gradeinfo->nmanual;
874 echo "<div style=\"text-align:center;\">".get_string("displayscorewithessays", "lesson", $a)."</div>";
875 } else {
876 echo "<div style=\"text-align:center;\">".get_string("displayscorewithoutessays", "lesson", $a)."</div>";
878 $a = new stdClass;
879 $a->grade = number_format($gradeinfo->grade * $lesson->grade / 100, 1);
880 $a->total = $lesson->grade;
881 echo "<p style=\"text-align:center;\">".get_string('yourcurrentgradeisoutof', 'lesson', $a)."</p>\n";
883 $grade->lessonid = $lesson->id;
884 $grade->userid = $USER->id;
885 $grade->grade = $gradeinfo->grade;
886 $grade->completed = time();
887 if (!$lesson->practice) {
888 if (isset($USER->modattempts[$lesson->id])) { // if reviewing, make sure update old grade record
889 if (!$grades = get_records_select("lesson_grades", "lessonid = $lesson->id and userid = $USER->id", "completed")) {
890 error("Could not find Grade Records");
892 $oldgrade = end($grades);
893 $grade->id = $oldgrade->id;
894 if (!$update = update_record("lesson_grades", $grade)) {
895 error("Navigation: grade not updated");
897 } else {
898 if (!$newgradeid = insert_record("lesson_grades", $grade)) {
899 error("Navigation: grade not inserted");
902 } else {
903 if (!delete_records("lesson_attempts", "lessonid", $lesson->id, "userid", $USER->id, "retry", $ntries)) {
904 error("Could not delete lesson attempts");
907 } else {
908 if ($lesson->timed) {
909 if ($outoftime == 'normal') {
910 $grade = new stdClass;
911 $grade->lessonid = $lesson->id;
912 $grade->userid = $USER->id;
913 $grade->grade = 0;
914 $grade->completed = time();
915 if (!$lesson->practice) {
916 if (!$newgradeid = insert_record("lesson_grades", $grade)) {
917 error("Navigation: grade not inserted");
920 echo get_string("eolstudentoutoftimenoanswers", "lesson");
922 } else {
923 echo get_string("welldone", "lesson");
927 // update central gradebook
928 lesson_update_grades($lesson, $USER->id);
930 } else {
931 // display for teacher
932 echo "<p style=\"text-align:center;\">".get_string("displayofgrade", "lesson")."</p>\n";
934 print_simple_box_end(); //End of Lesson button to Continue.
936 // after all the grade processing, check to see if "Show Grades" is off for the course
937 // if yes, redirect to the course page
938 if (!$course->showgrades) {
939 redirect($CFG->wwwroot.'/course/view.php?id='.$course->id);
942 // high scores code
943 if ($lesson->highscores && !has_capability('mod/lesson:manage', $context) && !$lesson->practice) {
944 echo "<div style=\"text-align:center;\"><br />";
945 if ($grades = get_records_select("lesson_grades", "lessonid = $lesson->id", "completed")) {
946 $madeit = false;
947 if ($highscores = get_records_select("lesson_high_scores", "lessonid = $lesson->id")) {
948 // get all the high scores into an array
949 $topscores = array();
950 $uniquescores = array();
951 foreach ($highscores as $highscore) {
952 $grade = $grades[$highscore->gradeid]->grade;
953 $topscores[] = $grade;
954 $uniquescores[$grade] = 1;
956 // sort to find the lowest score
957 sort($topscores);
958 $lowscore = $topscores[0];
960 if ($gradeinfo->grade >= $lowscore || count($uniquescores) <= $lesson->maxhighscores) {
961 $madeit = true;
964 if (!$highscores or $madeit) {
965 echo '<p>'.get_string("youmadehighscore", "lesson", $lesson->maxhighscores).
966 '</p>
967 <form method="post" id="highscores" action="'.$CFG->wwwroot.'/mod/lesson/highscores.php">
968 <div>
969 <input type="hidden" name="mode" value="add" />
970 <input type="hidden" name="id" value="'.$cm->id.'" />
971 <input type="hidden" name="sesskey" value="'.sesskey().'" />
972 <p>';
973 lesson_print_submit_link(get_string('clicktopost', 'lesson'), 'highscores');
974 echo '</p>
975 </div>
976 </form>';
977 } else {
978 echo get_string("nothighscore", "lesson", $lesson->maxhighscores)."<br />";
981 echo "<br /><div style=\"padding: 5px;\" class=\"lessonbutton standardbutton\"><a href=\"$CFG->wwwroot/mod/lesson/highscores.php?id=$cm->id&amp;link=1\">".get_string("viewhighscores", "lesson").'</a></div>';
982 echo "</div>";
985 if ($lesson->modattempts && !has_capability('mod/lesson:manage', $context)) {
986 // make sure if the student is reviewing, that he/she sees the same pages/page path that he/she saw the first time
987 // look at the attempt records to find the first QUESTION page that the user answered, then use that page id
988 // to pass to view again. This is slick cause it wont call the empty($pageid) code
989 // $ntries is decremented above
990 if (!$attempts = get_records_select("lesson_attempts", "lessonid = $lesson->id AND userid = $USER->id AND retry = $ntries", "timeseen")) {
991 $attempts = array();
993 $firstattempt = current($attempts);
994 $pageid = $firstattempt->pageid;
995 // IF the student wishes to review, need to know the last question page that the student answered. This will help to make
996 // sure that the student can leave the lesson via pushing the continue button.
997 $lastattempt = end($attempts);
998 $USER->modattempts[$lesson->id] = $lastattempt->pageid;
999 echo "<div style=\"text-align:center; padding:5px;\" class=\"lessonbutton standardbutton\"><a href=\"view.php?id=$cm->id&amp;pageid=$pageid\">".get_string("reviewlesson", "lesson")."</a></div>\n";
1000 } elseif ($lesson->modattempts && has_capability('mod/lesson:manage', $context)) {
1001 echo "<p style=\"text-align:center;\">".get_string("modattemptsnoteacher", "lesson")."</p>";
1004 if ($lesson->activitylink) {
1005 if ($module = get_record('course_modules', 'id', $lesson->activitylink)) {
1006 if ($modname = get_field('modules', 'name', 'id', $module->module))
1007 if ($instance = get_record($modname, 'id', $module->instance)) {
1008 echo "<div style=\"text-align:center; padding:5px;\" class=\"lessonbutton standardbutton\">".
1009 "<a href=\"$CFG->wwwroot/mod/$modname/view.php?id=$lesson->activitylink\">".
1010 get_string('activitylinkname', 'lesson', $instance->name)."</a></div>\n";
1015 echo "<div style=\"text-align:center; padding:5px;\" class=\"lessonbutton standardbutton\"><a href=\"$CFG->wwwroot/course/view.php?id=$course->id\">".get_string('returnto', 'lesson', format_string($course->fullname, true))."</a></div>\n";
1016 echo "<div style=\"text-align:center; padding:5px;\" class=\"lessonbutton standardbutton\"><a href=\"$CFG->wwwroot/grade/index.php?id=$course->id\">".get_string('viewgrades', 'lesson')."</a></div>\n";
1019 /// Finish the page
1020 print_footer($course);