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