quiz: MDL-19891 fix that quiz navigation block that was broken by the blocks changes.
[moodle.git] / mod / lesson / locallib.php
CommitLineData
9fcf51d9 1<?php // $Id$
5491947a 2/**
3 * Local library file for Lesson. These are non-standard functions that are used
4 * only by Lesson.
5 *
6 * @version $Id$
7 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
8 * @package lesson
9 **/
4b55d2af 10
11/**
12* Next page -> any page not seen before
13*/
5e7856af 14if (!defined("LESSON_UNSEENPAGE")) {
ac8e16be 15 define("LESSON_UNSEENPAGE", 1); // Next page -> any page not seen before
4b55d2af 16}
17/**
18* Next page -> any page not answered correctly
19*/
5e7856af 20if (!defined("LESSON_UNANSWEREDPAGE")) {
ac8e16be 21 define("LESSON_UNANSWEREDPAGE", 2); // Next page -> any page not answered correctly
4b55d2af 22}
5e7856af 23
4b55d2af 24/**
25* Define different lesson flows for next page
26*/
5e7856af 27$LESSON_NEXTPAGE_ACTION = array (0 => get_string("normal", "lesson"),
28 LESSON_UNSEENPAGE => get_string("showanunseenpage", "lesson"),
29 LESSON_UNANSWEREDPAGE => get_string("showanunansweredpage", "lesson") );
30
4b55d2af 31// Lesson jump types defined
32// TODO: instead of using define statements, create an array with all the jump values
5e7856af 33
4b55d2af 34/**
35 * Jump to Next Page
36 */
5e7856af 37if (!defined("LESSON_NEXTPAGE")) {
4b55d2af 38 define("LESSON_NEXTPAGE", -1);
39}
40/**
41 * End of Lesson
42 */
5e7856af 43if (!defined("LESSON_EOL")) {
4b55d2af 44 define("LESSON_EOL", -9);
45}
46/**
47 * Jump to an unseen page within a branch and end of branch or end of lesson
48 */
5e7856af 49if (!defined("LESSON_UNSEENBRANCHPAGE")) {
4b55d2af 50 define("LESSON_UNSEENBRANCHPAGE", -50);
51}
52/**
53 * Jump to Previous Page
54 */
5e7856af 55if (!defined("LESSON_PREVIOUSPAGE")) {
4b55d2af 56 define("LESSON_PREVIOUSPAGE", -40);
57}
58/**
59 * Jump to a random page within a branch and end of branch or end of lesson
60 */
5e7856af 61if (!defined("LESSON_RANDOMPAGE")) {
4b55d2af 62 define("LESSON_RANDOMPAGE", -60);
63}
64/**
65 * Jump to a random Branch
66 */
5e7856af 67if (!defined("LESSON_RANDOMBRANCH")) {
4b55d2af 68 define("LESSON_RANDOMBRANCH", -70);
69}
70/**
71 * Cluster Jump
72 */
5e7856af 73if (!defined("LESSON_CLUSTERJUMP")) {
4b55d2af 74 define("LESSON_CLUSTERJUMP", -80);
75}
76/**
77 * Undefined
78 */
5e7856af 79if (!defined("LESSON_UNDEFINED")) {
4b55d2af 80 define("LESSON_UNDEFINED", -99);
81}
82
83// Lesson question types defined
5e7856af 84
4b55d2af 85/**
86 * Short answer question type
87 */
5e7856af 88if (!defined("LESSON_SHORTANSWER")) {
89 define("LESSON_SHORTANSWER", "1");
90}
4b55d2af 91/**
92 * True/False question type
93 */
5e7856af 94if (!defined("LESSON_TRUEFALSE")) {
95 define("LESSON_TRUEFALSE", "2");
96}
4b55d2af 97/**
98 * Multichoice question type
99 *
100 * If you change the value of this then you need
101 * to change it in restorelib.php as well.
102 */
103if (!defined("LESSON_MULTICHOICE")) {
5e7856af 104 define("LESSON_MULTICHOICE", "3");
105}
4b55d2af 106/**
107 * Random question type - not used
108 */
5e7856af 109if (!defined("LESSON_RANDOM")) {
110 define("LESSON_RANDOM", "4");
111}
4b55d2af 112/**
113 * Matching question type
114 *
115 * If you change the value of this then you need
116 * to change it in restorelib.php, in mysql.php
117 * and postgres7.php as well.
118 */
119if (!defined("LESSON_MATCHING")) {
b9869082 120 define("LESSON_MATCHING", "5");
5e7856af 121}
4b55d2af 122/**
123 * Not sure - not used
124 */
5e7856af 125if (!defined("LESSON_RANDOMSAMATCH")) {
126 define("LESSON_RANDOMSAMATCH", "6");
127}
4b55d2af 128/**
129 * Not sure - not used
130 */
5e7856af 131if (!defined("LESSON_DESCRIPTION")) {
132 define("LESSON_DESCRIPTION", "7");
133}
4b55d2af 134/**
135 * Numerical question type
136 */
5e7856af 137if (!defined("LESSON_NUMERICAL")) {
138 define("LESSON_NUMERICAL", "8");
139}
4b55d2af 140/**
141 * Multichoice with multianswer question type
142 */
5e7856af 143if (!defined("LESSON_MULTIANSWER")) {
144 define("LESSON_MULTIANSWER", "9");
145}
4b55d2af 146/**
147 * Essay question type
148 */
5e7856af 149if (!defined("LESSON_ESSAY")) {
ac8e16be 150 define("LESSON_ESSAY", "10");
5e7856af 151}
5e7856af 152
4b55d2af 153/**
154 * Lesson question type array.
155 * Contains all question types used
156 */
5e7856af 157$LESSON_QUESTION_TYPE = array ( LESSON_MULTICHOICE => get_string("multichoice", "quiz"),
158 LESSON_TRUEFALSE => get_string("truefalse", "quiz"),
159 LESSON_SHORTANSWER => get_string("shortanswer", "quiz"),
160 LESSON_NUMERICAL => get_string("numerical", "quiz"),
161 LESSON_MATCHING => get_string("match", "quiz"),
62eda6ea 162 LESSON_ESSAY => get_string("essay", "lesson")
5e7856af 163// LESSON_DESCRIPTION => get_string("description", "quiz"),
164// LESSON_RANDOM => get_string("random", "quiz"),
165// LESSON_RANDOMSAMATCH => get_string("randomsamatch", "quiz"),
166// LESSON_MULTIANSWER => get_string("multianswer", "quiz"),
167 );
168
4b55d2af 169// Non-question page types
170
171/**
172 * Branch Table page
173 */
5e7856af 174if (!defined("LESSON_BRANCHTABLE")) {
175 define("LESSON_BRANCHTABLE", "20");
176}
4b55d2af 177/**
178 * End of Branch page
179 */
5e7856af 180if (!defined("LESSON_ENDOFBRANCH")) {
181 define("LESSON_ENDOFBRANCH", "21");
182}
4b55d2af 183/**
184 * Start of Cluster page
185 */
186if (!defined("LESSON_CLUSTER")) {
187 define("LESSON_CLUSTER", "30");
188}
189/**
190 * End of Cluster page
191 */
192if (!defined("LESSON_ENDOFCLUSTER")) {
193 define("LESSON_ENDOFCLUSTER", "31");
194}
195
196// other variables...
5e7856af 197
4b55d2af 198/**
199 * Flag for the editor for the answer textarea.
200 */
5e7856af 201if (!defined("LESSON_ANSWER_EDITOR")) {
202 define("LESSON_ANSWER_EDITOR", "1");
203}
4b55d2af 204/**
205 * Flag for the editor for the response textarea.
206 */
5e7856af 207if (!defined("LESSON_RESPONSE_EDITOR")) {
208 define("LESSON_RESPONSE_EDITOR", "2");
209}
210
211//////////////////////////////////////////////////////////////////////////////////////
212/// Any other lesson functions go here. Each of them must have a name that
213/// starts with lesson_
214
9fcf51d9 215/**
216 * Print the standard header for lesson module
217 *
40d6de1a 218 * This will also print up to three
219 * buttons in the breadcrumb, lesson heading
220 * lesson tabs, lesson notifications and perhaps
221 * a popup with a media file.
222 *
9fcf51d9 223 * @param object $cm Course module record object
40d6de1a 224 * @param object $course Course record object
225 * @param object $lesson Lesson record object
9fcf51d9 226 * @param string $currenttab Current tab for the lesson tabs
40d6de1a 227 * @param boolean $extraeditbuttons Show the extra edit buttons next to the 'Update this lesson' button.
228 * @param integer $lessonpageid if $extraeditbuttons is true then you must pass the page id here.
9fcf51d9 229 **/
40d6de1a 230function lesson_print_header($cm, $course, $lesson, $currenttab = '', $extraeditbuttons = false, $lessonpageid = NULL) {
231 global $CFG, $PAGE;
888f0c54 232
40d6de1a 233 // Note: MDL-19010 there will be further changes to printing header and blocks.
234 // The code will be much nicer than this eventually.
235 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
236 $activityname = format_string($lesson->name, true, $course->id);
41d50337 237 $strlesson = get_string('modulename', 'lesson');
888f0c54 238
40d6de1a 239 if (empty($title)) {
240 $title = "{$course->shortname}: $activityname";
241 }
888f0c54 242
40d6de1a 243/// Build the buttons
fb992d71 244 if (has_capability('mod/lesson:edit', $context)) {
40d6de1a 245 $buttons = update_module_button($cm->id, $course->id, $strlesson);
246 if ($extraeditbuttons) {
247 if ($lessonpageid === NULL) {
248 print_error('invalidpageid', 'lesson');
249 }
250 if (!empty($lessonpageid) and $lessonpageid != LESSON_EOL) {
251 $buttons .= '<form '.$CFG->frametarget.' method="get" action="'.$CFG->wwwroot.'/mod/lesson/lesson.php">'.
252 '<input type="hidden" name="id" value="'.$cm->id.'" />'.
253 '<input type="hidden" name="action" value="editpage" />'.
254 '<input type="hidden" name="redirect" value="navigation" />'.
255 '<input type="hidden" name="pageid" value="'.$lessonpageid.'" />'.
256 '<input type="submit" value="'.get_string('editpagecontent', 'lesson').'" />'.
257 '</form>';
258
259 if (!empty($CFG->showblocksonmodpages) and $PAGE->user_allowed_editing()) {
260 if ($PAGE->user_is_editing()) {
261 $onoff = 'off';
262 } else {
263 $onoff = 'on';
264 }
265 $buttons .= '<form '.$CFG->frametarget.' method="get" action="'.$CFG->wwwroot.'/mod/lesson/view.php">'.
266 '<input type="hidden" name="id" value="'.$cm->id.'" />'.
267 '<input type="hidden" name="pageid" value="'.$lessonpageid.'" />'.
268 '<input type="hidden" name="edit" value="'.$onoff.'" />'.
269 '<input type="submit" value="'.get_string("blocksedit$onoff").'" />
270 </form>';
271 }
272 }
273 $buttons = '<span class="edit_buttons">' . $buttons .'</span>';
274 }
fb992d71 275 } else {
40d6de1a 276 $buttons = '&nbsp;';
fb992d71 277 }
888f0c54 278
9fcf51d9 279/// Header setup
40d6de1a 280 $navigation = build_navigation(array(), $cm);
281 print_header($title, $course->fullname, $navigation, '', '', true, $buttons, navmenu($course, $cm));
888f0c54 282
0ae3b5d3 283 if (has_capability('mod/lesson:manage', $context)) {
40d6de1a 284 print_heading_with_help($activityname, 'overview', 'lesson');
888f0c54 285
286 if (!empty($currenttab)) {
287 include($CFG->dirroot.'/mod/lesson/tabs.php');
288 }
d1b025d0 289 } else {
40d6de1a 290 print_heading($activityname);
9fcf51d9 291 }
888f0c54 292
f15eb92c 293 lesson_print_messages();
9fcf51d9 294}
295
296/**
297 * Returns course module, course and module instance given
298 * either the course module ID or a lesson module ID.
299 *
300 * @param int $cmid Course Module ID
301 * @param int $lessonid Lesson module instance ID
302 * @return array array($cm, $course, $lesson)
303 **/
304function lesson_get_basics($cmid = 0, $lessonid = 0) {
646fc290 305 global $DB;
306
9fcf51d9 307 if ($cmid) {
f15eb92c 308 if (!$cm = get_coursemodule_from_id('lesson', $cmid)) {
86f93345 309 print_error('invalidcoursemodule');
9fcf51d9 310 }
646fc290 311 if (!$course = $DB->get_record('course', array('id' => $cm->course))) {
86f93345 312 print_error('coursemisconf');
9fcf51d9 313 }
646fc290 314 if (!$lesson = $DB->get_record('lesson', array('id' => $cm->instance))) {
86f93345 315 print_error('invalidcoursemodule');
9fcf51d9 316 }
317 } else if ($lessonid) {
646fc290 318 if (!$lesson = $DB->get_record('lesson', array('id' => $lessonid))) {
86f93345 319 print_error('invalidcoursemodule');
9fcf51d9 320 }
646fc290 321 if (!$course = $DB->get_record('course', array('id' => $lesson->course))) {
86f93345 322 print_error('coursemisconf');
9fcf51d9 323 }
324 if (!$cm = get_coursemodule_from_instance('lesson', $lesson->id, $course->id)) {
86f93345 325 print_error('invalidcoursemodule');
9fcf51d9 326 }
327 } else {
86f93345 328 print_error('invalidid', 'lesson');
9fcf51d9 329 }
330
331 return array($cm, $course, $lesson);
332}
333
6e1ff5c8 334/**
335 * Sets a message to be printed. Messages are printed
336 * by calling {@link lesson_print_messages()}.
337 *
338 * @uses $SESSION
339 * @param string $message The message to be printed
340 * @param string $class Class to be passed to {@link notify()}. Usually notifyproblem or notifysuccess.
341 * @param string $align Alignment of the message
342 * @return boolean
343 **/
344function lesson_set_message($message, $class="notifyproblem", $align='center') {
345 global $SESSION;
346
347 if (empty($SESSION->lesson_messages) or !is_array($SESSION->lesson_messages)) {
348 $SESSION->lesson_messages = array();
349 }
350
351 $SESSION->lesson_messages[] = array($message, $class, $align);
352
353 return true;
354}
355
356/**
357 * Print all set messages.
358 *
359 * See {@link lesson_set_message()} for setting messages.
360 *
361 * Uses {@link notify()} to print the messages.
362 *
363 * @uses $SESSION
364 * @return boolean
365 **/
366function lesson_print_messages() {
367 global $SESSION;
368
369 if (empty($SESSION->lesson_messages)) {
370 // No messages to print
371 return true;
372 }
373
374 foreach($SESSION->lesson_messages as $message) {
375 notify($message[0], $message[1], $message[2]);
376 }
377
378 // Reset
379 unset($SESSION->lesson_messages);
380
381 return true;
382}
383
259990d2 384/**
385 * Prints a lesson link that submits a form.
386 *
387 * If Javascript is disabled, then a regular submit button is printed
388 *
68a1e8fb 389 * @param string $name Name of the link or button
390 * @param string $form The name of the form to be submitted
391 * @param string $align Alignment of the button
392 * @param string $class Class names to add to the div wrapper
393 * @param string $title Title for the link (Not used if javascript is disabled)
394 * @param string $id ID tag
395 * @param boolean $return Return flag
259990d2 396 * @return mixed boolean/html
397 **/
398function lesson_print_submit_link($name, $form, $align = 'center', $class='standardbutton', $title = '', $id = '', $return = false) {
563106f0 399 if (!empty($align)) {
4085962a 400 $align = " style=\"text-align:$align\"";
563106f0 401 }
259990d2 402 if (!empty($id)) {
403 $id = " id=\"$id\"";
404 }
405 if (empty($title)) {
406 $title = $name;
407 }
62bb11d8 408
4cb35c1b 409 $output = "<div class=\"lessonbutton $class\" $align>\n";
37aa59a9 410 $output .= "<input type=\"submit\" value=\"$name\" $align $id />";
259990d2 411 $output .= "</div>\n";
412
2cb24b64 413 if ($return) {
414 return $output;
415 } else {
416 echo $output;
417 return true;
418 }
419}
420
421/**
422 * Prints a time remaining in the following format: H:MM:SS
423 *
424 * @param int $starttime Time when the lesson started
425 * @param int $maxtime Length of the lesson
426 * @param boolean $return Return output switch
427 * @return mixed boolean/string
428 **/
2163c226 429function lesson_print_time_remaining($starttime, $maxtime, $return = false) {
2cb24b64 430 // Calculate hours, minutes and seconds
431 $timeleft = $starttime + $maxtime * 60 - time();
432 $hours = floor($timeleft/3600);
433 $timeleft = $timeleft - ($hours * 3600);
434 $minutes = floor($timeleft/60);
435 $secs = $timeleft - ($minutes * 60);
436
437 if ($minutes < 10) {
438 $minutes = "0$minutes";
439 }
440 if ($secs < 10) {
441 $secs = "0$secs";
442 }
443 $output = array();
444 $output[] = $hours;
445 $output[] = $minutes;
446 $output[] = $secs;
447
448 $output = implode(':', $output);
449
259990d2 450 if ($return) {
451 return $output;
452 } else {
453 echo $output;
454 return true;
455 }
456}
457
68a1e8fb 458/**
459 * Prints the page action buttons
460 *
461 * Move/Edit/Preview/Delete
462 *
463 * @uses $CFG
464 * @param int $cmid Course Module ID
260a56b1 465 * @param object $page Page record
68a1e8fb 466 * @param boolean $printmove Flag to print the move button or not
260a56b1 467 * @param boolean $printaddpage Flag to print the add page drop-down or not
68a1e8fb 468 * @param boolean $return Return flag
469 * @return mixed boolean/string
470 **/
260a56b1 471function lesson_print_page_actions($cmid, $page, $printmove, $printaddpage = false, $return = false) {
4096752d 472 global $CFG, $OUTPUT;
40d6de1a 473
68a1e8fb 474 $context = get_context_instance(CONTEXT_MODULE, $cmid);
475 $actions = array();
40d6de1a 476
68a1e8fb 477 if (has_capability('mod/lesson:edit', $context)) {
478 if ($printmove) {
2ba9db3c 479 $actions[] = "<a title=\"".get_string('move')."\" href=\"$CFG->wwwroot/mod/lesson/lesson.php?id=$cmid&amp;action=move&amp;pageid=$page->id\">
4096752d 480 <img src=\"" . $OUTPUT->old_icon_url('t/move') . "\" class=\"iconsmall\" alt=\"".get_string('move')."\" /></a>\n";
68a1e8fb 481 }
260a56b1 482 $actions[] = "<a title=\"".get_string('update')."\" href=\"$CFG->wwwroot/mod/lesson/lesson.php?id=$cmid&amp;action=editpage&amp;pageid=$page->id\">
4096752d 483 <img src=\"" . $OUTPUT->old_icon_url('t/edit') . "\" class=\"iconsmall\" alt=\"".get_string('update')."\" /></a>\n";
68a1e8fb 484
260a56b1 485 $actions[] = "<a title=\"".get_string('preview')."\" href=\"$CFG->wwwroot/mod/lesson/view.php?id=$cmid&amp;pageid=$page->id\">
4096752d 486 <img src=\"" . $OUTPUT->old_icon_url('t/preview') . "\" class=\"iconsmall\" alt=\"".get_string('preview')."\" /></a>\n";
40d6de1a 487
260a56b1 488 $actions[] = "<a title=\"".get_string('delete')."\" href=\"$CFG->wwwroot/mod/lesson/lesson.php?id=$cmid&amp;sesskey=".sesskey()."&amp;action=confirmdelete&amp;pageid=$page->id\">
4096752d 489 <img src=\"" . $OUTPUT->old_icon_url('t/delete') . "\" class=\"iconsmall\" alt=\"".get_string('delete')."\" /></a>\n";
40d6de1a 490
260a56b1 491 if ($printaddpage) {
492 // Add page drop-down
493 $options = array();
494 $options['addcluster&amp;sesskey='.sesskey()] = get_string('clustertitle', 'lesson');
495 $options['addendofcluster&amp;sesskey='.sesskey()] = get_string('endofclustertitle', 'lesson');
496 $options['addbranchtable'] = get_string('branchtable', 'lesson');
497 $options['addendofbranch&amp;sesskey='.sesskey()] = get_string('endofbranch', 'lesson');
498 $options['addpage'] = get_string('question', 'lesson');
499 // Base url
500 $common = "$CFG->wwwroot/mod/lesson/lesson.php?id=$cmid&amp;pageid=$page->id&amp;action=";
40d6de1a 501
260a56b1 502 $actions[] = popup_form($common, $options, "addpage_$page->id", '', get_string('addpage', 'lesson').'...', '', '', true);
503 }
68a1e8fb 504 }
40d6de1a 505
68a1e8fb 506 $actions = implode(' ', $actions);
40d6de1a 507
68a1e8fb 508 if ($return) {
509 return $actions;
510 } else {
511 echo $actions;
512 return false;
513 }
514}
515
516/**
517 * Prints the add links in expanded view or single view when editing
518 *
519 * @uses $CFG
520 * @param int $cmid Course Module ID
521 * @param int $prevpageid Previous page id
522 * @param boolean $return Return flag
523 * @return mixed boolean/string
524 * @todo &amp;pageid does not make sense, it is prevpageid
525 **/
526function lesson_print_add_links($cmid, $prevpageid, $return = false) {
527 global $CFG;
528
529 $context = get_context_instance(CONTEXT_MODULE, $cmid);
530
531 $links = '';
532 if (has_capability('mod/lesson:edit', $context)) {
533 $links = array();
534 $links[] = "<a href=\"$CFG->wwwroot/mod/lesson/import.php?id=$cmid&amp;pageid=$prevpageid\">".
535 get_string('importquestions', 'lesson').'</a>';
536
537 $links[] = "<a href=\"$CFG->wwwroot/mod/lesson/lesson.php?id=$cmid&amp;sesskey=".sesskey()."&amp;action=addcluster&amp;pageid=$prevpageid\">".
538 get_string('addcluster', 'lesson').'</a>';
539
540 if ($prevpageid != 0) {
541 $links[] = "<a href=\"$CFG->wwwroot/mod/lesson/lesson.php?id=$cmid&amp;sesskey=".sesskey()."&amp;action=addendofcluster&amp;pageid=$prevpageid\">".
542 get_string('addendofcluster', 'lesson').'</a>';
543 }
544 $links[] = "<a href=\"$CFG->wwwroot/mod/lesson/lesson.php?id=$cmid&amp;action=addbranchtable&amp;pageid=$prevpageid\">".
545 get_string('addabranchtable', 'lesson').'</a>';
546
547 if ($prevpageid != 0) {
548 $links[] = "<a href=\"$CFG->wwwroot/mod/lesson/lesson.php?id=$cmid&amp;sesskey=".sesskey()."&amp;action=addendofbranch&amp;pageid=$prevpageid\">".
549 get_string('addanendofbranch', 'lesson').'</a>';
550 }
551
552 $links[] = "<a href=\"$CFG->wwwroot/mod/lesson/lesson.php?id=$cmid&amp;action=addpage&amp;pageid=$prevpageid\">".
553 get_string('addaquestionpagehere', 'lesson').'</a>';
554
555 $links = implode(" | \n", $links);
556 $links = "\n<div class=\"addlinks\">\n$links\n</div>\n";
557 }
558
559 if ($return) {
560 return $links;
561 } else {
562 echo $links;
563 return true;
564 }
565}
566
567/**
568 * Returns the string for a page type
569 *
570 * @uses $LESSON_QUESTION_TYPE
571 * @param int $qtype Page type
572 * @return string
573 **/
574function lesson_get_qtype_name($qtype) {
575 global $LESSON_QUESTION_TYPE;
576 switch ($qtype) {
577 case LESSON_ESSAY :
578 case LESSON_SHORTANSWER :
579 case LESSON_MULTICHOICE :
580 case LESSON_MATCHING :
581 case LESSON_TRUEFALSE :
582 case LESSON_NUMERICAL :
583 return $LESSON_QUESTION_TYPE[$qtype];
584 break;
585 case LESSON_BRANCHTABLE :
586 return get_string("branchtable", "lesson");
587 break;
588 case LESSON_ENDOFBRANCH :
589 return get_string("endofbranch", "lesson");
590 break;
591 case LESSON_CLUSTER :
592 return get_string("clustertitle", "lesson");
593 break;
594 case LESSON_ENDOFCLUSTER :
595 return get_string("endofclustertitle", "lesson");
596 break;
597 default:
598 return '';
599 break;
600 }
601}
602
603/**
604 * Returns the string for a jump name
605 *
606 * @param int $jumpto Jump code or page ID
607 * @return string
608 **/
609function lesson_get_jump_name($jumpto) {
646fc290 610 global $DB;
611
68a1e8fb 612 if ($jumpto == 0) {
613 $jumptitle = get_string('thispage', 'lesson');
614 } elseif ($jumpto == LESSON_NEXTPAGE) {
615 $jumptitle = get_string('nextpage', 'lesson');
616 } elseif ($jumpto == LESSON_EOL) {
617 $jumptitle = get_string('endoflesson', 'lesson');
618 } elseif ($jumpto == LESSON_UNSEENBRANCHPAGE) {
619 $jumptitle = get_string('unseenpageinbranch', 'lesson');
620 } elseif ($jumpto == LESSON_PREVIOUSPAGE) {
621 $jumptitle = get_string('previouspage', 'lesson');
622 } elseif ($jumpto == LESSON_RANDOMPAGE) {
623 $jumptitle = get_string('randompageinbranch', 'lesson');
624 } elseif ($jumpto == LESSON_RANDOMBRANCH) {
625 $jumptitle = get_string('randombranch', 'lesson');
626 } elseif ($jumpto == LESSON_CLUSTERJUMP) {
627 $jumptitle = get_string('clusterjump', 'lesson');
628 } else {
646fc290 629 if (!$jumptitle = $DB->get_field('lesson_pages', 'title', array('id' => $jumpto))) {
68a1e8fb 630 $jumptitle = '<strong>'.get_string('notdefined', 'lesson').'</strong>';
631 }
632 }
633
634 return format_string($jumptitle,true);
635}
636
4b55d2af 637/**
638 * Given some question info and some data about the the answers
639 * this function parses, organises and saves the question
640 *
641 * This is only used when IMPORTING questions and is only called
642 * from format.php
643 * Lifted from mod/quiz/lib.php -
644 * 1. all reference to oldanswers removed
645 * 2. all reference to quiz_multichoice table removed
646 * 3. In SHORTANSWER questions usecase is store in the qoption field
647 * 4. In NUMERIC questions store the range as two answers
648 * 5. TRUEFALSE options are ignored
649 * 6. For MULTICHOICE questions with more than one answer the qoption field is true
650 *
651 * @param opject $question Contains question data like question, type and answers.
652 * @return object Returns $result->error or $result->notice.
653 **/
5e7856af 654function lesson_save_question_options($question) {
646fc290 655 global $DB;
5e7856af 656
657 $timenow = time();
658 switch ($question->qtype) {
659 case LESSON_SHORTANSWER:
660
661 $answers = array();
662 $maxfraction = -1;
663
664 // Insert all the new answers
665 foreach ($question->answer as $key => $dataanswer) {
666 if ($dataanswer != "") {
f7ffb898 667 $answer = new stdClass;
5e7856af 668 $answer->lessonid = $question->lessonid;
669 $answer->pageid = $question->id;
670 if ($question->fraction[$key] >=0.5) {
671 $answer->jumpto = LESSON_NEXTPAGE;
672 }
673 $answer->timecreated = $timenow;
674 $answer->grade = $question->fraction[$key] * 100;
675 $answer->answer = $dataanswer;
c87a341c 676 $answer->response = $question->feedback[$key];
a8f3a651 677 $answer->id = $DB->insert_record("lesson_answers", $answer);
5e7856af 678 $answers[] = $answer->id;
679 if ($question->fraction[$key] > $maxfraction) {
680 $maxfraction = $question->fraction[$key];
681 }
682 }
683 }
684
685
686 /// Perform sanity checks on fractional grades
687 if ($maxfraction != 1) {
688 $maxfraction = $maxfraction * 100;
689 $result->notice = get_string("fractionsnomax", "quiz", $maxfraction);
690 return $result;
691 }
692 break;
693
694 case LESSON_NUMERICAL: // Note similarities to SHORTANSWER
695
696 $answers = array();
697 $maxfraction = -1;
698
699
700 // for each answer store the pair of min and max values even if they are the same
701 foreach ($question->answer as $key => $dataanswer) {
702 if ($dataanswer != "") {
f7ffb898 703 $answer = new stdClass;
5e7856af 704 $answer->lessonid = $question->lessonid;
705 $answer->pageid = $question->id;
706 $answer->jumpto = LESSON_NEXTPAGE;
707 $answer->timecreated = $timenow;
708 $answer->grade = $question->fraction[$key] * 100;
dd192b26 709 $min = $question->answer[$key] - $question->tolerance[$key];
710 $max = $question->answer[$key] + $question->tolerance[$key];
711 $answer->answer = $min.":".$max;
712 // $answer->answer = $question->min[$key].":".$question->max[$key]; original line for min/max
5e7856af 713 $answer->response = $question->feedback[$key];
a8f3a651 714 $answer->id = $DB->insert_record("lesson_answers", $answer);
5e7856af 715
716 $answers[] = $answer->id;
717 if ($question->fraction[$key] > $maxfraction) {
718 $maxfraction = $question->fraction[$key];
719 }
720 }
721 }
722
723 /// Perform sanity checks on fractional grades
724 if ($maxfraction != 1) {
725 $maxfraction = $maxfraction * 100;
726 $result->notice = get_string("fractionsnomax", "quiz", $maxfraction);
727 return $result;
728 }
729 break;
730
731
732 case LESSON_TRUEFALSE:
733
734 // the truth
735 $answer->lessonid = $question->lessonid;
736 $answer->pageid = $question->id;
737 $answer->timecreated = $timenow;
738 $answer->answer = get_string("true", "quiz");
739 $answer->grade = $question->answer * 100;
740 if ($answer->grade > 50 ) {
741 $answer->jumpto = LESSON_NEXTPAGE;
742 }
743 if (isset($question->feedbacktrue)) {
744 $answer->response = $question->feedbacktrue;
745 }
a8f3a651 746 $true->id = $DB->insert_record("lesson_answers", $answer);
5e7856af 747
748 // the lie
f7ffb898 749 $answer = new stdClass;
5e7856af 750 $answer->lessonid = $question->lessonid;
751 $answer->pageid = $question->id;
752 $answer->timecreated = $timenow;
753 $answer->answer = get_string("false", "quiz");
754 $answer->grade = (1 - (int)$question->answer) * 100;
755 if ($answer->grade > 50 ) {
756 $answer->jumpto = LESSON_NEXTPAGE;
757 }
758 if (isset($question->feedbackfalse)) {
759 $answer->response = $question->feedbackfalse;
760 }
a8f3a651 761 $false->id = $DB->insert_record("lesson_answers", $answer);
5e7856af 762
763 break;
764
765
766 case LESSON_MULTICHOICE:
767
768 $totalfraction = 0;
769 $maxfraction = -1;
770
771 $answers = array();
772
773 // Insert all the new answers
774 foreach ($question->answer as $key => $dataanswer) {
775 if ($dataanswer != "") {
f7ffb898 776 $answer = new stdClass;
5e7856af 777 $answer->lessonid = $question->lessonid;
778 $answer->pageid = $question->id;
779 $answer->timecreated = $timenow;
780 $answer->grade = $question->fraction[$key] * 100;
62eda6ea 781 // changed some defaults
ac8e16be 782 /* Original Code
783 if ($answer->grade > 50 ) {
5e7856af 784 $answer->jumpto = LESSON_NEXTPAGE;
785 }
ac8e16be 786 Replaced with: */
787 if ($answer->grade > 50 ) {
788 $answer->jumpto = LESSON_NEXTPAGE;
5e7856af 789 $answer->score = 1;
790 }
ac8e16be 791 // end Replace
5e7856af 792 $answer->answer = $dataanswer;
793 $answer->response = $question->feedback[$key];
a8f3a651 794 $answer->id = $DB->insert_record("lesson_answers", $answer);
5e7856af 795 // for Sanity checks
796 if ($question->fraction[$key] > 0) {
797 $totalfraction += $question->fraction[$key];
798 }
799 if ($question->fraction[$key] > $maxfraction) {
800 $maxfraction = $question->fraction[$key];
801 }
802 }
803 }
804
805 /// Perform sanity checks on fractional grades
806 if ($question->single) {
807 if ($maxfraction != 1) {
808 $maxfraction = $maxfraction * 100;
809 $result->notice = get_string("fractionsnomax", "quiz", $maxfraction);
810 return $result;
811 }
812 } else {
813 $totalfraction = round($totalfraction,2);
814 if ($totalfraction != 1) {
815 $totalfraction = $totalfraction * 100;
816 $result->notice = get_string("fractionsaddwrong", "quiz", $totalfraction);
817 return $result;
818 }
819 }
820 break;
821
822 case LESSON_MATCHING:
823
824 $subquestions = array();
825
826 $i = 0;
827 // Insert all the new question+answer pairs
828 foreach ($question->subquestions as $key => $questiontext) {
90455bb3 829 $answertext = $question->subanswers[$key];
5e7856af 830 if (!empty($questiontext) and !empty($answertext)) {
f7ffb898 831 $answer = new stdClass;
5e7856af 832 $answer->lessonid = $question->lessonid;
833 $answer->pageid = $question->id;
834 $answer->timecreated = $timenow;
835 $answer->answer = $questiontext;
836 $answer->response = $answertext;
837 if ($i == 0) {
838 // first answer contains the correct answer jump
839 $answer->jumpto = LESSON_NEXTPAGE;
840 }
a8f3a651 841 $subquestion->id = $DB->insert_record("lesson_answers", $answer);
5e7856af 842 $subquestions[] = $subquestion->id;
843 $i++;
844 }
845 }
846
847 if (count($subquestions) < 3) {
848 $result->notice = get_string("notenoughsubquestions", "quiz");
849 return $result;
850 }
851
852 break;
853
854
855 case LESSON_RANDOMSAMATCH:
856 $options->question = $question->id;
857 $options->choose = $question->choose;
646fc290 858 if ($existing = $DB->get_record("quiz_randomsamatch", array("question" => $options->question))) {
5e7856af 859 $options->id = $existing->id;
a8c31db2 860 $DB->update_record("quiz_randomsamatch", $options);
5e7856af 861 } else {
a8c31db2 862 $DB->insert_record("quiz_randomsamatch", $options);
5e7856af 863 }
864 break;
865
866 case LESSON_MULTIANSWER:
646fc290 867 if (!$oldmultianswers = $DB->get_records("quiz_multianswers", array("question" => $question->id), "id ASC")) {
5e7856af 868 $oldmultianswers = array();
869 }
870
871 // Insert all the new multi answers
872 foreach ($question->answers as $dataanswer) {
873 if ($oldmultianswer = array_shift($oldmultianswers)) { // Existing answer, so reuse it
874 $multianswer = $oldmultianswer;
875 $multianswer->positionkey = $dataanswer->positionkey;
876 $multianswer->norm = $dataanswer->norm;
877 $multianswer->answertype = $dataanswer->answertype;
878
879 if (! $multianswer->answers = quiz_save_multianswer_alternatives
880 ($question->id, $dataanswer->answertype,
881 $dataanswer->alternatives, $oldmultianswer->answers))
882 {
883 $result->error = "Could not update multianswer alternatives! (id=$multianswer->id)";
884 return $result;
885 }
a8c31db2 886 $DB->update_record("quiz_multianswers", $multianswer);
5e7856af 887 } else { // This is a completely new answer
f7ffb898 888 $multianswer = new stdClass;
5e7856af 889 $multianswer->question = $question->id;
890 $multianswer->positionkey = $dataanswer->positionkey;
891 $multianswer->norm = $dataanswer->norm;
892 $multianswer->answertype = $dataanswer->answertype;
893
894 if (! $multianswer->answers = quiz_save_multianswer_alternatives
895 ($question->id, $dataanswer->answertype,
896 $dataanswer->alternatives))
897 {
898 $result->error = "Could not insert multianswer alternatives! (questionid=$question->id)";
899 return $result;
900 }
a8c31db2 901 $DB->insert_record("quiz_multianswers", $multianswer);
5e7856af 902 }
903 }
904 break;
905
906 case LESSON_RANDOM:
907 break;
908
909 case LESSON_DESCRIPTION:
910 break;
911
912 default:
913 $result->error = "Unsupported question type ($question->qtype)!";
914 return $result;
915 break;
916 }
917 return true;
918}
4b55d2af 919
4b55d2af 920/**
921 * Determins if a jumpto value is correct or not.
922 *
923 * returns true if jumpto page is (logically) after the pageid page or
924 * if the jumpto value is a special value. Returns false in all other cases.
925 *
926 * @param int $pageid Id of the page from which you are jumping from.
927 * @param int $jumpto The jumpto number.
928 * @return boolean True or false after a series of tests.
4b55d2af 929 **/
5e7856af 930function lesson_iscorrect($pageid, $jumpto) {
646fc290 931 global $DB;
5e7856af 932
933 // first test the special values
934 if (!$jumpto) {
935 // same page
936 return false;
937 } elseif ($jumpto == LESSON_NEXTPAGE) {
938 return true;
ac8e16be 939 } elseif ($jumpto == LESSON_UNSEENBRANCHPAGE) {
5e7856af 940 return true;
941 } elseif ($jumpto == LESSON_RANDOMPAGE) {
942 return true;
943 } elseif ($jumpto == LESSON_CLUSTERJUMP) {
944 return true;
5e7856af 945 } elseif ($jumpto == LESSON_EOL) {
946 return true;
947 }
948 // we have to run through the pages from pageid looking for jumpid
646fc290 949 if ($lessonid = $DB->get_field('lesson_pages', 'lessonid', array('id' => $pageid))) {
950 if ($pages = $DB->get_records('lesson_pages', array('lessonid' => $lessonid), '', 'id, nextpageid')) {
f521f98a 951 $apageid = $pages[$pageid]->nextpageid;
952 while ($apageid != 0) {
953 if ($jumpto == $apageid) {
954 return true;
955 }
956 $apageid = $pages[$apageid]->nextpageid;
957 }
5e7856af 958 }
959 }
f521f98a 960 return false;
5e7856af 961}
962
4b55d2af 963/**
964 * Checks to see if a page is a branch table or is
965 * a page that is enclosed by a branch table and an end of branch or end of lesson.
966 * May call this function: {@link lesson_is_page_in_branch()}
967 *
f521f98a 968 * @param int $lesson Id of the lesson to which the page belongs.
4b55d2af 969 * @param int $pageid Id of the page.
970 * @return boolean True or false.
4b55d2af 971 **/
f521f98a 972function lesson_display_branch_jumps($lessonid, $pageid) {
646fc290 973 global $DB;
974
ac8e16be 975 if($pageid == 0) {
976 // first page
977 return false;
978 }
979 // get all of the lesson pages
646fc290 980 $params = array ("lessonid" => $lessonid);
981 if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) {
ac8e16be 982 // adding first page
983 return false;
984 }
985
986 if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
987 return true;
988 }
989
990 return lesson_is_page_in_branch($lessonpages, $pageid);
5e7856af 991}
992
4b55d2af 993/**
994 * Checks to see if a page is a cluster page or is
995 * a page that is enclosed by a cluster page and an end of cluster or end of lesson
996 * May call this function: {@link lesson_is_page_in_cluster()}
997 *
f521f98a 998 * @param int $lesson Id of the lesson to which the page belongs.
4b55d2af 999 * @param int $pageid Id of the page.
1000 * @return boolean True or false.
4b55d2af 1001 **/
f521f98a 1002function lesson_display_cluster_jump($lesson, $pageid) {
646fc290 1003 global $DB;
1004
ac8e16be 1005 if($pageid == 0) {
1006 // first page
1007 return false;
1008 }
1009 // get all of the lesson pages
646fc290 1010 $params = array ("lessonid" => $lesson);
1011 if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) {
ac8e16be 1012 // adding first page
1013 return false;
1014 }
1015
1016 if ($lessonpages[$pageid]->qtype == LESSON_CLUSTER) {
1017 return true;
1018 }
1019
1020 return lesson_is_page_in_cluster($lessonpages, $pageid);
5e7856af 1021
1022}
1023
4b55d2af 1024/**
1025 * Checks to see if a LESSON_CLUSTERJUMP or
1026 * a LESSON_UNSEENBRANCHPAGE is used in a lesson.
1027 *
1028 * This function is only executed when a teacher is
1029 * checking the navigation for a lesson.
1030 *
06469639 1031 * @param int $lesson Id of the lesson that is to be checked.
4b55d2af 1032 * @return boolean True or false.
1033 **/
06469639 1034function lesson_display_teacher_warning($lesson) {
646fc290 1035 global $DB;
1036
ac8e16be 1037 // get all of the lesson answers
646fc290 1038 $params = array ("lessonid" => $lesson);
1039 if (!$lessonanswers = $DB->get_records_select("lesson_answers", "lessonid = :lessonid", $params)) {
ac8e16be 1040 // no answers, then not useing cluster or unseen
1041 return false;
1042 }
1043 // just check for the first one that fulfills the requirements
1044 foreach ($lessonanswers as $lessonanswer) {
1045 if ($lessonanswer->jumpto == LESSON_CLUSTERJUMP || $lessonanswer->jumpto == LESSON_UNSEENBRANCHPAGE) {
1046 return true;
1047 }
1048 }
1049
1050 // if no answers use either of the two jumps
1051 return false;
5e7856af 1052}
1053
1054
4b55d2af 1055/**
1056 * Interprets LESSON_CLUSTERJUMP jumpto value.
1057 *
1058 * This will select a page randomly
1059 * and the page selected will be inbetween a cluster page and end of cluter or end of lesson
1060 * and the page selected will be a page that has not been viewed already
1061 * and if any pages are within a branch table or end of branch then only 1 page within
1062 * the branch table or end of branch will be randomly selected (sub clustering).
1063 *
f521f98a 1064 * @param int $lessonid Id of the lesson.
1065 * @param int $userid Id of the user.
4b55d2af 1066 * @param int $pageid Id of the current page from which we are jumping from.
1067 * @return int The id of the next page.
4b55d2af 1068 **/
f521f98a 1069function lesson_cluster_jump($lessonid, $userid, $pageid) {
646fc290 1070 global $DB;
1071
ac8e16be 1072 // get the number of retakes
318e3745 1073 if (!$retakes = $DB->count_records("lesson_grades", array("lessonid"=>$lessonid, "userid"=>$userid))) {
ac8e16be 1074 $retakes = 0;
1075 }
1076
1077 // get all the lesson_attempts aka what the user has seen
646fc290 1078 $params = array ("lessonid" => $lessonid, "userid" => $userid, "retry" => $retakes);
1079 if ($seen = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params, "timeseen DESC")) {
ac8e16be 1080 foreach ($seen as $value) { // load it into an array that I can more easily use
1081 $seenpages[$value->pageid] = $value->pageid;
1082 }
1083 } else {
1084 $seenpages = array();
1085 }
1086
1087 // get the lesson pages
e57bc529 1088 if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) {
86f93345 1089 print_error('cannotfindrecords', 'lesson');
ac8e16be 1090 }
1091 // find the start of the cluster
1092 while ($pageid != 0) { // this condition should not be satisfied... should be a cluster page
1093 if ($lessonpages[$pageid]->qtype == LESSON_CLUSTER) {
1094 break;
1095 }
1096 $pageid = $lessonpages[$pageid]->prevpageid;
1097 }
1098
1099 $pageid = $lessonpages[$pageid]->nextpageid; // move down from the cluster page
1100
1101 $clusterpages = array();
1102 while (true) { // now load all the pages into the cluster that are not already inside of a branch table.
1103 if ($lessonpages[$pageid]->qtype == LESSON_ENDOFCLUSTER) {
1104 // store the endofcluster page's jump
646fc290 1105 $exitjump = $DB->get_field("lesson_answers", "jumpto", array("pageid" => $pageid, "lessonid" => $lessonid));
ac8e16be 1106 if ($exitjump == LESSON_NEXTPAGE) {
1107 $exitjump = $lessonpages[$pageid]->nextpageid;
1108 }
1109 if ($exitjump == 0) {
1110 $exitjump = LESSON_EOL;
1111 }
1112 break;
1113 } elseif (!lesson_is_page_in_branch($lessonpages, $pageid) && $lessonpages[$pageid]->qtype != LESSON_ENDOFBRANCH) {
1114 // load page into array when it is not in a branch table and when it is not an endofbranch
1115 $clusterpages[] = $lessonpages[$pageid];
1116 }
1117 if ($lessonpages[$pageid]->nextpageid == 0) {
1118 // shouldn't ever get here... should be using endofcluster
1119 $exitjump = LESSON_EOL;
1120 break;
1121 } else {
1122 $pageid = $lessonpages[$pageid]->nextpageid;
1123 }
1124 }
1125
1126 // filter out the ones we have seen
1127 $unseen = array();
1128 foreach ($clusterpages as $clusterpage) {
1129 if ($clusterpage->qtype == LESSON_BRANCHTABLE) { // if branchtable, check to see if any pages inside have been viewed
1130 $branchpages = lesson_pages_in_branch($lessonpages, $clusterpage->id); // get the pages in the branchtable
1131 $flag = true;
1132 foreach ($branchpages as $branchpage) {
1133 if (array_key_exists($branchpage->id, $seenpages)) { // check if any of the pages have been viewed
1134 $flag = false;
1135 }
1136 }
1137 if ($flag && count($branchpages) > 0) {
1138 // add branch table
1139 $unseen[] = $clusterpage;
1140 }
1141 } else {
1142 // add any other type of page that has not already been viewed
1143 if (!array_key_exists($clusterpage->id, $seenpages)) {
1144 $unseen[] = $clusterpage;
1145 }
1146 }
1147 }
1148
1149 if (count($unseen) > 0) { // it does not contain elements, then use exitjump, otherwise find out next page/branch
1150 $nextpage = $unseen[rand(0, count($unseen)-1)];
1151 } else {
1152 return $exitjump; // seen all there is to see, leave the cluster
1153 }
1154
1155 if ($nextpage->qtype == LESSON_BRANCHTABLE) { // if branch table, then pick a random page inside of it
1156 $branchpages = lesson_pages_in_branch($lessonpages, $nextpage->id);
1157 return $branchpages[rand(0, count($branchpages)-1)]->id;
1158 } else { // otherwise, return the page's id
1159 return $nextpage->id;
1160 }
5e7856af 1161}
1162
4b55d2af 1163/**
1164 * Returns pages that are within a branch table and another branch table, end of branch or end of lesson
1165 *
1166 * @param array $lessonpages An array of lesson page objects.
1167 * @param int $branchid The id of the branch table that we would like the containing pages for.
1168 * @return array An array of lesson page objects.
1169 **/
5e7856af 1170function lesson_pages_in_branch($lessonpages, $branchid) {
ac8e16be 1171 $pageid = $lessonpages[$branchid]->nextpageid; // move to the first page after the branch table
1172 $pagesinbranch = array();
1173
1174 while (true) {
1175 if ($pageid == 0) { // EOL
1176 break;
1177 } elseif ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
1178 break;
1179 } elseif ($lessonpages[$pageid]->qtype == LESSON_ENDOFBRANCH) {
1180 break;
1181 }
1182 $pagesinbranch[] = $lessonpages[$pageid];
1183 $pageid = $lessonpages[$pageid]->nextpageid;
1184 }
1185
1186 return $pagesinbranch;
5e7856af 1187}
1188
4b55d2af 1189/**
1190 * Interprets the LESSON_UNSEENBRANCHPAGE jump.
1191 *
1192 * will return the pageid of a random unseen page that is within a branch
1193 *
1194 * @see lesson_pages_in_branch()
1195 * @param int $lesson Id of the lesson.
f521f98a 1196 * @param int $userid Id of the user.
4b55d2af 1197 * @param int $pageid Id of the page from which we are jumping.
1198 * @return int Id of the next page.
4b55d2af 1199 **/
5e7856af 1200function lesson_unseen_question_jump($lesson, $user, $pageid) {
646fc290 1201 global $DB;
1202
ac8e16be 1203 // get the number of retakes
318e3745 1204 if (!$retakes = $DB->count_records("lesson_grades", array("lessonid"=>$lesson, "userid"=>$user))) {
ac8e16be 1205 $retakes = 0;
1206 }
1207
1208 // get all the lesson_attempts aka what the user has seen
646fc290 1209 $params = array ("lessonid" => $lesson, "userid" => $user, "retry" => $retakes);
1210 if ($viewedpages = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params, "timeseen DESC")) {
ac8e16be 1211 foreach($viewedpages as $viewed) {
1212 $seenpages[] = $viewed->pageid;
1213 }
1214 } else {
1215 $seenpages = array();
1216 }
1217
1218 // get the lesson pages
e57bc529 1219 if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) {
86f93345 1220 print_error('cannotfindpages', 'lesson');
ac8e16be 1221 }
1222
1223 if ($pageid == LESSON_UNSEENBRANCHPAGE) { // this only happens when a student leaves in the middle of an unseen question within a branch series
1224 $pageid = $seenpages[0]; // just change the pageid to the last page viewed inside the branch table
1225 }
1226
1227 // go up the pages till branch table
1228 while ($pageid != 0) { // this condition should never be satisfied... only happens if there are no branch tables above this page
1229 if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
1230 break;
1231 }
1232 $pageid = $lessonpages[$pageid]->prevpageid;
1233 }
1234
1235 $pagesinbranch = lesson_pages_in_branch($lessonpages, $pageid);
1236
1237 // this foreach loop stores all the pages that are within the branch table but are not in the $seenpages array
1238 $unseen = array();
1239 foreach($pagesinbranch as $page) {
1240 if (!in_array($page->id, $seenpages)) {
1241 $unseen[] = $page->id;
1242 }
1243 }
1244
1245 if(count($unseen) == 0) {
1246 if(isset($pagesinbranch)) {
1247 $temp = end($pagesinbranch);
1248 $nextpage = $temp->nextpageid; // they have seen all the pages in the branch, so go to EOB/next branch table/EOL
1249 } else {
1250 // there are no pages inside the branch, so return the next page
1251 $nextpage = $lessonpages[$pageid]->nextpageid;
1252 }
1253 if ($nextpage == 0) {
1254 return LESSON_EOL;
1255 } else {
1256 return $nextpage;
1257 }
1258 } else {
1259 return $unseen[rand(0, count($unseen)-1)]; // returns a random page id for the next page
1260 }
5e7856af 1261}
1262
4b55d2af 1263/**
1264 * Handles the unseen branch table jump.
1265 *
f521f98a 1266 * @param int $lessonid Lesson id.
1267 * @param int $userid User id.
4b55d2af 1268 * @return int Will return the page id of a branch table or end of lesson
4b55d2af 1269 **/
362f2ce9 1270function lesson_unseen_branch_jump($lessonid, $userid) {
646fc290 1271 global $DB;
1272
318e3745 1273 if (!$retakes = $DB->count_records("lesson_grades", array("lessonid"=>$lessonid, "userid"=>$userid))) {
ac8e16be 1274 $retakes = 0;
1275 }
1276
646fc290 1277 $params = array ("lessonid" => $lessonid, "userid" => $userid, "retry" => $retakes);
1278 if (!$seenbranches = $DB->get_records_select("lesson_branch", "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params,
ac8e16be 1279 "timeseen DESC")) {
86f93345 1280 print_error('cannotfindrecords', 'lesson');
ac8e16be 1281 }
1282
1283 // get the lesson pages
e57bc529 1284 if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) {
86f93345 1285 print_error('cannotfindpages', 'lesson');
ac8e16be 1286 }
1287
1288 // this loads all the viewed branch tables into $seen untill it finds the branch table with the flag
1289 // which is the branch table that starts the unseenbranch function
1290 $seen = array();
1291 foreach ($seenbranches as $seenbranch) {
1292 if (!$seenbranch->flag) {
1293 $seen[$seenbranch->pageid] = $seenbranch->pageid;
1294 } else {
1295 $start = $seenbranch->pageid;
1296 break;
1297 }
1298 }
1299 // this function searches through the lesson pages to find all the branch tables
1300 // that follow the flagged branch table
1301 $pageid = $lessonpages[$start]->nextpageid; // move down from the flagged branch table
1302 while ($pageid != 0) { // grab all of the branch table till eol
1303 if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
1304 $branchtables[] = $lessonpages[$pageid]->id;
1305 }
1306 $pageid = $lessonpages[$pageid]->nextpageid;
1307 }
1308 $unseen = array();
1309 foreach ($branchtables as $branchtable) {
1310 // load all of the unseen branch tables into unseen
1311 if (!array_key_exists($branchtable, $seen)) {
1312 $unseen[] = $branchtable;
1313 }
1314 }
1315 if (count($unseen) > 0) {
1316 return $unseen[rand(0, count($unseen)-1)]; // returns a random page id for the next page
1317 } else {
1318 return LESSON_EOL; // has viewed all of the branch tables
1319 }
5e7856af 1320}
1321
4b55d2af 1322/**
1323 * Handles the random jump between a branch table and end of branch or end of lesson (LESSON_RANDOMPAGE).
1324 *
f521f98a 1325 * @param int $lessonid Lesson id.
4b55d2af 1326 * @param int $pageid The id of the page that we are jumping from (?)
1327 * @return int The pageid of a random page that is within a branch table
4b55d2af 1328 **/
f521f98a 1329function lesson_random_question_jump($lessonid, $pageid) {
646fc290 1330 global $DB;
1331
ac8e16be 1332 // get the lesson pages
646fc290 1333 $params = array ("lessonid" => $lessonid);
1334 if (!$lessonpages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid", $params)) {
86f93345 1335 print_error('cannotfindpages', 'lesson');
ac8e16be 1336 }
1337
1338 // go up the pages till branch table
1339 while ($pageid != 0) { // this condition should never be satisfied... only happens if there are no branch tables above this page
1340
1341 if ($lessonpages[$pageid]->qtype == LESSON_BRANCHTABLE) {
1342 break;
1343 }
1344 $pageid = $lessonpages[$pageid]->prevpageid;
1345 }
1346
1347 // get the pages within the branch
1348 $pagesinbranch = lesson_pages_in_branch($lessonpages, $pageid);
1349
1350 if(count($pagesinbranch) == 0) {
1351 // there are no pages inside the branch, so return the next page
1352 return $lessonpages[$pageid]->nextpageid;
1353 } else {
1354 return $pagesinbranch[rand(0, count($pagesinbranch)-1)]->id; // returns a random page id for the next page
1355 }
5e7856af 1356}
1357
4b55d2af 1358/**
1359 * Check to see if a page is below a branch table (logically).
1360 *
1361 * Will return true if a branch table is found logically above the page.
1362 * Will return false if an end of branch, cluster or the beginning
1363 * of the lesson is found before a branch table.
1364 *
1365 * @param array $pages An array of lesson page objects.
1366 * @param int $pageid Id of the page for testing.
1367 * @return boolean
1368 */
5e7856af 1369function lesson_is_page_in_branch($pages, $pageid) {
ac8e16be 1370 $pageid = $pages[$pageid]->prevpageid; // move up one
1371
1372 // go up the pages till branch table
1373 while (true) {
1374 if ($pageid == 0) { // ran into the beginning of the lesson
1375 return false;
1376 } elseif ($pages[$pageid]->qtype == LESSON_ENDOFBRANCH) { // ran into the end of another branch table
1377 return false;
1378 } elseif ($pages[$pageid]->qtype == LESSON_CLUSTER) { // do not look beyond a cluster
1379 return false;
1380 } elseif ($pages[$pageid]->qtype == LESSON_BRANCHTABLE) { // hit a branch table
1381 return true;
1382 }
1383 $pageid = $pages[$pageid]->prevpageid;
1384 }
5e7856af 1385
1386}
1387
4b55d2af 1388/**
1389 * Check to see if a page is below a cluster page (logically).
1390 *
1391 * Will return true if a cluster is found logically above the page.
1392 * Will return false if an end of cluster or the beginning
1393 * of the lesson is found before a cluster page.
1394 *
1395 * @param array $pages An array of lesson page objects.
1396 * @param int $pageid Id of the page for testing.
1397 * @return boolean
1398 */
5e7856af 1399function lesson_is_page_in_cluster($pages, $pageid) {
ac8e16be 1400 $pageid = $pages[$pageid]->prevpageid; // move up one
1401
1402 // go up the pages till branch table
1403 while (true) {
1404 if ($pageid == 0) { // ran into the beginning of the lesson
1405 return false;
1406 } elseif ($pages[$pageid]->qtype == LESSON_ENDOFCLUSTER) { // ran into the end of another branch table
1407 return false;
1408 } elseif ($pages[$pageid]->qtype == LESSON_CLUSTER) { // hit a branch table
1409 return true;
1410 }
1411 $pageid = $pages[$pageid]->prevpageid;
1412 }
5e7856af 1413}
1414
4b55d2af 1415/**
1416 * Calculates a user's grade for a lesson.
1417 *
4b55d2af 1418 * @param object $lesson The lesson that the user is taking.
4b55d2af 1419 * @param int $retries The attempt number.
88427c07 1420 * @param int $userid Id of the user (optinal, default current user).
1421 * @return object { nquestions => number of questions answered
1422 attempts => number of question attempts
1423 total => max points possible
1424 earned => points earned by student
1425 grade => calculated percentage grade
1426 nmanual => number of manually graded questions
1427 manualpoints => point value for manually graded questions }
4b55d2af 1428 */
88427c07 1429function lesson_grade($lesson, $ntries, $userid = 0) {
646fc290 1430 global $USER, $DB;
ac8e16be 1431
88427c07 1432 if (empty($userid)) {
1433 $userid = $USER->id;
1434 }
1435
1436 // Zero out everything
1437 $ncorrect = 0;
1438 $nviewed = 0;
1439 $score = 0;
1440 $nmanual = 0;
1441 $manualpoints = 0;
1442 $thegrade = 0;
1443 $nquestions = 0;
1444 $total = 0;
1445 $earned = 0;
1446
646fc290 1447 $params = array ("lessonid" => $lesson->id, "userid" => $userid, "retry" => $ntries);
1448 if ($useranswers = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND
1449 userid = :userid AND retry = :retry", $params, "timeseen")) {
88427c07 1450 // group each try with its page
1451 $attemptset = array();
1452 foreach ($useranswers as $useranswer) {
1453 $attemptset[$useranswer->pageid][] = $useranswer;
ac8e16be 1454 }
88427c07 1455
1456 // Drop all attempts that go beyond max attempts for the lesson
1457 foreach ($attemptset as $key => $set) {
1458 $attemptset[$key] = array_slice($set, 0, $lesson->maxattempts);
1459 }
1460
88427c07 1461 // get only the pages and their answers that the user answered
646fc290 1462 list($usql, $parameters) = $DB->get_in_or_equal(array_keys($attemptset));
1463 $parameters["lessonid"] = $lesson->id;
1464 $pages = $DB->get_records_select("lesson_pages", "lessonid = :lessonid AND id $usql", $parameters);
1465 $answers = $DB->get_records_select("lesson_answers", "lessonid = :lessonid AND pageid $usql", $parameters);
88427c07 1466
1467 // Number of pages answered
1468 $nquestions = count($pages);
1469
1470 foreach ($attemptset as $attempts) {
1471 if ($lesson->custom) {
1472 $attempt = end($attempts);
1473 // If essay question, handle it, otherwise add to score
1474 if ($pages[$attempt->pageid]->qtype == LESSON_ESSAY) {
ac8e16be 1475 $essayinfo = unserialize($attempt->useranswer);
88427c07 1476 $earned += $essayinfo->score;
1477 $nmanual++;
1478 $manualpoints += $answers[$attempt->answerid]->score;
ab1e7c39 1479 } else if (!empty($attempt->answerid)) {
88427c07 1480 $earned += $answers[$attempt->answerid]->score;
1481 }
1482 } else {
1483 foreach ($attempts as $attempt) {
1484 $earned += $attempt->correct;
1485 }
1486 $attempt = end($attempts); // doesn't matter which one
1487 // If essay question, increase numbers
1488 if ($pages[$attempt->pageid]->qtype == LESSON_ESSAY) {
1489 $nmanual++;
1490 $manualpoints++;
ac8e16be 1491 }
1492 }
88427c07 1493 // Number of times answered
1494 $nviewed += count($attempts);
1495 }
1496
1497 if ($lesson->custom) {
ac8e16be 1498 $bestscores = array();
88427c07 1499 // Find the highest possible score per page to get our total
1500 foreach ($answers as $answer) {
46341ab7 1501 if(!isset($bestscores[$answer->pageid])) {
88427c07 1502 $bestscores[$answer->pageid] = $answer->score;
46341ab7 1503 } else if ($bestscores[$answer->pageid] < $answer->score) {
88427c07 1504 $bestscores[$answer->pageid] = $answer->score;
ac8e16be 1505 }
1506 }
88427c07 1507 $total = array_sum($bestscores);
1508 } else {
1509 // Check to make sure the student has answered the minimum questions
1510 if ($lesson->minquestions and $nquestions < $lesson->minquestions) {
1511 // Nope, increase number viewed by the amount of unanswered questions
1512 $total = $nviewed + ($lesson->minquestions - $nquestions);
1513 } else {
1514 $total = $nviewed;
1515 }
ac8e16be 1516 }
88427c07 1517 }
1518
1519 if ($total) { // not zero
1520 $thegrade = round(100 * $earned / $total, 5);
1521 }
1522
1523 // Build the grade information object
1524 $gradeinfo = new stdClass;
1525 $gradeinfo->nquestions = $nquestions;
1526 $gradeinfo->attempts = $nviewed;
1527 $gradeinfo->total = $total;
1528 $gradeinfo->earned = $earned;
1529 $gradeinfo->grade = $thegrade;
1530 $gradeinfo->nmanual = $nmanual;
1531 $gradeinfo->manualpoints = $manualpoints;
1532
1533 return $gradeinfo;
1534}
1535
1536/**
1537 * Prints the on going message to the user.
1538 *
1539 * With custom grading On, displays points
1540 * earned out of total points possible thus far.
1541 * With custom grading Off, displays number of correct
1542 * answers out of total attempted.
1543 *
1544 * @param object $lesson The lesson that the user is taking.
1545 * @return void
1546 **/
1547function lesson_print_ongoing_score($lesson) {
318e3745 1548 global $USER, $DB;
1549
6e1ff5c8 1550 $cm = get_coursemodule_from_instance('lesson', $lesson->id);
1551 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1552
1553 if (has_capability('mod/lesson:manage', $context)) {
88427c07 1554 echo "<p align=\"center\">".get_string('teacherongoingwarning', 'lesson').'</p>';
1555 } else {
318e3745 1556 $ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id));
88427c07 1557 if (isset($USER->modattempts[$lesson->id])) {
1558 $ntries--;
1559 }
1560 $gradeinfo = lesson_grade($lesson, $ntries);
ac8e16be 1561
88427c07 1562 $a = new stdClass;
1563 if ($lesson->custom) {
1564 $a->score = $gradeinfo->earned;
1565 $a->currenthigh = $gradeinfo->total;
1566 print_simple_box(get_string("ongoingcustom", "lesson", $a), "center");
ac8e16be 1567 } else {
88427c07 1568 $a->correct = $gradeinfo->earned;
1569 $a->viewed = $gradeinfo->attempts;
1570 print_simple_box(get_string("ongoingnormal", "lesson", $a), "center");
ac8e16be 1571 }
1572 }
5e7856af 1573}
1574
4b55d2af 1575/**
1576 * Prints tabs for the editing and adding pages. Each tab is a question type.
1577 *
1578 * @param array $qtypes The question types array (may not need to pass this because it is defined in this file)
1579 * @param string $selected Current selected tab
1580 * @param string $link The base href value of the link for the tab
1581 * @param string $onclick Javascript for the tab link
1582 * @return void
1583 */
5e7856af 1584function lesson_qtype_menu($qtypes, $selected="", $link="", $onclick="") {
271fea97 1585 $tabs = array();
1586 $tabrows = array();
1587
9638a1f4 1588 foreach ($qtypes as $qtype => $qtypename) {
4085962a 1589 $tabrows[] = new tabobject($qtype, "$link&amp;qtype=$qtype\" onclick=\"$onclick", $qtypename);
ac8e16be 1590 }
271fea97 1591 $tabs[] = $tabrows;
1592 print_tabs($tabs, $selected);
1593 echo "<input type=\"hidden\" name=\"qtype\" value=\"$selected\" /> \n";
9638a1f4 1594
5e7856af 1595}
1596
62eda6ea 1597/**
1598 * Prints out a Progress Bar which depicts a user's progress within a lesson.
1599 *
1600 * Currently works best with a linear lesson. Clusters are counted as a single page.
1601 * Also, only viewed branch tables and questions that have been answered correctly count
1602 * toward lesson completion (or progress). Only Students can see the Progress bar as well.
1603 *
1604 * @param object $lesson The lesson that the user is currently taking.
1605 * @param object $course The course that the to which the lesson belongs.
1606 * @return boolean The return is not significant as of yet. Will return true/false.
62eda6ea 1607 **/
1608function lesson_print_progress_bar($lesson, $course) {
646fc290 1609 global $CFG, $USER, $DB;
318e3745 1610
6e1ff5c8 1611 $cm = get_coursemodule_from_instance('lesson', $lesson->id);
1612 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
1613
62eda6ea 1614 // lesson setting to turn progress bar on or off
1615 if (!$lesson->progressbar) {
1616 return false;
1617 }
1618
1619 // catch teachers
6e1ff5c8 1620 if (has_capability('mod/lesson:manage', $context)) {
9101efd3 1621 notify(get_string('progressbarteacherwarning2', 'lesson'));
62eda6ea 1622 return false;
1623 }
acab9099 1624 if (!isset($USER->modattempts[$lesson->id])) {
1625 // all of the lesson pages
646fc290 1626 if (!$pages = $DB->get_records('lesson_pages', array('lessonid' => $lesson->id))) {
acab9099 1627 return false;
1628 } else {
1629 foreach ($pages as $page) {
1630 if ($page->prevpageid == 0) {
1631 $pageid = $page->id; // find the first page id
1632 break;
1633 }
62eda6ea 1634 }
1635 }
62eda6ea 1636
acab9099 1637 // current attempt number
318e3745 1638 if (!$ntries = $DB->count_records("lesson_grades", array("lessonid"=>$lesson->id, "userid"=>$USER->id))) {
acab9099 1639 $ntries = 0; // may not be necessary
1640 }
62eda6ea 1641
acab9099 1642 $viewedpageids = array();
62eda6ea 1643
acab9099 1644 // collect all of the correctly answered questions
646fc290 1645 $params = array ("lessonid" => $lesson->id, "userid" => $USER->id, "retry" => $ntries);
1646 if ($viewedpages = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND userid = :userid AND retry = :retry AND correct = 1", $params, 'timeseen DESC', 'pageid, id')) {
acab9099 1647 $viewedpageids = array_keys($viewedpages);
1648 }
1649 // collect all of the branch tables viewed
646fc290 1650 if ($viewedbranches = $DB->get_records_select("lesson_branch", "lessonid = :lessonid AND userid = :userid AND retry = :retry", $params, 'timeseen DESC', 'pageid, id')) {
acab9099 1651 $viewedpageids = array_merge($viewedpageids, array_keys($viewedbranches));
1652 }
1653
1654 // Filter out the following pages:
1655 // End of Cluster
1656 // End of Branch
1657 // Pages found inside of Clusters
1658 // Do not filter out Cluster Page(s) because we count a cluster as one.
1659 // By keeping the cluster page, we get our 1
1660 $validpages = array();
1661 while ($pageid != 0) {
1662 if ($pages[$pageid]->qtype == LESSON_CLUSTER) {
1663 $clusterpageid = $pageid; // copy it
1664 $validpages[$clusterpageid] = 1; // add the cluster page as a valid page
1665 $pageid = $pages[$pageid]->nextpageid; // get next page
62eda6ea 1666
acab9099 1667 // now, remove all necessary viewed paged ids from the viewedpageids array.
1668 while ($pages[$pageid]->qtype != LESSON_ENDOFCLUSTER and $pageid != 0) {
1669 if (in_array($pageid, $viewedpageids)) {
1670 unset($viewedpageids[array_search($pageid, $viewedpageids)]); // remove it
1671 // since the user did see one page in the cluster, add the cluster pageid to the viewedpageids
1672 if (!in_array($clusterpageid, $viewedpageids)) {
1673 $viewedpageids[] = $clusterpageid;
1674 }
62eda6ea 1675 }
acab9099 1676 $pageid = $pages[$pageid]->nextpageid;
62eda6ea 1677 }
acab9099 1678 } elseif ($pages[$pageid]->qtype == LESSON_ENDOFCLUSTER or $pages[$pageid]->qtype == LESSON_ENDOFBRANCH) {
1679 // dont count these, just go to next
1680 $pageid = $pages[$pageid]->nextpageid;
1681 } else {
1682 // a counted page
1683 $validpages[$pageid] = 1;
62eda6ea 1684 $pageid = $pages[$pageid]->nextpageid;
1685 }
acab9099 1686 }
62eda6ea 1687
acab9099 1688 // progress calculation as a percent
1689 $progress = round(count($viewedpageids)/count($validpages), 2) * 100;
1690 } else {
1691 $progress = 100;
1692 }
62eda6ea 1693
1694 // print out the Progress Bar. Attempted to put as much as possible in the style sheets.
1695 echo '<div class="progress_bar" align="center">';
1696 echo '<table class="progress_bar_table"><tr>';
1697 if ($progress != 0) { // some browsers do not repsect the 0 width.
4085962a 1698 echo '<td style="width:'.$progress.'%;" class="progress_bar_completed">';
62eda6ea 1699 echo '</td>';
1700 }
1701 echo '<td class="progress_bar_todo">';
1702 echo '<div class="progress_bar_token"></div>';
1703 echo '</td>';
1704 echo '</tr></table>';
1705 echo '</div>';
1706
1707 return true;
1708}
1709
1710/**
1711 * Determines if a user can view the left menu. The determining factor
1712 * is whether a user has a grade greater than or equal to the lesson setting
1713 * of displayleftif
1714 *
1715 * @param object $lesson Lesson object of the current lesson
1716 * @return boolean 0 if the user cannot see, or $lesson->displayleft to keep displayleft unchanged
62eda6ea 1717 **/
1718function lesson_displayleftif($lesson) {
646fc290 1719 global $CFG, $USER, $DB;
62eda6ea 1720
1721 if (!empty($lesson->displayleftif)) {
1722 // get the current user's max grade for this lesson
646fc290 1723 $params = array ("userid" => $USER->id, "lessonid" => $lesson->id);
1724 if ($maxgrade = $DB->get_record_sql('SELECT userid, MAX(grade) AS maxgrade FROM {lesson_grades} WHERE userid = :userid AND lessonid = :lessonid GROUP BY userid', $params)) {
62eda6ea 1725 if ($maxgrade->maxgrade < $lesson->displayleftif) {
1726 return 0; // turn off the displayleft
1727 }
1728 } else {
1729 return 0; // no grades
1730 }
1731 }
1732
1733 // if we get to here, keep the original state of displayleft lesson setting
1734 return $lesson->displayleft;
1735}
5e7856af 1736
f521f98a 1737/**
1738 * If there is a media file associated with this
1739 * lesson, then print it in a block.
1740 *
1741 * @param int $cmid Course Module ID for this lesson
1742 * @param object $lesson Full lesson record object
1743 * @return void
1744 **/
888f0c54 1745function lesson_print_mediafile_block($cmid, $lesson) {
f521f98a 1746 if (!empty($lesson->mediafile)) {
1747 $url = '/mod/lesson/mediafile.php?id='.$cmid;
1748 $options = 'menubar=0,location=0,left=5,top=5,scrollbars,resizable,width='. $lesson->mediawidth .',height='. $lesson->mediaheight;
1749 $name = 'lessonmediafile';
1750
1751 $content = link_to_popup_window ($url, $name, get_string('mediafilepopup', 'lesson'), '', '', get_string('mediafilepopup', 'lesson'), $options, true);
1752 $content .= helpbutton("mediafilestudent", get_string("mediafile", "lesson"), "lesson", true, false, '', true);
1753
1754 print_side_block(get_string('linkedmedia', 'lesson'), $content, NULL, NULL, '', array('class' => 'mediafile'), get_string('linkedmedia', 'lesson'));
1755 }
1756}
1757
1758/**
1759 * If a timed lesson and not a teacher, then
1760 * print the clock
1761 *
1762 * @param int $cmid Course Module ID for this lesson
1763 * @param object $lesson Full lesson record object
1764 * @param object $timer Full timer record object
1765 * @return void
1766 **/
888f0c54 1767function lesson_print_clock_block($cmid, $lesson, $timer) {
ba458143 1768 global $CFG, $PAGE;
f521f98a 1769
1770 $context = get_context_instance(CONTEXT_MODULE, $cmid);
1771
1772 // Display for timed lessons and for students only
1773 if($lesson->timed and !has_capability('mod/lesson:manage', $context) and !empty($timer)) {
ba458143 1774
1775 $clocksettings = Array('starttime'=>$timer->starttime, 'servertime'=>time(),'testlength'=>($lesson->maxtime * 60));
1776 $content = $PAGE->requires->data_for_js('clocksettings', $clocksettings)->asap();
1777 $content .= $PAGE->requires->js('mod/lesson/timer.js')->asap();
1778 $content .= $PAGE->requires->js_function_call('show_clock')->asap();
1779 $content .= '<div class="jshidewhenenabled">';
f521f98a 1780 $content .= lesson_print_time_remaining($timer->starttime, $lesson->maxtime, true)."\n";
ba458143 1781 $content .= '</div>';
1782
f521f98a 1783 print_side_block(get_string('timeremaining', 'lesson'), $content, NULL, NULL, '', array('class' => 'clock'), get_string('timeremaining', 'lesson'));
1784 }
1785}
1786
1787/**
1788 * If left menu is turned on, then this will
1789 * print the menu in a block
1790 *
1791 * @param int $cmid Course Module ID for this lesson
1792 * @param object $lesson Full lesson record object
1793 * @return void
1794 **/
888f0c54 1795function lesson_print_menu_block($cmid, $lesson) {
646fc290 1796 global $CFG, $DB;
f521f98a 1797
1798 if ($lesson->displayleft) {
646fc290 1799 $pageid = $DB->get_field('lesson_pages', 'id', array('lessonid' => $lesson->id, 'prevpageid' => 0));
1800 $params = array ("lessonid" => $lesson->id);
1801 $pages = $DB->get_records_select('lesson_pages', "lessonid = :lessonid", $params);
f521f98a 1802 $currentpageid = optional_param('pageid', $pageid, PARAM_INT);
1803
1804 if ($pageid and $pages) {
1805 $content = '<a href="#maincontent" class="skip">'.get_string('skip', 'lesson')."</a>\n<div class=\"menuwrapper\">\n<ul>\n";
1806
1807 while ($pageid != 0) {
1808 $page = $pages[$pageid];
1809
1810 // Only process branch tables with display turned on
1811 if ($page->qtype == LESSON_BRANCHTABLE and $page->display) {
1812 if ($page->id == $currentpageid) {
1813 $content .= '<li class="selected">'.format_string($page->title,true)."</a></li>\n";
1814 } else {
1815 $content .= "<li class=\"notselected\"><a href=\"$CFG->wwwroot/mod/lesson/view.php?id=$cmid&amp;pageid=$page->id\">".format_string($page->title,true)."</a></li>\n";
1816 }
1817
1818 }
1819 $pageid = $page->nextpageid;
1820 }
1821 $content .= "</ul>\n</div>\n";
1822 print_side_block(get_string('lessonmenu', 'lesson'), $content, NULL, NULL, '', array('class' => 'menu'), get_string('lessonmenu', 'lesson'));
1823 }
1824 }
1825}
1826
888f0c54 1827/**
1828 * This is not ideal, but checks to see if a
1829 * column has "block" content.
1830 *
1831 * In the future, it would be nice if the lesson
1832 * media file, timer and navigation were blocks
1833 * then this would be unnecessary.
1834 *
1835 * @uses $CFG
1836 * @uses $PAGE
1837 * @param object $lesson Full lesson record object
1838 * @param array $pageblocks An array of block instances organized by left and right columns
1839 * @param string $column Pass either BLOCK_POS_RIGHT or BLOCK_POS_LEFT constants
1840 * @return boolean
1841 **/
1842function lesson_blocks_have_content($lesson, $pageblocks, $column) {
1843 global $CFG, $PAGE;
1844
1845 // First check lesson conditions
1846 if ($column == BLOCK_POS_RIGHT) {
1847 $managecap = false;
1848 if ($cm = get_coursemodule_from_instance('lesson', $lesson->id, $lesson->course)) {
1849 $managecap = has_capability('mod/lesson:manage', get_context_instance(CONTEXT_MODULE, $cm->id));
1850 }
1851 if (($lesson->timed and !$managecap) or !empty($lesson->mediafile)) {
1852 return true;
1853 }
1854 } else if ($column == BLOCK_POS_LEFT) {
1855 if ($lesson->displayleft) {
1856 return true;
1857 }
1858 }
1859 if (!empty($CFG->showblocksonmodpages)) {
1860 if ((blocks_have_content($pageblocks, $column) || $PAGE->user_is_editing())) {
1861 return true;
1862 }
1863 }
1864
1865 return false;
1866}
1867
2a488ba5 1868?>