]> git.mjollnir.org Git - moodle.git/commitdiff
Adding the Lesson module to the main CVS. Nice job Ray!
authormoodler <moodler>
Mon, 16 Feb 2004 05:41:13 +0000 (05:41 +0000)
committermoodler <moodler>
Mon, 16 Feb 2004 05:41:13 +0000 (05:41 +0000)
Still needs PostgreSQL support and wider testing

18 files changed:
lang/en/help/lesson/grade.html [new file with mode: 0644]
lang/en/help/lesson/jumpto.html [new file with mode: 0644]
lang/en/help/lesson/maxanswers.html [new file with mode: 0644]
lang/en/help/lesson/mods.html [new file with mode: 0644]
lang/en/help/lesson/overview.html [new file with mode: 0644]
lang/en/help/lesson/retake.html [new file with mode: 0644]
lang/en/lesson.php [new file with mode: 0644]
mod/lesson/backuplib.php [new file with mode: 0644]
mod/lesson/db/mysql.php [new file with mode: 0644]
mod/lesson/db/mysql.sql [new file with mode: 0644]
mod/lesson/icon.gif [new file with mode: 0755]
mod/lesson/index.php [new file with mode: 0644]
mod/lesson/lesson.php [new file with mode: 0644]
mod/lesson/lib.php [new file with mode: 0644]
mod/lesson/mod.html [new file with mode: 0644]
mod/lesson/restorelib.php [new file with mode: 0644]
mod/lesson/version.php [new file with mode: 0644]
mod/lesson/view.php [new file with mode: 0644]

diff --git a/lang/en/help/lesson/grade.html b/lang/en/help/lesson/grade.html
new file mode 100644 (file)
index 0000000..ded2142
--- /dev/null
@@ -0,0 +1,7 @@
+<p align="center"><b>The Grade of the Lesson</b></p>
+
+<p>This value determines the maximum grade which can be awarded in 
+       the lesson.     The range is 0 to 100%. This value can be changed at 
+       any time during the lesson. Any change has an immediate effect in 
+       the Grades page and on the grades shown to the students in various 
+    lists.</p>
diff --git a/lang/en/help/lesson/jumpto.html b/lang/en/help/lesson/jumpto.html
new file mode 100644 (file)
index 0000000..de7fc2e
--- /dev/null
@@ -0,0 +1,13 @@
+<p align="center"><b>The Jump-to Link</b></p>
+
+<p>Each answer has a Jump-to link. When this answer is chosen, the answer's response 
+    is shown to the student. Atfer that the student sees the page given in the Jump-to 
+    link. This link can be either relative or absolute. Relative links are <b>This 
+    page</b> and <b>Next page</b>. <b>This page</b> means that the student sees the 
+    current page again. <b>Next page</b> shows the page which follows this page in the
+    logical order of pages. An absolute page link is specified by choosing the page's 
+    <b>title</b>.</p>
+<p>Note that a (relative) <b>Next page</b> Jump-to link may show a different page 
+    after pages have been moved. Whereas Jump-to links which use page <b>titles</b>
+    always show the same page after pages have been moved.</p>
+
diff --git a/lang/en/help/lesson/maxanswers.html b/lang/en/help/lesson/maxanswers.html
new file mode 100644 (file)
index 0000000..a72db12
--- /dev/null
@@ -0,0 +1,7 @@
+<p align="center"><b>The Maximum Number of Answers in a Lesson</b></p>
+
+<p>This value determines the maximum number of answers the teacher can use.
+    The default value is 4. If the lesson uses only TRUE or FALSE
+    questions throughout then it is sensible to set this value to 2.</p>
+    
+<p>It is safe to change this value in a lesson with existing content.</p>
diff --git a/lang/en/help/lesson/mods.html b/lang/en/help/lesson/mods.html
new file mode 100644 (file)
index 0000000..c1c6988
--- /dev/null
@@ -0,0 +1,11 @@
+<IMG VALIGN=absmiddle SRC="<?php echo $CFG->wwwroot?>/mod/lesson/icon.gif">&nbsp;<B>Lesson</B>
+
+<UL>
+<P>A lesson delivers content in an interesting and flexible way. It consists of a 
+    number of pages. Each page normally ends with a question and a number of 
+    possible answers. Depending on the student's choice of answer they either 
+    progress to the next page or are taken back to a previous page. Navigation 
+    through the lesson can be straight forward or complex, depending largely 
+    on the structure of the material being presented.</p>
+</UL>
+
diff --git a/lang/en/help/lesson/overview.html b/lang/en/help/lesson/overview.html
new file mode 100644 (file)
index 0000000..0083ff2
--- /dev/null
@@ -0,0 +1,55 @@
+<p align="center"><b>Overview</b></p>
+
+<ol>
+<li>A lesson is made up of a number of <b>pages</b>.
+<li>A page contains some <b>content</b> and it normally ends with a <b>question</b>.
+<li>Each page normally has a set of <b>answers</b>. 
+<li>Each answer can have a short piece of text which is displayed if the answer is
+    chosen. This piece of text is called the <b>response</b>.
+<li>Also associated with each answer is a <b>jump</b>. The jump can be relative - 
+    this page, next page - or absolute - specifying any one of the pages in the 
+    lesson or the end of the lesson.
+<li>By default, the first answer jumps to the <b>next page</b> in the lesson. 
+    The subsequent answers jump to the same page. That is, the student is shown 
+    the same page of the lesson again if they do not chose the first answer.
+<li>The next page is determined by the lesson's <b>logical order</b>. This is 
+    the order of the pages as seen by the teacher. This order can be altered 
+    by moving pages within the lesson.
+<li>The lesson also has a <b>navigation order</b>. This is the order of the 
+    pages as seen by the students. This is determined by the jumps specified
+    for individual answers and it can be very different from the logical order.
+    (Although if the jumps are <i>not</i> changed from their default values
+     the two are strongly related.) The teacher has the option to check the 
+    navigation order.
+<li>When displayed to the students, the answers are always shuffled. That is, the
+    first answer from the teacher's point of view will not necessarily be the
+    first answer in the list shown to the students. (Further, each time the same
+    set of answers is displayed they are likely to appear in a different order.)
+<li>The number of answers can vary from page to page. For example, it is allowed
+    that some pages can end with a true/false question while others have questions
+    with one correct answer and three, say, distractors. 
+<li>It is possible to set up a page without any answers. The students are shown
+    a <b>Continue</b> link instead of the set of shuffled answers.
+<li>For the purposes of grading the lessons, <b>correct</b> answers are ones which 
+    jump to a page which is further <i>down</i> the logical order than the current page. 
+    <b>Wrong</b> answers are ones which either jump to the same page or to a page
+    further <i>up</i> the logical order than the current page. Thus, if the jumps are
+    <i>not</i> changed, the first answer is a correct answer and the other answers are 
+    wrong answers.
+<li>Questions can have more than one correct answer. For example, if two of the answers
+    jump to the next page then either answer is taken as a correct answer. (Although
+    the same destination page is shown to the students, the responses shown on the way 
+    to that page may well be different for the two answers.)
+<li>In the teacher's view of the lesson the correct answers have underlined Answer 
+    Labels.
+<li>The <b>end of the lesson</b> is reached by either jumping to that location explicitly 
+    or by jumping to the next page from the last (logical) page of the lesson. When the
+    end of the lesson is reached, the student receives a congratulations message and is 
+    shown their grade. The grade is (the number of correct answers checked / number of 
+    pages seen) * the grade of the lesson.
+<li>If the end of the lesson is <i>not</i> reached, when the student goes into the
+    lesson they are given the choice of starting at the begining or picking up the lesson
+    where they answered their last correct answer.
+<li> For a lesson which allow re-takes, students are allowed to re-take the lesson until
+    they have achieved the maximum grade.
+</ol>
diff --git a/lang/en/help/lesson/retake.html b/lang/en/help/lesson/retake.html
new file mode 100644 (file)
index 0000000..a0027e6
--- /dev/null
@@ -0,0 +1,16 @@
+<p align="center"><b>Allowing the Students to Re-take the Lesson</b></p>
+
+<p>This setting determines whether the students can take the lesson more than once
+    or only once. The teacher may decide that the lesson contains material which
+    the students ought to know throughly. In which case repeated viewings of the 
+    lesson should be allowed. If, however, the material is used more like an exam
+    then the students should not be allowed to re-take the lesson.</p>
+
+<p>When the students are allowed to re-take the lesson, the <b>grades</b> shown 
+    in the Grades page are the grades from their <b>best</b> attempts of the lesson. 
+    However, the <b>Question Analysis</b> always uses the answers from the 
+    first attempts of the lesson, subsequent attempts are ignored.</p>
+
+<p>By default this option is <b>Yes</b>, meaning that students are allowed to re-take
+    the lesson. It is expected that only in exceptional circumstances will this
+    option be set to <b>No</b>.
diff --git a/lang/en/lesson.php b/lang/en/lesson.php
new file mode 100644 (file)
index 0000000..7fbd87e
--- /dev/null
@@ -0,0 +1,39 @@
+<?PHP // $Id$ 
+      // lesson.php - created with Moodle 1.2 development (2003111400)
+
+
+$string['addanewpage'] = "Add a new page";
+$string['addpagehere'] = "Add page Here";
+$string['answer'] = "Answer";
+$string['attempt'] = "Attempt: \$a";
+$string['attempts'] = "Attempts";
+$string['available'] = "Available from";
+$string['canretake'] = "\$a can re-take";
+$string['checknavigation'] = "Check navigation";
+$string['confirmdeletionofthispage'] = "Confirm deletion of this page";
+$string['congratulations'] = "Congratulations - end of lesson reached";
+$string['deadline'] = "Deadline";
+$string['deletingpage'] = "Deleting page: \$a";
+$string['displayofgrade'] = "Display of grade (for student)";
+$string['endoflesson'] = "End of lesson";
+$string['gradeis'] = "Grade is \$a";
+$string['jumpto'] = "Jump to";
+$string['maximumnumberofanswers'] = "Maximum number of answers";
+$string['modulename'] = "Lesson";
+$string['modulenameplural'] = "Lessons";
+$string['moving'] = "Moving page: \$a";
+$string['nextpage'] = "Next page";
+$string['noanswer'] = "No answer given";
+$string['numberofcorrectanswers'] = "Number of correct answers: \$a";
+$string['numberofpagesviewed'] = "Number of pages viewed: \$a";
+$string['outof'] = "Out of \$a";
+$string['page'] = "Page: \$a";
+$string['pagecontents'] = "Page contents";
+$string['pagetitle'] = "Page title";
+$string['pleasecheckoneanswer'] = "Please check one answer";
+$string['response'] = "Response";
+$string['savepage'] = "Save page";
+$string['thispage'] = "This page";
+$string['youhaveseen'] = "You have seen more than one page of this lesson already.<br />Do you want to start at the last page you saw?";
+
+?>
diff --git a/mod/lesson/backuplib.php b/mod/lesson/backuplib.php
new file mode 100644 (file)
index 0000000..07ce4d3
--- /dev/null
@@ -0,0 +1,258 @@
+<?PHP //$Id$
+    //This php script contains all the stuff to backup/restore
+    //lesson mods
+
+    //This is the "graphical" structure of the lesson mod: 
+    //
+    //                                          lesson ----------------------------|
+    //                                       (CL,pk->id)                           | 
+    //                                             |                               |
+    //                                             |                         lesson_grades
+    //                                             |                  (UL, pk->id,fk->lessonid)
+    //                                      lesson_pages
+    //                                  (pk->id,fk->lessonid)
+    //                                             |
+    //                                             |
+    //                                             |
+    //                                       lesson_answers
+    //                                    (pk->id,fk->pageid)
+    //                                             |
+    //                                             |
+    //                                             |
+    //                                       lesson_attempts
+    //                                  (UL,pk->id,fk->answerid)
+    //
+    // Meaning: pk->primary key field of the table
+    //          fk->foreign key to link with parent
+    //          nt->nested field (recursive data)
+    //          CL->course level info
+    //          UL->user level info
+    //          files->table may have files)
+    //
+    //-----------------------------------------------------------
+
+    //This function executes all the backup procedure about this mod
+    function lesson_backup_mods($bf, $preferences) {
+
+        global $CFG;
+
+        $status = true;
+
+        //Iterate over lesson table
+        $lessons = get_records("lesson", "course", $preferences->backup_course, "id");
+        if ($lessons) {
+            foreach ($lessons as $lesson) {
+                //Start mod
+                fwrite ($bf,start_tag("MOD",3,true));
+                //Print lesson data
+                fwrite ($bf,full_tag("ID",4,false,$lesson->id));
+                fwrite ($bf,full_tag("MODTYPE",4,false,"lesson"));
+                fwrite ($bf,full_tag("NAME",4,false,$lesson->name));
+                fwrite ($bf,full_tag("GRADE",4,false,$lesson->grade));
+                fwrite ($bf,full_tag("MAXANSWERS",4,false,$lesson->maxanswers));
+                fwrite ($bf,full_tag("RETAKE",4,false,$lesson->retake));
+                fwrite ($bf,full_tag("AVAILABLE",4,false,$lesson->available));
+                fwrite ($bf,full_tag("DEADLINE",4,false,$lesson->deadline));
+                fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$lesson->timemodified));
+                //Now we backup lesson pages
+                $status = backup_lesson_pages($bf,$preferences,$lesson->id);
+                //if we've selected to backup users info, then backup grades
+                if ($status) {
+                    if ($preferences->mods["lesson"]->userinfo) {
+                        $status = backup_lesson_grades($bf, $preferences, $lesson->id);
+                    }
+                //End mod
+                $status =fwrite ($bf,end_tag("MOD",3,true));
+                }
+            }
+        }
+        return $status;  
+    }
+
+    //Backup lesson_pages contents (executed from lesson_backup_mods)
+    function backup_lesson_pages ($bf, $preferences, $lessonid) {
+
+        global $CFG;
+
+        $status = true;
+
+        // run through the pages in their logical order, get the first page
+        if ($page = get_record_select("lesson_pages", "lessonid = $lessonid AND prevpageid = 0")) {
+            //Write start tag
+            $status =fwrite ($bf,start_tag("PAGES",4,true));
+            //Iterate over each page
+            while (true) {
+                //Start of page
+                $status =fwrite ($bf,start_tag("PAGE",5,true));
+                //Print page contents (prevpageid and nextpageid not needed)
+                fwrite ($bf,full_tag("PAGEID",6,false,$page->id)); // needed to fix (absolute) jumps
+                fwrite ($bf,full_tag("TIMECREATED",6,false,$page->timecreated));
+                fwrite ($bf,full_tag("TIMEMODIFIED",6,false,$page->timemodified));
+                fwrite ($bf,full_tag("TITLE",6,false,$page->title));
+                fwrite ($bf,full_tag("CONTENTS",6,false,$page->contents));
+                //Now we backup lesson answers for this page
+                $status = backup_lesson_answers($bf, $preferences, $page->id);
+                //End of page
+                $status =fwrite ($bf,end_tag("PAGE",5,true));
+                // move to the next (logical) page
+                if ($page->nextpageid) {
+                    if (!$page = get_record("lesson_pages", "id", $page->nextpageid)) {
+                        error("Lesson Backup: Next page not found!");
+                    }
+                } else {
+                    // last page reached
+                    break;
+                }
+
+            }
+            //Write end tag
+            $status =fwrite ($bf,end_tag("PAGES",4,true));
+        }
+        return $status;
+    }
+
+    //Backup lesson_answers contents (executed from backup_lesson_pages)
+    function backup_lesson_answers($bf,$preferences,$pageno) {
+
+        global $CFG;
+
+        $status = true;
+
+        $lesson_answers = get_records("lesson_answers", "pageid", $pageno);
+
+        //If there is lesson_answers
+        if ($lesson_answers) {
+            //Write start tag
+            $status =fwrite ($bf,start_tag("ANSWERS",6,true));
+            //Iterate over each element
+            foreach ($lesson_answers as $answer) {
+                //Start answer
+                $status =fwrite ($bf,start_tag("ANSWER",7,true));
+                //Print answer contents
+                fwrite ($bf,full_tag("JUMPTO",8,false,$answer->jumpto));
+                fwrite ($bf,full_tag("TIMECREATED",8,false,$answer->timecreated));
+                fwrite ($bf,full_tag("TIMEMODIFIED",8,false,$answer->timemodified));
+                fwrite ($bf,full_tag("ANSWERTEXT",8,false,$answer->answer));
+                fwrite ($bf,full_tag("RESPONSE",8,false,$answer->response));
+                //Now we backup any lesson attempts (if student data required)
+                if ($preferences->mods["lesson"]->userinfo) {
+                    $status = backup_lesson_attempts($bf,$preferences,$answer->id);
+                }
+                //End rubric
+                $status =fwrite ($bf,end_tag("ANSWER",7,true));
+            }
+            //Write end tag
+            $status =fwrite ($bf,end_tag("ANSWERS",6,true));
+        }
+        return $status;
+    }
+
+    //Backup lesson_attempts contents (executed from lesson_backup_answers)
+    function backup_lesson_attempts ($bf,$preferences,$answerid) {
+
+        global $CFG;
+
+        $status = true;
+
+        $lesson_attempts = get_records("lesson_attempts","answerid", $answerid);
+        //If there are attempts
+        if ($lesson_attempts) {
+            //Write start tag
+            $status =fwrite ($bf,start_tag("ATTEMPTS",4,true));
+            //Iterate over each attempt
+            foreach ($lesson_attempts as $attempt) {
+                //Start Attempt
+                $status =fwrite ($bf,start_tag("ATTEMPT",5,true));
+                //Print attempt contents
+                fwrite ($bf,full_tag("USERID",6,false,$attempt->userid));       
+                fwrite ($bf,full_tag("CORRECT",6,false,$attempt->correct));       
+                fwrite ($bf,full_tag("TIMESEEN",6,false,$attempt->timeseen));       
+                fwrite ($bf,full_tag("RETRY",6,false,$attempt->retry));       
+                //End attempt
+                $status =fwrite ($bf,end_tag("ATTEMPT",5,true));
+            }
+            //Write end tag
+            $status =fwrite ($bf,end_tag("ATTEMPTS",4,true));
+        }
+        return $status;
+    }
+
+
+   //Backup lesson_grades contents (executed from backup_lesson_mods)
+    function backup_lesson_grades ($bf,$preferences,$lessonid) {
+
+        global $CFG;
+
+        $status = true;
+
+        $grades = get_records("lesson_grades", "lessonid", $lessonid);
+
+        //If there is grades
+        if ($grades) {
+            //Write start tag
+            $status =fwrite ($bf,start_tag("GRADES",8,true));
+            //Iterate over each grade
+            foreach ($grades as $grade) {
+                //Start grade
+                $status =fwrite ($bf,start_tag("GRADE",9,true));
+                //Print grade contents
+                fwrite ($bf,full_tag("USERID",10,false,$grade->userid));
+                fwrite ($bf,full_tag("GRADE_VALUE",10,false,$grade->grade));
+                fwrite ($bf,full_tag("LATE",10,false,$grade->late));
+                fwrite ($bf,full_tag("COMPLETED",10,false,$grade->completed));
+                //End comment
+                $status =fwrite ($bf,end_tag("GRADE",9,true));
+            }
+            //Write end tag
+            $status =fwrite ($bf,end_tag("GRADES",8,true));
+        }
+        return $status;
+    }
+    //Return an array of info (name,value)
+    function lesson_check_backup_mods($course,$user_data=false,$backup_unique_code) {
+        //First the course data
+        $info[0][0] = get_string("modulenameplural","lesson");
+        if ($ids = lesson_ids($course)) {
+            $info[0][1] = count($ids);
+        } else {
+            $info[0][1] = 0;
+        }
+
+        //Now, if requested, the user_data
+        if ($user_data) {
+            $info[1][0] = get_string("attempts","lesson");
+            if ($ids = lesson_attempts_ids_by_course ($course)) { 
+                $info[1][1] = count($ids);
+            } else {
+                $info[1][1] = 0;
+            }
+        }
+        return $info;
+    }
+
+
+
+    // INTERNAL FUNCTIONS. BASED IN THE MOD STRUCTURE
+
+    //Returns an array of lesson id 
+    function lesson_ids ($course) {
+
+        global $CFG;
+
+        return get_records_sql ("SELECT l.id, l.course
+                                 FROM {$CFG->prefix}lesson l
+                                 WHERE l.course = '$course'");
+    }
+    
+    //Returns an array of lesson_submissions id
+    function lesson_attempts_ids_by_course ($course) {
+
+        global $CFG;
+
+        return get_records_sql ("SELECT a.id , a.lessonid
+                                 FROM {$CFG->prefix}lesson_attempts a,
+                                      {$CFG->prefix}lesson l
+                                 WHERE l.course = '$course' AND
+                                       a.lessonid = l.id");
+    }
+?>
diff --git a/mod/lesson/db/mysql.php b/mod/lesson/db/mysql.php
new file mode 100644 (file)
index 0000000..b3bfa4d
--- /dev/null
@@ -0,0 +1,18 @@
+<?PHP
+
+function lesson_upgrade($oldversion) {
+/// This function does anything necessary to upgrade 
+/// older versions to match current functionality 
+
+    global $CFG;
+
+    if ($oldversion < 2004012400) {
+
+       # Do something ...
+
+    }
+
+    return true;
+}
+
+?>
diff --git a/mod/lesson/db/mysql.sql b/mod/lesson/db/mysql.sql
new file mode 100644 (file)
index 0000000..4561319
--- /dev/null
@@ -0,0 +1,72 @@
+# This file contains a complete database schema for all the 
+# tables used by the mlesson module, written in SQL
+
+# It may also contain INSERT statements for particular data 
+# that may be used, especially new entries in the table log_display
+
+CREATE TABLE `prefix_lesson` (
+  `id` int(10) unsigned NOT NULL auto_increment,
+  `course` int(10) unsigned NOT NULL default '0',
+  `name` varchar(255) NOT NULL default '',
+  `grade` tinyint(3) NOT NULL default '0',
+  `maxanswers` int(3) unsigned NOT NULL default '4',
+  `retake` int(3) unsigned NOT NULL default '1',
+  `available` int(10) unsigned NOT NULL default '0',
+  `deadline` int(10) unsigned NOT NULL default '0',
+  `timemodified` int(10) unsigned NOT NULL default '0',
+   PRIMARY KEY  (`id`)
+) COMMENT='Defines lesson';
+# --------------------------------------------------------
+
+CREATE TABLE `prefix_lesson_pages` (
+  `id` int(10) unsigned NOT NULL auto_increment,
+  `lessonid` int(10) unsigned NOT NULL default '0',
+  `prevpageid` int(10) unsigned NOT NULL default '0',
+  `nextpageid` int(10) unsigned NOT NULL default '0',
+  `timecreated` int(10) unsigned NOT NULL default '0',
+  `timemodified` int(10) unsigned NOT NULL default '0',
+  `title` varchar(255) NOT NULL default '',
+  `contents` text NOT NULL default '',
+  PRIMARY KEY  (`id`)
+) COMMENT='Defines lesson_pages';
+# --------------------------------------------------------
+
+CREATE TABLE `prefix_lesson_answers` (
+  `id` int(10) unsigned NOT NULL auto_increment,
+  `lessonid` int(10) unsigned NOT NULL default '0',
+  `pageid` int(10) unsigned NOT NULL default '0',
+  `jumpto` int(11) NOT NULL default '0',
+  `timecreated` int(10) unsigned NOT NULL default '0',
+  `timemodified` int(10) unsigned NOT NULL default '0',
+  `answer` text NOT NULL default '',
+  `response` text NOT NULL default '',
+  PRIMARY KEY  (`id`)
+) COMMENT='Defines lesson_answers';
+# --------------------------------------------------------
+
+CREATE TABLE `prefix_lesson_attempts` (
+  `id` int(10) unsigned NOT NULL auto_increment,
+  `lessonid` int(10) unsigned NOT NULL default '0',
+  `pageid` int(10) unsigned NOT NULL default '0',
+  `userid` int(10) unsigned NOT NULL default '0',
+  `answerid` int(10) unsigned NOT NULL default '0',
+  `retry` int(3) unsigned NOT NULL default '0',
+  `correct` int(10) unsigned NOT NULL default '0',
+  `timeseen` int(10) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`id`)
+) COMMENT='Defines lesson_attempts';
+# --------------------------------------------------------
+
+CREATE TABLE `prefix_lesson_grades` (
+  `id` int(10) unsigned NOT NULL auto_increment,
+  `lessonid` int(10) unsigned NOT NULL default '0',
+  `userid` int(10) unsigned NOT NULL default '0',
+  `grade` int(3) unsigned NOT NULL default '0',
+  `late` int(3) unsigned NOT NULL default '0',
+  `completed` int(10) unsigned NOT NULL default '0',
+  PRIMARY KEY  (`id`)
+) COMMENT='Defines lesson_grades';
+# --------------------------------------------------------
+
+
+
diff --git a/mod/lesson/icon.gif b/mod/lesson/icon.gif
new file mode 100755 (executable)
index 0000000..550df5d
Binary files /dev/null and b/mod/lesson/icon.gif differ
diff --git a/mod/lesson/index.php b/mod/lesson/index.php
new file mode 100644 (file)
index 0000000..f062d11
--- /dev/null
@@ -0,0 +1,105 @@
+<?PHP // $Id$
+
+/// This page lists all the instances of lesson in a particular course
+
+    require_once("../../config.php");
+    require_once("lib.php");
+
+    require_variable($id);   // course
+
+    if (!$course = get_record("course", "id", $id)) {
+        error("Course ID is incorrect");
+    }
+
+    require_login($course->id);
+
+    add_to_log($course->id, "lesson", "view all", "index.php?id=$course->id", "");
+
+
+/// Get all required strings
+
+    $strlessons = get_string("modulenameplural", "lesson");
+    $strlesson  = get_string("modulename", "lesson");
+
+
+/// Print the header
+
+    if ($course->category) {
+        $navigation = "<A HREF=\"../../course/view.php?id=$course->id\">$course->shortname</A> ->";
+    }
+
+    print_header("$course->shortname: $strlessons", "$course->fullname", "$navigation $strlessons", "", "", true, "", navmenu($course));
+
+/// Get all the appropriate data
+
+    if (! $lessons = get_all_instances_in_course("lesson", $course)) {
+        notice("There are no lessons", "../../course/view.php?id=$course->id");
+        die;
+    }
+
+/// Print the list of instances (your module will probably extend this)
+
+    $timenow = time();
+    $strname  = get_string("name");
+    $strgrade  = get_string("grade");
+    $strdeadline  = get_string("deadline", "lesson");
+    $strweek  = get_string("week");
+    $strtopic  = get_string("topic");
+
+    if ($course->format == "weeks") {
+        $table->head  = array ($strweek, $strname, $strgrade, $strdeadline);
+        $table->align = array ("CENTER", "LEFT", "CENTER", "CENTER");
+    } else if ($course->format == "topics") {
+        $table->head  = array ($strtopic, $strname);
+        $table->align = array ("CENTER", "LEFT", "CENTER", "CENTER");
+    } else {
+        $table->head  = array ($strname);
+        $table->align = array ("LEFT", "CENTER", "CENTER");
+    }
+
+    foreach ($lessons as $lesson) {
+        if (!$lesson->visible) {
+            //Show dimmed if the mod is hidden
+            $link = "<A class=\"dimmed\" HREF=\"view.php?id=$lesson->coursemodule\">$lesson->name</A>";
+        } else {
+            //Show normal if the mod is visible
+            $link = "<A HREF=\"view.php?id=$lesson->coursemodule\">$lesson->name</A>";
+        }
+
+        if ($lesson->deadline > $timenow) {
+            $due = userdate($lesson->deadline);
+        } else {
+            $due = "<FONT COLOR=\"red\">".userdate($lesson->deadline)."</FONT>";
+        }
+
+        if ($course->format == "weeks" or $course->format == "topics") {
+            if (isteacher($course->id)) {
+                $grade_value = $lesson->grade;
+            } else {
+                // it's a student, show their maximum grade
+                if ($grades = get_records_select("lesson_grades", "lessonid = $lesson->id AND 
+                            userid = $USER->id", "grade DESC")) {
+                    foreach ($grades as $grade) {
+                        // grades are stored as percentages
+                        $grade_value = number_format($grade->grade * $lesson->grade / 100, 1);
+                        break;  // only the first (largest) grade needed
+                    }
+                } else {
+                    $grade_value = 0;
+                }
+            }
+            $table->data[] = array ($lesson->section, $link, $grade_value, $due);
+        } else {
+            $table->data[] = array ($link, $grade_value, $due);
+        }
+    }
+
+    echo "<BR>";
+
+    print_table($table);
+
+/// Finish the page
+
+    print_footer($course);
+
+?>
diff --git a/mod/lesson/lesson.php b/mod/lesson/lesson.php
new file mode 100644 (file)
index 0000000..4654026
--- /dev/null
@@ -0,0 +1,669 @@
+<?PHP  // $Id: lesson.php, v 1.0 25 Jan 2004
+
+/*************************************************
+       ACTIONS handled are:
+
+       addpage
+    confirmdelete
+       delete
+       editpage
+    insertpage
+    move
+       moveit
+       updatepage
+
+************************************************/
+
+    require("../../config.php");
+       require("lib.php");
+
+       require_variable($id);    // Course Module ID
+    // get some esential stuff...
+       if (! $cm = get_record("course_modules", "id", $id)) {
+               error("Course Module ID was incorrect");
+       }
+
+       if (! $course = get_record("course", "id", $cm->course)) {
+               error("Course is misconfigured");
+       }
+
+       if (! $lesson = get_record("lesson", "id", $cm->instance)) {
+               error("Course module is incorrect");
+       }
+
+    require_login($course->id);
+       
+    // set up some general variables
+    $usehtmleditor = can_use_html_editor();
+    echo "\$usehtmleditor:$usehtmleditor"; 
+    
+    $navigation = "";
+    if ($course->category) {
+        $navigation = "<A HREF=\"../../course/view.php?id=$course->id\">$course->shortname</A> ->";
+    }
+
+    $strlessons = get_string("modulenameplural", "lesson");
+    $strlesson  = get_string("modulename", "lesson");
+    $strlessonname = $lesson->name;
+       
+       // ... print the header and...
+    print_header("$course->shortname: $lesson->name", "$course->fullname",
+                 "$navigation <A HREF=index.php?id=$course->id>$strlessons</A> -> 
+                  <A HREF=\"view.php?id=$cm->id\">$lesson->name</A> -> $action", 
+                  "", "", true);
+
+       //...get the action 
+       require_variable($action);
+       
+
+       /************** add page ************************************/
+       if ($action == 'addpage' ) {
+
+               if (!isteacher($course->id)) {
+               error("Only teachers can look at this page");
+           }
+
+        // first get the preceeding page
+        $pageid = $_GET['pageid'];
+            
+        // set of jump array
+        $jump[0] = get_string("thispage", "lesson");
+        $jump[NEXTPAGE] = get_string("nextpage", "lesson");
+        $jump[EOL] = get_string("endoflesson", "lesson");
+        if (!$apageid = get_field("lesson_pages", "id", "lessonid", $lesson->id, "prevpageid", 0)) {
+            error("Add page: first page not found");
+        }
+        while (true) {
+            if ($apageid) {
+                $title = get_field("lesson_pages", "title", "id", $apageid);
+                $jump[$apageid] = $title;
+                $apageid = get_field("lesson_pages", "nextpageid", "id", $apageid);
+            } else {
+                // last page reached
+                break;
+            }
+        }
+        // give teacher a blank proforma
+               print_heading_with_help(get_string("addanewpage", "lesson"), "overview", "lesson");
+        ?>
+        <form name="form" method="post" action="lesson.php">
+        <input type="hidden" name="id" value="<?PHP echo $cm->id ?>">
+        <input type="hidden" name="action" value="insertpage">
+        <input type="hidden" name="pageid" value="<?PHP echo $_GET['pageid'] ?>">
+        <center><table cellpadding=5 border=1>
+        <tr><td align="center">
+        <tr valign="top">
+        <td><b><?php print_string("pagetitle", "lesson"); ?>:</b><br />
+        <input type="text" name="title" size="80" maxsize="255" value=""></td></tr>
+        <?PHP
+        echo "<tr><td><b>";
+        echo get_string("pagecontents", "lesson").":</b><br />\n";
+        print_textarea($usehtmleditor, 25,70, 630, 400, "contents");
+        echo "</td></tr>\n";
+        for ($i = 0; $i < $lesson->maxanswers; $i++) {
+            $iplus1 = $i + 1;
+            echo "<tr><td><b>".get_string("answer", "lesson")." $iplus1:</b><br />\n";
+            print_textarea($usehtmleditor, 20, 70, 630, 300, "answer[$i]");
+            echo "</td></tr>\n";
+            echo "<tr><td><b>".get_string("response", "lesson")." $iplus1:</b><br />\n";
+            print_textarea($usehtmleditor, 20, 70, 630, 300, "response[$i]");
+            echo "</td></tr>\n";
+            echo "<tr><td><B>".get_string("jumpto", "lesson").":</b> \n";
+            if ($i) {
+                // answers 2, 3, 4... jumpto this page
+                lesson_choose_from_menu($jump, "jumpto[$i]", 0, "");
+            } else {
+                // answer 1 jumpto next page
+                lesson_choose_from_menu($jump, "jumpto[$i]", NEXTPAGE, "");
+            }
+            helpbutton("jumpto", get_string("jumpto", "lesson"), "lesson");
+            echo "</td></tr>\n";
+        }
+        use_html_editor();
+        // close table and form
+        ?>
+        </table><br />
+        <input type="submit" value="<?php  print_string("addanewpage", "lesson") ?>">
+        <input type="submit" name="cancel" value="<?php  print_string("cancel") ?>">
+        </center>
+        </form>
+        <?PHP
+               }
+       
+
+       /******************* confirm delete ************************************/
+    elseif ($action == 'confirmdelete' ) {
+
+               if (!isteacher($course->id)) {
+               error("Only teachers can look at this page");
+           }
+
+               if (empty($_GET['pageid'])) {
+                       error("Confirm delete: pageid missing");
+               }
+        $pageid = $_GET['pageid'];
+        if (!$thispage = get_record("lesson_pages", "id", $pageid)) {
+            error("Confirm delete: the page record not found");
+        }
+        print_heading(get_string("deletingpage", "lesson", $thispage->title));
+        // print the jumps to this page
+        if ($answers = get_records_select("lesson_answers", "lessonid = $lesson->id AND jumpto = $pageid + 1")) {
+            print_heading(get_string("thefollowingpagesjumptothispage", "lesson"));
+            echo "<p align=\"center\">\n";
+            foreach ($answers as $answer) {
+                if (!$title = get_field("lesson_pages", "title", "id", $answer->pageid)) {
+                    error("Confirm delete: page title not found");
+                }
+                echo $title."<br />\n";
+            }
+        }
+               notice_yesno(get_string("confirmdeletionofthispage","lesson"), 
+                        "lesson.php?action=delete&id=$cm->id&pageid=$pageid]", 
+             "view.php?id=$cm->id");
+               }
+       
+
+       /****************** continue ************************************/
+       elseif ($action == 'continue' ) {
+        // record answer (if necessary) and show response (if any)
+
+               if (empty($_POST['pageid'])) {
+                       error("Continue: pageid missing");
+               }
+        $pageid = $_POST['pageid'];
+        // get the answer
+        if (empty($_POST['answerid'])) {
+            print_heading(get_string("noanswer", "lesson"));
+                   redirect("view.php?id=$cm->id&action=navigation&pageid=$pageid", 
+                    get_string("continue", "lesson"));
+        } else {
+            $answerid = $_POST['answerid']; 
+            if (!$answer = get_record("lesson_answers", "id", $answerid)) {
+                error("Continue: answer record not found");
+            } 
+            $ntries = count_records("lesson_grades", "lessonid", $lesson->id, "userid", $USER->id); 
+            if (isstudent($course->id)) {
+                // record student's attempt
+                $correct = get_field("lesson_answers", "correct", "id", $answerid);
+                $attempt->lessonid = $lesson->id;
+                $attempt->pageid = $pageid;
+                $attempt->userid = $USER->id;
+                $attempt->answerid = $answerid;
+                $attempt->retry = $ntries;
+                $attempt->correct = lesson_iscorrect($pageid, $answer->jumpto);
+                $attempt->timeseen = time();
+                if (!$newattemptid = insert_record("lesson_attempts", $attempt)) {
+                    error("Continue: attempt not inserted");
+                }
+            }
+            
+            // convert jumpto to a proper page id
+            if ($answer->jumpto == 0) {
+                $newpageid = $pageid;
+            } elseif ($answer->jumpto == NEXTPAGE) {
+                if (!$newpageid = get_field("lesson_pages", "nextpageid", "id", $pageid)) {
+                    // no nextpage go to end of lesson
+                    $newpageid = EOL;
+                }
+            } else {
+                $newpageid = $answer->jumpto;
+            }
+            
+            // display response (if there is one)
+            if ($answer->response) {
+                $title = get_field("lesson_pages", "title", "id", $pageid);
+                print_heading($title);
+                echo "<table width=\"80%\" border=\"0\" align=\"center\"><tr><td>\n";
+                print_simple_box(format_text($answer->response), 'center');
+                echo "</td></tr></table>\n";
+                       print_continue("view.php?id=$cm->id&action=navigation&pageid=$newpageid");
+            } else {
+                // there's no response text - just go straight to the next page
+                           redirect("lesson.php?id=$cm->id&action=navigation&pageid=$newpageid", 
+                        get_string("continue"));
+            }
+        }
+       }
+       
+
+
+       /******************* delete ************************************/
+       elseif ($action == 'delete' ) {
+
+               if (!isteacher($course->id)) {
+               error("Only teachers can look at this page");
+           }
+
+               if (empty($_GET['pageid'])) {
+                       error("Delete: pageid missing");
+               }
+        $pageid = $_GET['pageid'];
+           if (!$thispage = get_record("lesson_pages", "id", $pageid)) {
+                   error("Delete: page record not found");
+        }
+        
+        print_string("deleting", "lesson");
+               // first delete all the associated records...
+               delete_records("lesson_attempts", "pageid", $pageid);
+               // ...now delete the answers...
+               delete_records("lesson_answers", "pageid", $pageid);
+        // ..and the page itself
+        delete_records("lesson_pages", "id", $pageid);
+               
+        // repair the hole in the linkage
+        if (!$thispage->prevpageid) {
+            // this is the first page...
+            if (!$page = get_record("lesson_pages", "id", $thispage->nextpageid)) {
+                error("Delete: next page not found");
+            }
+            if (!set_field("lesson_pages", "prevpageid", 0, "id", $page->id)) {
+                error("Delete: unable to set prevpage link");
+            }
+        } elseif (!$thispage->nextpageid) {
+            // this is the last page...
+            if (!$page = get_record("lesson_pages", "id", $thispage->prevpageid)) {
+                error("Delete: prev page not found");
+            }
+            if (!set_field("lesson_pages", "nextpageid", 0, "id", $page->id)) {
+                error("Delete: unable to set nextpage link");
+            }
+        } else {
+            // page is in the middle...
+            if (!$prevpage = get_record("lesson_pages", "id", $thispage->prevpageid)) {
+                error("Delete: prev page not found");
+            }
+            if (!$nextpage = get_record("lesson_pages", "id", $thispage->nextpageid)) {
+                error("Delete: next page not found");
+            }
+            if (!set_field("lesson_pages", "nextpageid", $nextpage->id, "id", $prevpage->id)) {
+                error("Delete: unable to set next link");
+            }
+            if (!set_field("lesson_pages", "prevpageid", $prevpage->id, "id", $nextpage->id)) {
+                error("Delete: unable to set prev link");
+            }
+        }
+               redirect("view.php?id=$cm->id", get_string("ok"));
+       }
+       
+
+
+       /************** edit page ************************************/
+    elseif ($action == 'editpage' ) {
+
+               if (!isteacher($course->id)) {
+               error("Only teachers can look at this page");
+           }
+
+        // get the page
+        if (!$page = get_record("lesson_pages", "id", $_GET['pageid'])) {
+            error("Edit page: page record not found");
+        }
+        // set of jump array
+        $jump[0] = get_string("thispage", "lesson");
+        $jump[NEXTPAGE] = get_string("nextpage", "lesson");
+        $jump[EOL] = get_string("endoflesson", "lesson");
+        if (!$apageid = get_field("lesson_pages", "id", "lessonid", $lesson->id, "prevpageid", 0)) {
+            error("Edit page: first page not found");
+        }
+        while (true) {
+            if ($apageid) {
+                $title = get_field("lesson_pages", "title", "id", $apageid);
+                $jump[$apageid] = $title;
+                $apageid = get_field("lesson_pages", "nextpageid", "id", $apageid);
+            } else {
+                // last page reached
+                break;
+            }
+        }
+        
+        // give teacher a proforma
+        ?>
+        <form name="form" method="post" action="lesson.php">
+        <input type="hidden" name="id" value="<?PHP echo $cm->id ?>">
+        <input type="hidden" name="action" value="updatepage">
+        <input type="hidden" name="pageid" value="<?PHP echo $_GET['pageid'] ?>">
+        <center><table cellpadding=5 border=1>
+        <tr><td align="center">
+        <tr valign="top">
+        <td><b><?php print_string("pagetitle", "lesson"); ?>:</b><br />
+        <input type="text" name="title" size="80" maxsize="255" value="<?PHP echo $page->title ?>"></td>
+        </tr>
+        <?PHP
+        echo "<tr><td><b>";
+        echo get_string("pagecontents", "lesson").":</b><br />\n";
+        print_textarea($usehtmleditor, 25, 70, 630, 400, "contents", $page->contents);
+        echo "</td></tr>\n";
+        $n = 0;
+        if ($answers = get_records("lesson_answers", "pageid", $page->id, "id")) {
+            foreach ($answers as $answer) {
+                $nplus1 = $n + 1;
+                echo "<input type=\"hidden\" name=\"answerid[$n]\" value=\"$answer->id\">\n";
+                echo "<tr><td><b>".get_string("answer", "lesson")." $nplus1:</b><br />\n";
+                print_textarea($usehtmleditor, 20, 70, 630, 300, "answer[$n]", $answer->answer);
+                echo "</td></tr>\n";
+                echo "<tr><td><b>".get_string("response", "lesson")." $nplus1:</b><br />\n";
+                print_textarea($usehtmleditor, 20, 70, 630, 300, "response[$n]", $answer->response);
+                echo "</td></tr>\n";
+                echo "<tr><td><B>".get_string("jumpto", "lesson").":</b> \n";
+                lesson_choose_from_menu($jump, "jumpto[$n]", $answer->jumpto, "");
+                helpbutton("jumpto", get_string("jumpto", "lesson"), "lesson");
+                echo "</td></tr>\n";
+                $n++;
+            }
+        }
+        for ($i = $n; $i < $lesson->maxanswers; $i++) {
+            $iplus1 = $i + 1;
+            echo "<input type=\"hidden\" name=\"answerid[$i]\" value=\"0\">\n";
+            echo "<tr><td><b>".get_string("answer", "lesson")." $iplus1:</b><br />\n";
+            print_textarea($usehtmleditor, 20, 70, 630, 300, "answer[$i]");
+            echo "</td></tr>\n";
+            echo "<tr><td><b>".get_string("response", "lesson")." $iplus1:</b><br />\n";
+            print_textarea($usehtmleditor, 20, 70, 630, 300, "response[$i]");
+            echo "</td></tr>\n";
+            echo "<tr><td><B>".get_string("jumpto", "lesson").":</b> \n";
+            lesson_choose_from_menu($jump, "jumpto[$i]", 0, "");
+            helpbutton("jumpto", get_string("jumpto", "lesson"), "lesson");
+            echo "</td></tr>\n";
+        }
+        use_html_editor();
+        // close table and form
+        ?>
+        </table><br />
+        <input type="submit" value="<?php  print_string("savepage", "lesson") ?>">
+        <input type="submit" name="cancel" value="<?php  print_string("cancel") ?>">
+        </center>
+        </form>
+        <?PHP
+               }
+       
+
+       /****************** insert page ************************************/
+       elseif ($action == 'insertpage' ) {
+        
+               if (!isteacher($course->id)) {
+               error("Only teachers can look at this page");
+           }
+
+        $timenow = time();
+               $form = (object) $HTTP_POST_VARS;
+        
+        if ($form->pageid) {
+            // the new page is not the first page
+            if (!$page = get_record("lesson_pages", "id", $form->pageid)) {
+                error("Insert page: page record not found");
+            }
+            $newpage->lessonid = $lesson->id;
+            $newpage->prevpageid = $form->pageid;
+            $newpage->nextpageid = $page->nextpageid;
+            $newpage->timecreated = $timenow;
+            $newpage->title = $form->title;
+            $newpage->contents = trim($form->contents);
+            $newpageid = insert_record("lesson_pages", $newpage);
+            if (!$newpageid) {
+                error("Insert page: new page not inserted");
+            }
+            // update the linked list
+            if (!set_field("lesson_pages", "nextpageid", $newpageid, "id", $form->pageid)) {
+                error("Insert page: unable to update link");
+            }
+        } else {
+            // new page is the first page
+            // get the existing (first) page (if any)
+            if (!$page = get_record_select("lesson_pages", "lessonid = $lesson->id AND prevpageid = 0")) {
+                // there are no existing pages
+                $newpage->lessonid = $lesson->id;
+                $newpage->prevpageid = 0; // this is a first page
+                $newpage->nextpageid = 0; // this is the only page
+                $newpage->timecreated = $timenow;
+                $newpage->title = $form->title;
+                $newpage->contents = trim($form->contents);
+                $newpageid = insert_record("lesson_pages", $newpage);
+                if (!$newpageid) {
+                    error("Insert page: new first page not inserted");
+                }
+            } else {
+                // there are existing pages put this at the start
+                $newpage->lessonid = $lesson->id;
+                $newpage->prevpageid = 0; // this is a first page
+                $newpage->nextpageid = $page->id;
+                $newpage->timecreated = $timenow;
+                $newpage->title = $form->title;
+                $newpage->contents = trim($form->contents);
+                $newpageid = insert_record("lesson_pages", $newpage);
+                if (!$newpageid) {
+                    error("Insert page: first page not inserted");
+                }
+                // update the linked list
+                if (!set_field("lesson_pages", "prevpageid", $newpageid, "id", $page->id)) {
+                    error("Insert page: unable to update link");
+                }
+            }
+        }
+        // now add the answers
+        for ($i = 0; $i < $lesson->maxanswers; $i++) {
+            if (trim(strip_tags($form->answer[$i]))) { // strip_tags because the HTML editor adds <p><br />...
+                $newanswer->lessonid = $lesson->id;
+                $newanswer->pageid = $newpageid;
+                $newanswer->timecreated = $timenow;
+                $newanswer->answer = trim($form->answer[$i]);
+                $newanswer->response = trim($form->response[$i]);
+                if (isset($form->jumpto[$i])) {
+                    $newanswer->jumpto = $form->jumpto[$i];
+                }
+                $newanswerid = insert_record("lesson_answers", $newanswer);
+                if (!$newanswerid) {
+                    error("Insert Page: answer record $i not inserted");
+                }
+            } else {
+                break;
+            }
+        }
+           redirect("view.php?id=$cm->id", get_string("ok"));
+       }
+       
+
+       /****************** move ************************************/
+    elseif ($action == 'move') {
+        
+               if (!isteacher($course->id)) {
+               error("Only teachers can look at this page");
+           }
+
+        $pageid = $_GET['pageid'];
+        $title = get_field("lesson_pages", "title", "id", $pageid);
+        print_heading(get_string("moving", "lesson", $title));
+        
+        if (!$page = get_record_select("lesson_pages", "lessonid = $lesson->id AND prevpageid = 0")) {
+            error("Move: first page not found");
+        }
+
+        echo "<center><table cellpadding=\"5\" border=\"1\">\n";
+        echo "<tr><td><a href=\"lesson.php?id=$cm->id&action=moveit&pageid=$pageid&after=0\"><small>".
+            get_string("movepagehere", "lesson")."</small></a></td></tr>\n";
+        while (true) {
+            if ($page->id != $pageid) {
+                echo "<tr><td bgcolor=\"$THEME->cellheading2\"><b>$page->title</b></td></tr>\n";
+                echo "<tr><td><a href=\"lesson.php?id=$cm->id&action=moveit&pageid=$pageid&after={$page->id}\"><small>".
+                    get_string("movepagehere", "lesson")."</small></a></td></tr>\n";
+            }
+            if ($page->nextpageid) {
+                if (!$page = get_record("lesson_pages", "id", $page->nextpageid)) {
+                    error("Teacher view: Next page not found!");
+                }
+            } else {
+                // last page reached
+                break;
+            }
+        }
+        echo "</table>\n";
+    }
+       
+
+       /****************** moveit ************************************/
+    elseif ($action == 'moveit') {
+        
+               if (!isteacher($course->id)) {
+               error("Only teachers can look at this page");
+           }
+
+        $pageid = $_GET['pageid']; //  page to move
+        if (!$page = get_record("lesson_pages", "id", $pageid)) {
+            error("Moveit: page not found");
+        }
+        $after = $_GET['after']; // target page
+
+        print_heading(get_string("moving", "lesson", $page->title));
+        
+        // first step. determine the new first page
+        // (this is done first as the current first page will be lost in the next step)
+        if (!$after) {
+            // the moved page is the new first page
+            $newfirstpageid = $pageid;
+            // reset $after so that is points to the last page 
+            // (when the pages are in a ring this will in effect be the first page)
+            if ($page->nextpageid) {
+                if (!$after = get_field("lesson_pages", "id", "lessonid", $lesson->id, "nextpageid", 0)) {
+                    error("Moveit: last page id not found");
+                }
+            } else {
+                // the page being moved is the last page, so the new last page will be
+                $after = $page->prevpageid;
+            }
+        } elseif (!$page->prevpageid) {
+            // the page to be moved was the first page, so the following page must be the new first page
+            $newfirstpageid = $page->nextpageid;
+        } else {
+            // the current first page remains the first page
+            if (!$newfirstpageid = get_field("lesson_pages", "id", "lessonid", $lesson->id, "prevpageid", 0)) {
+                error("Moveit: current first page id not found");
+            }
+        }
+        // the rest is all unconditional...
+        
+        // second step. join pages into a ring 
+        if (!$firstpageid = get_field("lesson_pages", "id", "lessonid", $lesson->id, "prevpageid", 0)) {
+            error("Moveit: firstpageid not found");
+        }
+        if (!$lastpageid = get_field("lesson_pages", "id", "lessonid", $lesson->id, "nextpageid", 0)) {
+            error("Moveit: lastpage not found");
+        }
+        if (!set_field("lesson_pages", "prevpageid", $lastpageid, "id", $firstpageid)) {
+            error("Moveit: unable to update link");
+        }
+        if (!set_field("lesson_pages", "nextpageid", $firstpageid, "id", $lastpageid)) {
+            error("Moveit: unable to update link");
+        }
+
+        echo "<p>\$newfirstpageid: $newfirstpageid";
+        echo "<p>\$after: $after";
+        
+        // third step. remove the page to be moved
+        if (!$prevpageid = get_field("lesson_pages", "prevpageid", "id", $pageid)) {
+            error("Moveit: prevpageid not found");
+        }
+        if (!$nextpageid = get_field("lesson_pages", "nextpageid", "id", $pageid)) {
+            error("Moveit: nextpageid not found");
+        }
+        if (!set_field("lesson_pages", "nextpageid", $nextpageid, "id", $prevpageid)) {
+            error("Moveit: unable to update link");
+        }
+        if (!set_field("lesson_pages", "prevpageid", $prevpageid, "id", $nextpageid)) {
+            error("Moveit: unable to update link");
+        }
+        
+        // fourth step. insert page to be moved in new place...
+        if (!$nextpageid = get_field("lesson_pages", "nextpageid", "id", $after)) {
+            error("Movit: nextpageid not found");
+        }
+        if (!set_field("lesson_pages", "nextpageid", $pageid, "id", $after)) {
+            error("Moveit: unable to update link");
+        }
+        if (!set_field("lesson_pages", "prevpageid", $pageid, "id", $nextpageid)) {
+            error("Moveit: unable to update link");
+        }
+        // ...and set the links in the moved page
+        if (!set_field("lesson_pages", "prevpageid", $after, "id", $pageid)) {
+            error("Moveit: unable to update link");
+        }
+        if (!set_field("lesson_pages", "nextpageid", $nextpageid, "id", $pageid)) {
+            error("Moveit: unable to update link");
+        }
+        
+        // fifth step. break the ring
+        if (!$newlastpageid = get_field("lesson_pages", "prevpageid", "id", $newfirstpageid)) {
+            error("Moveit: newlastpageid not found");
+        }
+        if (!set_field("lesson_pages", "prevpageid", 0, "id", $newfirstpageid)) {
+            error("Moveit: unable to update link");
+        }
+        if (!set_field("lesson_pages", "nextpageid", 0, "id", $newlastpageid)) {
+                error("Moveit: unable to update link");
+        }
+    }
+       
+
+       /****************** update page ************************************/
+    elseif ($action == 'updatepage' ) {
+        
+               if (!isteacher($course->id)) {
+               error("Only teachers can look at this page");
+           }
+
+        $timenow = time();
+        $form = (object) $HTTP_POST_VARS;
+
+        $page->id = $form->pageid;
+        $page->timemodified = $timenow;
+        $page->title = $form->title;
+        $page->contents = trim($form->contents);
+        if (!update_record("lesson_pages", $page)) {
+            error("Update page: page not updated");
+        }
+        for ($i = 0; $i < $lesson->maxanswers; $i++) {
+            if (trim(strip_tags($form->answer[$i]))) { // strip_tags because the HTML gives <p><br />...
+                if ($form->answerid[$i]) {
+                    $oldanswer->id = $form->answerid[$i];
+                    $oldanswer->timemodified = $timenow;
+                    $oldanswer->answer = trim($form->answer[$i]);
+                    $oldanswer->response = trim($form->response[$i]);
+                    $oldanswer->jumpto = $form->jumpto[$i];
+                    if (!update_record("lesson_answers", $oldanswer)) {
+                        error("Update page: answer $i not updated");
+                    }
+                } else {
+                    // it's a new answer
+                    $newanswer->lessonid = $lesson->id;
+                    $newanswer->pageid = $page->id;
+                    $newanswer->timecreated = $timenow;
+                    $newanswer->answer = trim($form->answer[$i]);
+                    $newanswer->response = trim($form->response[$i]);
+                    $newanswer->jumpto = $form->jumpto[$i];
+                    $newanswerid = insert_record("lesson_answers", $newanswer);
+                    if (!$newanswerid) {
+                        error("Update page: answer record not inserted");
+                    }
+                }
+            } else {
+                if ($form->answerid[$i]) {
+                    // need to delete blanked out answer
+                    if (!delete_records("lesson_answers", "id", $form->answerid[$i])) {
+                        error("Update page: unable to delete answer record");
+                    }
+                }
+            }
+        }
+               redirect("view.php?id=$cm->id", get_string("ok"));
+    }
+       
+
+       /*************** no man's land **************************************/
+       else {
+               error("Fatal Error: Unknown Action: ".$action."\n");
+       }
+
+       print_footer($course);
+?>
+
diff --git a/mod/lesson/lib.php b/mod/lesson/lib.php
new file mode 100644 (file)
index 0000000..d4800d3
--- /dev/null
@@ -0,0 +1,316 @@
+<?PHP  // $Id$
+
+/// Library of functions and constants for module lesson
+/// (replace lesson with the name of your module and delete this line)
+
+
+if (!defined("NEXTPAGE")) {
+       define("NEXTPAGE", -1); // Next page
+       }
+if (!defined("EOL")) {
+       define("EOL", -9); // End of Lesson
+       }
+if (!defined("UNDEFINED")) {
+       define("UNDEFINED", -99); // undefined
+       }
+
+/*******************************************************************/
+function lesson_choose_from_menu ($options, $name, $selected="", $nothing="choose", $script="", $nothingvalue="0", $return=false) {
+/// Given an array of value, creates a popup menu to be part of a form
+/// $options["value"]["label"]
+    
+    if ($nothing == "choose") {
+        $nothing = get_string("choose")."...";
+    }
+
+    if ($script) {
+        $javascript = "onChange=\"$script\"";
+    } else {
+        $javascript = "";
+    }
+
+    $output = "<SELECT NAME=$name $javascript>\n";
+    if ($nothing) {
+        $output .= "   <OPTION VALUE=\"$nothingvalue\"\n";
+        if ($nothingvalue == $selected) {
+            $output .= " SELECTED";
+        }
+        $output .= ">$nothing</OPTION>\n";
+    }
+    if (!empty($options)) {
+        foreach ($options as $value => $label) {
+            $output .= "   <OPTION VALUE=\"$value\"";
+            if ($value == $selected) {
+                $output .= " SELECTED";
+            }
+                       // stop zero label being replaced by array index value
+            // if ($label) {
+            //    $output .= ">$label</OPTION>\n";
+            // } else {
+            //     $output .= ">$value</OPTION>\n";
+                       //  }
+                       $output .= ">$label</OPTION>\n";
+            
+        }
+    }
+    $output .= "</SELECT>\n";
+
+    if ($return) {
+        return $output;
+    } else {
+        echo $output;
+    }
+}   
+
+
+/*******************************************************************/
+function lesson_add_instance($lesson) {
+/// Given an object containing all the necessary data, 
+/// (defined by the form in mod.html) this function 
+/// will create a new instance and return the id number 
+/// of the new instance.
+
+    $lesson->timemodified = time();
+
+    $lesson->available = make_timestamp($lesson->availableyear, 
+                       $lesson->availablemonth, $lesson->availableday, $lesson->availablehour, 
+                       $lesson->availableminute);
+
+    $lesson->deadline = make_timestamp($lesson->deadlineyear, 
+                       $lesson->deadlinemonth, $lesson->deadlineday, $lesson->deadlinehour, 
+                       $lesson->deadlineminute);
+
+    return insert_record("lesson", $lesson);
+}
+
+
+/*******************************************************************/
+function lesson_update_instance($lesson) {
+/// Given an object containing all the necessary data, 
+/// (defined by the form in mod.html) this function 
+/// will update an existing instance with new data.
+
+    $lesson->timemodified = time();
+    $lesson->available = make_timestamp($lesson->availableyear, 
+                       $lesson->availablemonth, $lesson->availableday, $lesson->availablehour, 
+                       $lesson->availableminute);
+    $lesson->deadline = make_timestamp($lesson->deadlineyear, 
+                       $lesson->deadlinemonth, $lesson->deadlineday, $lesson->deadlinehour, 
+                       $lesson->deadlineminute);
+    $lesson->id = $lesson->instance;
+
+    return update_record("lesson", $lesson);
+}
+
+
+/*******************************************************************/
+function lesson_delete_instance($id) {
+/// Given an ID of an instance of this module, 
+/// this function will permanently delete the instance 
+/// and any data that depends on it.  
+
+    if (! $lesson = get_record("lesson", "id", "$id")) {
+        return false;
+    }
+
+    $result = true;
+
+    if (! delete_records("lesson", "id", "$lesson->id")) {
+        $result = false;
+    }
+    if (! delete_records("lesson_pages", "lessonid", "$lesson->id")) {
+        $result = false;
+    }
+    if (! delete_records("lesson_answers", "lessonid", "$lesson->id")) {
+        $result = false;
+    }
+    if (! delete_records("lesson_attempts", "lessonid", "$lesson->id")) {
+        $result = false;
+    }
+    if (! delete_records("lesson_grades", "lessonid", "$lesson->id")) {
+        $result = false;
+    }
+
+    return $result;
+}
+
+/*******************************************************************/
+function lesson_user_outline($course, $user, $mod, $lesson) {
+/// Return a small object with summary information about what a 
+/// user has done with a given particular instance of this module
+/// Used for user activity reports.
+/// $return->time = the time they did it
+/// $return->info = a short text description
+
+    if ($grades = get_records_select("lesson_grades", "lessonid = $lesson->id AND userid = $user->id",
+                "grade DESC")) {
+        foreach ($grades as $grade) {
+            $max_grade = number_format($grade->grade * $lesson->grade / 100.0, 1);
+            break;
+        }
+        $return->time = $grade->completed;
+        if ($lesson->retake) {
+            $return->info = get_string("gradeis", "lesson", $max_grade)." (".
+                get_string("attempt", "lesson", count($grades)).")";
+        } else {
+            $return->info = get_string("gradeis", "lesson", $max_grade);
+        }
+    } else {
+        $return->info = get_string("no")." ".get_string("attempts", "lesson");
+    }
+    return $return;
+}
+
+/*******************************************************************/
+function lesson_user_complete($course, $user, $mod, $lesson) {
+/// Print a detailed representation of what a  user has done with 
+/// a given particular instance of this module, for user activity reports.
+
+    if ($attempts = get_records_select("lesson_attempts", "lessonid = $lesson->id AND userid = $user->id",
+                "retry, timeseen")) {
+        print_simple_box_start();
+               $table->head = array (get_string("attempt", "lesson"),  get_string("numberofpagesviewed", "lesson"),
+                       get_string("numberofcorrectanswers", "lesson"), get_string("time"));
+               $table->width = "100%";
+               $table->align = array ("center", "center", "center", "center");
+               $table->size = array ("*", "*", "*", "*");
+               $table->cellpadding = 2;
+               $table->cellspacing = 0;
+
+        $retry = 0;
+        $npages = 0;
+        $ncorrect = 0;
+        
+               foreach ($attempts as $attempt) {
+                       if ($attempt->retry == $retry) {
+                               $npages++;
+                if ($attempt->correct) {
+                    $ncorrect++;
+                }
+                $timeseen = $attempt->timeseen;
+            } else {
+                           $table->data[] = array($retry + 1, $npages, $ncorrect, userdate($timeseen));
+                $retry++;
+                $npages = 1;
+                if ($attempt->correct) {
+                    $ncorrect = 1;
+                } else {
+                    $ncorrect = 0;
+                }
+                       }
+               }
+        if ($npages) {
+                           $table->data[] = array($retry + 1, $npages, $ncorrect, userdate($timeseen));
+        }
+               print_table($table);
+           print_simple_box_end();
+        // also print grade summary
+        if ($grades = get_records_select("lesson_grades", "lessonid = $lesson->id AND userid = $user->id",
+                    "grade DESC")) {
+            foreach ($grades as $grade) {
+                $max_grade = number_format($grade->grade * $lesson->grade / 100.0, 1);
+                break;
+            }
+            if ($lesson->retake) {
+                echo "<p>".get_string("gradeis", "lesson", $max_grade)." (".
+                    get_string("attempts", "lesson").": ".count($grades).")</p>";
+            } else {
+                echo "<p>".get_string("gradeis", "lesson", $max_grade)."</p>";
+            }
+        }
+    } else {
+        echo get_string("no")." ".get_string("attempts", "lesson");
+    }
+
+    
+    return true;
+}
+
+/*******************************************************************/
+function lesson_print_recent_activity($course, $isteacher, $timestart) {
+/// Given a course and a time, this module should find recent activity 
+/// that has occurred in lesson activities and print it out. 
+/// Return true if there was output, or false is there was none.
+
+    global $CFG;
+
+    return false;  //  True if anything was printed, otherwise false 
+}
+
+/*******************************************************************/
+function lesson_cron () {
+/// Function to be run periodically according to the moodle cron
+/// This function searches for things that need to be done, such 
+/// as sending out mail, toggling flags etc ... 
+
+    global $CFG;
+
+    return true;
+}
+
+/*******************************************************************/
+function lesson_grades($lessonid) {
+/// Must return an array of grades for a given instance of this module, 
+/// indexed by user.  It also returns a maximum allowed grade.
+    global $CFG;
+
+       if (!$lesson = get_record("lesson", "id", $lessonid)) {
+               error("Lesson record not found");
+       }
+    $grades = get_records_sql_menu("SELECT userid,MAX(grade) FROM {$CFG->prefix}lesson_grades WHERE
+            lessonid = $lessonid GROUP BY userid");
+    
+    // convert grades from percentages and tidy the numbers
+    if ($grades) {
+        foreach ($grades as $userid => $grade) {
+            $return->grades[$userid] = number_format($grade * $lesson->grade / 100.0, 1);
+        }
+    }
+    $return->maxgrade = $lesson->grade;
+
+    return $return;
+}
+
+/*******************************************************************/
+function lesson_get_participants($lessonid) {
+//Must return an array of user records (all data) who are participants
+//for a given instance of lesson. Must include every user involved
+//in the instance, independient of his role (student, teacher, admin...)
+//See other modules as example.
+
+    return false;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+/// Any other lesson functions go here.  Each of them must have a name that 
+/// starts with lesson_
+
+/*******************************************************************/
+function lesson_iscorrect($pageid, $jumpto) {
+    // returns true is jumpto page is (logically) after the pageid page, other returns false
+    
+    // first test the special values
+    if (!$jumpto) {
+        // same page
+        return false;
+    } elseif ($jumpto == NEXTPAGE) {
+        return true;
+    } elseif ($jumpto == EOL) {
+        return true;
+    }
+    // we have to run through the pages from pageid looking for jumpid
+    $apageid = get_field("lesson_pages", "nextpageid", "id", $pageid);
+    while (true) {
+        if ($jumpto == $apageid) {
+            return true;
+        }
+        if ($apageid) {
+            $apageid = get_field("lesson_pages", "nextpageid", "id", $apageid);
+        } else {
+            return false;
+        }
+    }
+    return false; // should never be reached
+}
+
+?>
diff --git a/mod/lesson/mod.html b/mod/lesson/mod.html
new file mode 100644 (file)
index 0000000..f30cae3
--- /dev/null
@@ -0,0 +1,101 @@
+<!-- define a new instance of lesson -->
+<!-- It is used from /course/mod.php.  The whole instance is available as $form. -->
+<?php
+// set the defaults
+    if (empty($form->name)) {
+        $form->name = "";
+    }
+    if (!isset($form->grade)) {
+        $form->grade = 0;
+    }
+    if (!isset($form->maxanswers)) {
+        $form->maxanswers = 4;
+    }
+    if (!isset($form->retake)) {
+        $form->retake = 1;
+    }
+    if (!isset($form->available)) {
+        $form->available = 0;
+    }
+    if (!isset($form->deadline)) {
+        $form->deadline = 0;
+    }
+?>
+
+<FORM name="form" method="post" action="<?php echo $ME ?>">
+<CENTER>
+<TABLE cellpadding=5>
+<TR valign=top>
+    <TD align=right><P><B><?php  print_string("name") ?>:</B></P></TD>
+    <TD>
+        <INPUT type="text" name="name" size=30 value="<?php  p($form->name) ?>">
+    </TD>
+</TR>
+
+<tr valign=top>
+    <td align=right><P><B><?php  print_string("maximumgrade") ?>:</B></P></TD>
+    <td>
+        <?php
+        for ($i=100; $i>=0; $i--) {
+            $grades[$i] = $i;
+        }
+        choose_from_menu($grades, "grade", "$form->grade", "");
+       helpbutton("grade", get_string("maximumgrade", "lesson"), "lesson");
+        ?>
+    </td>
+</tr>
+
+<tr valign=top>
+    <td align=right><P><B><?php  print_string("maximumnumberofanswers", "lesson") ?>:</B></P></TD>
+    <td>
+        <?php
+        for ($i=10; $i>1; $i--) {
+            $numbers[$i] = $i;
+        }
+        choose_from_menu($numbers, "maxanswers", "$form->maxanswers", "");
+       helpbutton("maxanswers", get_string("maximumnumberofanswers", "lesson"), "lesson");
+        ?>
+    </td>
+</tr>
+
+<tr>
+    <td align=right><P><B><?php  print_string("canretake", "lesson", $course->student) ?>:</B></P></TD>
+    <td>
+    <?PHP 
+        $options[0] = get_string("no"); $options[1] = get_string("yes");
+        choose_from_menu($options, "retake", $form->retake, "");
+        helpbutton("retake", get_string("canretake", "lesson"), "lesson");
+    ?>
+    </td>
+</tr>
+
+<tr valign=top>
+    <td align=right><P><B><?php  print_string("available", "lesson") ?>:</B></td>
+    <td><?php
+           print_date_selector("availableday", "availablemonth", "availableyear", $form->available);
+           echo "&nbsp;-&nbsp;";
+           print_time_selector("availablehour", "availableminute", $form->available);
+    ?></td>
+</tr>
+
+<tr valign=top>
+    <td align=right><P><B><?php  print_string("deadline", "lesson") ?>:</B></td>
+    <td><?php
+           print_date_selector("deadlineday", "deadlinemonth", "deadlineyear", $form->deadline);
+           echo "&nbsp;-&nbsp;";
+           print_time_selector("deadlinehour", "deadlineminute", $form->deadline);
+    ?></td>
+</tr>
+
+</TABLE>
+<!-- These hidden variables are always the same -->
+<INPUT type="hidden" name=course        value="<?php  p($form->course) ?>">
+<INPUT type="hidden" name=coursemodule  value="<?php  p($form->coursemodule) ?>">
+<INPUT type="hidden" name=section       value="<?php  p($form->section) ?>">
+<INPUT type="hidden" name=module        value="<?php  p($form->module) ?>">
+<INPUT type="hidden" name=modulename    value="<?php  p($form->modulename) ?>">
+<INPUT type="hidden" name=instance      value="<?php  p($form->instance) ?>">
+<INPUT type="hidden" name=mode          value="<?php  p($form->mode) ?>">
+<INPUT type="submit" value="<?php  print_string("savechanges") ?>">
+</CENTER>
+</FORM>
diff --git a/mod/lesson/restorelib.php b/mod/lesson/restorelib.php
new file mode 100644 (file)
index 0000000..486507b
--- /dev/null
@@ -0,0 +1,329 @@
+<?PHP //$Id$
+    //This php script contains all the stuff to backup/restore
+    //lesson mods
+
+    //This is the "graphical" structure of the lesson mod: 
+    //
+    //                                          lesson ----------------------------|
+    //                                       (CL,pk->id)                           | 
+    //                                             |                               |
+    //                                             |                         lesson_grades
+    //                                             |                  (UL, pk->id,fk->lessonid)
+    //                                      lesson_pages
+    //                                  (pk->id,fk->lessonid)
+    //                                             |
+    //                                             |
+    //                                             |
+    //                                       lesson_answers
+    //                                    (pk->id,fk->pageid)
+    //                                             |
+    //                                             |
+    //                                             |
+    //                                       lesson_attempts
+    //                                  (UL,pk->id,fk->answerid)
+    //
+    // Meaning: pk->primary key field of the table
+    //          fk->foreign key to link with parent
+    //          nt->nested field (recursive data)
+    //          CL->course level info
+    //          UL->user level info
+    //          files->table may have files)
+    //
+    //-----------------------------------------------------------
+
+    //This function executes all the restore procedure about this mod
+    function lesson_restore_mods($mod,$restore) {
+
+        global $CFG;
+
+        $status = true;
+
+        //Get record from backup_ids
+        $data = backup_getid($restore->backup_unique_code,$mod->modtype,$mod->id);
+
+        if ($data) {
+            //Now get completed xmlized object   
+            $info = $data->info;
+            //traverse_xmlize($info);                                                              //Debug
+            //print_object ($GLOBALS['traverse_array']);                                           //Debug
+            //$GLOBALS['traverse_array']="";                                                       //Debug
+
+            //Now, build the lesson record structure
+            $lesson->course = $restore->course_id;
+            $lesson->name = backup_todb($info['MOD']['#']['NAME']['0']['#']);
+            $lesson->grade = backup_todb($info['MOD']['#']['GRADE']['0']['#']);
+            $lesson->maxanswers = backup_todb($info['MOD']['#']['MAXANSWERS']['0']['#']);
+            $lesson->retake = backup_todb($info['MOD']['#']['RETAKE']['0']['#']);
+            $lesson->available = backup_todb($info['MOD']['#']['AVAILABLE']['0']['#']);
+            $lesson->deadline = backup_todb($info['MOD']['#']['DEADLINE']['0']['#']);
+            $lesson->timemodified = backup_todb($info['MOD']['#']['TIMEMODIFIED']['0']['#']);
+
+            //The structure is equal to the db, so insert the lesson
+            $newid = insert_record("lesson", $lesson);
+
+            //Do some output     
+            echo "<ul><li>".get_string("modulename","lesson")." \"".$lesson->name."\"<br>";
+            backup_flush(300);
+
+            if ($newid) {
+                //We have the newid, update backup_ids
+                backup_putid($restore->backup_unique_code,$mod->modtype,
+                             $mod->id, $newid);
+                //We have to restore the lesson pages which are held in their logical order...
+                $status = lesson_pages_restore_mods($newid,$info,$restore);
+                //...and the user grades (if required)
+                if ($restore->mods['lesson']->userinfo) {
+                    $status = lesson_grades_restore_mods($newid,$info,$restore);
+                }
+            } else {
+                $status = false;
+            }
+
+            //Finalize ul        
+            echo "</ul>";
+        
+        } else {
+            $status = false;
+        }
+
+        return $status;
+    }
+
+    //This function restores the lesson_pages
+    function lesson_pages_restore_mods($lessonid,$info,$restore) {
+
+        global $CFG;
+
+        $status = true;
+
+        //Get the lesson_elements array
+        $pages = $info['MOD']['#']['PAGES']['0']['#']['PAGE'];
+
+        //Iterate over lesson pages (they are held in their logical order)
+        $prevpageid = 0;
+        for($i = 0; $i < sizeof($pages); $i++) {
+            $page_info = $pages[$i];
+            //traverse_xmlize($ele_info);                                                          //Debug
+            //print_object ($GLOBALS['traverse_array']);                                           //Debug
+            //$GLOBALS['traverse_array']="";                                                       //Debug
+
+           
+            //Now, build the lesson_pages record structure
+            $page->lessonid = $lessonid;
+            $page->prevpageid = $prevpageid;
+            $page->timecreated = backup_todb($page_info['#']['TIMECREATED']['0']['#']);
+            $page->timemodified = backup_todb($page_info['#']['TIMEMODIFIED']['0']['#']);
+            $page->title = backup_todb($page_info['#']['TITLE']['0']['#']);
+            $page->contents = backup_todb($page_info['#']['CONTENTS']['0']['#']);
+
+            //The structure is equal to the db, so insert the lesson_elements
+            $newid = insert_record ("lesson_pages",$page);
+
+            // save the new pageids (needed to fix the absolute jumps in the answers)
+            $newpageid[backup_todb($page_info['#']['PAGEID']['0']['#'])] = $newid; 
+            
+            // fix the forwards link of the previous page
+            if ($prevpageid) {
+                if (!set_field("lesson_pages", "nextpageid", $newid, "id", $prevpageid)) {
+                    error("Lesson restorelib: unable to update link");
+                }
+            }
+            $prevpageid = $newid;
+            
+            //Do some output
+            if (($i+1) % 10 == 0) {
+                echo ".";
+                if (($i+1) % 200 == 0) {
+                    echo "<br>";
+                }
+                backup_flush(300);
+            }
+
+            if ($newid) {
+                //We have to restore the lesson_answers table now (a page level table)
+                $status = lesson_answers_restore($lessonid,$newid,$page_info,$restore);
+            } else {
+                $status = false;
+            }
+        }
+        
+        // we've restored all the pages and answers, we now need to fix the jumps in the
+        // answer records if they are absolute
+        if ($answers = get_records("lesson_answers", "lessonid", $lessonid)) {
+            foreach ($answers as $answer) {
+                if ($answer->jumpto > 0) {
+                    // change the absolute page id
+                    if (!set_field("lesson_answers", "jumpto", $newpageid[$answer->jumpto], "id", 
+                                $answer->id)) {
+                        error("Lesson restorelib: unable to reset jump");
+                    }
+                }
+            }
+        }
+
+        return $status;
+    }
+
+
+    //This function restores the lesson_answers
+    function lesson_answers_restore($lessonid,$pageid,$info,$restore) {
+
+        global $CFG;
+
+        $status = true;
+
+        //Get the lesson_answers array (optional)
+        if (isset($info['#']['ANSWERS']['0']['#']['ANSWER'])) {
+            $answers = $info['#']['ANSWERS']['0']['#']['ANSWER'];
+
+            //Iterate over lesson_answers
+            for($i = 0; $i < sizeof($answers); $i++) {
+                $answer_info = $answers[$i];
+                //traverse_xmlize($rub_info);                                  //Debug
+                //print_object ($GLOBALS['traverse_array']);                   //Debug
+                //$GLOBALS['traverse_array']="";                               //Debug
+
+                //Now, build the lesson_answers record structure
+                $answer->lessonid = $lessonid;
+                $answer->pageid = $pageid;
+                // the absolute jumps will need fixing
+                $answer->jumpto = backup_todb($answer_info['#']['JUMPTO']['0']['#']);
+                $answer->timecreated = backup_todb($answer_info['#']['TIMECREATED']['0']['#']);
+                $answer->timemodified = backup_todb($answer_info['#']['TIMEMODIFIED']['0']['#']);
+                $answer->answer = backup_todb($answer_info['#']['ANSWERTEXT']['0']['#']);
+                $answer->response = backup_todb($answer_info['#']['RESPONSE']['0']['#']);
+
+                //The structure is equal to the db, so insert the lesson_rubrics
+                $newid = insert_record ("lesson_answers",$answer);
+
+                //Do some output
+                if (($i+1) % 10 == 0) {
+                    echo ".";
+                    if (($i+1) % 200 == 0) {
+                        echo "<br>";
+                    }
+                    backup_flush(300);
+                }
+
+                if ($newid) {
+                    if ($restore->mods['lesson']->userinfo) {
+                        //We have to restore the lesson_attempts table now (a answers level table)
+                        $status = lesson_attempts_restore($lessonid, $pageid, $newid, $answer_info, $restore);
+                    }
+                } else {
+                    $status = false;
+                }
+            }
+        }
+        return $status;
+    }
+
+
+    //This function restores the attempts
+    function lesson_attempts_restore($lessonid, $pageid, $answerid, $info, $restore) {
+
+        global $CFG;
+
+        $status = true;
+
+        //Get the attempts array (optional)
+        if (isset($info['#']['ATTEMPTS']['0']['#']['ATTEMPT'])) {
+            $attempts = $info['#']['ATTEMPTS']['0']['#']['ATTEMPT'];
+            //Iterate over attempts
+            for($i = 0; $i < sizeof($attempts); $i++) {
+                $attempt_info = $attempts[$i];
+                //traverse_xmlize($sub_info);                                                         //Debug
+                //print_object ($GLOBALS['traverse_array']);                                          //Debug
+                //$GLOBALS['traverse_array']="";                                                      //Debug
+
+                //We'll need this later!!
+                $olduserid = backup_todb($attempt_info['#']['USERID']['0']['#']);
+
+                //Now, build the lesson_attempts record structure
+                $attempt->lessonid = $lessonid;
+                $attempt->pageid = $pageid;
+                $attempt->answerid = $answerid;
+                $attempt->userid = backup_todb($attempt_info['#']['USERID']['0']['#']);
+                $attempt->correct = backup_todb($attempt_info['#']['CORRECT']['0']['#']);
+                $attempt->timeseen = backup_todb($attempt_info['#']['TIMESEEN']['0']['#']);
+                $attempt->retry = backup_todb($attempt_info['#']['RETRY']['0']['#']);
+
+                //We have to recode the userid field
+                $user = backup_getid($restore->backup_unique_code,"user",$olduserid);
+                if ($user) {
+                    $attempt->userid = $user->new_id;
+                }
+
+                //The structure is equal to the db, so insert the lesson_attempt
+                $newid = insert_record ("lesson_attempts",$attempt);
+
+                //Do some output
+                if (($i+1) % 50 == 0) {
+                    echo ".";
+                    if (($i+1) % 1000 == 0) {
+                        echo "<br>";
+                    }
+                    backup_flush(300);
+                }
+            }
+        }
+
+    return $status;
+    }
+
+    //This function restores the lesson_grades
+    function lesson_grades_restore_mods($lessonid, $info, $restore) {
+
+        global $CFG;
+
+        $status = true;
+
+        //Get the grades array (optional)
+        if (isset($info['MOD']['#']['GRADES']['0']['#']['GRADE'])) {
+            $grades = $info['MOD']['#']['GRADES']['0']['#']['GRADE'];
+
+            //Iterate over grades
+            for($i = 0; $i < sizeof($grades); $i++) {
+                $grade_info = $grades[$i];
+                //traverse_xmlize($grade_info);                         //Debug
+                //print_object ($GLOBALS['traverse_array']);            //Debug
+                //$GLOBALS['traverse_array']="";                        //Debug
+        
+                //We'll need this later!!
+                $olduserid = backup_todb($grade_info['#']['USERID']['0']['#']);
+
+                //Now, build the lesson_GRADES record structure
+                $grade->lessonid = $lessonid;
+                $grade->userid = backup_todb($grade_info['#']['USERID']['0']['#']);
+                $grade->grade = backup_todb($grade_info['#']['GRADE_VALUE']['0']['#']);
+                $grade->late = backup_todb($grade_info['#']['LATE']['0']['#']);
+                $grade->completed = backup_todb($grade_info['#']['COMPLETED']['0']['#']);
+
+                //We have to recode the userid field
+                $user = backup_getid($restore->backup_unique_code,"user",$olduserid);
+                if ($user) {
+                    $attempt->userid = $user->new_id;
+                }
+
+                //The structure is equal to the db, so insert the lesson_grade
+                $newid = insert_record ("lesson_grades",$grade);
+
+                //Do some output
+                if (($i+1) % 50 == 0) {
+                    echo ".";
+                    if (($i+1) % 1000 == 0) {
+                        echo "<br>";
+                    }
+                    backup_flush(300);
+                }
+
+                if (!$newid) {
+                    $status = false;
+                }
+            }
+        }
+
+        return $status;
+    }
+
+?>
diff --git a/mod/lesson/version.php b/mod/lesson/version.php
new file mode 100644 (file)
index 0000000..0e30fdd
--- /dev/null
@@ -0,0 +1,12 @@
+<?PHP // $Id$
+
+/////////////////////////////////////////////////////////////////////////////////
+///  Code fragment to define the version of lesson
+///  This fragment is called by moodle_needs_upgrading() and /admin/index.php
+/////////////////////////////////////////////////////////////////////////////////
+
+$module->version  = 2004021400;  // The current module version (Date: YYYYMMDDXX)
+$module->requires = 2004013101;  // Requires this Moodle version
+$module->cron     = 0;           // Period for cron to check this module (secs)
+
+?>
diff --git a/mod/lesson/view.php b/mod/lesson/view.php
new file mode 100644 (file)
index 0000000..a124986
--- /dev/null
@@ -0,0 +1,342 @@
+<?PHP  // $Id$
+
+/// This page prints a particular instance of lesson
+/// (Replace lesson with the name of your module)
+
+    require_once("../../config.php");
+    require_once("lib.php");
+
+    require_variable($id);    // Course Module ID, or
+
+    if (! $cm = get_record("course_modules", "id", $id)) {
+            error("Course Module ID was incorrect");
+    }
+
+    if (! $course = get_record("course", "id", $cm->course)) {
+        error("Course is misconfigured");
+    }
+
+    if (! $lesson = get_record("lesson", "id", $cm->instance)) {
+        error("Course module is incorrect");
+    }
+
+    require_login($course->id);
+
+    add_to_log($course->id, "lesson", "view", "view.php?id=$cm->id", "$lesson->id");
+
+/// Print the page header
+
+    if ($course->category) {
+        $navigation = "<A HREF=\"../../course/view.php?id=$course->id\">$course->shortname</A> ->";
+    }
+
+    $strlessons = get_string("modulenameplural", "lesson");
+    $strlesson  = get_string("modulename", "lesson");
+
+    print_header("$course->shortname: $lesson->name", "$course->fullname",
+                 "$navigation <A HREF=index.php?id=$course->id>$strlessons</A> -> <a href=\"view.php?id=$cm->id\">$lesson->name</a>", 
+                  "", "", true, update_module_button($cm->id, $course->id, $strlesson), 
+                  navmenu($course, $cm));
+
+    // set up some general variables
+    $usehtmleditor = can_use_html_editor();
+    $path = "$CFG->wwwroot/course";
+    if (empty($THEME->custompix)) {
+        $pixpath = "$path/../pix";
+    } else {
+        $pixpath = "$path/../theme/$CFG->theme/pix";
+    }
+
+    if (empty($action)) {
+        if (isteacher($course->id)) {
+            $action = 'teacherview';
+        } else {
+            $action = 'navigation';
+        }
+    }
+
+    /************** navigation **************************************/
+    if ($action == 'navigation') {
+        // display individual pages and their sets of answers
+        // if pageid is EOL then the end of the lesson has been reached
+        print_heading($lesson->name);
+               if (empty($_GET['pageid'])) {
+            // if no pageid given see if the lesson has been started
+            if ($grades = get_records_select("lesson_grades", "lessonid = $lesson->id AND userid = $USER->id",
+                        "grade DESC")) {
+                $retries = count($grades);
+            } else {
+                $retries = 0;
+            }
+            if ($retries) {
+                print_heading(get_string("attempt", "lesson", $retries + 1));
+            }
+            // if there are any questions have been answered correctly in this attempt
+            if ($attempts = get_records_select("lesson_attempts", 
+                        "lessonid = $lesson->id AND userid = $USER->id AND retry = $retries AND 
+                        correct = 1", "timeseen DESC")) {
+                // get the first page
+                if (!$firstpageid = get_field("lesson_pages", "id", "lessonid", $lesson->id,
+                            "prevpageid", 0)) {
+                    error("Navigation: first page not found");
+                }
+                foreach ($attempts as $attempt) {
+                    $jumpto = get_field("lesson_answers", "jumpto", "id", $attempt->answerid);
+                    // convert the jumpto to a proper page id
+                    if ($jumpto == 0) { // unlikely value!
+                        $lastpageseen = $attempt->pageid;
+                    } elseif ($jumpto == NEXTPAGE) {
+                        if (!$lastpageseen = get_field("lesson_pages", "nextpageid", "id", 
+                                    $attempt->pageid)) {
+                            // no nextpage go to end of lesson
+                            $lastpageseen = EOL;
+                        }
+                    } else {
+                        $lastpageseen = $jumpto;
+                    }
+                    break; // only look at the latest correct attempt 
+                }
+                if ($lastpageseen != $firstpageid) {
+                    notice_yesno(get_string("youhaveseen","lesson"), 
+                        "view.php?id=$cm->id&action=navigation&pageid=$lastpageseen", 
+                        "view.php?id=$cm->id&action=navigation&pageid=$firstpageid");
+                    print_footer($course);
+                    exit();
+                }
+            }
+            if ($grades) {
+                foreach ($grades as $grade) {
+                    $bestgrade = $grade->grade;
+                    break;
+                }
+                if (!$lesson->retake) {
+                           redirect("../../course/view.php?id=$course->id", get_string("alreadytaken", "lesson"));
+                // allow student to retake course even if they have the maximum grade
+                // } elseif ($bestgrade == 100) {
+                       //     redirect("../../course/view.php?id=$course->id", get_string("maximumgradeachieved",
+                //                 "lesson"));
+                }
+            }
+            // start at the first page
+                       if (!$pageid = get_field("lesson_pages", "id", "lessonid", $lesson->id, "prevpageid", 0)) {
+                error("Navigation: first page not found");
+            }
+               } else {
+            $pageid = $_GET['pageid'];
+        }
+        if ($pageid != EOL) {
+            if (!$page = get_record("lesson_pages", "id", $pageid)) {
+                error("Navigation: the page record not found");
+            }
+            echo "<table align=\"center\" width=\"80%\" border=\"0\"><tr><td>\n";
+            print_heading($page->title);
+            print_simple_box(format_text($page->contents), 'center');
+            echo "<br />\n";
+            if ($answers = get_records("lesson_answers", "pageid", $page->id)) {
+                shuffle($answers);
+                echo "<form name=\"pageform\" method =\"post\" action=\"lesson.php\">\n";
+                echo "<input type=\"hidden\" name=\"id\" value=\"$cm->id\">\n";
+                echo "<input type=\"hidden\" name=\"action\" value=\"continue\">\n";
+                echo "<input type=\"hidden\" name=\"pageid\" value=\"$pageid\">\n";
+                print_simple_box_start("center");
+                foreach ($answers as $answer) {
+                    echo "<p><input type=\"radio\" name=\"answerid\" value=\"{$answer->id}\"> \n";
+                    $options->para = false; // no <p></p>
+                    echo format_text(trim($answer->answer), FORMAT_MOODLE, $options); 
+                    echo "</p>\n";
+                }
+                print_simple_box_end();
+                echo "<p align=\"center\"><input type=\"submit\" name=\"continue\" value=\"".
+                    get_string("pleasecheckoneanswer", "lesson")."\"></p>\n";
+                echo "</form>\n";
+            } else {
+                // a page without answers - find the next (logical) page
+                if (!$newpageid = get_field("lesson_pages", "nextpageid", "id", $pageid)) {
+                    // this is the last page - flag end of lesson
+                    $newpageid = EOL;
+                }
+                       print_continue("view.php?id=$cm->id&action=navigation&pageid=$newpageid");
+            }
+            echo "</table>\n";
+        } else {
+            // end of lesson reached work out grade
+            print_heading(get_string("congratulations", "lesson"));
+            print_simple_box_start("center");
+            $ntries = count_records("lesson_grades", "lessonid", $lesson->id, "userid", $USER->id);
+            if (isstudent($course->id)) {
+                $ncorrect = count_records_select("lesson_attempts", "lessonid = $lesson->id AND
+                        userid = $USER->id AND retry = $ntries AND correct = 1");
+                $nviewed = count_records("lesson_attempts", "lessonid", $lesson->id, "userid", $USER->id,
+                        "retry", $ntries);
+                if ($nviewed) {
+                    $thegrade = intval(100 * $ncorrect / $nviewed);
+                } else {
+                    $thegrade = 0;
+                }
+                echo "<p align=\"center\">".get_string("numberofpagesviewed", "lesson", $nviewed)."</p>\n";
+                echo "<p align=\"center\">".get_string("numberofcorrectanswers", "lesson", $ncorrect).
+                    "</p>\n";
+                echo "<p align=\"center\">".get_string("gradeis", "lesson", 
+                        number_format($thegrade * $lesson->grade / 100, 1)).
+                        " (".get_string("outof", "lesson", $lesson->grade).")</p>\n";
+                $grade->lessonid = $lesson->id;
+                $grade->userid = $USER->id;
+                $grade->grade = $thegrade;
+                $grade->completed = time();
+                if (!$newgradeid = insert_record("lesson_grades", $grade)) {
+                    error("Navigation: grade not inserted");
+                }
+            } else { 
+                // display for teacher
+                echo "<p align=\"center\">".get_string("displayofgrade", "lesson")."</p>\n";
+            }
+            print_simple_box_end();
+                   print_continue("../../course/view.php?id=$course->id");
+        }
+            
+    }
+
+
+    /*******************teacher view **************************************/
+    elseif ($action == 'teacherview') {
+               print_heading_with_help($lesson->name, "overview", "lesson");
+        // get number of pages
+        if ($page = get_record_select("lesson_pages", "lessonid = $lesson->id AND prevpageid = 0")) {
+            $npages = 1;
+            while (true) {
+                if ($page->nextpageid) {
+                    if (!$page = get_record("lesson_pages", "id", $page->nextpageid)) {
+                        error("Teacher view: Next page not found!");
+                    }
+                } else {
+                    // last page reached
+                    break;
+                }
+                $npages++;
+            }
+        }
+
+        if (!$page = get_record_select("lesson_pages", "lessonid = $lesson->id AND prevpageid = 0")) {
+            // if there are no pages give teacher a blank proforma
+            ?>
+            <form name="form" method="post" action="lesson.php">
+            <input type="hidden" name="id" value="<?PHP echo $cm->id ?>">
+            <input type="hidden" name="action" value="insertpage">
+            <input type="hidden" name="pageid" value="0">
+            <center><table cellpadding=5 border=1>
+            <tr><td align="center">
+            <tr valign="top">
+            <td><p><b><?php print_string("pagetitle", "lesson"); ?>:</b></p></td></tr>
+            <tr><td><input type="text" name="title" size="80" maxsize="255" value=""></td></tr>
+            <?PHP
+            echo "<tr><td><b>";
+            echo get_string("pagecontents", "lesson").":</b><br />\n";
+            print_textarea($usehtmleditor, 25, 70, 630, 400, "contents");
+            echo "</td></tr>\n";
+            for ($i = 0; $i < $lesson->maxanswers; $i++) {
+                $iplus1 = $i + 1;
+                echo "<tr><td><b>".get_string("answer", "lesson")." $iplus1:</b><br />\n";
+                print_textarea($usehtmleditor, 20, 70, 630, 100, "answer[$i]");
+                echo "</td></tr>\n";
+                echo "<tr><td><b>".get_string("response", "lesson")." $iplus1:</b><br />\n";
+                print_textarea($usehtmleditor, 20, 70, 630, 100, "response[$i]");
+                echo "</td></tr>\n";
+                if ($i) {
+                    // answers 2,3,4... jump to this page
+                    echo "<input type=\"hidden\" name=\"jumpto[$i]\" value =\"0\">\n";
+                } else {
+                    // answer 1 jumps to next page
+                    echo "<input type=\"hidden\" name=\"jumpto[$i]\" value =\"".NEXTPAGE."\">\n";
+                }
+            }
+            use_html_editor();
+            // close table and form
+            ?>
+            </table><br />
+            <input type="submit" value="<?php  print_string("savepage", "lesson") ?>">
+            <input type="submit" name="cancel" value="<?php  print_string("cancel") ?>">
+            </center>
+            </form>
+            <?PHP
+        } else {
+            // print the pages
+            echo "<center><table cellpadding=\"5\" border=\"0\" width=\"80%\">\n";
+            echo "<tr><td align=\"right\"><a href=\"lesson.php?id=$cm->id&action=addpage&pageid=0\"><small>".
+                get_string("addpagehere", "lesson")."</small></a></td></tr><tr><td>\n";
+            while (true) {
+                echo "<table width=\"100%\" border=\"1\"><tr><td bgcolor=\"$THEME->cellheading2\" colspan=\"2\"><b>$page->title</b>&nbsp;&nbsp;\n";
+                if ($npages > 1) {
+                    echo "<a title=\"".get_string("move")."\" href=\"lesson.php?id=$cm->id&action=move&pageid=$page->id\">\n".
+                        "<img src=\"$pixpath/t/move.gif\" hspace=\"2\" height=11 width=11 border=0></a>\n";
+                }
+                echo "<a title=\"".get_string("update")."\" href=\"lesson.php?id=$cm->id&action=editpage&pageid=$page->id\">\n".
+                    "<img src=\"$pixpath/t/edit.gif\" hspace=\"2\" height=11 width=11 border=0></a>\n".
+                    "<a title=\"".get_string("delete")."\" href=\"lesson.php?id=$cm->id&action=confirmdelete&pageid=$page->id\">\n".
+                    "<img src=\"$pixpath/t/delete.gif\" hspace=\"2\" height=11 width=11 border=0></a>".
+                    "</td></tr>\n";             
+                echo "<tr><td colspan=\"2\">\n";
+                print_simple_box(format_text($page->contents), "center");
+                echo "</td></tr>\n";
+                if ($answers = get_records("lesson_answers", "pageid", $page->id, "id")) {
+                    $i = 1;
+                    foreach ($answers as $answer) {
+                        echo "<tr><td bgcolor=\"$THEME->cellheading2\" colspan=\"2\">&nbsp;</td></tr>\n";
+                        echo "<tr><td align=\"right\" valign=\"top\" width=\"20%\">\n";
+                        if (lesson_iscorrect($page->id, $answer->jumpto)) {
+                            // underline correct answers
+                            echo "<b><u>".get_string("answer", "lesson")." $i:</u></b> \n";
+                        } else {
+                            echo "<b>".get_string("answer", "lesson")." $i:</b> \n";
+                        }
+                        echo "</td><td width=\"80%\">\n";
+                        echo format_text($answer->answer);
+                        echo "</td></tr>\n";
+                        echo "<tr><td align=\"right\" valign=\"top\"><b>".get_string("response", "lesson")." $i:</b> \n";
+                        echo "</td><td>\n";
+                        echo format_text($answer->response); 
+                        echo "</td></tr>\n";
+                        if ($answer->jumpto == 0) {
+                            $jumptitle = get_string("thispage", "lesson");
+                        } elseif ($answer->jumpto == NEXTPAGE) {
+                            $jumptitle = get_string("nextpage", "lesson");
+                        } elseif ($answer->jumpto == EOL) {
+                            $jumptitle = get_string("endoflesson", "lesson");
+                        } else {
+                            if (!$jumptitle = get_field("lesson_pages", "title", "id", $answer->jumpto)) {
+                                $jumptitle = "<b>".get_string("notdefined", "lesson")."</b>";
+                            }
+                        }
+                        echo "<tr><td align=\"right\"><b>".get_string("jumpto", "lesson").": </b>\n";
+                        echo "</td><td>\n";
+                        echo "$jumptitle</td></tr>\n";
+                        $i++;
+                    }
+                    // print_simple_box_end();
+                }
+                echo "</td></tr></table></td></tr><tr><td align=\"right\"><a href=\"lesson.php?id=$cm->id&action=addpage&pageid=$page->id\"><small>".
+                    get_string("addpagehere", "lesson")."</small></a></td></tr><tr><td>\n";
+                if ($page->nextpageid) {
+                    if (!$page = get_record("lesson_pages", "id", $page->nextpageid)) {
+                        error("Teacher view: Next page not found!");
+                    }
+                } else {
+                    // last page reached
+                    break;
+                }
+            }
+            echo "</table>\n";
+            print_heading("<a href=\"view.php?id=$cm->id&action=navigation\">".get_string("checknavigation",
+                        "lesson")."</a>\n");
+        }
+    }
+
+
+    /*************** no man's land **************************************/
+       else {
+               error("Fatal Error: Unknown Action: ".$action."\n");
+       }
+
+/// Finish the page
+    print_footer($course);
+
+?>