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