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