]> git.mjollnir.org Git - moodle.git/commitdiff
Removed tabs
authormoodler <moodler>
Wed, 9 Aug 2006 13:45:49 +0000 (13:45 +0000)
committermoodler <moodler>
Wed, 9 Aug 2006 13:45:49 +0000 (13:45 +0000)
67 files changed:
mod/assignment/lib.php
mod/assignment/mod.html
mod/chat/gui_header_js/index.php
mod/chat/lib.php
mod/chat/report.php
mod/chat/view.php
mod/choice/lib.php
mod/choice/report.php
mod/choice/view.php
mod/data/comment.php
mod/data/field.php
mod/data/import.php
mod/data/lib.php
mod/data/restorelib.php
mod/data/tabs.php
mod/data/templates.php
mod/data/view.php
mod/exercise/assessments.php
mod/exercise/view.php
mod/glossary/approve.php
mod/glossary/comment.php
mod/glossary/comments.php
mod/glossary/deleteentry.php
mod/glossary/edit.php
mod/glossary/editcategories.php
mod/glossary/export.php
mod/glossary/exportentry.php
mod/glossary/exportfile.php
mod/glossary/import.php
mod/glossary/lib.php
mod/glossary/report.php
mod/glossary/tabs.html
mod/glossary/view.php
mod/hotpot/attempt.php
mod/hotpot/config.html
mod/hotpot/db/mysql.php
mod/hotpot/db/update_to_v2.php
mod/hotpot/index.php
mod/hotpot/lib.php
mod/hotpot/mod.html
mod/hotpot/report.php
mod/hotpot/report/default.php
mod/hotpot/review.php
mod/hotpot/show.php
mod/hotpot/template/default.php
mod/hotpot/template/v6.php
mod/hotpot/view.php
mod/lesson/mediafile.php
mod/lesson/mod.html
mod/quiz/attempt.php
mod/quiz/db/mysql.php
mod/quiz/db/postgres7.php
mod/quiz/defaults.php
mod/quiz/styles.php
mod/scorm/api.php
mod/scorm/coefficientconfirm.php
mod/scorm/coefficientsetting.php
mod/scorm/datamodels/scorm1_3.js.php
mod/scorm/db/mysql.php
mod/scorm/db/postgres7.php
mod/scorm/index.php
mod/scorm/lib.php
mod/scorm/loadSCO.php
mod/scorm/mod.html
mod/scorm/report.php
mod/wiki/ewiki/ewiki.php
mod/wiki/view.php

index b8bd546502146ee5f7e3931f445083173e14ddad..6d3e4e08316a04372128d2bc2083506d7c0ed98d 100644 (file)
@@ -107,10 +107,10 @@ class assignment_base {
      */
     function view() {
       
-               $context = get_context_instance(CONTEXT_MODULE,$this->cm->id);
+        $context = get_context_instance(CONTEXT_MODULE,$this->cm->id);
         has_capability('mod/assignment:view', $context->id, true);
         
-               add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}", 
+        add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}", 
                    $this->assignment->id, $this->cm->id);
 
         $this->view_header();
@@ -281,7 +281,7 @@ class assignment_base {
 
         // if this user can mark and is put in a group
         // then he can only see/mark submission in his own groups
-            if (user_group($this->course->id, $USER->id)) {                    
+            if (user_group($this->course->id, $USER->id)) {             
                 $count = $this->count_real_submissions($this->currentgroup);  // Only their groups
             } else {
                 $count = $this->count_real_submissions();                     // Everyone
index 891f57aa4aab03d67cfb68e4451a0db6c6de386e..0d5e4dc9aec9c62923387ea31f114e6442683bb5 100644 (file)
@@ -35,7 +35,7 @@
     var availableitems = ['availableday','availablemonth','availableyear','availablehour', 'availableminute'];
 </script>
 
-<form name="form" method="post" action="../mod/assignment/details.php">        
+<form name="form" method="post" action="../mod/assignment/details.php"> 
 <table cellpadding="5">
 <tr valign="top">
     <td align="right"><b><?php print_string("assignmentname", "assignment") ?>:</b></td>
index ddd1d749915be4387df759c1f42cbce92b49947d..6c35be3ee20d4e1a6f19728342c0763254da8606 100644 (file)
     if (!$cm = get_coursemodule_from_instance('chat', $chat->id, $course->id)) {
         error('Course Module ID was incorrect');
     }
-       
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
     
-       require_login($course->id, false, $cm);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    
+    require_login($course->id, false, $cm);
 
-       has_capability('mod/chat:chat',$context->id, true);
-       /*
+    has_capability('mod/chat:chat',$context->id, true);
+    /*
     if (isguest()) {
         error('Guest does not have access to chat rooms');
     }
-       */
+    */
     if (!$cm->visible and !isteacher($course->id)) {
         print_header();
         notice(get_string("activityiscurrentlyhidden"));
index d963d5caa27d21c983c316c89956b4e66a21cca2..0052d558e5833e79923eb77d3b815bc828b348a6 100644 (file)
@@ -200,17 +200,17 @@ function chat_print_recent_activity($course, $isteacher, $timestart) {
             }
             if ($chat = get_record('chat', 'id', $chatuser->chatid)) {
               
-               // we find the course module id
-               $chatmod = get_record('modules', 'name', 'chat');
-               $SQL = "select * from {$CFG->prefix}course_modules where
-                               course = $course->id 
-                                               and module = $chatmod->id
-                               and instance = $chat->id";
-               $cm = get_records_sql($SQL);
-               $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+                // we find the course module id
+                $chatmod = get_record('modules', 'name', 'chat');
+                $SQL = "select * from {$CFG->prefix}course_modules where
+                        course = $course->id 
+                        and module = $chatmod->id
+                        and instance = $chat->id";
+                $cm = get_records_sql($SQL);
+                $context = get_context_instance(CONTEXT_MODULE, $cm->id);
               
-               // needs to be fixed
-                               if (!(has_capability('mod/chat:readlog', $context->id) or instance_is_visible('chat', $chat))) {  // Chat hidden to students
+                // needs to be fixed
+                if (!(has_capability('mod/chat:readlog', $context->id) or instance_is_visible('chat', $chat))) {  // Chat hidden to students
                 //if (!($isteacher or instance_is_visible('chat', $chat))) {  // Chat hidden to students
                     continue;
                 }
index 5bcf6a6116109ed199b2458327f7304c441e3229..8f9ec6a370ce5abb318cf5aacc75b3dd53771cca 100644 (file)
         error('Course is misconfigured');
     }
 
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
     require_login($course->id, false, $cm);
 
     $isteacher     = isteacher($course->id);
     $isteacheredit = isteacheredit($course->id);
 
     //if (isguest() or (!$isteacher and !$chat->studentlogs)) {
-       //error('You can not view these chat reports');
+        //error('You can not view these chat reports');
     //}
-       has_capability('mod/chat:readlog', $context->id, true); // if can't even read, kill
+    has_capability('mod/chat:readlog', $context->id, true); // if can't even read, kill
 
     add_to_log($course->id, 'chat', 'report', "report.php?id=$cm->id", $chat->id, $cm->id);
 
@@ -89,7 +89,7 @@
             print_simple_box_end('center');
         }
 
-               if (!$deletesession or !has_capability('mod/chat:deletelog', $context->id)) {
+        if (!$deletesession or !has_capability('mod/chat:deletelog', $context->id)) {
         //if (!$deletesession or !$isteacheredit) {
             print_continue("report.php?id=$cm->id");
         }
 
 /// Delete a session if one has been specified
 
-       if ($deletesession and has_capability('mod/chat:deletelog', $context->id) and $confirmdelete and $start and $end and confirm_sesskey()) {
+    if ($deletesession and has_capability('mod/chat:deletelog', $context->id) and $confirmdelete and $start and $end and confirm_sesskey()) {
     //if ($deletesession and $isteacheredit and $confirmdelete and $start and $end and confirm_sesskey()) {
         delete_records_select('chat_messages', "chatid = $chat->id AND
                                             timestamp >= '$start' AND
                 echo '<p align="right">';
                 echo "<a href=\"report.php?id=$cm->id&amp;start=$sessionstart&amp;end=$sessionend\">$strseesession</a>";
                 //if ($isteacheredit)
-                               if (has_capability('mod/chat:deletelog', $context->id)) {
+                if (has_capability('mod/chat:deletelog', $context->id)) {
                     echo "<br /><a href=\"report.php?id=$cm->id&amp;start=$sessionstart&amp;end=$sessionend&amp;deletesession=1\">$strdeletesession</a>";
                 }
                 echo '</p>';
index 5a125ed3b7633cdb5072606d4ad16213ef4a2cd6..5d96bd95434f43709a3cf80d1e5986e614e428db 100644 (file)
@@ -43,9 +43,9 @@
 
     require_course_login($course, true, $cm);
     
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
     
-       add_to_log($course->id, 'chat', 'view', "view.php?id=$cm->id", $chat->id, $cm->id);
+    add_to_log($course->id, 'chat', 'view', "view.php?id=$cm->id", $chat->id, $cm->id);
 
 // Initialize $PAGE, compute blocks
 
@@ -76,7 +76,7 @@
 
     echo '<td id="middle-column">';
     
-       if ($chat->studentlogs or has_capability('mod/chat:readlog',$context->id)) {
+    if ($chat->studentlogs or has_capability('mod/chat:readlog',$context->id)) {
     //if (($chat->studentlogs or isteacher($course->id)) and !isguest()) {
         echo '<div class="reportlink">';
         echo "<a href=\"report.php?id=$cm->id\">".
index d7051a93f223dab2ee0b3ca8bbf55521f3be8f2b..4ed0247baa347b32c0cec8e65779bcefa1ba52ec 100644 (file)
@@ -144,7 +144,7 @@ function choice_update_instance($choice) {
 }
 
 function choice_show_form($choice, $user, $cm) {
-       
+    
 //$cdisplay is an array of the display info for a choice $cdisplay[$optionid]->text  - text name of option.
 //                                                                            ->maxanswers -maxanswers for this option
 //                                                                            ->full - whether this option is full or not. 0=not full, 1=full
@@ -157,9 +157,9 @@ $cdisplay = array();
             $countans = 0;           
             $context = get_context_instance(CONTEXT_MODULE, $cm->id);
             if (!empty($countanswers)) {
-                foreach ($countanswers as $ca) { //only return enrolled users.                                 
-                                   if (has_capability('mod/choice:choose', $context->id)) {
-                                       //if (isstudent($cm->course, $ca->userid) or isteacher($cm->course, $ca->userid)) {     
+                foreach ($countanswers as $ca) { //only return enrolled users.                  
+                    if (has_capability('mod/choice:choose', $context->id)) {
+                    //if (isstudent($cm->course, $ca->userid) or isteacher($cm->course, $ca->userid)) { 
                         $countans = $countans+1;
                     }
                 }
@@ -171,21 +171,21 @@ $cdisplay = array();
             }
             $maxans = $choice->maxanswers[$optionid];
 
-               $cdisplay[$aid]->optionid = $optionid;
-                   $cdisplay[$aid]->text = $text;
-                   $cdisplay[$aid]->maxanswers = $maxans;
-                   $cdisplay[$aid]->countanswers = $countans;
+            $cdisplay[$aid]->optionid = $optionid;
+            $cdisplay[$aid]->text = $text;
+            $cdisplay[$aid]->maxanswers = $maxans;
+            $cdisplay[$aid]->countanswers = $countans;
 
-                   if ($current = get_record('choice_answers', 'choiceid', $choice->id, 'userid', $user->id, 'optionid', $optionid)) {
-                       $cdisplay[$aid]->checked = ' checked="checked" ';       
-                   } else {
-                       $cdisplay[$aid]->checked = '';  
-               }
+            if ($current = get_record('choice_answers', 'choiceid', $choice->id, 'userid', $user->id, 'optionid', $optionid)) {
+                $cdisplay[$aid]->checked = ' checked="checked" ';   
+            } else {
+                $cdisplay[$aid]->checked = '';  
+            }
             if ($choice->limitanswers && ($countans >= $maxans) && (empty($cdisplay[$aid]->checked)) ) {
-                               $cdisplay[$aid]->disabled = ' disabled="disabled" ';    
-                       } else {
-                               $cdisplay[$aid]->disabled = ''; 
-                   }
+                $cdisplay[$aid]->disabled = ' disabled="disabled" ';    
+            } else {
+                $cdisplay[$aid]->disabled = ''; 
+            }
             $aid++;
         }
     }
@@ -193,13 +193,13 @@ $cdisplay = array();
         switch ($choice->display) {
             case CHOICE_DISPLAY_HORIZONTAL:
                 echo "<table cellpadding=\"20\" cellspacing=\"20\" align=\"center\"><tr>";
-                                                   
+                                    
                 foreach ($cdisplay as $cd) { 
                     echo "<td align=\"center\" valign=\"top\">";
                     echo "<input type=\"radio\" name=\"answer\" value=\"".$cd->optionid."\" alt=\"".strip_tags(format_text($cd->text))."\"". $cd->checked.$cd->disabled." />";                    
                     if (!empty($cd->disabled)) {               
-                            echo format_text($cd->text."<br /><strong>".get_string('full', 'choice')."</strong>");                                 
-                                   } else {
+                            echo format_text($cd->text."<br /><strong>".get_string('full', 'choice')."</strong>");                  
+                    } else {
                         echo format_text($cd->text);
                     }
                         echo "</td>";                    
@@ -222,8 +222,8 @@ $cdisplay = array();
                             
                             if (!empty($cd->disabled)) {
                                 echo get_string('full', 'choice');
-                                                   } elseif(!empty($cd->checked)) {
-                                                           //currently do nothing - maybe some text could be added here to signfy that the choice has been 'selected'
+                            } elseif(!empty($cd->checked)) {
+                                //currently do nothing - maybe some text could be added here to signfy that the choice has been 'selected'
                             } elseif ($cd->maxanswers-$cd->countanswers==1) {
                                 echo ($cd->maxanswers - $cd->countanswers);
                                 echo " ".get_string('spaceleft', 'choice');
@@ -256,26 +256,26 @@ $cdisplay = array();
 function choice_user_submit_response($formanswer, $choice, $userid, $courseid, $cm) {
 
 $current = get_record('choice_answers', 'choiceid', $choice->id, 'userid', $userid);
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       $countanswers = get_records("choice_answers", "optionid", $formanswer);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $countanswers = get_records("choice_answers", "optionid", $formanswer);
             if ($countanswers) {
             $countans = 0;
             foreach ($countanswers as $ca) { //only return enrolled users.
-                               if (has_capability('mod/choice:choose', $context->id)) {
-                               //if (isstudent($courseid, $ca->userid) or isteacher($courseid, $ca->userid)) { 
-                                   $countans = $countans+1;
-                           }
-                       }                               
-                               
+                if (has_capability('mod/choice:choose', $context->id)) {
+                //if (isstudent($courseid, $ca->userid) or isteacher($courseid, $ca->userid)) { 
+                    $countans = $countans+1;
+                }
+            }               
+                
                 $countanswers = count($countans);
                 } else {
                     $countanswers = 0;
                 }
             $maxans = $choice->maxanswers[$formanswer];
             
-            if (!($choice->limitanswers && ($countanswers >= $maxans) )) {                             
+            if (!($choice->limitanswers && ($countanswers >= $maxans) )) {              
                 if ($current) {
-                                       
+                    
                     $newanswer = $current;
                     $newanswer->optionid = $formanswer;
                     $newanswer->timemodified = time();
@@ -304,11 +304,11 @@ $current = get_record('choice_answers', 'choiceid', $choice->id, 'userid', $user
 
 function choice_show_reportlink($choice, $courseid, $cmid) {
         $context = get_context_instance(CONTEXT_MODULE, $cmid);
-           if ( $allanswers = get_records("choice_answers", "choiceid", $choice->id)) {
+        if ( $allanswers = get_records("choice_answers", "choiceid", $choice->id)) {
             $responsecount = 0;
             foreach ($allanswers as $aa) {
                 if (has_capability('mod/choice:readresponses', $context->id)) {
-                               //if (isstudent($courseid, $aa->userid) or isteacher($courseid, $aa->userid)) { //check to make sure user is enrolled in course.
+                //if (isstudent($courseid, $aa->userid) or isteacher($courseid, $aa->userid)) { //check to make sure user is enrolled in course.
                     $responsecount++;
                 }
             }
@@ -323,12 +323,12 @@ function choice_show_reportlink($choice, $courseid, $cmid) {
 function choice_show_results($choice, $course, $cm, $forcepublish='') {
             
         global $CFG, $COLUMN_HEIGHT, $USER;
-               $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+        $context = get_context_instance(CONTEXT_MODULE, $cm->id);
         print_heading(get_string("responses", "choice"));        
         if (empty($forcepublish)) { //alow the publish setting to be overridden
-                       $forcepublish = $choice->publish;
-               }               
-                       
+            $forcepublish = $choice->publish;
+        }       
+                
         /// Check to see if groups are being used in this choice
     if ($groupmode = groupmode($course, $cm)) {   // Groups are being used
         $currentgroup = setup_and_print_groups($course, $groupmode, $_SERVER['PHP_SELF']."?id=$cm->id");
@@ -383,9 +383,9 @@ function choice_show_results($choice, $course, $cm, $forcepublish='') {
             //$isteacher = isteacher($course->id);
 
             $tablewidth = (int) (100.0 / count($useranswer));
-                       if (has_capability('mod/choice:readresponses', $context->id)) {
+            if (has_capability('mod/choice:readresponses', $context->id)) {
             //if (isteacher($course->id, $USER->id)) {
-                               echo '<div id="tablecontainer">';
+                echo '<div id="tablecontainer">';
                 echo '<form id="attemptsform" method="post" action="'.$_SERVER['PHP_SELF'].'" onsubmit="var menu = document.getElementById(\'menuaction\'); return (menu.options[menu.selectedIndex].value == \'delete\' ? \''.addslashes(get_string('deleteattemptcheck','quiz')).'\' : true);">';
                 echo '<input type="hidden" name="id" value="'.$cm->id.'" />';
                 echo '<input type="hidden" name="mode" value="overview" />';
@@ -420,7 +420,7 @@ function choice_show_results($choice, $course, $cm, $forcepublish='') {
 
                 echo "<table width=\"100%\">";
                 foreach ($userlist as $user) {
-                       // this needs to be fixed
+                    // this needs to be fixed
                     if (!($optionid==0 && isadmin($user->id)) && !($optionid==0 && isteacher($course->id, $user->id) && !(isteacheredit($course->id, $user->id)) )  ) { //make sure admins and hidden teachers are not shown in not answered yet column.
                         echo "<tr>";
                         if (isteacher($course->id, $USER->id) && !($optionid==0)) {
@@ -450,12 +450,12 @@ function choice_show_results($choice, $course, $cm, $forcepublish='') {
                 $countanswers = get_records("choice_answers", "optionid", $optionid);                
                 $countans = 0;  
                 if (!empty($countanswers)) {              
-                    foreach ($countanswers as $ca) { //only return enrolled users.             
-                                               // needs fixing too                                     
-                                       if (isstudent($course->id, $ca->userid) or isteacher($course->id, $ca->userid)) {                                                       
-                                          $countans = $countans+1;
-                                   }                           
-                               }
+                    foreach ($countanswers as $ca) { //only return enrolled users.      
+                        // needs fixing too                         
+                        if (isstudent($course->id, $ca->userid) or isteacher($course->id, $ca->userid)) {                           
+                           $countans = $countans+1;
+                        }                   
+                    }
                 }
                 if ($choice->limitanswers && !$optionid==0) {
                     echo get_string("taken", "choice").":";
@@ -490,8 +490,8 @@ function choice_show_results($choice, $course, $cm, $forcepublish='') {
             echo "</tr></table>";
             //if (isteacher($course->id, $USER->id)) {
             if (has_capability('mod/choice:readresponses', $context->id)) {
-                           echo "</form></div>";
-                       }
+                echo "</form></div>";
+            }
             break;
 
 
@@ -572,13 +572,13 @@ function choice_show_results($choice, $course, $cm, $forcepublish='') {
             echo "</tr></table>";
 
             break;
-        }      
+        }   
 }
 
 
 function choice_delete_responses($attemptids) {
-       
-       if(!is_array($attemptids) || empty($attemptids)) {
+    
+    if(!is_array($attemptids) || empty($attemptids)) {
         return false;
     }
 
index c813d58e0eddda4387c11aee93a8bea6e6fa5d49..bb56faa63fb682dde3ac6511fc7f2919467ea395 100644 (file)
 
     require_login($course->id, false, $cm);
     
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
     
     has_capability('mod/choice:readresponses', $context->id, true);
     
-       //if (!isteacher($course->id)) {
+    //if (!isteacher($course->id)) {
     //    error("Only teachers can look at this page");
     //}
 
@@ -40,7 +40,7 @@
     //if ($action == 'delete') { //some responses need to be deleted
         $attemptids = isset($_POST['attemptid']) ? $_POST['attemptid'] : array(); //get array of repsonses to delete.
         choice_delete_responses($attemptids); //delete responses.
-        redirect("report.php?id=$cm->id");                                 
+        redirect("report.php?id=$cm->id");                      
     }
         
     if ($download <> "xls" and $download <> "txt" ) {
                     $ug2 = '';
                     if ($usergrps = user_group($course->id, $user->id)) {
                         foreach ($usergrps as $ug) {
-                                                   $ug2 = $ug2. $ug->name;
-                                           }
-                               }
+                            $ug2 = $ug2. $ug->name;
+                        }
+                    }
                     $myxls->write_string($row,3,$ug2);
                     
                     $useroption = choice_get_option_text($choice, $answers[$user->id]->optionid);
         exit;
     } 
     // print text file  
-       //if ($download == "txt") {   
+    //if ($download == "txt") {   
     if ($download == "txt" && has_capability('mod/choice:downloadresponses', $context->id, true)) {
         $filename = clean_filename("$course->shortname ".strip_tags(format_string($choice->name,true))).'.txt';
             
               echo "\t".$user->firstname;
               $studentid = " ";
               if (!empty($user->idnumber)) {
-                             $studentid = $user->idnumber;
-                         }              
+                  $studentid = $user->idnumber;
+              }              
               echo "\t". $studentid."\t";
               $ug2 = '';
               if ($usergrps = user_group($course->id, $user->id)) {
                   foreach ($usergrps as $ug) {
-                                 $ug2 = $ug2. $ug->name;
-                             }
-                         }
+                      $ug2 = $ug2. $ug->name;
+                  }
+              }
               echo $ug2. "\t";
               echo format_string(choice_get_option_text($choice, $answers[$user->id]->optionid),true). "\n";
           }
index ff052f7ec3c9e7c06a2254e74b18e319c40e78cb..fa6849ab407eed13c22b7f2cf787dba8a84207f4 100644 (file)
@@ -33,7 +33,7 @@
 
     if ($form = data_submitted()) {
         $timenow = time();
-               if (has_capability('mod/choice:deleteresponses', $context->id)) {
+        if (has_capability('mod/choice:deleteresponses', $context->id)) {
         //if (isteacher($course->id, $USER->id)) {
             if ($action == 'delete') { //some responses need to be deleted     
                 choice_delete_responses($attemptids); //delete responses.
@@ -59,7 +59,7 @@
                  "<a href=\"index.php?id=$course->id\">$strchoices</a> -> ".format_string($choice->name), "", "", true,
                   update_module_button($cm->id, $course->id, $strchoice), navmenu($course, $cm));
                                                       
-       if (has_capability('mod/choice:readresponses', $context->id)) {
+    if (has_capability('mod/choice:readresponses', $context->id)) {
     //if (isteacher($course->id)) {
         choice_show_reportlink($choice, $course->id, $cm->id);
     } else if (!$cm->visible) {
         ( $choice->showresults == CHOICE_SHOWRESULTS_AFTER_ANSWER and $current ) or
         ( $choice->showresults == CHOICE_SHOWRESULTS_AFTER_CLOSE and $choice->timeclose <= time() ) )  {
 
-               choice_show_results($choice, $course, $cm);
+        choice_show_results($choice, $course, $cm);
     }
 
     print_footer($course);
index 2a79131121dda9c04af03b9bb92b7c383bb18882..34a883759d52097234510d72400e53cdaef19d70 100755 (executable)
     }
 
     require_login($course->id);
-       
-       $cm = data_get_cm($data);
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
     
-       if ($commentid) {
+    $cm = data_get_cm($data);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    
+    if ($commentid) {
         if (! $comment = get_record('data_comments', 'id', $commentid)) {
             error('Comment ID is misconfigured');
         }
index 4cd279c8683a53d3bbec58a7a3fdd22ef736bac9..b129a749a290519565382bebb6c5f294f6a25d9e 100755 (executable)
@@ -65,8 +65,8 @@
 
     require_course_login($course, true, $cm);
 
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       has_capability('mod/data:managetemplates', $context->id, true);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    has_capability('mod/data:managetemplates', $context->id, true);
 
 
     if (!isteacheredit($course->id)){
index d29911500bbfba37780c8dc28ed34240f3fc5969..2c7e922fa73f891b7230ced85bd4261fba659038 100755 (executable)
@@ -57,8 +57,8 @@
         }
     }
     
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       has_capability('mod/data:uploadentries', $context->id, true);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    has_capability('mod/data:uploadentries', $context->id, true);
     
     if (has_capability('mod/data:managetemplates', $context->id)) {
         if (!count_records('data_fields','dataid',$data->id)) {      // Brand new database!
index 17fc862ea51b84a5220894be1eab3bea4420ba63..b0b827a94ee31b4002f80555a52e0f559e0aacad 100755 (executable)
@@ -557,7 +557,7 @@ function data_add_record($data, $groupid=0){
     $record->groupid = $groupid;
     $record->timecreated = $record->timemodified = time();
     if (has_capability('mod/data:approve', $context->id)) {
-       //if (isteacher($data->course)) {
+    //if (isteacher($data->course)) {
         $record->approved = 1;
     } else {
         $record->approved = 0;
@@ -839,8 +839,8 @@ function data_get_coursemodule_info($coursemodule) {
 function data_print_template($template, $records, $data, $search='',$page=0, $return=false) {
     global $CFG;
 
-       $cm = data_get_cm($data);
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $cm = data_get_cm($data);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 
     static $fields = NULL;
     static $isteacher;
@@ -991,9 +991,9 @@ function data_print_preference_form($data, $perpage, $search, $sort='', $order='
 function data_print_ratings($data, $record) {
     global $USER;
 
-       $cm = data_get_cm($data);
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       
+    $cm = data_get_cm($data);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    
     $ratingsmenuused = false;
     if ($data->ratings and !empty($USER->id)) {
         if ($ratings->scale = make_grades_menu($data->scale)) {
@@ -1165,10 +1165,10 @@ function data_print_comment($data, $comment, $page=0) {
 
     global $USER, $CFG;
     
-       $cm = data_get_cm($data);
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $cm = data_get_cm($data);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
     
-       $stredit = get_string('edit');
+    $stredit = get_string('edit');
     $strdelete = get_string('delete');
 
     $user = get_record('user','id',$comment->userid);
@@ -1254,13 +1254,13 @@ function data_convert_arrays_to_strings(&$fieldinput) {
 
 // returns the $cm given $data
 function data_get_cm($data) {
-       global $CFG, $course;
-       $datamod = get_record('modules', 'name', 'data');
-       $SQL = "select * from {$CFG->prefix}course_modules
-                       where course = $course->id and
-                       module = $datamod->id and
-                       instance = $data->id";
-       return get_record_sql($SQL);
+    global $CFG, $course;
+    $datamod = get_record('modules', 'name', 'data');
+    $SQL = "select * from {$CFG->prefix}course_modules
+            where course = $course->id and
+            module = $datamod->id and
+            instance = $data->id";
+    return get_record_sql($SQL);
 }
 
 ?>
index 1adf4d45f50949f5ba6a2d828014c43abc85b98a..80b149cb6cf55d2ec7ed8e83ad419fc7d0d293d2 100644 (file)
@@ -92,11 +92,11 @@ function data_restore_mods($mod,$restore) {
                              $mod->id, $newid);
             //Now check if want to restore user data and do it.
             if (function_exists('restore_userdata_selected')) {
-               // Moodle 1.6
-                   $restore_userdata_selected = restore_userdata_selected($restore, 'data', $mod->id);
+                // Moodle 1.6
+                $restore_userdata_selected = restore_userdata_selected($restore, 'data', $mod->id);
             } else {
                 // Moodle 1.5
-                   $restore_userdata_selected = $restore->mods['data']->userinfo;
+                $restore_userdata_selected = $restore->mods['data']->userinfo;
             }
             if ($restore_userdata_selected) {
                 //Restore data_fields first!!! need to hold an array of [oldid]=>newid due to double dependencies
index b35cf31675fc47061257c0a1c68f5f1bf1232ae5..82e5e8c02c4838c5769996838ab6ed0c9130067f 100755 (executable)
@@ -30,7 +30,7 @@
     }
     
     $cm = data_get_cm($data);
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 
     $inactive = NULL;
     $row = array();
@@ -46,7 +46,7 @@
     //if (isloggedin() and !isguest()) {
     if (isloggedin()) {
         if (has_capability('mod/data:writeentry', $context->id)) { // took out participation list here!
-                       $addstring = empty($editentry) ? get_string('add', 'data') : get_string('editentry', 'data');
+            $addstring = empty($editentry) ? get_string('add', 'data') : get_string('editentry', 'data');
             $row[] = new tabobject('add', $CFG->wwwroot.'/mod/data/edit.php?d='.$data->id, $addstring, '', true);
         }
         if (has_capability('mod/data:managetemplates', $context->id)) {
index 9c6c92f0682392c52107404d0aa513dffbb43e10..4931b7e1a319a10b4897373c777ce152555c7cae 100755 (executable)
@@ -56,9 +56,9 @@
     }
 
     require_course_login($course, true, $cm);
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       has_capability('mod/data:managetemplates', $context->id, true);
-/*     
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    has_capability('mod/data:managetemplates', $context->id, true);
+/*  
     if (!isteacheredit($course->id)){
         error(get_string('noaccess','data'));
     }
index 9621ba24f7709410a283079b1a716a042bdce5a8..10dd24cf2605969bbe0551234d307f3bddc5d636 100755 (executable)
@@ -82,9 +82,9 @@
     }
 
     require_course_login($course, true, $cm);
-       
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       has_capability('mod/data:readentry', $context->id, true);
+    
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    has_capability('mod/data:readentry', $context->id, true);
 
 /// If it's hidden then it's don't show anything.  :)
     if (empty($cm->visible) and !has_capability('mod/data:managetemplates', $context->id)) {
index 4ebeab314064391d62f8a5d7c0ebe021f701e3e2..27fae0061820abcc9f68e62fedb27a4300bd4ea3 100644 (file)
@@ -55,7 +55,7 @@
 
     require_login($course->id, false, $cm);
 
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 
     $strexercises = get_string("modulenameplural", "exercise");
     $strexercise  = get_string("modulename", "exercise");
index aa7a0afb3d16fbdfe448c82ec102ebdb9771fa71..e10dbbab929ea15b372023c28bf9add0bdea6734 100644 (file)
@@ -38,7 +38,7 @@
 
     require_login($course->id, false, $cm);
 
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 
     // ...log activity...
     add_to_log($course->id, "exercise", "view", "view.php?id=$cm->id", $exercise->id, $cm->id);
index 5448d92447b40e4d1e572077de6d4ee7f6f496cf..364886f79622e6cb167f0ae62cac57e322299c48 100644 (file)
@@ -22,9 +22,9 @@
     }
 
     require_login($course->id, false, $cm);    
-       
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       has_capability('mod/glossary:approve', $context->id, true);
+    
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    has_capability('mod/glossary:approve', $context->id, true);
 
     $newentry->id = $eid;
     $newentry->approved = 1;
index 316143197c5fef3bc3f5552bdab74bfb579b6aa0..365f65820dc858185030f33d5eb91c17c36130a3 100644 (file)
@@ -38,9 +38,9 @@
 
     require_login($course->id, false, $cm);
     
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
     
-       if (isguest()) {
+    if (isguest()) {
         error('Guests are not allowed to post comments', $_SERVER['HTTP_REFERER']);
     }
     add_to_log($course->id, 'glossary', 'view', "view.php?id=$cm->id", "$glossary->id",$cm->id);
index 38a54638d5d939cb16cac79eea85c8cd3dd80117..176fced3bf1a825266a713fa360d44e7608edf9a 100644 (file)
@@ -25,7 +25,7 @@
         error("Entry is incorrect");
     }
 
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 
     require_login($course->id, false, $cm);
 
index 3d20b8124f199f8932d9397cbb13cee66a0932b6..b66d84168bd0ddabade308e44be0e71cfd94b43c 100644 (file)
@@ -29,8 +29,8 @@
     }
 
     require_login($course->id, false, $cm);
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    
     if (isguest()) {
         error("Guests are not allowed to edit or delete entries", $_SERVER["HTTP_REFERER"]);
     }
index 95e6623acc0bb8081b7006d9bc58db9d92085c73..5e073954560734729432d1bce080e3ec25fdf2d0 100644 (file)
@@ -166,7 +166,7 @@ if ( $confirm ) {
             error("Could not update this glossary entry because this concept already exist.");
         }
     } else {
-               
+        
         $newentry->userid = $USER->id;
         $newentry->timecreated = $timenow;
         $newentry->sourceglossaryid = 0;
@@ -332,7 +332,7 @@ $tab = GLOSSARY_ADDENTRY_VIEW;
 include("tabs.html");
 
 if (!$e) {
-       has_capability('glossary_write', $context->id, true);  
+    has_capability('glossary_write', $context->id, true);  
 }
 
 include("edit.html");
index 83d6dd55b8def278add635d9c74ceb6835a2e980..94d3f478f30892a8a24154a9ad2d25fd3d583af9 100644 (file)
@@ -44,7 +44,7 @@
     require_login($course->id, false);
 
     $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       has_capability('mod/glossary:managecategories', $context->id, true);
+    has_capability('mod/glossary:managecategories', $context->id, true);
 
     $strglossaries   = get_string("modulenameplural", "glossary");
     $strglossary     = get_string("modulename", "glossary");
index 712cf758cb1f68eb4d9f74022d37274704a87c65..cbe03fe5c757e27ea3f2fb020e68c43b324d274a 100644 (file)
         error("Course module is incorrect");
     }
 
-    require_login($course->id, false); 
-       
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       has_capability('mod/glossary:export', $context->id, true);
+    require_login($course->id, false);  
+    
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    has_capability('mod/glossary:export', $context->id, true);
 
     $strglossaries = get_string("modulenameplural", "glossary");
     $strglossary = get_string("modulename", "glossary");
index 8619cc684fe503aeba065b722470209449aacb67..735eec4cae991ea00c5085627b76b002917a2ce9 100644 (file)
@@ -29,8 +29,8 @@
             $lcase = 'lcase';
     }
 
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       has_capability('mod/glossary:export', $context->id, true);
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    has_capability('mod/glossary:export', $context->id, true);
 
     if (! $course = get_record('course', 'id', $cm->course)) {
         error('Course is misconfigured');
index e4f163de5b44d3741e11002f6a98b2be0e074a34..ca3338cf6b40e88f5c1dea30b38118222498dd14 100644 (file)
     }
 
     require_login($course->id, false);
-       
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       has_capability('mod/glossary:export', $context->id, true);
-       
+    
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    has_capability('mod/glossary:export', $context->id, true);
+    
     $filename = clean_filename(strip_tags(format_string($glossary->name,true)).'.xml');
     $content = glossary_generate_export_file($glossary,$l,$cat);
     
index 0f1c029af53fe6ae79b512648b5a8aa2df481194..ad2f018ca68e4b877ed8ee5c8ed058fd4b3c6d60 100644 (file)
@@ -18,7 +18,7 @@
     if (! $cm = get_coursemodule_from_id('glossary', $id)) {
         error("Course Module ID was incorrect");
     }
-       
+    
     if (! $course = get_record("course", "id", $cm->course)) {
         error("Course is misconfigured");
     }
         error("Course module is incorrect");
     }
 
-    require_login($course->id, false); 
-       
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       has_capability('mod/glossary:import', $context->id, true);
+    require_login($course->id, false);  
+    
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    has_capability('mod/glossary:import', $context->id, true);
 
     if ($dest != 'new' and $dest != 'current') {
         $dest = 'current';
index 5df9c68df913eda6e5859821d8df406db3448808..0185ab0ee16249c19ee350ba67ff51aff76ad12c 100644 (file)
@@ -738,8 +738,8 @@ function  glossary_print_entry_aliases($course, $cm, $glossary, $entry,$mode='',
 
 function glossary_print_entry_icons($course, $cm, $glossary, $entry, $mode='',$hook='', $type = 'print') {
     global $USER, $CFG;
-       
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 
     $output = false;   //To decide if we must really return text in "return". Activate when needed only!
     $importedentry = ($entry->sourceglossaryid == $glossary->id);
@@ -754,15 +754,15 @@ function glossary_print_entry_icons($course, $cm, $glossary, $entry, $mode='',$h
     $return .= glossary_print_entry_commentslink($course, $cm, $glossary, $entry,$mode,$hook,'html');
     
     if (has_capability('mod/glossary:comment', $context->id)) {
-           $output = true;
+        $output = true;
         $return .= ' <a title="' . get_string('addcomment','glossary') . '" href="comment.php?id='.$cm->id.'&amp;eid='.$entry->id.'"><img src="comment.gif" height="11" width="11" border="0" alt="'.get_string('addcomment','glossary').'" /></a>';
     }
 
 
     if (has_capability('mod/glossary:write', $context->id) or (!empty($USER->id) and $glossary->studentcanpost and $entry->userid == $USER->id)) {
         // only teachers can export entries so check it out
-       if (has_capability('mod/glossary:export', $context->id) and !$ismainglossary and !$importedentry) {
-               $mainglossary = get_record('glossary','mainglossary',1,'course',$course->id);
+        if (has_capability('mod/glossary:export', $context->id) and !$ismainglossary and !$importedentry) {
+            $mainglossary = get_record('glossary','mainglossary',1,'course',$course->id);
             if ( $mainglossary ) {  // if there is a main glossary defined, allow to export the current entry
                 $output = true;
                 $return .= ' <a title="'.get_string('exporttomainglossary','glossary') . '" href="exportentry.php?id='.$cm->id.'&amp;entry='.$entry->id.'&amp;mode='.$mode.'&amp;hook='.$hook.'"><img src="export.gif" height="11" width="11" border="0" alt="'.get_string('exporttomainglossary','glossary').'" /></a>';
@@ -1303,9 +1303,9 @@ function glossary_print_author_menu($cm, $glossary,$mode, $hook, $sortkey = '',
 
 function glossary_print_categories_menu($cm, $glossary, $hook, $category) {
      
-        global $CFG;
-        
-        $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+     global $CFG;
+     
+     $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 
      echo '<table border="0" width="100%">';
      echo '<tr>';
@@ -1563,8 +1563,8 @@ function  glossary_print_entry_ratings($course, $entry, $ratings = NULL) {
     $glossary = get_record('glossary', 'id', $entry->glossaryid);
     $glossarymod = get_record('modules','name','glossary');
     $cm = get_record_sql("select * from {$CFG->prefix}course_modules where course = $course->id 
-                                         and module = $glossarymod->id and instance = $glossary->id");
-                                         
+                          and module = $glossarymod->id and instance = $glossary->id");
+                          
     $context = get_context_instance(CONTEXT_MODULE, $cm->id);
 
     $ratingsmenuused = false;
index 2492525b01f353dadd2c898c8a90d1a3b0222a19..8ac786f6e2b7b3d95ee4e681e8537750caf33f50 100644 (file)
@@ -21,8 +21,8 @@
     
     $module = get_record("modules","name","glossary");
     $cm = get_record("course_modules","module",$module->id,"instance",$entry->glossaryid);
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    
     if (!has_capability('mod/glossary:manageentries', $context->id) and $USER->id != $entry->userid) {
         error("You can only look at results for your own entries");
     }
index ad1ed7323c96c95ac552938a6d2c3c96392ad089..6ada25b1898402b92b1a4d5e227fd2a176aaf399 100644 (file)
@@ -23,8 +23,8 @@
     }
     if (has_capability('mod/glossary:import', $context->id)) {
         $data[GLOSSARY_IMPORT_VIEW]->caption = get_string("importentries", "glossary");
-       $data[GLOSSARY_IMPORT_VIEW]->link = "import.php?id=$cm->id";
-       }
+        $data[GLOSSARY_IMPORT_VIEW]->link = "import.php?id=$cm->id";
+    }
         
     if (has_capability('mod/glossary:export', $context->id)) {
         $data[GLOSSARY_EXPORT_VIEW]->caption = get_string("exportentries", "glossary");     
@@ -39,8 +39,8 @@
     $data[GLOSSARY_CATEGORY_VIEW]->link = "view.php?id=$id&amp;mode=cat";
     $data[GLOSSARY_AUTHOR_VIEW]->link = "view.php?id=$id&amp;mode=author";
 
-       if (has_capability('mod/glossary:approve', $context->id)) {
-           $data[GLOSSARY_APPROVAL_VIEW]->caption = get_string("waitingapproval", "glossary");
+    if (has_capability('mod/glossary:approve', $context->id)) {
+        $data[GLOSSARY_APPROVAL_VIEW]->caption = get_string("waitingapproval", "glossary");
         $data[GLOSSARY_APPROVAL_VIEW]->link = "";
 
         $hiddenentries = get_records_select("glossary_entries","glossaryid  = $glossary->id and approved = 0");
index d013974033de079ecce57f82781cc2542b0ef357..71f27968e01376cbbe36199b40c479ab005b0aed 100644 (file)
@@ -44,8 +44,8 @@
         error("Must specify glossary ID or course module ID");
     }
 
-       $context = get_context_instance(CONTEXT_MODULE, $cm->id);
-       has_capability('mod/glossary:view', $context->id, true); // kill the page if user can't even read
+    $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+    has_capability('mod/glossary:view', $context->id, true); // kill the page if user can't even read
 
     if ($CFG->forcelogin) {
         require_login();
index b7d5e55a34222820e26b660dffd26a8af8db23ef..68c612c8f0895a9184368ce491e2c35fe3fcab14 100644 (file)
 <?php // $Id$
-       require_once("../../config.php");
-       require_once("lib.php");
-
-       $attemptid = required_param("attemptid");
-
-       // get attempt, hotpot, course and course_module records
-       if (! $attempt = get_record("hotpot_attempts", "id", $attemptid)) {
-               error("Hot Potatoes attempt record $attemptid could not be accessed: ".$db->ErrorMsg());
-       }
-       if ($attempt->userid != $USER->id) {
-               error("User ID is incorrect");
-       }
-       if (! $hotpot = get_record("hotpot", "id", $attempt->hotpot)) {
-               error("Hot Potatoes ID is incorrect (attempt id = $attempt->id)");
-       }
-       if (! $course = get_record("course", "id", $hotpot->course)) {
-               error("Course ID is incorrect (hotpot id = $hotpot->id)");
-       }
-       if (! $cm = get_coursemodule_from_instance("hotpot", $hotpot->id, $course->id)) {
-               error("Course Module ID is incorrect");
-       }
-
-       // make sure this user is enrolled in this course
-       require_login($course->id);
-
-       $next_url = "$CFG->wwwroot/course/view.php?id=$course->id";
-       $time = time();
-
-       // update attempt record fields using incoming data
-       $attempt->score = optional_param('mark', NULL, PARAM_INT);
-       $attempt->status = optional_param('status', NULL, PARAM_INT);
-       $attempt->details = optional_param('detail', NULL, PARAM_RAW);
-       $attempt->endtime = optional_param('endtime', NULL, PARAM_ALPHA);
-       $attempt->starttime = optional_param('starttime', NULL, PARAM_ALPHA);
-       $attempt->timefinish = $time;
-
-       // convert times, if necessary
-       if (empty($attempt->starttime)) {
-               $attempt->starttime = 0;
-       } else {
-                $attempt->starttime = strtotime($attempt->starttime);
-       }
-       if (empty($attempt->endtime)) {
-               $attempt->endtime = 0;
-       } else {
-                $attempt->endtime = strtotime($attempt->endtime);
-       }
-
-       // set clickreportid, (for click reporting)
-       $attempt->clickreportid = $attempt->id;
-
-       $quiztype = optional_param('quiztype', 0, PARAM_INT);
-
-       if (empty($attempt->details)) {
-               hotpot_set_attempt_details($attempt);
-               $javascript_is_off = true;
-       } else {
-               $javascript_is_off = false;
-       }
-
-       if (empty($attempt->status)) {
-               if (empty($attempt->endtime)) {
-                       $attempt->status = HOTPOT_STATUS_INPROGRESS;
-               } else {
-                       $attempt->status = HOTPOT_STATUS_COMPLETED;
-               }
-       }
-
-       // check if this is the second (or subsequent) click
-       if (get_field("hotpot_attempts", "timefinish", "id", $attempt->id)) {
-
-               if ($hotpot->clickreporting==HOTPOT_YES) {
-                       // add attempt record for each form submission
-                       // records are linked via the "clickreportid" field
-
-                       // update status in previous records in this group
-                       set_field("hotpot_attempts", "status", $attempt->status, "clickreportid", $attempt->clickreportid);
-
-                       // add new attempt record
-                       unset ($attempt->id);
-                       $attempt->id = insert_record("hotpot_attempts", $attempt);
-
-                       if (empty($attempt->id)) {
-                               error("Could not insert attempt record: ".$db->ErrorMsg(), $next_url);
-                       }
-
-                       // add attempt details record, if necessary
-                       if (!empty($attempt->details)) {
-                               unset($details);
-                               $details->attempt = $attempt->id;
-                               $details->details = $attempt->details;
-                               if (! insert_record("hotpot_details", $details, false)) {
-                                       error("Could not insert attempt details record: ".$db->ErrorMsg(), $next_url);
-                               }
-                       }
-               } else {
-                       // remove previous responses for this attempt, if required
-                       // (N.B. this does NOT remove the attempt record, just the responses)
-                       delete_records("hotpot_responses", "attempt", $attempt->id);
-               }
-       }
-
-       // remove slashes added by lib/setup.php
-       $attempt->details = stripslashes($attempt->details);
-
-       // add details of this attempt
-       hotpot_add_attempt_details($attempt);
-
-       // add slashes again, so the details can be added to the database
-       $attempt->details = addslashes($attempt->details);
-
-       // update the attempt record
-       if (! update_record("hotpot_attempts", $attempt)) {
-               error("Could not update attempt record: ".$db->ErrorMsg(), $next_url);
-       }
-
-       // get previous attempt details record, if any
-       $details_exist = record_exists("hotpot_details", "attempt", $attempt->id);
-
-       // delete/update/add the attempt details record
-       if (empty($attempt->details)) {
-               if ($details_exist) {
-                       delete_records("hotpot_details", "attempt", $attempt->id);
-               }
-       } else {
-               if ($details_exist) {
-                       set_field("hotpot_details", "details", $attempt->details, "attempt", $attempt->id);
-               } else {
-                       unset($details);
-                       $details->attempt = $attempt->id;
-                       $details->details = $attempt->details;
-                       if (! insert_record("hotpot_details", $details)) {
-                               error("Could not insert attempt details record: ".$db->ErrorMsg(), $next_url);
-                       }
-               }
-       }
-
-       if ($attempt->status==HOTPOT_STATUS_INPROGRESS) {
-               if ($javascript_is_off) {
-                       // regenerate HTML page
-                       define('HOTPOT_FIRST_ATTEMPT', false);
-                       include ("$CFG->hotpotroot/view.php");
-               } else {
-                       // continue without reloading the page
-                       header("Status: 204");
-                       header("HTTP/1.0 204 No Response");
-               }
-
-       } else { // quiz is finished
-
-               add_to_log($course->id, "hotpot", "submit", "review.php?id=$cm->id&attempt=$attempt->id", "$hotpot->id", "$cm->id");
-
-               if ($hotpot->shownextquiz==HOTPOT_YES) {
-                       if (is_numeric($next_cm = hotpot_get_next_cm($cm))) {
-                               $next_url = "$CFG->wwwroot/mod/hotpot/view.php?id=$next_cm";
-                       }
-               }
-
-               // redirect to the next quiz or the course page 
-               redirect($next_url, get_string('resultssaved', 'hotpot'));
-       }
+    require_once("../../config.php");
+    require_once("lib.php");
+
+    $attemptid = required_param("attemptid");
+
+    // get attempt, hotpot, course and course_module records
+    if (! $attempt = get_record("hotpot_attempts", "id", $attemptid)) {
+        error("Hot Potatoes attempt record $attemptid could not be accessed: ".$db->ErrorMsg());
+    }
+    if ($attempt->userid != $USER->id) {
+        error("User ID is incorrect");
+    }
+    if (! $hotpot = get_record("hotpot", "id", $attempt->hotpot)) {
+        error("Hot Potatoes ID is incorrect (attempt id = $attempt->id)");
+    }
+    if (! $course = get_record("course", "id", $hotpot->course)) {
+        error("Course ID is incorrect (hotpot id = $hotpot->id)");
+    }
+    if (! $cm = get_coursemodule_from_instance("hotpot", $hotpot->id, $course->id)) {
+        error("Course Module ID is incorrect");
+    }
+
+    // make sure this user is enrolled in this course
+    require_login($course->id);
+
+    $next_url = "$CFG->wwwroot/course/view.php?id=$course->id";
+    $time = time();
+
+    // update attempt record fields using incoming data
+    $attempt->score = optional_param('mark', NULL, PARAM_INT);
+    $attempt->status = optional_param('status', NULL, PARAM_INT);
+    $attempt->details = optional_param('detail', NULL, PARAM_RAW);
+    $attempt->endtime = optional_param('endtime', NULL, PARAM_ALPHA);
+    $attempt->starttime = optional_param('starttime', NULL, PARAM_ALPHA);
+    $attempt->timefinish = $time;
+
+    // convert times, if necessary
+    if (empty($attempt->starttime)) {
+        $attempt->starttime = 0;
+    } else {
+         $attempt->starttime = strtotime($attempt->starttime);
+    }
+    if (empty($attempt->endtime)) {
+        $attempt->endtime = 0;
+    } else {
+         $attempt->endtime = strtotime($attempt->endtime);
+    }
+
+    // set clickreportid, (for click reporting)
+    $attempt->clickreportid = $attempt->id;
+
+    $quiztype = optional_param('quiztype', 0, PARAM_INT);
+
+    if (empty($attempt->details)) {
+        hotpot_set_attempt_details($attempt);
+        $javascript_is_off = true;
+    } else {
+        $javascript_is_off = false;
+    }
+
+    if (empty($attempt->status)) {
+        if (empty($attempt->endtime)) {
+            $attempt->status = HOTPOT_STATUS_INPROGRESS;
+        } else {
+            $attempt->status = HOTPOT_STATUS_COMPLETED;
+        }
+    }
+
+    // check if this is the second (or subsequent) click
+    if (get_field("hotpot_attempts", "timefinish", "id", $attempt->id)) {
+
+        if ($hotpot->clickreporting==HOTPOT_YES) {
+            // add attempt record for each form submission
+            // records are linked via the "clickreportid" field
+
+            // update status in previous records in this group
+            set_field("hotpot_attempts", "status", $attempt->status, "clickreportid", $attempt->clickreportid);
+
+            // add new attempt record
+            unset ($attempt->id);
+            $attempt->id = insert_record("hotpot_attempts", $attempt);
+
+            if (empty($attempt->id)) {
+                error("Could not insert attempt record: ".$db->ErrorMsg(), $next_url);
+            }
+
+            // add attempt details record, if necessary
+            if (!empty($attempt->details)) {
+                unset($details);
+                $details->attempt = $attempt->id;
+                $details->details = $attempt->details;
+                if (! insert_record("hotpot_details", $details, false)) {
+                    error("Could not insert attempt details record: ".$db->ErrorMsg(), $next_url);
+                }
+            }
+        } else {
+            // remove previous responses for this attempt, if required
+            // (N.B. this does NOT remove the attempt record, just the responses)
+            delete_records("hotpot_responses", "attempt", $attempt->id);
+        }
+    }
+
+    // remove slashes added by lib/setup.php
+    $attempt->details = stripslashes($attempt->details);
+
+    // add details of this attempt
+    hotpot_add_attempt_details($attempt);
+
+    // add slashes again, so the details can be added to the database
+    $attempt->details = addslashes($attempt->details);
+
+    // update the attempt record
+    if (! update_record("hotpot_attempts", $attempt)) {
+        error("Could not update attempt record: ".$db->ErrorMsg(), $next_url);
+    }
+
+    // get previous attempt details record, if any
+    $details_exist = record_exists("hotpot_details", "attempt", $attempt->id);
+
+    // delete/update/add the attempt details record
+    if (empty($attempt->details)) {
+        if ($details_exist) {
+            delete_records("hotpot_details", "attempt", $attempt->id);
+        }
+    } else {
+        if ($details_exist) {
+            set_field("hotpot_details", "details", $attempt->details, "attempt", $attempt->id);
+        } else {
+            unset($details);
+            $details->attempt = $attempt->id;
+            $details->details = $attempt->details;
+            if (! insert_record("hotpot_details", $details)) {
+                error("Could not insert attempt details record: ".$db->ErrorMsg(), $next_url);
+            }
+        }
+    }
+
+    if ($attempt->status==HOTPOT_STATUS_INPROGRESS) {
+        if ($javascript_is_off) {
+            // regenerate HTML page
+            define('HOTPOT_FIRST_ATTEMPT', false);
+            include ("$CFG->hotpotroot/view.php");
+        } else {
+            // continue without reloading the page
+            header("Status: 204");
+            header("HTTP/1.0 204 No Response");
+        }
+
+    } else { // quiz is finished
+
+        add_to_log($course->id, "hotpot", "submit", "review.php?id=$cm->id&attempt=$attempt->id", "$hotpot->id", "$cm->id");
+
+        if ($hotpot->shownextquiz==HOTPOT_YES) {
+            if (is_numeric($next_cm = hotpot_get_next_cm($cm))) {
+                $next_url = "$CFG->wwwroot/mod/hotpot/view.php?id=$next_cm";
+            }
+        }
+
+        // redirect to the next quiz or the course page 
+        redirect($next_url, get_string('resultssaved', 'hotpot'));
+    }
 
 // =================
-//     functions
+//  functions
 // =================
 
 function hotpot_get_next_cm(&$cm) {
-       // gets the next module in this section of the course
-       // that is the same type of module as the current module
-
-       $next_mod = false;
-
-       // get a list of $ids of modules in this section
-       if ($ids = get_field('course_sections', 'sequence', 'id', $cm->section)) {
-
-               $found = false;
-               $ids = explode(',', $ids);
-               foreach ($ids as $id) {
-                       if ($found && ($cm->module==get_field('course_modules', 'module', 'id', $id))) {
-                               $next_mod = $id;
-                               break;
-                       } else if ($cm->id==$id) {
-                               $found = true;
-                       }
-               }
-       }
-       return $next_mod;
+    // gets the next module in this section of the course
+    // that is the same type of module as the current module
+
+    $next_mod = false;
+
+    // get a list of $ids of modules in this section
+    if ($ids = get_field('course_sections', 'sequence', 'id', $cm->section)) {
+
+        $found = false;
+        $ids = explode(',', $ids);
+        foreach ($ids as $id) {
+            if ($found && ($cm->module==get_field('course_modules', 'module', 'id', $id))) {
+                $next_mod = $id;
+                break;
+            } else if ($cm->id==$id) {
+                $found = true;
+            }
+        }
+    }
+    return $next_mod;
 }
 function hotpot_set_attempt_details(&$attempt) {
-       global $CFG, $HOTPOT_QUIZTYPE;
-
-       // optional_param('showallquestions', 0, PARAM_INT);
-
-       $attempt->details = '';
-       $attempt->score = 0;
-       $attempt->status = HOTPOT_STATUS_COMPLETED;
-
-       $buttons = array('clues', 'hints', 'checks');
-       $textfields = array('correct', 'wrong', 'ignored');
-
-       $ok = false;
-       $quiztype = optional_param('quiztype', 0, PARAM_ALPHANUM);
-       if ($quiztype) {
-               if (is_numeric($quiztype)) {
-                       $ok = array_key_exists($quiztype, $HOTPOT_QUIZTYPE);
-               } else {
-                       $quiztype = array_search($quiztype, $HOTPOT_QUIZTYPE);
-                       $ok = is_numeric($quiztype);
-               }
-       }
-       if (!$ok) {
-               return;
-               // error('Quiz type is missing or invalid');
-               // error(get_string('error_invalidquiztype', 'hotpot'));
-               //
-               // script finishes here if quiztype is invalid
-               //
-       }
-
-       // special flag to detect jquiz multiselect
-       $is_jquiz_multiselect = false;
-
-       // set maximum question number
-       $q_max = 0;;
-       do {
-               switch ($quiztype) {
-                       case HOTPOT_JCLOZE:
-                       case HOTPOT_JQUIZ:
-                               $field="q{$q_max}_a0_text";
-                               break;
-                       case HOTPOT_JCB:
-                       case HOTPOT_JCROSS:
-                       case HOTPOT_JMATCH:
-                       case HOTPOT_JMIX:
-                       default:
-                               $field = '';
-               }
-       } while ($field && isset($_POST[$field]) && ($q_max = $q_max+1));
-
-       // check JQuiz navigation buttons
-       switch (true) {
-               case isset($_POST['ShowAllQuestionsButton']):
-                       $_POST['ShowAllQuestions'] = 1;
-                       break;
-               case isset($_POST['ShowOneByOneButton']):
-                       $_POST['ShowAllQuestions'] = 0;
-                       break;
-               case isset($_POST['PrevQButton']):
-                       $_POST['ThisQuestion']--;
-                       break;
-               case isset($_POST['NextQButton']):
-                       $_POST['ThisQuestion']++;
-                       break;
-       }
-
-       $q = 0;
-       while ($q<$q_max) {
-               $responsefield="q{$q}";
-
-               $questiontype = optional_param("{$responsefield}_questiontype", 0, PARAM_INT);
-               $is_jquiz_multiselect = ($quiztype==HOTPOT_JQUIZ && $questiontype==HOTPOT_JQUIZ_MULTISELECT);
-
-               if (isset($_POST[$responsefield]) && is_array($_POST[$responsefield])) {
-                       $responsevalue = array();
-                       foreach ($_POST[$responsefield] as $key=>$value) {
-                               $responsevalue[$key] = clean_param($value, PARAM_CLEAN);
-                       }
-               } else {
-                       $responsevalue = optional_param($responsefield, '');
-               }
-               if (is_array($responsevalue)) {
-                       // incomplete jquiz multi-select
-                       $responsevalues = $responsevalue;
-                       $responsevalue = implode('+', $responsevalue);
-               } else {
-                       $responsevalues = explode('+', $responsevalue);
-               }
-
-               // initialize $response object
-               $response = new stdClass();
-               $response->correct = array();
-               $response->wrong   = array();
-               $response->ignored = array();
-               $response->clues  = 0;
-               $response->hints  = 0;
-               $response->checks = 0;
-               $response->score  = 0;
-               $response->weighting = 0;
-
-               // create another empty object to hold all previous responses (from database)
-               $oldresponse = new stdClass();
-               $vars = get_object_vars($response);
-               foreach($vars as $name=>$value) {
-                       $oldresponse->$name = $value;
-               }
-
-               foreach ($buttons as $button) {
-                       if (($field = "q{$q}_{$button}_button") && isset($_POST[$field])) {
-                               $value = optional_param($field, '', PARAM_RAW);
-                               if (!empty($value)) {
-                                       $response->$button++;
-                               }
-                       }
-               }
-
-               // loop through possible answers to this question
-               $firstcorrectvalue = '';
-               $percents = array();
-               $a = 0;
-               while (($valuefield="q{$q}_a{$a}_text") && isset($_POST[$valuefield])) {
-                       $value = optional_param($valuefield, '', PARAM_RAW);
-
-                       if (($percentfield="q{$q}_a{$a}_percent") && isset($_POST[$percentfield])) {
-                               $percent = optional_param($percentfield, 0, PARAM_INT);
-                               if ($percent) {
-                                       $percents[$value] = $percent;
-                               }
-                       }
-
-                       if (($correctfield="q{$q}_a{$a}_correct") && isset($_POST[$correctfield])) {
-                               $correct = optional_param($correctfield, 0, PARAM_INT);
-                       } else {
-                               $correct = false;
-                       }
-
-                       if ($correct && empty($firstcorrectvalue)) {
-                               $firstcorrectvalue = $value;
-                       }
-
-                       if ($is_jquiz_multiselect) {
-                               $selected = in_array($value, $responsevalues);
-                               if ($correct) {
-                                       $response->correct[] = $value;
-                                       if (empty($selected)) {
-                                               $response->wrong[] = true;
-                                       }
-                               } else {
-                                       if ($selected) {
-                                               $response->wrong[] = true;
-                                       }
-                               }
-                       } else {
-                               // single answer only required
-                               if ($responsevalue==$value) {
-                                       if ($correct) {
-                                               $response->correct[] = $value;
-                                       } else {
-                                               $response->wrong[] = $value;
-                                       }
-                               } else {
-                                       $response->ignored[] = $value;
-                               }
-                       }
-                       $a++;
-               }
-
-               // number of answers for this question
-               $a_max = $a;
-
-               if ($is_jquiz_multiselect) {
-                       if (empty($response->wrong) && count($responsevalues)==count($response->correct)) {
-                               $response->wrong = array();
-                               $response->correct = array($responsevalue);
-                       } else {
-                               $response->correct = array();
-                               $response->wrong = array($responsevalue);
-                       }
-               } else {
-                       // if response did not match any answer, then this response is wrong
-                       if (empty($response->correct) && empty($response->wrong)) {
-                               $response->wrong[] = $responsevalue;
-                       }
-               }
-
-               // if this question has not been answered correctly, quiz is still in progress
-               if (empty($response->correct)) {
-
-                       if (isset($_POST["q{$q}_ShowAnswers_button"])) {
-                                       $_POST[$responsefield] = $firstcorrectvalue;
-                       } else {
-                               $attempt->status = HOTPOT_STATUS_INPROGRESS;
-
-                               if (isset($_POST["q{$q}_Hint_button"])) {
-                                       // a particular hint button in JQuiz shortanswer
-                                       $_POST['HintButton'] = true;
-                               }
-
-                               // give a hint, if necessary
-                               if (isset($_POST['HintButton']) && $firstcorrectvalue) {
-
-                                       // make sure we only come through here once
-                                       unset($_POST['HintButton']);
-
-                                       $correctlen = strlen($firstcorrectvalue);
-                                       $responselen = strlen($responsevalue);
-
-                                       // check how many letters are the same
-                                       $i = 0;
-                                       while ($i<$responselen && $i<$correctlen && $responsevalue{$i}==$firstcorrectvalue{$i}) {
-                                               $i++;
-                                       }
-
-                                       if ($i<$responselen) {
-                                               // remove incorrect characters on the end of the response
-                                               $responsevalue = substr($responsevalue, 0, $i);
-                                       }
-                                       if ($i<$correctlen) {
-                                               // append next correct letter
-                                               $responsevalue .= $firstcorrectvalue{$i};
-                                       }
-                                       $_POST[$responsefield] = $responsevalue;
-                                       $response->hints++;
-                               } // end if hint
-                       }
-               } // end if not correct
-
-               // get clue text, if any
-               if (($field="q{$q}_clue") && isset($_POST[$field])) {
-                       $response->clue_text = optional_param($field, '', PARAM_RAW);
-               }
-
-               // get question name
-               $qq = sprintf('%02d', $q); // (a padded, two-digit version of $q)
-               if (($field="q{$q}_name") && isset($_POST[$field])) {
-                       $questionname = optional_param($field, '',  PARAM_RAW);
-                       $questionname = strip_tags($questionname);
-               } else {
-                       $questionname = $qq;
-               }
-
-               // get previous responses to this question (if any)
-               $records = get_records_sql("
-                       SELECT
-                               r.*
-                       FROM
-                               {$CFG->prefix}hotpot_attempts AS a,
-                               {$CFG->prefix}hotpot_questions AS q,
-                               {$CFG->prefix}hotpot_responses AS r
-                       WHERE
-                               a.clickreportid = $attempt->clickreportid AND
-                               a.id = r.attempt AND
-                               r.question = q.id AND
-                               q.name = '$questionname' AND
-                               q.hotpot = $attempt->hotpot
-                       ORDER BY
-                               a.timefinish
-               ");
-
-               if ($records) {
-                       foreach ($records as $record) {
-                               foreach ($buttons as $button) {
-                                       $oldresponse->$button = max($oldresponse->$button, $record->$button);
-                               }
-                               foreach ($textfields as $field) {
-                                       if ($record->$field && ($field=='correct' || $field=='wrong')) {
-                                               $values = explode(',', hotpot_strings($record->$field));
-                                               $oldresponse->$field = array_merge($oldresponse->$field, $values);
-                                       }
-                               }
-                       }
-               }
-
-               // remove "correct" and "wrong" values from "ignored" values
-               $response->ignored = array_diff($response->ignored, 
-                       $response->correct, $response->wrong, $oldresponse->correct, $oldresponse->wrong
-               );
-
-               foreach ($buttons as $button) {
-                       $response->$button += $oldresponse->$button;
-               }
-
-               $value_has_changed = false;
-               foreach ($textfields as $field) {
-                       $response->$field = array_merge($oldresponse->$field, $response->$field);
-                       $response->$field = array_unique($response->$field);
-                       $response->$field  = implode(',', $response->$field);
-
-                       if ($field=='correct' || $field=='wrong') {
-                               $array = $oldresponse->$field;
-                               $array = array_unique($array);
-                               $oldresponse->$field  = implode(',', $array);
-                               if ($response->$field<>$oldresponse->$field) {
-                                       $value_has_changed = true;
-                               }
-                       }
-               }
-               if ($value_has_changed) {
-                       $response->checks++;
-               }
-
-               // $response now holds amalgamation of all responses so far to this question
-
-               // set question score and weighting
-               if ($response->correct) {
-                       switch ($quiztype) {
-                               case HOTPOT_JCB:
-                                       break;
-                               case HOTPOT_JCLOZE:
-                                       $strlen = strlen($response->correct);
-                                       $response->score = 100*($strlen-($response->checks-1))/$strlen;
-                                       $attempt->score += $response->score;
-                                       break;
-                               case HOTPOT_JCROSS:
-                                       break;
-                               case HOTPOT_JMATCH:
-                                       break;
-                               case HOTPOT_JMIX:
-                                       break;
-                               case HOTPOT_JQUIZ:
-                                       switch ($questiontype) {
-                                               case HOTPOT_JQUIZ_MULTICHOICE:
-                                                       $wrong = explode(',', $response->wrong);
-                                                       foreach ($wrong as $value) {
-                                                               if (isset($percents[$value])) {
-                                                                       $percent = $percents[$value];
-                                                               } else {
-                                                                       $percent = 0;
-                                                               }
-                                                       }
-                                               case HOTPOT_JQUIZ_SHORTANSWER:
-                                                       $strlen = strlen($response->correct);
-                                                       $response->score = 100*($strlen-($response->checks-1))/$strlen;
-                                                       break;
-                                               case HOTPOT_JQUIZ_MULTISELECT:
-                                                       if (isset($percents[$response->correct])) {
-                                                               $percent = $percents[$response->correct];
-                                                       } else {
-                                                               $percent = 0;
-                                                       }
-                                                       if ($a_max>0 && $response->checks>0 && $a_max>$response->checks) {
-                                                               $response->score = $percent*($a_max-($response->checks-1))/$a_max;
-                                                       }
-                                                       break;
-                                       }
-                                       $attempt->score += $response->score;
-                                       break;
-                       }
-               }
-
-               $fieldname = $HOTPOT_QUIZTYPE[$quiztype]."_q{$qq}_name";
-               $attempt->details .= "<field><fieldname>$fieldname</fieldname><fielddata>$questionname</fielddata></field>";
-
-               // encode $response fields as XML
-               $vars = get_object_vars($response);
-               foreach($vars as $name=>$value) {
-                       if (!empty($value)) {
-                               $fieldname = $HOTPOT_QUIZTYPE[$quiztype]."_q{$qq}_{$name}";
-                               $attempt->details .= "<field><fieldname>$fieldname</fieldname><fielddata>$value</fielddata></field>";
-                       }
-               }
-
-               $q++;
-       } // end main loop through $q(uestions)
-
-       // set attempt score
-       if ($q>0) {
-               switch ($quiztype) {
-                       case HOTPOT_JCB:
-                               break;
-                       case HOTPOT_JCLOZE:
-                               $attempt->score = floor($attempt->score / $q);
-                               break;
-                       case HOTPOT_JCROSS:
-                               break;
-                       case HOTPOT_JMATCH:
-                               break;
-                       case HOTPOT_JMIX:
-                               break;
-                       case HOTPOT_JQUIZ:
-                               break;
-               }
-       }
-
-       if ($attempt->details) {
-               $attempt->details = '<?xml version="1.0"?><hpjsresult><fields>'.$attempt->details.'</fields></hpjsresult>';
-       }
-
-//     print "forcing status to in progress ..<br>\n";
-//     $attempt->status = HOTPOT_STATUS_INPROGRESS;
+    global $CFG, $HOTPOT_QUIZTYPE;
+
+    // optional_param('showallquestions', 0, PARAM_INT);
+
+    $attempt->details = '';
+    $attempt->score = 0;
+    $attempt->status = HOTPOT_STATUS_COMPLETED;
+
+    $buttons = array('clues', 'hints', 'checks');
+    $textfields = array('correct', 'wrong', 'ignored');
+
+    $ok = false;
+    $quiztype = optional_param('quiztype', 0, PARAM_ALPHANUM);
+    if ($quiztype) {
+        if (is_numeric($quiztype)) {
+            $ok = array_key_exists($quiztype, $HOTPOT_QUIZTYPE);
+        } else {
+            $quiztype = array_search($quiztype, $HOTPOT_QUIZTYPE);
+            $ok = is_numeric($quiztype);
+        }
+    }
+    if (!$ok) {
+        return;
+        // error('Quiz type is missing or invalid');
+        // error(get_string('error_invalidquiztype', 'hotpot'));
+        //
+        // script finishes here if quiztype is invalid
+        //
+    }
+
+    // special flag to detect jquiz multiselect
+    $is_jquiz_multiselect = false;
+
+    // set maximum question number
+    $q_max = 0;;
+    do {
+        switch ($quiztype) {
+            case HOTPOT_JCLOZE:
+            case HOTPOT_JQUIZ:
+                $field="q{$q_max}_a0_text";
+                break;
+            case HOTPOT_JCB:
+            case HOTPOT_JCROSS:
+            case HOTPOT_JMATCH:
+            case HOTPOT_JMIX:
+            default:
+                $field = '';
+        }
+    } while ($field && isset($_POST[$field]) && ($q_max = $q_max+1));
+
+    // check JQuiz navigation buttons
+    switch (true) {
+        case isset($_POST['ShowAllQuestionsButton']):
+            $_POST['ShowAllQuestions'] = 1;
+            break;
+        case isset($_POST['ShowOneByOneButton']):
+            $_POST['ShowAllQuestions'] = 0;
+            break;
+        case isset($_POST['PrevQButton']):
+            $_POST['ThisQuestion']--;
+            break;
+        case isset($_POST['NextQButton']):
+            $_POST['ThisQuestion']++;
+            break;
+    }
+
+    $q = 0;
+    while ($q<$q_max) {
+        $responsefield="q{$q}";
+
+        $questiontype = optional_param("{$responsefield}_questiontype", 0, PARAM_INT);
+        $is_jquiz_multiselect = ($quiztype==HOTPOT_JQUIZ && $questiontype==HOTPOT_JQUIZ_MULTISELECT);
+
+        if (isset($_POST[$responsefield]) && is_array($_POST[$responsefield])) {
+            $responsevalue = array();
+            foreach ($_POST[$responsefield] as $key=>$value) {
+                $responsevalue[$key] = clean_param($value, PARAM_CLEAN);
+            }
+        } else {
+            $responsevalue = optional_param($responsefield, '');
+        }
+        if (is_array($responsevalue)) {
+            // incomplete jquiz multi-select
+            $responsevalues = $responsevalue;
+            $responsevalue = implode('+', $responsevalue);
+        } else {
+            $responsevalues = explode('+', $responsevalue);
+        }
+
+        // initialize $response object
+        $response = new stdClass();
+        $response->correct = array();
+        $response->wrong   = array();
+        $response->ignored = array();
+        $response->clues  = 0;
+        $response->hints  = 0;
+        $response->checks = 0;
+        $response->score  = 0;
+        $response->weighting = 0;
+
+        // create another empty object to hold all previous responses (from database)
+        $oldresponse = new stdClass();
+        $vars = get_object_vars($response);
+        foreach($vars as $name=>$value) {
+            $oldresponse->$name = $value;
+        }
+
+        foreach ($buttons as $button) {
+            if (($field = "q{$q}_{$button}_button") && isset($_POST[$field])) {
+                $value = optional_param($field, '', PARAM_RAW);
+                if (!empty($value)) {
+                    $response->$button++;
+                }
+            }
+        }
+
+        // loop through possible answers to this question
+        $firstcorrectvalue = '';
+        $percents = array();
+        $a = 0;
+        while (($valuefield="q{$q}_a{$a}_text") && isset($_POST[$valuefield])) {
+            $value = optional_param($valuefield, '', PARAM_RAW);
+
+            if (($percentfield="q{$q}_a{$a}_percent") && isset($_POST[$percentfield])) {
+                $percent = optional_param($percentfield, 0, PARAM_INT);
+                if ($percent) {
+                    $percents[$value] = $percent;
+                }
+            }
+
+            if (($correctfield="q{$q}_a{$a}_correct") && isset($_POST[$correctfield])) {
+                $correct = optional_param($correctfield, 0, PARAM_INT);
+            } else {
+                $correct = false;
+            }
+
+            if ($correct && empty($firstcorrectvalue)) {
+                $firstcorrectvalue = $value;
+            }
+
+            if ($is_jquiz_multiselect) {
+                $selected = in_array($value, $responsevalues);
+                if ($correct) {
+                    $response->correct[] = $value;
+                    if (empty($selected)) {
+                        $response->wrong[] = true;
+                    }
+                } else {
+                    if ($selected) {
+                        $response->wrong[] = true;
+                    }
+                }
+            } else {
+                // single answer only required
+                if ($responsevalue==$value) {
+                    if ($correct) {
+                        $response->correct[] = $value;
+                    } else {
+                        $response->wrong[] = $value;
+                    }
+                } else {
+                    $response->ignored[] = $value;
+                }
+            }
+            $a++;
+        }
+
+        // number of answers for this question
+        $a_max = $a;
+
+        if ($is_jquiz_multiselect) {
+            if (empty($response->wrong) && count($responsevalues)==count($response->correct)) {
+                $response->wrong = array();
+                $response->correct = array($responsevalue);
+            } else {
+                $response->correct = array();
+                $response->wrong = array($responsevalue);
+            }
+        } else {
+            // if response did not match any answer, then this response is wrong
+            if (empty($response->correct) && empty($response->wrong)) {
+                $response->wrong[] = $responsevalue;
+            }
+        }
+
+        // if this question has not been answered correctly, quiz is still in progress
+        if (empty($response->correct)) {
+
+            if (isset($_POST["q{$q}_ShowAnswers_button"])) {
+                    $_POST[$responsefield] = $firstcorrectvalue;
+            } else {
+                $attempt->status = HOTPOT_STATUS_INPROGRESS;
+
+                if (isset($_POST["q{$q}_Hint_button"])) {
+                    // a particular hint button in JQuiz shortanswer
+                    $_POST['HintButton'] = true;
+                }
+
+                // give a hint, if necessary
+                if (isset($_POST['HintButton']) && $firstcorrectvalue) {
+
+                    // make sure we only come through here once
+                    unset($_POST['HintButton']);
+
+                    $correctlen = strlen($firstcorrectvalue);
+                    $responselen = strlen($responsevalue);
+
+                    // check how many letters are the same
+                    $i = 0;
+                    while ($i<$responselen && $i<$correctlen && $responsevalue{$i}==$firstcorrectvalue{$i}) {
+                        $i++;
+                    }
+
+                    if ($i<$responselen) {
+                        // remove incorrect characters on the end of the response
+                        $responsevalue = substr($responsevalue, 0, $i);
+                    }
+                    if ($i<$correctlen) {
+                        // append next correct letter
+                        $responsevalue .= $firstcorrectvalue{$i};
+                    }
+                    $_POST[$responsefield] = $responsevalue;
+                    $response->hints++;
+                } // end if hint
+            }
+        } // end if not correct
+
+        // get clue text, if any
+        if (($field="q{$q}_clue") && isset($_POST[$field])) {
+            $response->clue_text = optional_param($field, '', PARAM_RAW);
+        }
+
+        // get question name
+        $qq = sprintf('%02d', $q); // (a padded, two-digit version of $q)
+        if (($field="q{$q}_name") && isset($_POST[$field])) {
+            $questionname = optional_param($field, '',  PARAM_RAW);
+            $questionname = strip_tags($questionname);
+        } else {
+            $questionname = $qq;
+        }
+
+        // get previous responses to this question (if any)
+        $records = get_records_sql("
+            SELECT
+                r.*
+            FROM
+                {$CFG->prefix}hotpot_attempts AS a,
+                {$CFG->prefix}hotpot_questions AS q,
+                {$CFG->prefix}hotpot_responses AS r
+            WHERE
+                a.clickreportid = $attempt->clickreportid AND
+                a.id = r.attempt AND
+                r.question = q.id AND
+                q.name = '$questionname' AND
+                q.hotpot = $attempt->hotpot
+            ORDER BY
+                a.timefinish
+        ");
+
+        if ($records) {
+            foreach ($records as $record) {
+                foreach ($buttons as $button) {
+                    $oldresponse->$button = max($oldresponse->$button, $record->$button);
+                }
+                foreach ($textfields as $field) {
+                    if ($record->$field && ($field=='correct' || $field=='wrong')) {
+                        $values = explode(',', hotpot_strings($record->$field));
+                        $oldresponse->$field = array_merge($oldresponse->$field, $values);
+                    }
+                }
+            }
+        }
+
+        // remove "correct" and "wrong" values from "ignored" values
+        $response->ignored = array_diff($response->ignored, 
+            $response->correct, $response->wrong, $oldresponse->correct, $oldresponse->wrong
+        );
+
+        foreach ($buttons as $button) {
+            $response->$button += $oldresponse->$button;
+        }
+
+        $value_has_changed = false;
+        foreach ($textfields as $field) {
+            $response->$field = array_merge($oldresponse->$field, $response->$field);
+            $response->$field = array_unique($response->$field);
+            $response->$field  = implode(',', $response->$field);
+
+            if ($field=='correct' || $field=='wrong') {
+                $array = $oldresponse->$field;
+                $array = array_unique($array);
+                $oldresponse->$field  = implode(',', $array);
+                if ($response->$field<>$oldresponse->$field) {
+                    $value_has_changed = true;
+                }
+            }
+        }
+        if ($value_has_changed) {
+            $response->checks++;
+        }
+
+        // $response now holds amalgamation of all responses so far to this question
+
+        // set question score and weighting
+        if ($response->correct) {
+            switch ($quiztype) {
+                case HOTPOT_JCB:
+                    break;
+                case HOTPOT_JCLOZE:
+                    $strlen = strlen($response->correct);
+                    $response->score = 100*($strlen-($response->checks-1))/$strlen;
+                    $attempt->score += $response->score;
+                    break;
+                case HOTPOT_JCROSS:
+                    break;
+                case HOTPOT_JMATCH:
+                    break;
+                case HOTPOT_JMIX:
+                    break;
+                case HOTPOT_JQUIZ:
+                    switch ($questiontype) {
+                        case HOTPOT_JQUIZ_MULTICHOICE:
+                            $wrong = explode(',', $response->wrong);
+                            foreach ($wrong as $value) {
+                                if (isset($percents[$value])) {
+                                    $percent = $percents[$value];
+                                } else {
+                                    $percent = 0;
+                                }
+                            }
+                        case HOTPOT_JQUIZ_SHORTANSWER:
+                            $strlen = strlen($response->correct);
+                            $response->score = 100*($strlen-($response->checks-1))/$strlen;
+                            break;
+                        case HOTPOT_JQUIZ_MULTISELECT:
+                            if (isset($percents[$response->correct])) {
+                                $percent = $percents[$response->correct];
+                            } else {
+                                $percent = 0;
+                            }
+                            if ($a_max>0 && $response->checks>0 && $a_max>$response->checks) {
+                                $response->score = $percent*($a_max-($response->checks-1))/$a_max;
+                            }
+                            break;
+                    }
+                    $attempt->score += $response->score;
+                    break;
+            }
+        }
+
+        $fieldname = $HOTPOT_QUIZTYPE[$quiztype]."_q{$qq}_name";
+        $attempt->details .= "<field><fieldname>$fieldname</fieldname><fielddata>$questionname</fielddata></field>";
+
+        // encode $response fields as XML
+        $vars = get_object_vars($response);
+        foreach($vars as $name=>$value) {
+            if (!empty($value)) {
+                $fieldname = $HOTPOT_QUIZTYPE[$quiztype]."_q{$qq}_{$name}";
+                $attempt->details .= "<field><fieldname>$fieldname</fieldname><fielddata>$value</fielddata></field>";
+            }
+        }
+
+        $q++;
+    } // end main loop through $q(uestions)
+
+    // set attempt score
+    if ($q>0) {
+        switch ($quiztype) {
+            case HOTPOT_JCB:
+                break;
+            case HOTPOT_JCLOZE:
+                $attempt->score = floor($attempt->score / $q);
+                break;
+            case HOTPOT_JCROSS:
+                break;
+            case HOTPOT_JMATCH:
+                break;
+            case HOTPOT_JMIX:
+                break;
+            case HOTPOT_JQUIZ:
+                break;
+        }
+    }
+
+    if ($attempt->details) {
+        $attempt->details = '<?xml version="1.0"?><hpjsresult><fields>'.$attempt->details.'</fields></hpjsresult>';
+    }
+
+//  print "forcing status to in progress ..<br>\n";
+//  $attempt->status = HOTPOT_STATUS_INPROGRESS;
 }
 
 ?>
index 48585a715785326f63d9ca608257474d392f4bf2..a783402612ac7c17de90af59b716208a8be09956 100644 (file)
@@ -2,24 +2,24 @@
 <INPUT type="hidden" name="sesskey" value="<?PHP print isset($USER->sesskey) ? $USER->sesskey : '' ?>">
 
 <TABLE cellpadding="9" cellspacing="0">
-       <TR valign="top">
-               <TD align="right"><P>hotpot_showtimes:</TD>
-               <TD><?PHP 
-                       unset($choices);
-                       $choices["0"] = get_string("no");
-                       $choices["1"] = get_string("yes");
-                       choose_from_menu ($choices, "hotpot_showtimes", $CFG->hotpot_showtimes, "");
-               ?></TD>
-               <TD><?PHP print_string("configshowtimes", "hotpot") ?></TD>
-       </TR>
-       <TR valign=top>
-               <TD align="right"><P>hotpot_excelencodings:</TD>
-               <TD><INPUT name=hotpot_excelencodings type=text size=30 value="<?PHP p($CFG->hotpot_excelencodings) ?>"></TD>
-               <TD><?PHP print_string("configexcelencodings", "hotpot") ?></TD>
-       </TR>
-       <TR>
-               <TD colspan="3" align="center"><INPUT type="submit" value="<?PHP print_string("savechanges") ?>"></TD>
-       </TR>
+    <TR valign="top">
+        <TD align="right"><P>hotpot_showtimes:</TD>
+        <TD><?PHP 
+            unset($choices);
+            $choices["0"] = get_string("no");
+            $choices["1"] = get_string("yes");
+            choose_from_menu ($choices, "hotpot_showtimes", $CFG->hotpot_showtimes, "");
+        ?></TD>
+        <TD><?PHP print_string("configshowtimes", "hotpot") ?></TD>
+    </TR>
+    <TR valign=top>
+        <TD align="right"><P>hotpot_excelencodings:</TD>
+        <TD><INPUT name=hotpot_excelencodings type=text size=30 value="<?PHP p($CFG->hotpot_excelencodings) ?>"></TD>
+        <TD><?PHP print_string("configexcelencodings", "hotpot") ?></TD>
+    </TR>
+    <TR>
+        <TD colspan="3" align="center"><INPUT type="submit" value="<?PHP print_string("savechanges") ?>"></TD>
+    </TR>
 </TABLE>
 
 </FORM>
index 561f6260c5f7b191ce7eca99950a56f2d2815a4e..ab75b1e84f6eea1f7b5ae64b4355a5488bd42f87 100644 (file)
@@ -1,43 +1,43 @@
 <?PHP
 function hotpot_upgrade($oldversion) {
-       global $CFG;
-       $ok = true;
+    global $CFG;
+    $ok = true;
 
-       if ($oldversion < 2004021400) {
-               execute_sql(" ALTER TABLE `{$CFG->prefix}hotpot_events` ADD `starttime` INT(10) unsigned NOT NULL DEFAULT '0' AFTER `time`");
-               execute_sql(" ALTER TABLE `{$CFG->prefix}hotpot_events` ADD `endtime` INT(10) unsigned NOT NULL DEFAULT '0' AFTER `time`");
-       }
+    if ($oldversion < 2004021400) {
+        execute_sql(" ALTER TABLE `{$CFG->prefix}hotpot_events` ADD `starttime` INT(10) unsigned NOT NULL DEFAULT '0' AFTER `time`");
+        execute_sql(" ALTER TABLE `{$CFG->prefix}hotpot_events` ADD `endtime` INT(10) unsigned NOT NULL DEFAULT '0' AFTER `time`");
+    }
 
-       // set path to update functions
-       $update_to_v2 = "$CFG->dirroot/mod/hotpot/db/update_to_v2.php";
+    // set path to update functions
+    $update_to_v2 = "$CFG->dirroot/mod/hotpot/db/update_to_v2.php";
 
-       // update from HotPot v1 to HotPot v2
-       if ($oldversion < 2005031400) {
-               require_once $update_to_v2;
-               $ok = $ok && hotpot_update_to_v2_from_v1();
-       }
-       if ($oldversion < 2005090700) {
-               require_once $update_to_v2;
-               $ok = $ok && hotpot_update_to_v2_1();
-       }
-       if ($oldversion > 2005031419 && $oldversion < 2005090702) {
-               // update to from HotPot v2.1.0 or v2.1.1
-               require_once $update_to_v2;
-               $ok = $ok && hotpot_update_to_v2_1_2();
-       }
-       if ($oldversion < 2006042103) {
-               require_once $update_to_v2;
-               $ok = $ok && hotpot_update_to_v2_1_16();
-       }
-       if ($oldversion < 2006042601) {
-               require_once $update_to_v2;
-               $ok = $ok && hotpot_update_to_v2_1_17();
-       }
-       if ($oldversion < 2006042803) {
-               require_once $update_to_v2;
-               $ok = $ok && hotpot_update_to_v2_1_18();
-       }
+    // update from HotPot v1 to HotPot v2
+    if ($oldversion < 2005031400) {
+        require_once $update_to_v2;
+        $ok = $ok && hotpot_update_to_v2_from_v1();
+    }
+    if ($oldversion < 2005090700) {
+        require_once $update_to_v2;
+        $ok = $ok && hotpot_update_to_v2_1();
+    }
+    if ($oldversion > 2005031419 && $oldversion < 2005090702) {
+        // update to from HotPot v2.1.0 or v2.1.1
+        require_once $update_to_v2;
+        $ok = $ok && hotpot_update_to_v2_1_2();
+    }
+    if ($oldversion < 2006042103) {
+        require_once $update_to_v2;
+        $ok = $ok && hotpot_update_to_v2_1_16();
+    }
+    if ($oldversion < 2006042601) {
+        require_once $update_to_v2;
+        $ok = $ok && hotpot_update_to_v2_1_17();
+    }
+    if ($oldversion < 2006042803) {
+        require_once $update_to_v2;
+        $ok = $ok && hotpot_update_to_v2_1_18();
+    }
 
-       return $ok;
+    return $ok;
 }
 ?>
index 9c8eb457b743a0bd425d2e3f750198864a30997b..b8eb14a854de95f3f4a2b1481dca2996e5ad24dc 100644 (file)
@@ -3,7 +3,7 @@ function hotpot_update_to_v2_1_21() {
     global $CFG;
     $ok = true;
 
-       if (strtolower($CFG->dbtype)=='postgres7') {
+    if (strtolower($CFG->dbtype)=='postgres7') {
         // ensure setting of default values on certain fields
         // this was originally done in postgres7.php, but was found to be incompatible with PG7 :-(
         $table="hotpot";
@@ -36,1293 +36,1293 @@ function hotpot_update_to_v2_1_21() {
     return $ok;
 }
 function hotpot_update_to_v2_1_18() {
-       $ok = true;
+    $ok = true;
 
-       // remove all orphan records (there shouldn't be any, but if there are they can mess up the utfdbmigrate)
+    // remove all orphan records (there shouldn't be any, but if there are they can mess up the utfdbmigrate)
 
-       $ok = $ok && hotpot_remove_orphans('hotpot_attempts', 'hotpot', 'hotpot');
-       $ok = $ok && hotpot_remove_orphans('hotpot_questions', 'hotpot', 'hotpot');
-       $ok = $ok && hotpot_remove_orphans('hotpot_responses', 'attempt', 'hotpot_attempts');
-       $ok = $ok && hotpot_remove_orphans('hotpot_responses', 'question', 'hotpot_questions');
-       $ok = $ok && hotpot_remove_orphans('hotpot_details', 'attempt', 'hotpot_attempts');
+    $ok = $ok && hotpot_remove_orphans('hotpot_attempts', 'hotpot', 'hotpot');
+    $ok = $ok && hotpot_remove_orphans('hotpot_questions', 'hotpot', 'hotpot');
+    $ok = $ok && hotpot_remove_orphans('hotpot_responses', 'attempt', 'hotpot_attempts');
+    $ok = $ok && hotpot_remove_orphans('hotpot_responses', 'question', 'hotpot_questions');
+    $ok = $ok && hotpot_remove_orphans('hotpot_details', 'attempt', 'hotpot_attempts');
 
-       // allow negative weighting and scores
+    // allow negative weighting and scores
 
-       $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'weighting', '6', false);
-       $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'score', '6', false);
+    $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'weighting', '6', false);
+    $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'score', '6', false);
 
-       return $ok;
+    return $ok;
 }
 function hotpot_remove_orphans($secondarytable, $secondarykeyfield, $primarytable, $primarykeyfield='id') {
-       global $CFG,$db;
-       $ok = true;
+    global $CFG,$db;
+    $ok = true;
 
-       // save and switch off SQL message echo
-       $debug = $db->debug;
-       $db->debug = false;
+    // save and switch off SQL message echo
+    $debug = $db->debug;
+    $db->debug = false;
 
-       $records = get_records_sql("
-               SELECT 
-                       t2.$secondarykeyfield, t2.$secondarykeyfield
-               FROM 
-                       {$CFG->prefix}$secondarytable AS t2 LEFT JOIN {$CFG->prefix}$primarytable AS t1 
-                       ON (t2.$secondarykeyfield = t1.id)
-               WHERE 
-                       t1.$primarykeyfield IS NULL
-       ");
+    $records = get_records_sql("
+        SELECT 
+            t2.$secondarykeyfield, t2.$secondarykeyfield
+        FROM 
+            {$CFG->prefix}$secondarytable AS t2 LEFT JOIN {$CFG->prefix}$primarytable AS t1 
+            ON (t2.$secondarykeyfield = t1.id)
+        WHERE 
+            t1.$primarykeyfield IS NULL
+    ");
 
-       // restore SQL message echo setting
-       $db->debug = $debug;
+    // restore SQL message echo setting
+    $db->debug = $debug;
 
-       if ($records) {
-               $keys = implode(',', array_keys($records));
-               print "removing orphan record(s) from {$CFG->prefix}$secondarytable<br>";
-               $ok = $ok && execute_sql("DELETE FROM {$CFG->prefix}$secondarytable WHERE $secondarykeyfield IN ($keys)");
-       }
+    if ($records) {
+        $keys = implode(',', array_keys($records));
+        print "removing orphan record(s) from {$CFG->prefix}$secondarytable<br>";
+        $ok = $ok && execute_sql("DELETE FROM {$CFG->prefix}$secondarytable WHERE $secondarykeyfield IN ($keys)");
+    }
 
-       return $ok;
+    return $ok;
 }
 function hotpot_update_to_v2_1_17() {
-       global $CFG;
-       $ok = true;
+    global $CFG;
+    $ok = true;
 
-       // convert and disable null values on certain numeric fields
+    // convert and disable null values on certain numeric fields
 
-       $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'starttime', '10');
-       $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'endtime', '10');
-       $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'score', '6');
-       $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'penalties',  '6');
-       $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'timestart', '10');
-       $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'timefinish', '10');
-       $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'clickreportid', '10');
+    $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'starttime', '10');
+    $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'endtime', '10');
+    $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'score', '6');
+    $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'penalties',  '6');
+    $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'timestart', '10');
+    $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'timefinish', '10');
+    $ok = $ok && hotpot_denull_int_field('hotpot_attempts', 'clickreportid', '10');
 
-       $ok = $ok && hotpot_denull_int_field('hotpot_questions', 'type', '4');
-       $ok = $ok && hotpot_denull_int_field('hotpot_questions', 'text', '10');
+    $ok = $ok && hotpot_denull_int_field('hotpot_questions', 'type', '4');
+    $ok = $ok && hotpot_denull_int_field('hotpot_questions', 'text', '10');
 
-       $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'weighting', '6', false);
-       $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'score', '6', false);
-       $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'hints', '6');
-       $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'clues', '6');
-       $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'checks', '6');
-       return $ok;
+    $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'weighting', '6', false);
+    $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'score', '6', false);
+    $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'hints', '6');
+    $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'clues', '6');
+    $ok = $ok && hotpot_denull_int_field('hotpot_responses', 'checks', '6');
+    return $ok;
 }
 function hotpot_denull_int_field($table, $field, $size, $unsigned=true) {
-       global $CFG;
-       $ok = true;
+    global $CFG;
+    $ok = true;
 
-       $ok = $ok && execute_sql("UPDATE {$CFG->prefix}$table SET $field=0 WHERE $field IS NULL", false);
-       if ($unsigned) {
-               $ok = $ok && execute_sql("UPDATE {$CFG->prefix}$table SET $field=0 WHERE $field<0", false);
-       }
-       $ok = $ok && hotpot_db_update_field_type($table, $field, $field, 'INTEGER', $size, $unsigned, 'NOT NULL', 0);
+    $ok = $ok && execute_sql("UPDATE {$CFG->prefix}$table SET $field=0 WHERE $field IS NULL", false);
+    if ($unsigned) {
+        $ok = $ok && execute_sql("UPDATE {$CFG->prefix}$table SET $field=0 WHERE $field<0", false);
+    }
+    $ok = $ok && hotpot_db_update_field_type($table, $field, $field, 'INTEGER', $size, $unsigned, 'NOT NULL', 0);
 
-       return $ok;
+    return $ok;
 }
 function hotpot_update_to_v2_1_16() {
-       global $CFG;
-       $ok = true;
+    global $CFG;
+    $ok = true;
 
-       // settings for the "hotpot_questions_name_idx" index
-       $length = 20;
-       $field = 'name';
-       $table = 'hotpot_questions';
-       $index = "{$table}_{$field}_idx";
+    // settings for the "hotpot_questions_name_idx" index
+    $length = 20;
+    $field = 'name';
+    $table = 'hotpot_questions';
+    $index = "{$table}_{$field}_idx";
 
-       // remove the index
-       hotpot_db_delete_index("{$CFG->prefix}$table", $index);
-       hotpot_db_delete_index("{$CFG->prefix}$table", "{$CFG->prefix}$index");
+    // remove the index
+    hotpot_db_delete_index("{$CFG->prefix}$table", $index);
+    hotpot_db_delete_index("{$CFG->prefix}$table", "{$CFG->prefix}$index");
 
-       // make sure type of 'name' is a text field (not varchar 255)
-       $ok = $ok && hotpot_db_update_field_type($table, $field, $field, 'TEXT',   '',  '', 'NOT NULL', '');
+    // make sure type of 'name' is a text field (not varchar 255)
+    $ok = $ok && hotpot_db_update_field_type($table, $field, $field, 'TEXT',   '',  '', 'NOT NULL', '');
 
-       // restore the index
-       $ok = $ok && hotpot_db_add_index($table, $field, $length);
+    // restore the index
+    $ok = $ok && hotpot_db_add_index($table, $field, $length);
 
-       if (strtolower($CFG->dbtype)=='mysql') {
+    if (strtolower($CFG->dbtype)=='mysql') {
 
-               // set default values on certain VARCHAR(255) fields
-               $varchar_fields = array(
-                       'hotpot.studentfeedbackurl',
-                       'hotpot_responses.correct',
-                       'hotpot_responses.wrong',
-                       'hotpot_responses.ignored'
-               );
-               foreach ($varchar_fields as $varchar_field) {
-                       list ($table, $field) = explode('.', $varchar_field);
-                       execute_sql("UPDATE {$CFG->prefix}$table SET $field='' WHERE $field IS NULL");
-                       $ok = $ok && hotpot_db_update_field_type($table, $field, $field, 'VARCHAR', 255, '', 'NOT NULL', '');
-               }
+        // set default values on certain VARCHAR(255) fields
+        $varchar_fields = array(
+            'hotpot.studentfeedbackurl',
+            'hotpot_responses.correct',
+            'hotpot_responses.wrong',
+            'hotpot_responses.ignored'
+        );
+        foreach ($varchar_fields as $varchar_field) {
+            list ($table, $field) = explode('.', $varchar_field);
+            execute_sql("UPDATE {$CFG->prefix}$table SET $field='' WHERE $field IS NULL");
+            $ok = $ok && hotpot_db_update_field_type($table, $field, $field, 'VARCHAR', 255, '', 'NOT NULL', '');
+        }
 
-               // remove $CFG->prefix from all index names
-               $ok = $ok && hotpot_index_remove_prefix('hotpot_attempts', 'hotpot');
-               $ok = $ok && hotpot_index_remove_prefix('hotpot_attempts', 'userid');
-               $ok = $ok && hotpot_index_remove_prefix('hotpot_details', 'attempt');
-               $ok = $ok && hotpot_index_remove_prefix('hotpot_questions', 'hotpot');
-               //$ok = $ok && hotpot_index_remove_prefix('hotpot_questions', 'name', 20);
-               $ok = $ok && hotpot_index_remove_prefix('hotpot_responses', 'attempt');
-               $ok = $ok && hotpot_index_remove_prefix('hotpot_responses', 'question');
-               $ok = $ok && hotpot_index_remove_prefix('hotpot_strings', 'string', 20);
-       }
-       return $ok;
+        // remove $CFG->prefix from all index names
+        $ok = $ok && hotpot_index_remove_prefix('hotpot_attempts', 'hotpot');
+        $ok = $ok && hotpot_index_remove_prefix('hotpot_attempts', 'userid');
+        $ok = $ok && hotpot_index_remove_prefix('hotpot_details', 'attempt');
+        $ok = $ok && hotpot_index_remove_prefix('hotpot_questions', 'hotpot');
+        //$ok = $ok && hotpot_index_remove_prefix('hotpot_questions', 'name', 20);
+        $ok = $ok && hotpot_index_remove_prefix('hotpot_responses', 'attempt');
+        $ok = $ok && hotpot_index_remove_prefix('hotpot_responses', 'question');
+        $ok = $ok && hotpot_index_remove_prefix('hotpot_strings', 'string', 20);
+    }
+    return $ok;
 }
 function hotpot_index_remove_prefix($table, $field, $length=0) {
-       global $CFG;
-       $index = "{$table}_{$field}_idx";
-       hotpot_db_delete_index("{$CFG->prefix}$table", "{$CFG->prefix}$index");
-       hotpot_db_delete_index("{$CFG->prefix}$table", $index);
-       return hotpot_db_add_index($table, $field, $length);
+    global $CFG;
+    $index = "{$table}_{$field}_idx";
+    hotpot_db_delete_index("{$CFG->prefix}$table", "{$CFG->prefix}$index");
+    hotpot_db_delete_index("{$CFG->prefix}$table", $index);
+    return hotpot_db_add_index($table, $field, $length);
 }
 
 function hotpot_update_to_v2_1_8() {
-       global $CFG;
-       $ok = true;
-       if (strtolower($CFG->dbtype)=='postgres7') {
-               // add, delete and rename certain fields and indexes
-               // that were not correctly setup by postgres7.sql
+    global $CFG;
+    $ok = true;
+    if (strtolower($CFG->dbtype)=='postgres7') {
+        // add, delete and rename certain fields and indexes
+        // that were not correctly setup by postgres7.sql
 
-               // hotpot
-               $table = 'hotpot';
-               if (hotpot_db_field_exists($table, 'microreporting')) {
-                       $ok = $ok && hotpot_db_update_field_type($table, 'microreporting', 'clickreporting', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', '0');
-               }
-       }
-       return $ok;
+        // hotpot
+        $table = 'hotpot';
+        if (hotpot_db_field_exists($table, 'microreporting')) {
+            $ok = $ok && hotpot_db_update_field_type($table, 'microreporting', 'clickreporting', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', '0');
+        }
+    }
+    return $ok;
 }
 function hotpot_update_to_v2_1_6() {
-       global $CFG;
-       $ok = true;
+    global $CFG;
+    $ok = true;
 
-       if (strtolower($CFG->dbtype)=='postgres7') {
-               // add, delete and rename certain fields and indexes
-               // that were not correctly setup by postgres7.sql
+    if (strtolower($CFG->dbtype)=='postgres7') {
+        // add, delete and rename certain fields and indexes
+        // that were not correctly setup by postgres7.sql
 
-               // hotpot
-               $table = 'hotpot';
-               if (hotpot_db_field_exists($table, 'studentfeedback') && !hotpot_db_field_exists($table, 'studentfeedbackurl')) {
-                       $ok = $ok && hotpot_db_update_field_type($table, 'studentfeedback', 'studentfeedbackurl', 'VARCHAR', 255, '', 'NULL');
-                       $ok = $ok && hotpot_db_update_field_type($table, '', 'studentfeedback', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', '0');
-               }
+        // hotpot
+        $table = 'hotpot';
+        if (hotpot_db_field_exists($table, 'studentfeedback') && !hotpot_db_field_exists($table, 'studentfeedbackurl')) {
+            $ok = $ok && hotpot_db_update_field_type($table, 'studentfeedback', 'studentfeedbackurl', 'VARCHAR', 255, '', 'NULL');
+            $ok = $ok && hotpot_db_update_field_type($table, '', 'studentfeedback', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', '0');
+        }
 
-               // hotpot_attempts
-               $table = 'hotpot_attempts';
-               $ok = $ok && hotpot_db_remove_field($table, 'groupid');
-               if (hotpot_db_field_exists($table, 'microreportid') && !hotpot_db_field_exists($table, 'clickreportid')) {
-                       $ok = $ok && hotpot_db_update_field_type($table, 'microreportid', 'clickreportid', 'INTEGER', 10, 'UNSIGNED', 'NULL');
-               }
+        // hotpot_attempts
+        $table = 'hotpot_attempts';
+        $ok = $ok && hotpot_db_remove_field($table, 'groupid');
+        if (hotpot_db_field_exists($table, 'microreportid') && !hotpot_db_field_exists($table, 'clickreportid')) {
+            $ok = $ok && hotpot_db_update_field_type($table, 'microreportid', 'clickreportid', 'INTEGER', 10, 'UNSIGNED', 'NULL');
+        }
 
-               // hotpot_questions (add index on question "name")
-               $table = 'hotpot_questions';
-               $field = 'name';
-               $index = "{$table}_{$field}_idx";
-               if (!hotpot_db_index_exists("{$CFG->prefix}$table", "{$CFG->prefix}$index")) {
-                       hotpot_db_add_index($table, $field, '20');
-               }
+        // hotpot_questions (add index on question "name")
+        $table = 'hotpot_questions';
+        $field = 'name';
+        $index = "{$table}_{$field}_idx";
+        if (!hotpot_db_index_exists("{$CFG->prefix}$table", "{$CFG->prefix}$index")) {
+            hotpot_db_add_index($table, $field, '20');
+        }
 
-               // hotpot_strings (add index on "string")
-               $table = "hotpot_strings";
-               $field = 'string';
-               $index = "{$table}_{$field}_idx";
-               if (!hotpot_db_index_exists("{$CFG->prefix}$table", "{$CFG->prefix}$index")) {
-                       hotpot_db_add_index($table, $field, '20');
-               }
-       }
+        // hotpot_strings (add index on "string")
+        $table = "hotpot_strings";
+        $field = 'string';
+        $index = "{$table}_{$field}_idx";
+        if (!hotpot_db_index_exists("{$CFG->prefix}$table", "{$CFG->prefix}$index")) {
+            hotpot_db_add_index($table, $field, '20');
+        }
+    }
 
-       return $ok;
+    return $ok;
 }
 function hotpot_update_to_v2_1_2() {
-       global $CFG, $db;
-       $ok = true;
+    global $CFG, $db;
+    $ok = true;
 
-       // save and switch off SQL message echo
-       $debug = $db->debug;
-       $db->debug = false;
+    // save and switch off SQL message echo
+    $debug = $db->debug;
+    $db->debug = false;
 
-       // extract info about attempts by each user on each hotpot (cases where 
-       // the user has only one attempt, or no "in progess" attempt are ignored)
-       $rs = $db->Execute("
-               SELECT userid, hotpot, COUNT(*), MIN(status)
-               FROM {$CFG->prefix}hotpot_attempts
-               GROUP BY userid, hotpot
-               HAVING COUNT(*)>1 AND MIN(status)=1
-       ");
-       if ($rs && $rs->RecordCount()) {
-               $records = $rs->GetArray();
+    // extract info about attempts by each user on each hotpot (cases where 
+    // the user has only one attempt, or no "in progess" attempt are ignored)
+    $rs = $db->Execute("
+        SELECT userid, hotpot, COUNT(*), MIN(status)
+        FROM {$CFG->prefix}hotpot_attempts
+        GROUP BY userid, hotpot
+        HAVING COUNT(*)>1 AND MIN(status)=1
+    ");
+    if ($rs && $rs->RecordCount()) {
+        $records = $rs->GetArray();
 
-               // start message to browser
-               print "adjusting status of ".count($records)." &quot;in progress&quot; attempts ... ";
+        // start message to browser
+        print "adjusting status of ".count($records)." &quot;in progress&quot; attempts ... ";
 
-               // loop through records
-               foreach ($records as $record) {
+        // loop through records
+        foreach ($records as $record) {
 
-                       // get all attempts by this user at this hotpot
-                       $attempts = get_records_sql("
-                               SELECT id, userid, hotpot, score, timestart, timefinish, status 
-                               FROM {$CFG->prefix}hotpot_attempts 
-                               WHERE userid = ".$record['userid']." AND hotpot=".$record['hotpot']."
-                               ORDER BY timestart DESC, id DESC
-                       ");
+            // get all attempts by this user at this hotpot
+            $attempts = get_records_sql("
+                SELECT id, userid, hotpot, score, timestart, timefinish, status 
+                FROM {$CFG->prefix}hotpot_attempts 
+                WHERE userid = ".$record['userid']." AND hotpot=".$record['hotpot']."
+                ORDER BY timestart DESC, id DESC
+            ");
 
-                       unset($previous_timestart);
+            unset($previous_timestart);
 
-                       foreach ($attempts as $attempt) {
-                               // if this attempt has a status of "in progress" and is not 
-                               // the most recent one in the group, set the status to "abandoned"
-                               if ($attempt->status==1 && isset($previous_timestart)) {
-                                       $values = 'status=3';
-                                       if (empty($attempt->score)) {
-                                               $values .= ',score=0';
-                                       }
-                                       if (empty($attempt->timefinish)) {
-                                               $values .= ",timefinish=$previous_timestart";
-                                       }
-                                       execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET $values WHERE id=$attempt->id", false);
-                                       print ".";
-                                       hotpot_flush(300);
-                               }
-                               $previous_timestart = $attempt->timestart;
-                       } // end foreach $attempts
-               } // end foreach $records
+            foreach ($attempts as $attempt) {
+                // if this attempt has a status of "in progress" and is not 
+                // the most recent one in the group, set the status to "abandoned"
+                if ($attempt->status==1 && isset($previous_timestart)) {
+                    $values = 'status=3';
+                    if (empty($attempt->score)) {
+                        $values .= ',score=0';
+                    }
+                    if (empty($attempt->timefinish)) {
+                        $values .= ",timefinish=$previous_timestart";
+                    }
+                    execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET $values WHERE id=$attempt->id", false);
+                    print ".";
+                    hotpot_flush(300);
+                }
+                $previous_timestart = $attempt->timestart;
+            } // end foreach $attempts
+        } // end foreach $records
 
-               // finish message to browser
-               print $ok ? get_string('success') : 'failed';
-               print "<br />\n";
-       }
+        // finish message to browser
+        print $ok ? get_string('success') : 'failed';
+        print "<br />\n";
+    }
 
-       // restore SQL message echo setting
-       $db->debug = $debug;
+    // restore SQL message echo setting
+    $db->debug = $debug;
 
-       return $ok;
+    return $ok;
 }
 function hotpot_update_to_v2_1() {
-       global $CFG, $db;
-       $ok = true;
-       // hotpot_questions: reduce size of "type" field to "4"
-       $ok = $ok && hotpot_db_update_field_type('hotpot_questions', 'type', 'type', 'INTEGER', 4,  'UNSIGNED', 'NULL');
-       // hotpot_questions: change type of "name" field to "text"
-       $ok = $ok && hotpot_db_update_field_type('hotpot_questions', 'name', 'name', 'TEXT',   '',  '', 'NOT NULL', '');
-       // hotpot_questions: nullify empty and non-numeric (shouldn't be any) values in "text" field
-       switch (strtolower($CFG->dbtype)) {
-               case 'mysql' : 
-                       $NOT_REGEXP = 'NOT REGEXP';
-               break;
-               case 'postgres7' :
-                       $NOT_REGEXP = '!~';
-               break;
-               default:
-                       $NOT_REGEXP = '';
-               break;
-       }
-       if ($NOT_REGEXP) {
-               $ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_questions SET text=NULL WHERE text $NOT_REGEXP '^[0-9]+$'");
-       }
-       // hotpot_questions: change type of "text" field to "INT(10)"
-       $ok = $ok && hotpot_db_update_field_type('hotpot_questions', 'text', 'text', 'INTEGER', 10, 'UNSIGNED', 'NULL');
-       // hotpot_attempts
-       // hotpot_attempts: move "details" to separate table
-       $table = 'hotpot_details';
-       if (hotpot_db_table_exists($table)) {
-               // do nothing
-       } else {
-               $ok = $ok && hotpot_create_table($table);
-               switch (strtolower($CFG->dbtype)) {
-                       case 'mysql' : 
-                       case 'postgres7' :
-                               $sql = "
-                                       INSERT INTO {$CFG->prefix}$table (attempt, details) 
-                                       SELECT a.id AS attempt, a.details AS details
-                                               FROM {$CFG->prefix}hotpot_attempts AS a
-                                               WHERE 
-                                                       a.details IS NOT NULL AND a.details <> ''
-                                                       AND a.details LIKE '<?xml%' AND a.details LIKE '%</hpjsresult>'
-                               ";
-                       break;
-                       default:
-                               $sql = '';
-                       break;
-               }
-               if ($sql) {
-                       $ok = $ok && execute_sql($sql);
-               }
-       }
-       // hotpot_attempts: remove the "details" field
-       $ok = $ok && hotpot_db_remove_field('hotpot_attempts', 'details');
-       // hotpot_attempts: create and set status field (1=in-progress, 2=timed-out, 3=abandoned, 4=completed)
-       $ok = $ok && hotpot_db_update_field_type('hotpot_attempts', '', 'status', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 1);
-       $ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=1 WHERE timefinish=0 AND SCORE IS NULL");
-       $ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=3 WHERE timefinish>0 AND SCORE IS NULL");
-       $ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=4 WHERE timefinish>0 AND SCORE IS NOT NULL");
-       // hotpot_attempts: create and set clickreport fields
-       $ok = $ok && hotpot_db_update_field_type('hotpot', '', 'clickreporting', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
-       $ok = $ok && hotpot_db_update_field_type('hotpot_attempts', '', 'clickreportid', 'INTEGER', 10, 'UNSIGNED', 'NULL');
-       $ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET clickreportid=id WHERE clickreportid IS NULL");
-       // hotpot_attempts: create and set studentfeedback field (0=none, 1=formmail, 2=moodleforum, 3=moodlemessaging)
-       $ok = $ok && hotpot_db_update_field_type('hotpot', '', 'studentfeedback', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', '0');
-       $ok = $ok && hotpot_db_update_field_type('hotpot', '', 'studentfeedbackurl', 'VARCHAR', 255, '', 'NULL');
-       // add indexes
-       $ok = $ok && hotpot_db_add_index('hotpot_attempts', 'hotpot');
-       $ok = $ok && hotpot_db_add_index('hotpot_attempts', 'userid');
-       $ok = $ok && hotpot_db_add_index('hotpot_details', 'attempt');
-       $ok = $ok && hotpot_db_add_index('hotpot_questions', 'name', 20);
-       $ok = $ok && hotpot_db_add_index('hotpot_questions', 'hotpot');
-       $ok = $ok && hotpot_db_add_index('hotpot_responses', 'attempt');
-       $ok = $ok && hotpot_db_add_index('hotpot_responses', 'question');
-       $ok = $ok && hotpot_db_add_index('hotpot_strings', 'string', 20);
-       // hotpot_string: correct double-encoded HTML entities
-       $ok = $ok && execute_sql("
-               UPDATE {$CFG->prefix}hotpot_strings 
-               SET string = REPLACE(string, '&amp;','&') 
-               WHERE string LIKE '%&amp;#%' 
-               AND (string LIKE '<' OR string LIKE '>')
-       ");
-       // hotpot_question: remove questions which refer to deleted hotpots
-       if ($ok) {
-               // try and get all hotpot records
-               if ($records = get_records('hotpot')) {
-                       $ids = implode(',', array_keys($records));
-                       $sql = "DELETE FROM {$CFG->prefix}hotpot_questions WHERE hotpot NOT IN ($ids)";
-               } else {
-                       // remove all question records (because there are no valid hotpot ids)
-                       $sql = "TRUNCATE {$CFG->prefix}hotpot_questions";
-               }
-               print "Removing unused question records ...";
-               execute_sql($sql);
-       }
-       if ($ok) {
-               // remove old 'v6' templates folder (replaced by 'template' folder)
-               $ds = DIRECTORY_SEPARATOR;
-               $dir = "mod{$ds}hotpot{$ds}v6";
-               print "removing old templates ($dir) ... ";
-               if (hotpot_rm("$CFG->dirroot{$ds}$dir", false)) {
-                       print get_string('success');
-               } else {
-                       print "failed<br>Please remove '$CFG->dirroot{$ds}$dir' manually";
-               }
-               print "<br />\n";
-       }
-       return $ok;
+    global $CFG, $db;
+    $ok = true;
+    // hotpot_questions: reduce size of "type" field to "4"
+    $ok = $ok && hotpot_db_update_field_type('hotpot_questions', 'type', 'type', 'INTEGER', 4,  'UNSIGNED', 'NULL');
+    // hotpot_questions: change type of "name" field to "text"
+    $ok = $ok && hotpot_db_update_field_type('hotpot_questions', 'name', 'name', 'TEXT',   '',  '', 'NOT NULL', '');
+    // hotpot_questions: nullify empty and non-numeric (shouldn't be any) values in "text" field
+    switch (strtolower($CFG->dbtype)) {
+        case 'mysql' : 
+            $NOT_REGEXP = 'NOT REGEXP';
+        break;
+        case 'postgres7' :
+            $NOT_REGEXP = '!~';
+        break;
+        default:
+            $NOT_REGEXP = '';
+        break;
+    }
+    if ($NOT_REGEXP) {
+        $ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_questions SET text=NULL WHERE text $NOT_REGEXP '^[0-9]+$'");
+    }
+    // hotpot_questions: change type of "text" field to "INT(10)"
+    $ok = $ok && hotpot_db_update_field_type('hotpot_questions', 'text', 'text', 'INTEGER', 10, 'UNSIGNED', 'NULL');
+    // hotpot_attempts
+    // hotpot_attempts: move "details" to separate table
+    $table = 'hotpot_details';
+    if (hotpot_db_table_exists($table)) {
+        // do nothing
+    } else {
+        $ok = $ok && hotpot_create_table($table);
+        switch (strtolower($CFG->dbtype)) {
+            case 'mysql' : 
+            case 'postgres7' :
+                $sql = "
+                    INSERT INTO {$CFG->prefix}$table (attempt, details) 
+                    SELECT a.id AS attempt, a.details AS details
+                        FROM {$CFG->prefix}hotpot_attempts AS a
+                        WHERE 
+                            a.details IS NOT NULL AND a.details <> ''
+                            AND a.details LIKE '<?xml%' AND a.details LIKE '%</hpjsresult>'
+                ";
+            break;
+            default:
+                $sql = '';
+            break;
+        }
+        if ($sql) {
+            $ok = $ok && execute_sql($sql);
+        }
+    }
+    // hotpot_attempts: remove the "details" field
+    $ok = $ok && hotpot_db_remove_field('hotpot_attempts', 'details');
+    // hotpot_attempts: create and set status field (1=in-progress, 2=timed-out, 3=abandoned, 4=completed)
+    $ok = $ok && hotpot_db_update_field_type('hotpot_attempts', '', 'status', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 1);
+    $ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=1 WHERE timefinish=0 AND SCORE IS NULL");
+    $ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=3 WHERE timefinish>0 AND SCORE IS NULL");
+    $ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET status=4 WHERE timefinish>0 AND SCORE IS NOT NULL");
+    // hotpot_attempts: create and set clickreport fields
+    $ok = $ok && hotpot_db_update_field_type('hotpot', '', 'clickreporting', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
+    $ok = $ok && hotpot_db_update_field_type('hotpot_attempts', '', 'clickreportid', 'INTEGER', 10, 'UNSIGNED', 'NULL');
+    $ok = $ok && execute_sql("UPDATE {$CFG->prefix}hotpot_attempts SET clickreportid=id WHERE clickreportid IS NULL");
+    // hotpot_attempts: create and set studentfeedback field (0=none, 1=formmail, 2=moodleforum, 3=moodlemessaging)
+    $ok = $ok && hotpot_db_update_field_type('hotpot', '', 'studentfeedback', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', '0');
+    $ok = $ok && hotpot_db_update_field_type('hotpot', '', 'studentfeedbackurl', 'VARCHAR', 255, '', 'NULL');
+    // add indexes
+    $ok = $ok && hotpot_db_add_index('hotpot_attempts', 'hotpot');
+    $ok = $ok && hotpot_db_add_index('hotpot_attempts', 'userid');
+    $ok = $ok && hotpot_db_add_index('hotpot_details', 'attempt');
+    $ok = $ok && hotpot_db_add_index('hotpot_questions', 'name', 20);
+    $ok = $ok && hotpot_db_add_index('hotpot_questions', 'hotpot');
+    $ok = $ok && hotpot_db_add_index('hotpot_responses', 'attempt');
+    $ok = $ok && hotpot_db_add_index('hotpot_responses', 'question');
+    $ok = $ok && hotpot_db_add_index('hotpot_strings', 'string', 20);
+    // hotpot_string: correct double-encoded HTML entities
+    $ok = $ok && execute_sql("
+        UPDATE {$CFG->prefix}hotpot_strings 
+        SET string = REPLACE(string, '&amp;','&') 
+        WHERE string LIKE '%&amp;#%' 
+        AND (string LIKE '<' OR string LIKE '>')
+    ");
+    // hotpot_question: remove questions which refer to deleted hotpots
+    if ($ok) {
+        // try and get all hotpot records
+        if ($records = get_records('hotpot')) {
+            $ids = implode(',', array_keys($records));
+            $sql = "DELETE FROM {$CFG->prefix}hotpot_questions WHERE hotpot NOT IN ($ids)";
+        } else {
+            // remove all question records (because there are no valid hotpot ids)
+            $sql = "TRUNCATE {$CFG->prefix}hotpot_questions";
+        }
+        print "Removing unused question records ...";
+        execute_sql($sql);
+    }
+    if ($ok) {
+        // remove old 'v6' templates folder (replaced by 'template' folder)
+        $ds = DIRECTORY_SEPARATOR;
+        $dir = "mod{$ds}hotpot{$ds}v6";
+        print "removing old templates ($dir) ... ";
+        if (hotpot_rm("$CFG->dirroot{$ds}$dir", false)) {
+            print get_string('success');
+        } else {
+            print "failed<br>Please remove '$CFG->dirroot{$ds}$dir' manually";
+        }
+        print "<br />\n";
+    }
+    return $ok;
 }
 function hotpot_update_to_v2_from_v1() {
-       global $CFG;
-       $ok = true;
-       // remove, alter and add fields in database
-       $table = 'hotpot';
-       if (hotpot_db_table_exists($table)) {
-               $ok = $ok && hotpot_update_fields($table);
-       } else {
-               $ok = $ok && hotpot_create_table($table);
-       }
-       $table = 'hotpot_attempts';
-       $oldtable = 'hotpot_events';
-       if (hotpot_db_table_exists($oldtable)) {
-               $ok = $ok && hotpot_update_fields($oldtable);
-               $ok = $ok && hotpot_db_append_table($oldtable, $table);
-       } else {
-               $ok = $ok && hotpot_create_table($table);
-       }
-       // create new tables (from mysql.sql)
-       $ok = $ok && hotpot_create_table('hotpot_questions');
-       $ok = $ok && hotpot_create_table('hotpot_responses');
-       $ok = $ok && hotpot_create_table('hotpot_strings');
-       // remove redundant scripts
-       $files = array('coursefiles.php', 'details.php', 'dummy.html', 'hotpot.php', 'hotpot2db.php');
-       foreach ($files as $file) {
-               $filepath = "$CFG->dirroot/mod/hotpot/$file";
-               if (file_exists($filepath)) {
-                       @unlink($filepath); // don't worry about errors
-               }
-       }
-       return $ok;
+    global $CFG;
+    $ok = true;
+    // remove, alter and add fields in database
+    $table = 'hotpot';
+    if (hotpot_db_table_exists($table)) {
+        $ok = $ok && hotpot_update_fields($table);
+    } else {
+        $ok = $ok && hotpot_create_table($table);
+    }
+    $table = 'hotpot_attempts';
+    $oldtable = 'hotpot_events';
+    if (hotpot_db_table_exists($oldtable)) {
+        $ok = $ok && hotpot_update_fields($oldtable);
+        $ok = $ok && hotpot_db_append_table($oldtable, $table);
+    } else {
+        $ok = $ok && hotpot_create_table($table);
+    }
+    // create new tables (from mysql.sql)
+    $ok = $ok && hotpot_create_table('hotpot_questions');
+    $ok = $ok && hotpot_create_table('hotpot_responses');
+    $ok = $ok && hotpot_create_table('hotpot_strings');
+    // remove redundant scripts
+    $files = array('coursefiles.php', 'details.php', 'dummy.html', 'hotpot.php', 'hotpot2db.php');
+    foreach ($files as $file) {
+        $filepath = "$CFG->dirroot/mod/hotpot/$file";
+        if (file_exists($filepath)) {
+            @unlink($filepath); // don't worry about errors
+        }
+    }
+    return $ok;
 }
 function hotpot_update_to_v2_from_hotpotatoes() {
-       global $CFG;
-       $ok = true; // hope for the best!
-       // check we have the minimum required hotpot module
-       $minimum = 2005031400; 
-       $module = get_record("modules", "name", "hotpot");
-       if (empty($module) || $module->version<$minimum) {
-               if ($module) {
-                       print ("<p>The update to the HotPotatoes module requires at least version $minimum of the HotPot module.</p>");
-                       print ("<p>The current version of the HotPot module on this site is $module->version.</p>");
-               }
-               print ("<p>Please install the latest version of the HotPot module and then try the update again.</p>");
-               $ok = false;
-       } else {
-               // arrays to map foreign keys
-               $new = array();
-               $new['hotpot'] = array();
-               $new['attempt'] = array();
-               $new['question'] = array();
-               $new['string'] = array();
-               // save and switch off SQL message echo
-               global $db;
-               $debug = $db->debug;
-               $db->debug = false;
-               // import hotpotatoes (and save old ids)
-               $ok = $ok && hotpot_update_fields('hotpotatoes');
-               $ok = $ok && hotpot_transfer_records('hotpotatoes', 'hotpot', array(), 'hotpot', $new);
-               // update course modules and logs
-               $ok = $ok && hotpot_update_course_modules('hotpotatoes', 'hotpot', $new);
-               // import hotpotatoes_strings (and save old ids)
-               $ok = $ok && hotpot_transfer_records('hotpotatoes_strings', 'hotpot_strings', array(), 'string', $new);
-               // import hotpotatoes_attempts (and save old ids)
-               $ok = $ok && hotpot_transfer_records('hotpotatoes_attempts', 'hotpot_attempts', array('hotpotatoes'=>'hotpot'), 'attempt', $new);
-               // import hotpotatoes_questions (and save old ids)
-               $ok = $ok && hotpot_transfer_records('hotpotatoes_questions', 'hotpot_questions', array('hotpotatoes'=>'hotpot'), 'question', $new);
-               // import hotpotatoes_responses
-               $ok = $ok && hotpot_transfer_records('hotpotatoes_responses', 'hotpot_responses', array('attempt'=>'attempt', 'question'=>'question'), 'response', $new);
-               // restore SQL message echo setting
-               $db->debug = $debug;
-               // remove the hotpotatoes tables, if the update went ok
-               if ($ok) {
-               //      hotpot_db_remove_table('hotpotatoes');
-               //      hotpot_db_remove_table('hotpotatoes_attempts');
-               //      hotpot_db_remove_table('hotpotatoes_questions');
-               //      hotpot_db_remove_table('hotpotatoes_responses');
-               //      hotpot_db_remove_table('hotpotatoes_strings');
-               }
-               // hide the hotpotatoes module (see admin/modules.php))
-               if ($ok && ($module = get_record("modules", "name", "hotpotatoes"))) {
-                       set_field("modules", "visible", "0", "id", $module->id);
-                       print '<p>All HotPotatoes activities have been imported to the HotPot module.<br />'."\n";
-                       print 'The HotPotatoes module has been hidden and can safely be deleted from this Moodle site.<br />'."\n";
-                       print ' &nbsp; &nbsp; <a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/modules.php">Configuration -> Modules</A>, then click &quot;Delete&quot; for &quot;Hot Potatoes XML Quiz&quot;</p>'."\n";
-               }
-       }
-       if ($ok) {
-               print '<p align="center">Thank you for using the HotPotatoes module.<br />';
-               print 'The HotPotatoes module has been replaced by<br />version 2 of the HotPot module. Enjoy!</p>';
-       }
-       return $ok;
+    global $CFG;
+    $ok = true; // hope for the best!
+    // check we have the minimum required hotpot module
+    $minimum = 2005031400; 
+    $module = get_record("modules", "name", "hotpot");
+    if (empty($module) || $module->version<$minimum) {
+        if ($module) {
+            print ("<p>The update to the HotPotatoes module requires at least version $minimum of the HotPot module.</p>");
+            print ("<p>The current version of the HotPot module on this site is $module->version.</p>");
+        }
+        print ("<p>Please install the latest version of the HotPot module and then try the update again.</p>");
+        $ok = false;
+    } else {
+        // arrays to map foreign keys
+        $new = array();
+        $new['hotpot'] = array();
+        $new['attempt'] = array();
+        $new['question'] = array();
+        $new['string'] = array();
+        // save and switch off SQL message echo
+        global $db;
+        $debug = $db->debug;
+        $db->debug = false;
+        // import hotpotatoes (and save old ids)
+        $ok = $ok && hotpot_update_fields('hotpotatoes');
+        $ok = $ok && hotpot_transfer_records('hotpotatoes', 'hotpot', array(), 'hotpot', $new);
+        // update course modules and logs
+        $ok = $ok && hotpot_update_course_modules('hotpotatoes', 'hotpot', $new);
+        // import hotpotatoes_strings (and save old ids)
+        $ok = $ok && hotpot_transfer_records('hotpotatoes_strings', 'hotpot_strings', array(), 'string', $new);
+        // import hotpotatoes_attempts (and save old ids)
+        $ok = $ok && hotpot_transfer_records('hotpotatoes_attempts', 'hotpot_attempts', array('hotpotatoes'=>'hotpot'), 'attempt', $new);
+        // import hotpotatoes_questions (and save old ids)
+        $ok = $ok && hotpot_transfer_records('hotpotatoes_questions', 'hotpot_questions', array('hotpotatoes'=>'hotpot'), 'question', $new);
+        // import hotpotatoes_responses
+        $ok = $ok && hotpot_transfer_records('hotpotatoes_responses', 'hotpot_responses', array('attempt'=>'attempt', 'question'=>'question'), 'response', $new);
+        // restore SQL message echo setting
+        $db->debug = $debug;
+        // remove the hotpotatoes tables, if the update went ok
+        if ($ok) {
+        //  hotpot_db_remove_table('hotpotatoes');
+        //  hotpot_db_remove_table('hotpotatoes_attempts');
+        //  hotpot_db_remove_table('hotpotatoes_questions');
+        //  hotpot_db_remove_table('hotpotatoes_responses');
+        //  hotpot_db_remove_table('hotpotatoes_strings');
+        }
+        // hide the hotpotatoes module (see admin/modules.php))
+        if ($ok && ($module = get_record("modules", "name", "hotpotatoes"))) {
+            set_field("modules", "visible", "0", "id", $module->id);
+            print '<p>All HotPotatoes activities have been imported to the HotPot module.<br />'."\n";
+            print 'The HotPotatoes module has been hidden and can safely be deleted from this Moodle site.<br />'."\n";
+            print ' &nbsp; &nbsp; <a href="'.$CFG->wwwroot.'/'.$CFG->admin.'/modules.php">Configuration -> Modules</A>, then click &quot;Delete&quot; for &quot;Hot Potatoes XML Quiz&quot;</p>'."\n";
+        }
+    }
+    if ($ok) {
+        print '<p align="center">Thank you for using the HotPotatoes module.<br />';
+        print 'The HotPotatoes module has been replaced by<br />version 2 of the HotPot module. Enjoy!</p>';
+    }
+    return $ok;
 }
 function hotpot_create_table($table) {
-       global $CFG;
-       $ok = true;
-       static $sql;
-       if (empty($sql)) { // first time only
-               $filepath = "$CFG->dirroot/mod/hotpot/db/$CFG->dbtype.sql";
-               if (function_exists('file_get_contents')) {
-                       $sql = file_get_contents($filepath);
-               } else { // PHP < 4.3
-                       $sql = file($filepath);
-                       if (is_array($sql)) {
-                                $sql = implode('', $sql);
-                       }
-               }
-               if(empty($sql)) { // $sql==false
-                        $sql = '';
-               }
-       }
-       // check table does not already exist
-       if (!hotpot_db_table_exists($table)) {
-               // extract and execute all CREATE statements relating to this table
-               if (preg_match_all("/CREATE (TABLE|INDEX)(\s[^;]*)? prefix_{$table}(\s[^;]*)?;/s", $sql, $strings)) {
-                       foreach ($strings[0] as $string) {
-                               $ok = $ok && modify_database('', $string);
-                       }
-               } else {
-                       // no CREATE statements found for this $table
-                       $ok = false;
-               }
-       }
-       return $ok;
+    global $CFG;
+    $ok = true;
+    static $sql;
+    if (empty($sql)) { // first time only
+        $filepath = "$CFG->dirroot/mod/hotpot/db/$CFG->dbtype.sql";
+        if (function_exists('file_get_contents')) {
+            $sql = file_get_contents($filepath);
+        } else { // PHP < 4.3
+            $sql = file($filepath);
+            if (is_array($sql)) {
+                 $sql = implode('', $sql);
+            }
+        }
+        if(empty($sql)) { // $sql==false
+             $sql = '';
+        }
+    }
+    // check table does not already exist
+    if (!hotpot_db_table_exists($table)) {
+        // extract and execute all CREATE statements relating to this table
+        if (preg_match_all("/CREATE (TABLE|INDEX)(\s[^;]*)? prefix_{$table}(\s[^;]*)?;/s", $sql, $strings)) {
+            foreach ($strings[0] as $string) {
+                $ok = $ok && modify_database('', $string);
+            }
+        } else {
+            // no CREATE statements found for this $table
+            $ok = false;
+        }
+    }
+    return $ok;
 }
 function hotpot_transfer_records($oldtable, $table, $foreignkeys, $primarykey, &$new) {
-       global $db;
-       $ok = true;
-       // get the records, if any
-       if (hotpot_db_table_exists($oldtable) && ($records = get_records($oldtable))) {
-               // start progress report
-               $i = 0;
-               $count = count($records);
-               hotpot_update_print("Transferring $count records from &quot;$oldtable&quot; to &quot;$table&quot; ... ");
-               // transfer all $records
-               foreach ($records as $record) {
-                       switch ($table) {
-                               case 'hotpot' :
-                                       $record->summary = addslashes($record->summary);
-                                       break;
-                               case 'hotpot_attempts' :
-                                       $record->details = addslashes($record->details);
-                                       break;
-                               case 'hotpot_questions' :
-                                       $record->name = addslashes($record->name);
-                                       hotpot_update_string_id_list($table, $record, 'TEXT', $new);
-                                       break;
-                               case 'hotpot_responses' :
-                                       hotpot_update_string_id_list($table, $record, 'correct', $new);
-                                       hotpot_update_string_id_list($table, $record, 'ignored', $new);
-                                       hotpot_update_string_id_list($table, $record, 'wrong', $new);
-                                       break;
-                               case 'hotpot_strings' :
-                                       $record->string = addslashes($record->string);
-                                       break;
-                       }
-                       // update foreign keys, if any
-                       foreach ($foreignkeys as $oldkey=>$key) {
-                               // transfer (and update) key
-                               $value = $record->$oldkey;
-                               if (isset($new[$key][$value])) {
-                                       $record->$key = $new[$key][$value];
-                               } else {
-                                       // foreign key could not be updated
-                                       $ok = hotpot_update_print_warning($key, $value, $oldtable, $record->id) && $ok;
-                                       unset($record->id);
-                               }
-                       }
-                       if ($ok && isset($record->id)) {
-                               // store and remove old primary key
-                               $id = $record->id;
-                               unset($record->id);
-                               // add the updated record and store the new id
-                               $new[$primarykey][$id] = insert_record($table, $record, true);
-                               // check id is numeric
-                               if (!is_numeric($new[$primarykey][$id])) {
-                                       hotpot_update_print("<li>Record could not added to $table table ($oldtable id=$id)</li>\n");
-                                       //$ok = false;
-                               }
-                       }
-                       $i++;
-                       hotpot_update_print_progress($i);
-               }
-               // finish progress report
-               hotpot_update_print_ok($ok);
-       }
-       return $ok;
+    global $db;
+    $ok = true;
+    // get the records, if any
+    if (hotpot_db_table_exists($oldtable) && ($records = get_records($oldtable))) {
+        // start progress report
+        $i = 0;
+        $count = count($records);
+        hotpot_update_print("Transferring $count records from &quot;$oldtable&quot; to &quot;$table&quot; ... ");
+        // transfer all $records
+        foreach ($records as $record) {
+            switch ($table) {
+                case 'hotpot' :
+                    $record->summary = addslashes($record->summary);
+                    break;
+                case 'hotpot_attempts' :
+                    $record->details = addslashes($record->details);
+                    break;
+                case 'hotpot_questions' :
+                    $record->name = addslashes($record->name);
+                    hotpot_update_string_id_list($table, $record, 'TEXT', $new);
+                    break;
+                case 'hotpot_responses' :
+                    hotpot_update_string_id_list($table, $record, 'correct', $new);
+                    hotpot_update_string_id_list($table, $record, 'ignored', $new);
+                    hotpot_update_string_id_list($table, $record, 'wrong', $new);
+                    break;
+                case 'hotpot_strings' :
+                    $record->string = addslashes($record->string);
+                    break;
+            }
+            // update foreign keys, if any
+            foreach ($foreignkeys as $oldkey=>$key) {
+                // transfer (and update) key
+                $value = $record->$oldkey;
+                if (isset($new[$key][$value])) {
+                    $record->$key = $new[$key][$value];
+                } else {
+                    // foreign key could not be updated
+                    $ok = hotpot_update_print_warning($key, $value, $oldtable, $record->id) && $ok;
+                    unset($record->id);
+                }
+            }
+            if ($ok && isset($record->id)) {
+                // store and remove old primary key
+                $id = $record->id;
+                unset($record->id);
+                // add the updated record and store the new id
+                $new[$primarykey][$id] = insert_record($table, $record, true);
+                // check id is numeric
+                if (!is_numeric($new[$primarykey][$id])) {
+                    hotpot_update_print("<li>Record could not added to $table table ($oldtable id=$id)</li>\n");
+                    //$ok = false;
+                }
+            }
+            $i++;
+            hotpot_update_print_progress($i);
+        }
+        // finish progress report
+        hotpot_update_print_ok($ok);
+    }
+    return $ok;
 }
 function hotpot_update_course_modules($oldmodulename, $modulename, &$new) {
-       $ok = true;
-       $oldmoduleid = get_field('modules', 'id', 'name', $oldmodulename);
-       $moduleid = get_field('modules', 'id', 'name', $modulename);
-       if (is_numeric($oldmoduleid) && is_numeric($moduleid)) {
-               // get module records
-               if ($records = get_records('course_modules', 'module', $oldmoduleid)) {
-                       // start progress report
-                       $count = count($records);
-                       hotpot_update_print("Updating $count course modules from &quot;$oldmodulename&quot; to &quot;$modulename&quot; ... ");
-                       // update foreign keys in all $records
-                       foreach ($records as $record) {
-                               // update instance
-                               $instance = $record->instance;
-                               if (isset($new[$modulename][$instance])) {
-                                       $record->instance = $new[$modulename][$instance];
-                               } else if ($record->deleted) {
-                                       unset($record->id);
-                               } else {
-                                       // could not find new id of course module
-                                       $ok = hotpot_update_print_warning("$modulename instance", $instance, 'course_modules', $record->id) && $ok;
-                                       unset($record->id);
-                               }
-                               // update module id
-                               if ($ok && isset($record->id)) {
-                                       $record->module = $moduleid;
-                                       $ok = update_record('course_modules', $record);
-                               }
-                       }
-                       // finish progress report
-                       hotpot_update_print_ok($ok);
-               }
-               // update logs
-               $ok = $ok && hotpot_update_logs($oldmodulename, $modulename, $moduleid, $new);
-       }
-       return $ok;
+    $ok = true;
+    $oldmoduleid = get_field('modules', 'id', 'name', $oldmodulename);
+    $moduleid = get_field('modules', 'id', 'name', $modulename);
+    if (is_numeric($oldmoduleid) && is_numeric($moduleid)) {
+        // get module records
+        if ($records = get_records('course_modules', 'module', $oldmoduleid)) {
+            // start progress report
+            $count = count($records);
+            hotpot_update_print("Updating $count course modules from &quot;$oldmodulename&quot; to &quot;$modulename&quot; ... ");
+            // update foreign keys in all $records
+            foreach ($records as $record) {
+                // update instance
+                $instance = $record->instance;
+                if (isset($new[$modulename][$instance])) {
+                    $record->instance = $new[$modulename][$instance];
+                } else if ($record->deleted) {
+                    unset($record->id);
+                } else {
+                    // could not find new id of course module
+                    $ok = hotpot_update_print_warning("$modulename instance", $instance, 'course_modules', $record->id) && $ok;
+                    unset($record->id);
+                }
+                // update module id
+                if ($ok && isset($record->id)) {
+                    $record->module = $moduleid;
+                    $ok = update_record('course_modules', $record);
+                }
+            }
+            // finish progress report
+            hotpot_update_print_ok($ok);
+        }
+        // update logs
+        $ok = $ok && hotpot_update_logs($oldmodulename, $modulename, $moduleid, $new);
+    }
+    return $ok;
 }
 function hotpot_update_logs($oldmodulename, $modulename, $moduleid, &$new) {
-       $table = 'log';
-       $ok = true;
-       // get log records for the oldmodule
-       if ($records = get_records($table, 'module', $oldmodulename)) {
-               // start progress report
-               $i = 0;
-               $count = count($records);
-               hotpot_update_print("Updating $count log records ... ");
-               // update foreign keys in all $records
-               foreach ($records as $record) {
-                       // update course module name
-                       $record->module = $modulename;
-                       // check if module id was given (usually it is)
-                       if ($record->cmid) {
-                               // update course module id, if necessary
-                               if (isset($new[$modulename][$record->cmid])) {
-                                       $record->cmid = $new[$modulename][$record->cmid];
-                               } else {
-                                       // could not update course module id
-                                       $ok = hotpot_update_print_warning('cmid', $record->cmid, 'log', $record->id) && $ok;
-                                       unset($record->id);
-                               }
-                               // update url and info
-                               switch ($record->action) {
-                                       case "add":
-                                       case "update":
-                                       case "view":
-                                               $record->url = "view.php?id=".$record->cmid;
-                                               $record->info = $moduleid;
-                                               break;
-                                       case "view all":
-                                               // do nothing
-                                               break;
-                                       case "report":
-                                               $record->url = "report.php?id=".$record->cmid;
-                                               $record->info = $moduleid;
-                                               break;
-                                       case "attempt":
-                                       case "submit":
-                                       case "review": 
-                                               $id = substr(strrchr($record->url,"="),1);
-                                               if (isset($new->attempt[$id])) { 
-                                                       $id = $new->attempt[$id];
-                                               }
-                                               $record->url = "review.php?id=".$record->cmid."&attempt=$id";
-                                               $record->info = $moduleid;
-                                               break;
-                                       default:
-                                               // unknown log action
-                                               $ok = hotpot_update_print_warning('action', $record->action, 'log', $record->id) && $ok;
-                                               unset($record->id);
-                               } // end switch
-                       }
-                       if (isset($record->id)) {
-                               $ok = $ok && update_record($table, $record);
-                       }
-                       $i++;
-                       hotpot_update_print_progress($i);
-               } // end foreach
-               // finish progress report
-               hotpot_update_print_ok($ok);
-       }
-       return $ok;
+    $table = 'log';
+    $ok = true;
+    // get log records for the oldmodule
+    if ($records = get_records($table, 'module', $oldmodulename)) {
+        // start progress report
+        $i = 0;
+        $count = count($records);
+        hotpot_update_print("Updating $count log records ... ");
+        // update foreign keys in all $records
+        foreach ($records as $record) {
+            // update course module name
+            $record->module = $modulename;
+            // check if module id was given (usually it is)
+            if ($record->cmid) {
+                // update course module id, if necessary
+                if (isset($new[$modulename][$record->cmid])) {
+                    $record->cmid = $new[$modulename][$record->cmid];
+                } else {
+                    // could not update course module id
+                    $ok = hotpot_update_print_warning('cmid', $record->cmid, 'log', $record->id) && $ok;
+                    unset($record->id);
+                }
+                // update url and info
+                switch ($record->action) {
+                    case "add":
+                    case "update":
+                    case "view":
+                        $record->url = "view.php?id=".$record->cmid;
+                        $record->info = $moduleid;
+                        break;
+                    case "view all":
+                        // do nothing
+                        break;
+                    case "report":
+                        $record->url = "report.php?id=".$record->cmid;
+                        $record->info = $moduleid;
+                        break;
+                    case "attempt":
+                    case "submit":
+                    case "review": 
+                        $id = substr(strrchr($record->url,"="),1);
+                        if (isset($new->attempt[$id])) { 
+                            $id = $new->attempt[$id];
+                        }
+                        $record->url = "review.php?id=".$record->cmid."&attempt=$id";
+                        $record->info = $moduleid;
+                        break;
+                    default:
+                        // unknown log action
+                        $ok = hotpot_update_print_warning('action', $record->action, 'log', $record->id) && $ok;
+                        unset($record->id);
+                } // end switch
+            }
+            if (isset($record->id)) {
+                $ok = $ok && update_record($table, $record);
+            }
+            $i++;
+            hotpot_update_print_progress($i);
+        } // end foreach
+        // finish progress report
+        hotpot_update_print_ok($ok);
+    }
+    return $ok;
 }
 function hotpot_update_fields($table, $feedback=false) {
-       global $CFG, $db;
-       $ok = true;
-       // check the table exists
-       if (hotpot_db_table_exists($table)) {
-               switch ($table) {
-                       case 'hotpot' :
-                               // == ADD ==
-                               hotpot_db_update_field_type($table, '', 'location',     'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
-                               hotpot_db_update_field_type($table, '', 'navigation',   'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 1);
-                               hotpot_db_update_field_type($table, '', 'outputformat', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 1);
-                               hotpot_db_update_field_type($table, '', 'shownextquiz', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
-                               hotpot_db_update_field_type($table, '', 'forceplugins', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
-                               hotpot_db_update_field_type($table, '', 'password',     'VARCHAR', 255, '',       'NOT NULL', '');
-                               hotpot_db_update_field_type($table, '', 'subnet',       'VARCHAR', 255, '',       'NOT NULL', '');
-                               // == ALTER ==
-                               hotpot_db_update_field_type($table, 'summary',   'summary',   'TEXT',    '',  '', 'NOT NULL', '');
-                               hotpot_db_update_field_type($table, 'reference', 'reference', 'VARCHAR', 255, '', 'NOT NULL', '');
-                               // == REMOVE ==
-                               hotpot_db_remove_field($table, 'intro');
-                               hotpot_db_remove_field($table, 'attemptonlast');
-                               hotpot_db_remove_field($table, 'sumgrades');
-                               hotpot_db_set_table_comment($table, 'details about Hot Potatoes quizzes');
-                       break;
-                       case 'hotpot_events' :
-                               // == ADD ==
-                               hotpot_db_update_field_type($table, '', 'hotpot',     'INTEGER', 10, 'UNSIGNED', 'NOT NULL');
-                               hotpot_db_update_field_type($table, '', 'attempt',    'INTEGER', 6,  'UNSIGNED', 'NOT NULL');
-                               hotpot_db_update_field_type($table, '', 'details',    'TEXT',    '', '', '', '');
-                               hotpot_db_update_field_type($table, '', 'timestart',  'INTEGER', 10, 'UNSIGNED', 'NOT NULL', 0);
-                               hotpot_db_update_field_type($table, '', 'timefinish', 'INTEGER', 10, 'UNSIGNED', 'NOT NULL', 0);
-                               // == ALTER ==
-                               hotpot_db_update_field_type($table, 'score',     'score',      'INTEGER', 6,  'UNSIGNED', 'NULL');
-                               hotpot_db_update_field_type($table, 'wrong',     'penalties',  'INTEGER', 6,  'UNSIGNED', 'NULL');
-                               hotpot_db_update_field_type($table, 'starttime', 'starttime',  'INTEGER', 10, 'UNSIGNED', 'NULL');
-                               hotpot_db_update_field_type($table, 'endtime',   'endtime',    'INTEGER', 10, 'UNSIGNED', 'NULL');
-                               // save and switch off SQL message echo
-                               $debug = $db->debug;
-                               $db->debug = $feedback;
-                               // get array mapping course module ids to hotpot ids
-                               $hotpotmoduleid = get_field('modules', 'id', 'name', 'hotpot');
-                               $coursemodules = get_records('course_modules', 'module', $hotpotmoduleid, 'id', 'id, instance');
-                               // get all event records
-                               if (hotpot_db_field_exists($table, 'hotpotid')) {
-                                       $records = get_records($table, '', '', 'userid,hotpotid,time');
-                               } else {
-                                       $records = false; // table has already been updated
-                               }
-                               if ($records) {
-                                       $count = count($records);
-                                       hotpot_update_print("Updating $count records in $table ... ");
-                                       $ids = array_keys($records);
-                                       foreach ($ids as $i=>$id) {
-                                               // reference to current record
-                                               $record = &$records[$id];
-                                               // set timestart and timefinish (the times recorded by Moodle)
-                                               if (empty($record->timestart) && $record->time) {
-                                                       $record->timestart = $record->time;
-                                               }
-                                               if (empty($record->timefinish) && $record->timestart) {
-                                                       if ($record->starttime && $record->endtime) {
-                                                               $duration = ($record->endtime - $record->starttime);
-                                                       } else {
-                                                               if (($i+1)>=$count) {
-                                                                       $nextrecord = NULL;
-                                                               } else {
-                                                                       $nextrecord = &$records[$ids[$i+1]];
-                                                               }
-                                                               if (isset($nextrecord) && $nextrecord->userid==$record->userid && $nextrecord->hotpotid==$record->hotpotid) {
-                                                                       $duration = $nextrecord->time - $record->time;
-                                                               } else {
-                                                                       $duration = NULL;
-                                                               }
-                                                       }
-                                                       if (isset($duration)) {
-                                                               $record->timefinish = $record->timestart + $duration;
-                                                       }
-                                               }
-                                               // unset score and penalties, if quiz was abandoned
-                                               if (empty($record->endtime) || (empty($record->penalties) && empty($record->score))) {
-                                                       unset($record->score);
-                                                       unset($record->penalties);
-                                               }
-                                               // get last (=previous) record
-                                               if ($i==0) {
-                                                       $lastrecord = NULL;
-                                               } else {
-                                                       $lastrecord = &$records[$ids[$i-1]];
-                                               }
-                                               // increment or reset $attempt number
-                                               if (isset($lastrecord) && $lastrecord->userid==$record->userid && $lastrecord->hotpotid==$record->hotpotid) {
-                                                       $attempt++;
-                                               } else {
-                                                       $attempt = 1;
-                                               }
-                                               // set $record->$attempt, if necessary
-                                               if (empty($record->attempt) || $record->attempt<$attempt) {
-                                                       $record->attempt = $attempt;
-                                               } else {
-                                                       $attempt = $record->attempt;
-                                               }
-                                               // set hotpot id and update record
-                                               if (isset($record->hotpotid) && isset($record->id)) {
-                                                       if (isset($coursemodules[$record->hotpotid])) {
-                                                               $record->hotpot = $coursemodules[$record->hotpotid]->instance;
-                                                               hotpot_db_update_record($table, $record, true);
-                                                       } else {
-                                                               // hotpotid is invalid (shouldn't happen)
-                                                               $ok = hotpot_update_print_warning('hotpotid', $record->hotpotid, $table, $record->id) && $ok;
-                                                               delete_records($table, 'id', $record->id);
-                                                       }
-                                               } else {
-                                                               // empty record (shouldn't happen)
-                                               }
-                                               hotpot_update_print_progress($i);
-                                       }
-                                       // finish progress report
-                                       hotpot_update_print_ok($ok);
-                               }
-                               // restore SQL message echo setting
-                               $db->debug = $debug;
-                               // == REMOVE ==
-                               hotpot_db_remove_field($table, 'hotpotid');
-                               hotpot_db_remove_field($table, 'course');
-                               hotpot_db_remove_field($table, 'time');
-                               hotpot_db_remove_field($table, 'event');
-                               hotpot_db_set_table_comment($table, 'details about Hot Potatoes quiz attempts');
-                       break;
-                       case 'hotpotatoes' :
-                               // == ALTER ==
-                               hotpot_db_update_field_type($table, 'intro', 'summary', 'TEXT', '', '', '', 'NULL');
-                       break;
-               }
-       }
-       return $ok;
+    global $CFG, $db;
+    $ok = true;
+    // check the table exists
+    if (hotpot_db_table_exists($table)) {
+        switch ($table) {
+            case 'hotpot' :
+                // == ADD ==
+                hotpot_db_update_field_type($table, '', 'location',     'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
+                hotpot_db_update_field_type($table, '', 'navigation',   'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 1);
+                hotpot_db_update_field_type($table, '', 'outputformat', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 1);
+                hotpot_db_update_field_type($table, '', 'shownextquiz', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
+                hotpot_db_update_field_type($table, '', 'forceplugins', 'INTEGER', 4, 'UNSIGNED', 'NOT NULL', 0);
+                hotpot_db_update_field_type($table, '', 'password',     'VARCHAR', 255, '',       'NOT NULL', '');
+                hotpot_db_update_field_type($table, '', 'subnet',       'VARCHAR', 255, '',       'NOT NULL', '');
+                // == ALTER ==
+                hotpot_db_update_field_type($table, 'summary',   'summary',   'TEXT',    '',  '', 'NOT NULL', '');
+                hotpot_db_update_field_type($table, 'reference', 'reference', 'VARCHAR', 255, '', 'NOT NULL', '');
+                // == REMOVE ==
+                hotpot_db_remove_field($table, 'intro');
+                hotpot_db_remove_field($table, 'attemptonlast');
+                hotpot_db_remove_field($table, 'sumgrades');
+                hotpot_db_set_table_comment($table, 'details about Hot Potatoes quizzes');
+            break;
+            case 'hotpot_events' :
+                // == ADD ==
+                hotpot_db_update_field_type($table, '', 'hotpot',     'INTEGER', 10, 'UNSIGNED', 'NOT NULL');
+                hotpot_db_update_field_type($table, '', 'attempt',    'INTEGER', 6,  'UNSIGNED', 'NOT NULL');
+                hotpot_db_update_field_type($table, '', 'details',    'TEXT',    '', '', '', '');
+                hotpot_db_update_field_type($table, '', 'timestart',  'INTEGER', 10, 'UNSIGNED', 'NOT NULL', 0);
+                hotpot_db_update_field_type($table, '', 'timefinish', 'INTEGER', 10, 'UNSIGNED', 'NOT NULL', 0);
+                // == ALTER ==
+                hotpot_db_update_field_type($table, 'score',     'score',      'INTEGER', 6,  'UNSIGNED', 'NULL');
+                hotpot_db_update_field_type($table, 'wrong',     'penalties',  'INTEGER', 6,  'UNSIGNED', 'NULL');
+                hotpot_db_update_field_type($table, 'starttime', 'starttime',  'INTEGER', 10, 'UNSIGNED', 'NULL');
+                hotpot_db_update_field_type($table, 'endtime',   'endtime',    'INTEGER', 10, 'UNSIGNED', 'NULL');
+                // save and switch off SQL message echo
+                $debug = $db->debug;
+                $db->debug = $feedback;
+                // get array mapping course module ids to hotpot ids
+                $hotpotmoduleid = get_field('modules', 'id', 'name', 'hotpot');
+                $coursemodules = get_records('course_modules', 'module', $hotpotmoduleid, 'id', 'id, instance');
+                // get all event records
+                if (hotpot_db_field_exists($table, 'hotpotid')) {
+                    $records = get_records($table, '', '', 'userid,hotpotid,time');
+                } else {
+                    $records = false; // table has already been updated
+                }
+                if ($records) {
+                    $count = count($records);
+                    hotpot_update_print("Updating $count records in $table ... ");
+                    $ids = array_keys($records);
+                    foreach ($ids as $i=>$id) {
+                        // reference to current record
+                        $record = &$records[$id];
+                        // set timestart and timefinish (the times recorded by Moodle)
+                        if (empty($record->timestart) && $record->time) {
+                            $record->timestart = $record->time;
+                        }
+                        if (empty($record->timefinish) && $record->timestart) {
+                            if ($record->starttime && $record->endtime) {
+                                $duration = ($record->endtime - $record->starttime);
+                            } else {
+                                if (($i+1)>=$count) {
+                                    $nextrecord = NULL;
+                                } else {
+                                    $nextrecord = &$records[$ids[$i+1]];
+                                }
+                                if (isset($nextrecord) && $nextrecord->userid==$record->userid && $nextrecord->hotpotid==$record->hotpotid) {
+                                    $duration = $nextrecord->time - $record->time;
+                                } else {
+                                    $duration = NULL;
+                                }
+                            }
+                            if (isset($duration)) {
+                                $record->timefinish = $record->timestart + $duration;
+                            }
+                        }
+                        // unset score and penalties, if quiz was abandoned
+                        if (empty($record->endtime) || (empty($record->penalties) && empty($record->score))) {
+                            unset($record->score);
+                            unset($record->penalties);
+                        }
+                        // get last (=previous) record
+                        if ($i==0) {
+                            $lastrecord = NULL;
+                        } else {
+                            $lastrecord = &$records[$ids[$i-1]];
+                        }
+                        // increment or reset $attempt number
+                        if (isset($lastrecord) && $lastrecord->userid==$record->userid && $lastrecord->hotpotid==$record->hotpotid) {
+                            $attempt++;
+                        } else {
+                            $attempt = 1;
+                        }
+                        // set $record->$attempt, if necessary
+                        if (empty($record->attempt) || $record->attempt<$attempt) {
+                            $record->attempt = $attempt;
+                        } else {
+                            $attempt = $record->attempt;
+                        }
+                        // set hotpot id and update record
+                        if (isset($record->hotpotid) && isset($record->id)) {
+                            if (isset($coursemodules[$record->hotpotid])) {
+                                $record->hotpot = $coursemodules[$record->hotpotid]->instance;
+                                hotpot_db_update_record($table, $record, true);
+                            } else {
+                                // hotpotid is invalid (shouldn't happen)
+                                $ok = hotpot_update_print_warning('hotpotid', $record->hotpotid, $table, $record->id) && $ok;
+                                delete_records($table, 'id', $record->id);
+                            }
+                        } else {
+                                // empty record (shouldn't happen)
+                        }
+                        hotpot_update_print_progress($i);
+                    }
+                    // finish progress report
+                    hotpot_update_print_ok($ok);
+                }
+                // restore SQL message echo setting
+                $db->debug = $debug;
+                // == REMOVE ==
+                hotpot_db_remove_field($table, 'hotpotid');
+                hotpot_db_remove_field($table, 'course');
+                hotpot_db_remove_field($table, 'time');
+                hotpot_db_remove_field($table, 'event');
+                hotpot_db_set_table_comment($table, 'details about Hot Potatoes quiz attempts');
+            break;
+            case 'hotpotatoes' :
+                // == ALTER ==
+                hotpot_db_update_field_type($table, 'intro', 'summary', 'TEXT', '', '', '', 'NULL');
+            break;
+        }
+    }
+    return $ok;
 }
 function hotpot_update_string_id_list($table, &$record, $field, &$new) {
-       $ok = true;
-       if (isset($record->$field)) {
-               $oldids = explode(',', $record->$field);
-               $newids = array();
-               foreach ($oldids as $id) {
-                       if (isset($new['string'][$id])) {
-                               $newids[] = $new['string'][$id];
-                       } else if (is_numeric($id)) {
-                               // string id could not be updated
-                               $ok = hotpot_update_print_warning("string id in $field", $id, $table, $record->id) && $ok;
-                       } else {
-                               // ignore non-numeric ids (e.g. blanks)
-                       }
-               }
-               if ($ok) {
-                       $record->$field = implode(',', $newids);
-               }
-       }
-       return $ok;
+    $ok = true;
+    if (isset($record->$field)) {
+        $oldids = explode(',', $record->$field);
+        $newids = array();
+        foreach ($oldids as $id) {
+            if (isset($new['string'][$id])) {
+                $newids[] = $new['string'][$id];
+            } else if (is_numeric($id)) {
+                // string id could not be updated
+                $ok = hotpot_update_print_warning("string id in $field", $id, $table, $record->id) && $ok;
+            } else {
+                // ignore non-numeric ids (e.g. blanks)
+            }
+        }
+        if ($ok) {
+            $record->$field = implode(',', $newids);
+        }
+    }
+    return $ok;
 }
 ///////////////////////////
 //     print functions
 ///////////////////////////
 function hotpot_update_print($msg=false, $n=300) {
-       // this function prints $msg and flush output buffer
-       if ($msg) {
-               if (is_string($msg)) {
-                       print $msg;
-               } else {
-                       print strftime("%X", time());
-               }
-       }
-       // fill output buffer
-       if ($n) {
-               print str_repeat(" ", $n);
-       }
-       // some browser's require newline to flush
-       print "\n";
-       // flush PHP's output buffer
-       flush();
+    // this function prints $msg and flush output buffer
+    if ($msg) {
+        if (is_string($msg)) {
+            print $msg;
+        } else {
+            print strftime("%X", time());
+        }
+    }
+    // fill output buffer
+    if ($n) {
+        print str_repeat(" ", $n);
+    }
+    // some browser's require newline to flush
+    print "\n";
+    // flush PHP's output buffer
+    flush();
 }
 function hotpot_update_print_progress($i) {
-       if ($i%10==0) {
-               $msg = '.';
-               hotpot_update_print($msg);
-       }
+    if ($i%10==0) {
+        $msg = '.';
+        hotpot_update_print($msg);
+    }
 }
 function hotpot_update_print_ok($ok) {
-       if ($ok) {
-               hotpot_update_print('<font color="green">'.get_string('success')."</font><br />\n");
-       } else {
-               hotpot_update_print('<font color="red">'.get_string('error')."</font><br />\n");
-       }
+    if ($ok) {
+        hotpot_update_print('<font color="green">'.get_string('success')."</font><br />\n");
+    } else {
+        hotpot_update_print('<font color="red">'.get_string('error')."</font><br />\n");
+    }
 }
 function hotpot_update_print_warning($field, $value, $table, $id) {
-       hotpot_update_print("<li><b>Warning:</b> invalid $field field (value=$value) in $table (id=$id)</li>\n");
-       return true;
+    hotpot_update_print("<li><b>Warning:</b> invalid $field field (value=$value) in $table (id=$id)</li>\n");
+    return true;
 }
 ///////////////////////////
 //     database functions
 ///////////////////////////
 function hotpot_db_index_exists($table, $index, $feedback=false) {
-       global $CFG, $db;
-       $exists = false;
-       // save and switch off SQL message echo
-       $debug = $db->debug;
-       $db->debug = $feedback;
-       switch (strtolower($CFG->dbtype)) {
-               case 'mysql' : 
-                       $rs = $db->Execute("SHOW INDEX FROM `$table`");
-                       if ($rs && $rs->RecordCount()>0) {
-                               $records = $rs->GetArray();
-                               foreach ($records as $record) {
-                                       if (isset($record['Key_name']) && $record['Key_name']==$index) {
-                                               $exists = true;
-                                               break;
-                                       }
-                               }
-                       }
-               break;
-               case 'postgres7' :
-                       $rs = $db->Execute("SELECT relname FROM pg_class WHERE relname = '$index' AND relkind='i'");
-                       if ($rs && $rs->RecordCount()>0) {
-                               $exists = true;
-                       }
-               break;
-       }
-       // restore SQL message echo
-       $db->debug = $debug;
-       return $exists;
+    global $CFG, $db;
+    $exists = false;
+    // save and switch off SQL message echo
+    $debug = $db->debug;
+    $db->debug = $feedback;
+    switch (strtolower($CFG->dbtype)) {
+        case 'mysql' : 
+            $rs = $db->Execute("SHOW INDEX FROM `$table`");
+            if ($rs && $rs->RecordCount()>0) {
+                $records = $rs->GetArray();
+                foreach ($records as $record) {
+                    if (isset($record['Key_name']) && $record['Key_name']==$index) {
+                        $exists = true;
+                        break;
+                    }
+                }
+            }
+        break;
+        case 'postgres7' :
+            $rs = $db->Execute("SELECT relname FROM pg_class WHERE relname = '$index' AND relkind='i'");
+            if ($rs && $rs->RecordCount()>0) {
+                $exists = true;
+            }
+        break;
+    }
+    // restore SQL message echo
+    $db->debug = $debug;
+    return $exists;
 }
 function hotpot_db_delete_index($table, $index, $feedback=false) {
-       global $CFG, $db;
-       $ok = true;
-       // check index exists
-       if (hotpot_db_index_exists($table, $index)) {
-               switch (strtolower($CFG->dbtype)) {
-                       case 'mysql' : 
-                               $sql = "ALTER TABLE `$table` DROP INDEX `$index`";
-                       break;
-                       case 'postgres7' :
-                               $sql = "DROP INDEX $index";
-                       break;
-                       default: // unknown database type
-                               $sql = '';
-                       break;
-               }
-               if ($sql) {
-                       // save and switch off SQL message echo
-                       $debug = $db->debug;
-                       $db->debug = $feedback;
-                       $ok = $db->Execute($sql) ? true : false;
-                       // restore SQL message echo
-                       $db->debug = $debug;
-               } else { // unknown database type
-                       $ok = false;
-               }
-       }
-       return $ok;
+    global $CFG, $db;
+    $ok = true;
+    // check index exists
+    if (hotpot_db_index_exists($table, $index)) {
+        switch (strtolower($CFG->dbtype)) {
+            case 'mysql' : 
+                $sql = "ALTER TABLE `$table` DROP INDEX `$index`";
+            break;
+            case 'postgres7' :
+                $sql = "DROP INDEX $index";
+            break;
+            default: // unknown database type
+                $sql = '';
+            break;
+        }
+        if ($sql) {
+            // save and switch off SQL message echo
+            $debug = $db->debug;
+            $db->debug = $feedback;
+            $ok = $db->Execute($sql) ? true : false;
+            // restore SQL message echo
+            $db->debug = $debug;
+        } else { // unknown database type
+            $ok = false;
+        }
+    }
+    return $ok;
 }
 function hotpot_db_add_index($table, $field, $length='') {
-       global $CFG, $db;
+    global $CFG, $db;
 
-       if (strtolower($CFG->dbtype)=='postgres7') {
-               $index = "{$CFG->prefix}{$table}_{$field}_idx";
-       } else {
-               // mysql (and others)
-               $index = "{$table}_{$field}_idx";
-       }
-       $table = "{$CFG->prefix}$table";
+    if (strtolower($CFG->dbtype)=='postgres7') {
+        $index = "{$CFG->prefix}{$table}_{$field}_idx";
+    } else {
+        // mysql (and others)
+        $index = "{$table}_{$field}_idx";
+    }
+    $table = "{$CFG->prefix}$table";
 
-       // delete $index if it already exists
-       $ok = hotpot_db_delete_index($table, $index);
+    // delete $index if it already exists
+    $ok = hotpot_db_delete_index($table, $index);
 
-       switch (strtolower($CFG->dbtype)) {
-               case 'mysql' :
-                       $length = empty($length) ? '' : " ($length)";
-                       $ok = $ok && $db->Execute("ALTER TABLE `$table` ADD INDEX `$index` (`$field`$length)");
-               break;
-               case 'postgres7' :
-                       if ($length) {
-                               $field = "SUBSTR(\"$field\",$length)";
-                       }
-                       $ok = $ok && $db->Execute("CREATE INDEX $index ON $table ($field)");
-               break;
-               default: // unknown database type
-                       $ok = false;
-               break;
-       }
-       return $ok;
+    switch (strtolower($CFG->dbtype)) {
+        case 'mysql' :
+            $length = empty($length) ? '' : " ($length)";
+            $ok = $ok && $db->Execute("ALTER TABLE `$table` ADD INDEX `$index` (`$field`$length)");
+        break;
+        case 'postgres7' :
+            if ($length) {
+                $field = "SUBSTR(\"$field\",$length)";
+            }
+            $ok = $ok && $db->Execute("CREATE INDEX $index ON $table ($field)");
+        break;
+        default: // unknown database type
+            $ok = false;
+        break;
+    }
+    return $ok;
 }
 function hotpot_db_table_exists($table, $feedback=false) {
-       return hotpot_db_object_exists($table, '', $feedback);
+    return hotpot_db_object_exists($table, '', $feedback);
 }
 function hotpot_db_field_exists($table, $field, $feedback=false) {
-       return 
-               hotpot_db_object_exists($table, '', $feedback) &&
-               hotpot_db_object_exists($table, $field, $feedback)
-       ;
+    return 
+        hotpot_db_object_exists($table, '', $feedback) &&
+        hotpot_db_object_exists($table, $field, $feedback)
+    ;
 }
 function hotpot_db_object_exists($table, $field='', $feedback=false) {
-       global $CFG,$db;
-       // expand table name
-       $table = "{$CFG->prefix}$table";
-       // set $sql
-       switch (strtolower($CFG->dbtype)) {
-               case 'mysql' : 
-                       if (empty($field)) {
-                               $sql = "SHOW TABLES LIKE '$table'";
-                       } else {
-                               $sql = "SHOW COLUMNS FROM `$table` LIKE '$field'";
-                       }
-               break;
-               case 'postgres7' :
-                       if (empty($field)) {
-                               $sql = "SELECT relname FROM pg_class WHERE relname = '$table' AND relkind='r'";
-                       } else {
-                               $sql = "
-                                       SELECT attname FROM pg_attribute WHERE attname = '$field' 
-                                       AND attrelid = (SELECT oid FROM pg_class WHERE relname = '$table')
-                               ";
-                       }
-               break;
-       }
-       // save and switch off SQL message echo
-       $debug = $db->debug;
-       $db->debug = $feedback;
-       // execute sql
-       $rs = $db->Execute($sql);
-       // restore SQL message echo setting
-       $db->debug = $debug;
-       // report error if required
-       if (empty($rs) && isset($CFG->debug) and $CFG->debug > 7) {
-               notify($db->ErrorMsg()."<br /><br />$sql");
-       }
-       return ($rs && $rs->RecordCount()>0);
+    global $CFG,$db;
+    // expand table name
+    $table = "{$CFG->prefix}$table";
+    // set $sql
+    switch (strtolower($CFG->dbtype)) {
+        case 'mysql' : 
+            if (empty($field)) {
+                $sql = "SHOW TABLES LIKE '$table'";
+            } else {
+                $sql = "SHOW COLUMNS FROM `$table` LIKE '$field'";
+            }
+        break;
+        case 'postgres7' :
+            if (empty($field)) {
+                $sql = "SELECT relname FROM pg_class WHERE relname = '$table' AND relkind='r'";
+            } else {
+                $sql = "
+                    SELECT attname FROM pg_attribute WHERE attname = '$field' 
+                    AND attrelid = (SELECT oid FROM pg_class WHERE relname = '$table')
+                ";
+            }
+        break;
+    }
+    // save and switch off SQL message echo
+    $debug = $db->debug;
+    $db->debug = $feedback;
+    // execute sql
+    $rs = $db->Execute($sql);
+    // restore SQL message echo setting
+    $db->debug = $debug;
+    // report error if required
+    if (empty($rs) && isset($CFG->debug) and $CFG->debug > 7) {
+        notify($db->ErrorMsg()."<br /><br />$sql");
+    }
+    return ($rs && $rs->RecordCount()>0);
 }
 function hotpot_db_remove_table($table, $feedback=true) {
-       global $CFG;
-       if (hotpot_db_table_exists($table)) {
-               $ok = execute_sql("DROP TABLE {$CFG->prefix}$table", $feedback);
-       } else {
-               $ok = true;
-       }
-       return $ok;
+    global $CFG;
+    if (hotpot_db_table_exists($table)) {
+        $ok = execute_sql("DROP TABLE {$CFG->prefix}$table", $feedback);
+    } else {
+        $ok = true;
+    }
+    return $ok;
 }
 function hotpot_db_rename_table($oldtable, $table, $feedback=true) {
-       global $CFG;
-       if (hotpot_db_table_exists($oldtable)) {
-               $ok = execute_sql("ALTER TABLE {$CFG->prefix}$oldtable RENAME TO {$CFG->prefix}$table", $feedback);
-       } else {
-               $ok = true;
-       }
-       return $ok;
+    global $CFG;
+    if (hotpot_db_table_exists($oldtable)) {
+        $ok = execute_sql("ALTER TABLE {$CFG->prefix}$oldtable RENAME TO {$CFG->prefix}$table", $feedback);
+    } else {
+        $ok = true;
+    }
+    return $ok;
 }
 function hotpot_db_append_table($oldtable, $table, $feedback=true) {
-       global $CFG, $db;
-       if (hotpot_db_table_exists($oldtable)) {
-               if (hotpot_db_table_exists($table)) {
-                       // expand table names
-                       $table = "{$CFG->prefix}$table";
-                       $oldtable = "{$CFG->prefix}$oldtable";
-                       // get field info
-                       $fields = $db->MetaColumns($table);
-                       $oldfields = $db->MetaColumns($oldtable);
-                       $fieldnames = array();
-                       if (!empty($fields) || !empty($oldfields)) {
-                               foreach ($fields as $field) {
-                                       if ($field->name!='id' && isset($oldfields[strtoupper($field->name)])) {
-                                               $fieldnames[] = $field->name;
-                                       }
-                               }
-                       }
-                       $fieldnames = implode(',', $fieldnames);
-                       if (empty($fieldnames)) {
-                               $ok = false;
-                       } else {
-                               switch (strtolower($CFG->dbtype)) {
-                                       case 'mysql':
-                                               $ok = execute_sql("INSERT INTO `$table` ($fieldnames) SELECT $fieldnames FROM `$oldtable` WHERE 1");
-                                               break;
-                                       case 'postgres7':
-                                               $ok = execute_sql("INSERT INTO $table ($fieldnames) SELECT $fieldnames FROM $oldtable");
-                                               break;
-                                       default:
-                                               $ok = false;
-                                               break;
-                               }
-                       }
-               } else { // $table does not exist
-                       $ok = hotpot_db_rename_table($oldtable, $table, $feedback);
-               }
-       } else { // $oldtable does not exist
-               $ok = hotpot_db_table_exists($table, $feedback);
-       }
-       return $ok;
+    global $CFG, $db;
+    if (hotpot_db_table_exists($oldtable)) {
+        if (hotpot_db_table_exists($table)) {
+            // expand table names
+            $table = "{$CFG->prefix}$table";
+            $oldtable = "{$CFG->prefix}$oldtable";
+            // get field info
+            $fields = $db->MetaColumns($table);
+            $oldfields = $db->MetaColumns($oldtable);
+            $fieldnames = array();
+            if (!empty($fields) || !empty($oldfields)) {
+                foreach ($fields as $field) {
+                    if ($field->name!='id' && isset($oldfields[strtoupper($field->name)])) {
+                        $fieldnames[] = $field->name;
+                    }
+                }
+            }
+            $fieldnames = implode(',', $fieldnames);
+            if (empty($fieldnames)) {
+                $ok = false;
+            } else {
+                switch (strtolower($CFG->dbtype)) {
+                    case 'mysql':
+                        $ok = execute_sql("INSERT INTO `$table` ($fieldnames) SELECT $fieldnames FROM `$oldtable` WHERE 1");
+                        break;
+                    case 'postgres7':
+                        $ok = execute_sql("INSERT INTO $table ($fieldnames) SELECT $fieldnames FROM $oldtable");
+                        break;
+                    default:
+                        $ok = false;
+                        break;
+                }
+            }
+        } else { // $table does not exist
+            $ok = hotpot_db_rename_table($oldtable, $table, $feedback);
+        }
+    } else { // $oldtable does not exist
+        $ok = hotpot_db_table_exists($table, $feedback);
+    }
+    return $ok;
 }
 function hotpot_db_set_table_comment($table, $comment, $feedback=true) {
-       global $CFG;
-       $ok = true;
-       switch (strtolower($CFG->dbtype)) {
-               case 'mysql' :
-                       $ok = execute_sql("ALTER TABLE {$CFG->prefix}$table COMMENT='$comment'");
-                       break;
-               case 'postgres7' :
-                       $ok = execute_sql("COMMENT ON TABLE {$CFG->prefix}$table IS '$comment'");
-                       break;
-       }
-       return $ok;
+    global $CFG;
+    $ok = true;
+    switch (strtolower($CFG->dbtype)) {
+        case 'mysql' :
+            $ok = execute_sql("ALTER TABLE {$CFG->prefix}$table COMMENT='$comment'");
+            break;
+        case 'postgres7' :
+            $ok = execute_sql("COMMENT ON TABLE {$CFG->prefix}$table IS '$comment'");
+            break;
+    }
+    return $ok;
 }
 function hotpot_db_remove_field($table, $field, $feedback=true) {
-       global $CFG;
-       if (hotpot_db_field_exists($table, $field)) {
-               $ok = execute_sql("ALTER TABLE {$CFG->prefix}$table DROP COLUMN $field", $feedback);
-       } else {
-               $ok = true;
-       }
-       return $ok;
+    global $CFG;
+    if (hotpot_db_field_exists($table, $field)) {
+        $ok = execute_sql("ALTER TABLE {$CFG->prefix}$table DROP COLUMN $field", $feedback);
+    } else {
+        $ok = true;
+    }
+    return $ok;
 }
 function hotpot_db_update_field_type($table, $oldfield, $field, $type, $size, $unsigned, $notnull, $default=NULL, $after=NULL) {
-       $ok = true;
-       global $CFG,$db;
-       // check validity of arguments, and adjust if necessary
-       if ($oldfield && !hotpot_db_field_exists($table, $oldfield)) {
-               $oldfield = '';
-       }
-       if (empty($oldfield) && hotpot_db_field_exists($table, $field)) {
-               $oldfield = $field;
-       
-       if (is_string($unsigned)) {
-               $unsigned = (strtoupper($unsigned)=='UNSIGNED');
-       }
-       if (is_string($notnull)) {
-               $notnull = (strtoupper($notnull)=='NOT NULL');
-       }
-       if (isset($default)) {
-               if (!is_numeric($default) && strtoupper($default)!='NULL' && !preg_match("|^'.*'$|", $default)) {
-                       $default = "'$default'";
-               }
-       }
-       // set full table name
-       $table = "{$CFG->prefix}$table";
-       // update the field in the database
-       switch (strtolower($CFG->dbtype)) {
-               case 'mysql':
-                       // optimize integer types
-                       switch (strtoupper($type)) {
-                               case 'TEXT':
-                                       $size = '';
-                                       $unsigned = false;
-                               break;
-                               case 'INTEGER' :
-                                       if (!is_numeric($size)) {
-                                               $size = '';
-                                       } else if ($size <= 4) {
-                                               $type = "TINYINT";   // 1 byte
-                                       } else if ($size <= 6) {
-                                               $type = "SMALLINT";  // 2 bytes
-                                       } else if ($size <= 8) {
-                                               $type = "MEDIUMINT"; // 3 bytes
-                                       } else if ($size <= 10) {
-                                               $type = "INTEGER";   // 4 bytes (=INT)
-                                       } else if ($size > 10) {
-                                               $type = "BIGINT";    // 8 bytes
-                                       }
-                               break;
-                               case 'VARCHAR':
-                                       $unsigned = false;
-                               break;
-                       }
-                       // set action
-                       if (empty($oldfield)) {
-                               $action = "ADD";
-                       } else {
-                               $action = "CHANGE `$oldfield`";
-                       }
-                       // set fieldtype
-                       $fieldtype = $type;
-                       if ($size) {
-                               $fieldtype .= "($size)";
-                       }
-                       if ($unsigned) {
-                               $fieldtype .= ' UNSIGNED';
-                       }
-                       if ($notnull) {
-                               $fieldtype .= ' NOT NULL';
-                       }
-                       if (isset($default)) {
-                               $fieldtype .= " DEFAULT $default";
-                       }
-                       if (!empty($after)) {
-                               $fieldtype .= " AFTER `$after`";
-                       }
-                       $ok = $ok && execute_sql("ALTER TABLE `$table` $action `$field` $fieldtype");
-               break;
-               case 'postgres7':
-                       // get db version
-                       $dbinfo = $db->ServerInfo();
-                       $dbversion = substr($dbinfo['version'],0,3);
-                       // prevent conflicts with reserved words
-                       $tmpfield = "\"temporary_{$field}_".time()."\"";
-                       $oldfield = "\"$oldfield\"";
-                       $field    = "\"$field\"";
-                       switch (strtoupper($type)) {
-                               case "INTEGER":
-                                       if (!is_numeric($size)) {
-                                               $fieldtype = "INTEGER";
-                                       } else if ($size <= 4) {
-                                               $fieldtype = "INT2"; // 2 bytes
-                                       } else if ($size <= 10) {
-                                               $fieldtype = "INT4"; // 4 bytes (=INTEGER)
-                                       } else if ($size > 10) {
-                                               $fieldtype = "INT8"; // 8 bytes
-                                       }
-                               break;
-                               case "VARCHAR":
-                                       $fieldtype = "VARCHAR($size)";
-                               break;
-                               default:
-                                       $fieldtype = $type;
-                       }
-                       // start transaction
-                       execute_sql("BEGIN");
-                       // create temporary field
-                       execute_sql("ALTER TABLE $table ADD COLUMN $tmpfield $fieldtype");
-                       // set default
-                       if (isset($default)) {
-                               execute_sql("UPDATE $table SET $tmpfield = $default");
-                               execute_sql("ALTER TABLE $table ALTER COLUMN $tmpfield SET DEFAULT $default");
-                       } else {
-                               execute_sql("ALTER TABLE $table ALTER COLUMN $tmpfield DROP DEFAULT");
-                       }
-                       // set not null
-                       if ($dbversion >= "7.3") {
-                               $notnull = ($notnull ? "SET NOT NULL" : "DROP NOT NULL");
-                               execute_sql("ALTER TABLE $table ALTER COLUMN $tmpfield $notnull");
-                       } else {
-                               execute_sql("
-                                       UPDATE pg_attribute SET attnotnull=".($notnull ? 'TRUE' : 'FALSE')." 
-                                       WHERE attname = $tmpfield
-                                       AND attrelid = (SELECT oid FROM pg_class WHERE relname = '$table')
-                               ");
-                       }
-                       // transfer $oldfield values, if necessary
-                       if ( $oldfield != '""' ) {
-                               execute_sql("UPDATE $table SET $tmpfield = CAST ($oldfield AS $fieldtype)");
-                               execute_sql("ALTER TABLE $table DROP COLUMN $oldfield");
-                       }
-                       // rename $tmpfield to $field
-                       execute_sql("ALTER TABLE $table RENAME COLUMN $tmpfield TO $field");
-                       // do the transaction
-                       execute_sql("COMMIT");
-                       // reclaim disk space (must be done outside transaction)
-                       if ($oldfield != '""' && $dbversion >= "7.3") {
-                               execute_sql("UPDATE $table SET $field = $field");
-                               execute_sql("VACUUM FULL $table");
-                       }
-               break;
-       } // end switch $CGF->dbtype
-       return $ok;
+    $ok = true;
+    global $CFG,$db;
+    // check validity of arguments, and adjust if necessary
+    if ($oldfield && !hotpot_db_field_exists($table, $oldfield)) {
+        $oldfield = '';
+    }
+    if (empty($oldfield) && hotpot_db_field_exists($table, $field)) {
+        $oldfield = $field;
+    } 
+    if (is_string($unsigned)) {
+        $unsigned = (strtoupper($unsigned)=='UNSIGNED');
+    }
+    if (is_string($notnull)) {
+        $notnull = (strtoupper($notnull)=='NOT NULL');
+    }
+    if (isset($default)) {
+        if (!is_numeric($default) && strtoupper($default)!='NULL' && !preg_match("|^'.*'$|", $default)) {
+            $default = "'$default'";
+        }
+    }
+    // set full table name
+    $table = "{$CFG->prefix}$table";
+    // update the field in the database
+    switch (strtolower($CFG->dbtype)) {
+        case 'mysql':
+            // optimize integer types
+            switch (strtoupper($type)) {
+                case 'TEXT':
+                    $size = '';
+                    $unsigned = false;
+                break;
+                case 'INTEGER' :
+                    if (!is_numeric($size)) {
+                        $size = '';
+                    } else if ($size <= 4) {
+                        $type = "TINYINT";   // 1 byte
+                    } else if ($size <= 6) {
+                        $type = "SMALLINT";  // 2 bytes
+                    } else if ($size <= 8) {
+                        $type = "MEDIUMINT"; // 3 bytes
+                    } else if ($size <= 10) {
+                        $type = "INTEGER";   // 4 bytes (=INT)
+                    } else if ($size > 10) {
+                        $type = "BIGINT";    // 8 bytes
+                    }
+                break;
+                case 'VARCHAR':
+                    $unsigned = false;
+                break;
+            }
+            // set action
+            if (empty($oldfield)) {
+                $action = "ADD";
+            } else {
+                $action = "CHANGE `$oldfield`";
+            }
+            // set fieldtype
+            $fieldtype = $type;
+            if ($size) {
+                $fieldtype .= "($size)";
+            }
+            if ($unsigned) {
+                $fieldtype .= ' UNSIGNED';
+            }
+            if ($notnull) {
+                $fieldtype .= ' NOT NULL';
+            }
+            if (isset($default)) {
+                $fieldtype .= " DEFAULT $default";
+            }
+            if (!empty($after)) {
+                $fieldtype .= " AFTER `$after`";
+            }
+            $ok = $ok && execute_sql("ALTER TABLE `$table` $action `$field` $fieldtype");
+        break;
+        case 'postgres7':
+            // get db version
+            $dbinfo = $db->ServerInfo();
+            $dbversion = substr($dbinfo['version'],0,3);
+            // prevent conflicts with reserved words
+            $tmpfield = "\"temporary_{$field}_".time()."\"";
+            $oldfield = "\"$oldfield\"";
+            $field    = "\"$field\"";
+            switch (strtoupper($type)) {
+                case "INTEGER":
+                    if (!is_numeric($size)) {
+                        $fieldtype = "INTEGER";
+                    } else if ($size <= 4) {
+                        $fieldtype = "INT2"; // 2 bytes
+                    } else if ($size <= 10) {
+                        $fieldtype = "INT4"; // 4 bytes (=INTEGER)
+                    } else if ($size > 10) {
+                        $fieldtype = "INT8"; // 8 bytes
+                    }
+                break;
+                case "VARCHAR":
+                    $fieldtype = "VARCHAR($size)";
+                break;
+                default:
+                    $fieldtype = $type;
+            }
+            // start transaction
+            execute_sql("BEGIN");
+            // create temporary field
+            execute_sql("ALTER TABLE $table ADD COLUMN $tmpfield $fieldtype");
+            // set default
+            if (isset($default)) {
+                execute_sql("UPDATE $table SET $tmpfield = $default");
+                execute_sql("ALTER TABLE $table ALTER COLUMN $tmpfield SET DEFAULT $default");
+            } else {
+                execute_sql("ALTER TABLE $table ALTER COLUMN $tmpfield DROP DEFAULT");
+            }
+            // set not null
+            if ($dbversion >= "7.3") {
+                $notnull = ($notnull ? "SET NOT NULL" : "DROP NOT NULL");
+                execute_sql("ALTER TABLE $table ALTER COLUMN $tmpfield $notnull");
+            } else {
+                execute_sql("
+                    UPDATE pg_attribute SET attnotnull=".($notnull ? 'TRUE' : 'FALSE')." 
+                    WHERE attname = $tmpfield
+                    AND attrelid = (SELECT oid FROM pg_class WHERE relname = '$table')
+                ");
+            }
+            // transfer $oldfield values, if necessary
+            if ( $oldfield != '""' ) {
+                execute_sql("UPDATE $table SET $tmpfield = CAST ($oldfield AS $fieldtype)");
+                execute_sql("ALTER TABLE $table DROP COLUMN $oldfield");
+            }
+            // rename $tmpfield to $field
+            execute_sql("ALTER TABLE $table RENAME COLUMN $tmpfield TO $field");
+            // do the transaction
+            execute_sql("COMMIT");
+            // reclaim disk space (must be done outside transaction)
+            if ($oldfield != '""' && $dbversion >= "7.3") {
+                execute_sql("UPDATE $table SET $field = $field");
+                execute_sql("VACUUM FULL $table");
+            }
+        break;
+    } // end switch $CGF->dbtype
+    return $ok;
 }
 function hotpot_db_update_record($table, $record, $forcenull=false) {
-       global $CFG, $db;
-       $ok = true;
-       // set full table name
-       $table = "{$CFG->prefix}$table";
-       // get field names
-       $fields = $db->MetaColumns($table);
-       if (empty($fields)) {
-               $ok = false;
-       } else {
-               // get values
-               $values = array();
-               foreach ($fields as $field) {
-                       $fieldname = $field->name;
-                       if ($fieldname!='id' && ($forcenull || isset($record->$fieldname))) {
-                               $value = isset($record->$fieldname) ? "'".$record->$fieldname."'" : 'NULL';
-                               $values[] = "$fieldname = $value";
-                       }
-               }
-               $values = implode(',', $values);
-               // update values (if there are any)
-               if ($values) {
-                       $sql = "UPDATE $table SET $values WHERE id='$record->id'";
-                       $rs = $db->Execute($sql);
-                       if (empty($rs)) {
-                               $ok = false;
-                               if (isset($CFG->debug) and $CFG->debug > 7) {
-                                       notify($db->ErrorMsg()."<br /><br />$sql");
-                               }
-                       }
-               }
-       }
-       return $ok;
+    global $CFG, $db;
+    $ok = true;
+    // set full table name
+    $table = "{$CFG->prefix}$table";
+    // get field names
+    $fields = $db->MetaColumns($table);
+    if (empty($fields)) {
+        $ok = false;
+    } else {
+        // get values
+        $values = array();
+        foreach ($fields as $field) {
+            $fieldname = $field->name;
+            if ($fieldname!='id' && ($forcenull || isset($record->$fieldname))) {
+                $value = isset($record->$fieldname) ? "'".$record->$fieldname."'" : 'NULL';
+                $values[] = "$fieldname = $value";
+            }
+        }
+        $values = implode(',', $values);
+        // update values (if there are any)
+        if ($values) {
+            $sql = "UPDATE $table SET $values WHERE id='$record->id'";
+            $rs = $db->Execute($sql);
+            if (empty($rs)) {
+                $ok = false;
+                if (isset($CFG->debug) and $CFG->debug > 7) {
+                    notify($db->ErrorMsg()."<br /><br />$sql");
+                }
+            }
+        }
+    }
+    return $ok;
 }
 function hotpot_rm($target, $output=true) {
-       $ok = true;
-       if (!empty($target)) {
-               if (is_file($target)) {
-                       if ($output) {
-                               print "removing file: $target ... ";
-                       }
-                       $ok = @unlink($target);
-               } else if (is_dir($target)) {
-                       $dir = dir($target);
-                       while(false !== ($entry = $dir->read())) {
-                               if ($entry!='.' && $entry!='..') {
-                                       $ok = $ok && hotpot_rm($target.DIRECTORY_SEPARATOR.$entry, $output);
-                               }
-                       }
-                       $dir->close();
-                       if ($output) {
-                               print "removing folder: $target ... ";
-                       }
-                       $ok = $ok && @rmdir($target);
-               } else { // not a file or directory (probably doesn't exist)
-                       $output = false;
-               }
-               if ($output) {
-                       if ($ok) {
-                               print '<font color="green">OK</font><br />';
-                       } else {
-                               print '<font color="red">Failed</font><br />';
-                       }
-               }
-       }
-       return $ok;
+    $ok = true;
+    if (!empty($target)) {
+        if (is_file($target)) {
+            if ($output) {
+                print "removing file: $target ... ";
+            }
+            $ok = @unlink($target);
+        } else if (is_dir($target)) {
+            $dir = dir($target);
+            while(false !== ($entry = $dir->read())) {
+                if ($entry!='.' && $entry!='..') {
+                    $ok = $ok && hotpot_rm($target.DIRECTORY_SEPARATOR.$entry, $output);
+                }
+            }
+            $dir->close();
+            if ($output) {
+                print "removing folder: $target ... ";
+            }
+            $ok = $ok && @rmdir($target);
+        } else { // not a file or directory (probably doesn't exist)
+            $output = false;
+        }
+        if ($output) {
+            if ($ok) {
+                print '<font color="green">OK</font><br />';
+            } else {
+                print '<font color="red">Failed</font><br />';
+            }
+        }
+    }
+    return $ok;
 }
 function hotpot_flush($n=0, $time=false) {
-       if ($time) {
-               $t = strftime("%X",time());
-       } else {
-               $t = "";
-       }
-       echo str_repeat(" ", $n) . $t . "\n";
-       flush();
+    if ($time) {
+        $t = strftime("%X",time());
+    } else {
+        $t = "";
+    }
+    echo str_repeat(" ", $n) . $t . "\n";
+    flush();
 }
 ?>
index 3aceb5e80ebed69e300eebca88e1ced3758c802e..e7226ac5a535a85bc3afd2a3466e5dd334ac162e 100644 (file)
 
 // This page lists all the instances of hotpot in a particular course
 
-       require_once("../../config.php");
-       require_once("../../course/lib.php");
-       require_once("lib.php");
-
-       $id = required_param("id");   // course
-
-       if (! $course = get_record("course", "id", $id)) {
-               error("Course ID is incorrect");
-       }
-
-       require_login($course->id);
-
-       add_to_log($course->id, "hotpot", "view all", "index.php?id=$course->id", "");
-
-       // Moodle 1.4+ requires sesskey to be passed in forms
-       if (isset($USER->sesskey)) {
-               $sesskey = '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
-       } else {
-               $sesskey = '';
-       }
-
-       // get message strings for titles
-       $strmodulenameplural = get_string("modulenameplural", "hotpot");
-       $strmodulename  = get_string("modulename", "hotpot");
-
-       // string translation array for single and double quotes
-       $quotes = array("'"=>"\'", '"'=>'&quot;');
-
-       // Print the header
-
-       $title = "$course->shortname: $strmodulenameplural";
-       $heading = "$course->fullname";
-       $navigation = "$strmodulenameplural";
-       if ($course->category) {
-               $navigation = "<a href=\"../../course/view.php?id=$course->id\">$course->shortname</a> -> $navigation";
-       }
-       print_header($title, $heading, $navigation, "", "", true, "", navmenu($course));
-
-       $next_url = "$CFG->wwwroot/course/view.php?id=$course->id";
-
-       // get display section, if any
-       $section = optional_param('section', 0);
-       if ($section) {
-               $displaysection = course_set_display($course->id, $section);
-       } else {
-               if (isset($USER->display[$course->id])) {
-                       $displaysection = $USER->display[$course->id];
-               } else {
-                       $displaysection = 0;
-               }
-       }
-
-       // Get all instances of this module
-       if (!$hotpots = hotpot_get_all_instances_in_course("hotpot", $course)) {
-               $hotpots = array();
-       }
-
-       // if necessary, remove hotpots that are not in section0 or this $USER's display section
-       if ($displaysection) {
-               foreach ($hotpots as $coursemodule=>$hotpot) {
-                       if ($hotpot->section!=0 && $hotpot->section!=$displaysection) {
-                               unset($hotpots[$coursemodule]);
-                       }
-               }
-       }
-
-       if (empty($hotpots)) {
-               notice("There are no $strmodulenameplural", $next_url);
-               exit;
-       }
-
-       // get list of hotpot ids
-       $hotpotids = array();
-       foreach ($hotpots as $cmid=>$hotpot) {
-               $hotpotids[] = $hotpot->id;
-       }
-       $hotpotids = implode(',', $hotpotids);
-
-       if (isadmin()) {
-
-               // get regrade settings, if any
-               $regrade = optional_param("regrade");
-               $confirm = optional_param("confirm");
-
-               // check regrade is valid
-               unset($regrade_cmid);
-               if (isset($regrade)) {
-                       foreach ($hotpots as $cmid=>$hotpot) {
-                               $found = false;
-                               if ($hotpot->id==$regrade) {
-                                       $regrade_cmid = $cmid;
-                               }
-                       }
-               }
-
-               // regrade, if necessary
-               if (isset($regrade_cmid)) {
-
-                       if (empty($confirm)) {
-
-                               $strregradecheck = get_string('regradecheck', 'hotpot', $hotpots[$regrade_cmid]->name);
-
-                               print_simple_box_start("center", "60%", "#FFAAAA", 20, "noticebox");
-                               print_heading($strregradecheck);
-                               print ''
-                               .       '<table border="0"><tr><td>'
-                               .       '<form target="_parent" method="post" action="'.$ME.'">'
-                               .       '<input type="hidden" name="id" value="'.$course->id.'">'
-                               .       '<input type="hidden" name="regrade" value="'.$regrade.'" />'
-                               .       '<input type="hidden" name="confirm" value="1" />'
-                               .       $sesskey
-                               .       '<input type="submit" value="'.get_string("yes").'" />'
-                               .       '</form>'
-                               .       '</td><td> &nbsp; </td><td>'
-                               .       '<form target="_parent" method="post" action="'.$ME.'">'
-                               .       '<input type="hidden" name="id" value="'.$course->id.'">'
-                               .       $sesskey
-                               .       '<input type="submit" value="'.get_string("no").'" />'
-                               .       '</form>'
-                               .       '</td></tr></table>'
-                               ;
-                               print_simple_box_end();
-                               print_footer($course);
-                               exit;
-
-                       } else { // regrade has been confirmed, so proceed
-
-                               if ($regrade=='all') {
-                                       $select = "hotpot IN ($hotpotids)";
-                               } else {
-                                       $select = "hotpot=$regrade";
-                               }
-
-                               $questionids = array();
-                               if ($questions = get_records_select("hotpot_questions", $select)) {
-                                       $questionids = array_keys($questions);
-                               }
-                               $questionids = implode(',', $questionids);
-
-                               if ($questionids) {
-                                       hotpot_delete_and_notify('hotpot_questions', "id IN ($questionids)", get_string('question', 'quiz'));
-                                       hotpot_delete_and_notify('hotpot_responses', "question IN ($questionids)", get_string('answer', 'quiz'));
-                               }
-
-                               if ($attempts = get_records_select('hotpot_attempts', $select)) {
-
-                                       // start counter and timer
-                                       $start = microtime();
-                                       $count = 0;
-
-                                       // use while loop instead of foreach loop
-                                       // to allow the possibility of splitting a regrade 
-                                       // and so avoid "maximum script time exceeded" errors
-                                       $attemptids = array_keys($attempts);
-                                       $i_max = count($attemptids);
-                                       $i = 0;
-                                       while ($i<$i_max) {
-
-                                               $attemptid = $attemptids[$i];
-                                               $attempt =&$attempts[$attemptid];
-
-                                               $attempt->details = get_field('hotpot_details', 'details', 'attempt', $attemptid);
-                                               if ($attempt->details) {
-
-                                                       hotpot_add_attempt_details($attempt);
-                                                       if (! update_record('hotpot_attempts', $attempt)) {
-                                                               error("Could not update attempt record: ".$db->ErrorMsg(), $next_url);
-                                                       }
-                                               }
-                                               $count++;
-                                               $i++;
-                                       }
-                                       if ($count) {
-                                               notify(get_string('added', 'moodle', "$count x ".get_string('attempts', 'quiz')));
-                                       }
-                                       $msg = get_string('regradecomplete', 'quiz');
-                                       if (!empty($CFG->hotpot_showtimes)) {
-                                               $duration = format_time(sprintf("%0.2f", microtime_diff($start, microtime())));
-                                               $msg .= " ($duration)";
-                                       }
-                                       notify($msg);
-                               }
-                       }
-               } // end regrade
-
-               //print '<center><form action="'.$ME.'" method="post">';
-               //print '<input type="hidden" name="id" value="'.$course->id.'">';
-               //print '<input type="submit" name="regrade" value="'.get_string('regrade', 'quiz').'">';
-               //print '</form></center>'."\n";
-
-
-               // get duplicate hotpot-name questions
-               //      - JMatch LHS is longer than 255 bytes
-               //      - JQuiz question text is longer than 255 bytes
-               //      - other unidentified situations ?!?
-
-               $field = '';
-               $questions = false;
-               $regradehotpots = array();
-
-               switch (strtolower($CFG->dbtype)) {
-                       case 'mysql' : 
-                               $field = "CONCAT(hotpot, '_', name)";
-                               break;
-                       case 'postgres7' :
-                               $field = "hotpot||'_'||name";
-                               break;
-               }
-               if ($field) {
-                       $questions = get_records_sql("
-                               SELECT $field, COUNT(*), hotpot, name
-                               FROM {$CFG->prefix}hotpot_questions 
-                               WHERE hotpot IN ($hotpotids)
-                               GROUP BY hotpot, name 
-                               HAVING COUNT(*) >1
-                       ");
-               }
-               if ($questions) {
-                       foreach ($questions as $question) {
-                               $regradehotpots[] = $question->hotpot;
-                       }
-                       $regradehotpots = array_unique($regradehotpots);
-                       sort($regradehotpots);
-               }
-       }
-
-       // start timer
-       $start = microtime();
-
-       // get total number of attempts, users and details for these hotpots
-       $tables = "{$CFG->prefix}hotpot_attempts AS a";
-       $fields = "
-               a.hotpot AS hotpot,
-               COUNT(DISTINCT a.clickreportid) AS attemptcount,
-               COUNT(DISTINCT a.userid) AS usercount,
-               MAX(a.score) AS maxscore
-       ";
-       $select = "a.hotpot IN ($hotpotids)";
-       if (isteacher($course->id)) {
-               // do nothing (=get all users)
-       } else {
-               // restrict results to this user only
-               $select .= " AND a.userid='$USER->id'";
-       }
-       $usejoin = 1;
-       if (isadmin() && $usejoin) {
-               // join attempts table and details table
-               $tables .= ",{$CFG->prefix}hotpot_details AS d";
-               $fields .= ',COUNT(DISTINCT d.id) AS detailcount';
-               $select .= " AND a.id=d.attempt";
-
-               // this may take about twice as long as getting the gradecounts separately :-(
-               // so this operation could be done after getting the $totals from the attempts table
-       }
-       $totals = get_records_sql("SELECT $fields FROM $tables WHERE $select GROUP BY a.hotpot");
-
-       if (isadmin() && empty($usejoin)) {
-               foreach ($hotpots as $hotpot) {
-                       $totals[$hotpot->id]->detailcount = 0;
-                       if ($ids = get_records('hotpot_attempts', 'hotpot', $hotpot->id)) {
-                               $ids = join(',', array_keys($ids));
-                               $totals[$hotpot->id]->detailcount = count_records_select('hotpot_details', "attempt IN ($ids)");
-                       }
-               }
-       }
-
-       // message strings for main table
-       $strusers  = get_string('users');
-       $strupdate = get_string('update');
-       $strregrade = get_string('regrade', 'hotpot');
-       $strneverclosed = get_string('neverclosed', 'hotpot');
-       $strregraderequired = get_string('regraderequired', 'hotpot');
-
-       // column headings and attributes
-       $table->head = array();
-       $table->align = array();
-
-       if (!empty($CFG->hotpot_showtimes)) {
-               print '<H3>'.sprintf("%0.3f", microtime_diff($start, microtime())).' secs'."</H3>\n";
-       }
-
-       switch ($course->format) {
-               case 'weeks' : 
-                       $title = get_string("week");
-                       break;
-               case 'topics' : 
-                       $title = get_string("topic");
-                       break;
-               default : 
-                       $title = '';
-                       break;
-       }
-       if ($title) {
-               array_push($table->head, $title); 
-               array_push($table->align, "center");
-       }
-       if (isteacheredit($course->id)) {
-               array_push($table->head, $strupdate);
-               array_push($table->align, "center");
-       }
-       array_push($table->head, 
-               get_string("name"), 
-               get_string("quizcloses", "quiz"), 
-               get_string("bestgrade", "quiz"), 
-               get_string("attempts", "quiz")
-       );
-       array_push($table->align, 
-               "left", "left", "center", "left"
-       );
-       if (isadmin()) {
-               array_push($table->head, $strregrade);
-               array_push($table->align, "center");
-       }
-
-       $currentsection = -1;
-       foreach ($hotpots as $hotpot) {
-
-               $printsection = "";
-               if ($hotpot->section != $currentsection) {
-                       if ($hotpot->section) {
-                               $printsection = $hotpot->section;
-                               if ($course->format=='weeks' || $course->format=='topics') {
-                                       // Show the zoom boxes
-                                       if ($displaysection==$hotpot->section) {
-                                               $strshowall = get_string('showall'.$course->format);
-                                               $printsection .= '<br /><a href="index.php?id='.$course->id.'&section=all" title="'.$strshowall.'"><img src="'.$CFG->pixpath.'/i/all.gif" height=25 width=16 border=0></a><br />';
-                                       } else {
-                                               $strshowone = get_string('showonly'.preg_replace('|s$|', '', $course->format, 1), '', $hotpot->section);
-                                               $printsection .=  '<br /><a href="index.php?id='.$course->id.'&section='.$hotpot->section.'" title="'.$strshowone.'"><img src="'.$CFG->pixpath.'/i/one.gif" height=16 width=16 border=0></a><br />';
-                                       }
-                               }
-                       }
-                       if ($currentsection>=0) {
-                               $table->data[] = 'hr';
-                       }
-                       $currentsection = $hotpot->section;
-               }
-
-               $class = ($hotpot->visible) ? '' : 'class="dimmed" ';
-               $quizname = '<a '.$class.'href="view.php?id='.$hotpot->coursemodule.'">'.$hotpot->name.'</A>';
-               $quizclose = empty($hotpot->timeclose) ? $strneverclosed : userdate($hotpot->timeclose);
-
-               // are there any totals for this hotpot?
-               if (empty($totals[$hotpot->id]->attemptcount)) {
-                       $report = "&nbsp;";
-                       $bestscore = "&nbsp;";
-
-               } else {
-                       // report number of attempts and users
-                       $report = get_string("viewallreports","quiz", $totals[$hotpot->id]->attemptcount);
-                       if (isteacher($course->id)) {
-                               $report .= " (".$totals[$hotpot->id]->usercount." $strusers)";
-                       }
-                       $report = '<a href="report.php?hp='.$hotpot->id.'">'.$report.'</a>';
-
-                       // get best score
-                       if (is_numeric($totals[$hotpot->id]->maxscore)) {
-                               $bestscore = $totals[$hotpot->id]->maxscore." / $hotpot->grade";
-                       } else {
-                               $bestscore = "&nbsp;";
-                       }
-               }
-
-               if (isadmin()) {
-                       if (in_array($hotpot->id, $regradehotpots)) {
-                               $report .= ' <font color="red">'.$strregraderequired.'</font>';
-                       }
-               }
-
-               $data = array ();
-
-               if ($course->format=="weeks" || $course->format=="topics") {
-                       array_push($data, $printsection);
-               }
-
-               if (isteacheredit($course->id)) {
-                       $updatebutton = ''
-                       .       '<form target="'.$CFG->framename.'" method="get" action="'.$CFG->wwwroot.'/course/mod.php">'
-                       .       '<input type="hidden" name="update" value="'.$hotpot->coursemodule.'" />'
-                       .       $sesskey
-                       .       '<input type="submit" value="'.$strupdate.'" />'
-                       .       '</form>'
-                       ;
-                       array_push($data, $updatebutton);
-               }
-
-               array_push($data, $quizname, $quizclose, $bestscore, $report);
-
-               if (isadmin()) {
-                       if (empty($totals[$hotpot->id]->detailcount)) {
-                               // no details records for this hotpot, so disable regrade
-                               $regradebutton = '&nbsp;';
-                       } else {
-                               $strregradecheck = get_string('regradecheck', 'hotpot', strtr($hotpot->name, $quotes));
-                               $regradebutton = ''
-                               .       '<form target="_parent" method="post" action="'.$ME.'" onsubmit="var x=window.confirm('."'$strregradecheck'".');this.confirm.value=x;return x;">'
-                               .       '<input type="hidden" name="id" value="'.$course->id.'">'
-                               .       '<input type="hidden" name="regrade" value="'.$hotpot->id.'" />'
-                               .       '<input type="hidden" name="confirm" value="" />'
-                               .       $sesskey
-                               .       '<input type="submit" value="'.$strregrade.'" />'
-                               .       '</form>'
-                               ;
-                       }
-                       array_push($data, $regradebutton);
-               }
-
-               $table->data[] = $data;
-       }
-
-       echo "<br />";
-
-       print_table($table);
-
-       // Finish the page
-       print_footer($course);
+    require_once("../../config.php");
+    require_once("../../course/lib.php");
+    require_once("lib.php");
+
+    $id = required_param("id");   // course
+
+    if (! $course = get_record("course", "id", $id)) {
+        error("Course ID is incorrect");
+    }
+
+    require_login($course->id);
+
+    add_to_log($course->id, "hotpot", "view all", "index.php?id=$course->id", "");
+
+    // Moodle 1.4+ requires sesskey to be passed in forms
+    if (isset($USER->sesskey)) {
+        $sesskey = '<input type="hidden" name="sesskey" value="'.$USER->sesskey.'" />';
+    } else {
+        $sesskey = '';
+    }
+
+    // get message strings for titles
+    $strmodulenameplural = get_string("modulenameplural", "hotpot");
+    $strmodulename  = get_string("modulename", "hotpot");
+
+    // string translation array for single and double quotes
+    $quotes = array("'"=>"\'", '"'=>'&quot;');
+
+    // Print the header
+
+    $title = "$course->shortname: $strmodulenameplural";
+    $heading = "$course->fullname";
+    $navigation = "$strmodulenameplural";
+    if ($course->category) {
+        $navigation = "<a href=\"../../course/view.php?id=$course->id\">$course->shortname</a> -> $navigation";
+    }
+    print_header($title, $heading, $navigation, "", "", true, "", navmenu($course));
+
+    $next_url = "$CFG->wwwroot/course/view.php?id=$course->id";
+
+    // get display section, if any
+    $section = optional_param('section', 0);
+    if ($section) {
+        $displaysection = course_set_display($course->id, $section);
+    } else {
+        if (isset($USER->display[$course->id])) {
+            $displaysection = $USER->display[$course->id];
+        } else {
+            $displaysection = 0;
+        }
+    }
+
+    // Get all instances of this module
+    if (!$hotpots = hotpot_get_all_instances_in_course("hotpot", $course)) {
+        $hotpots = array();
+    }
+
+    // if necessary, remove hotpots that are not in section0 or this $USER's display section
+    if ($displaysection) {
+        foreach ($hotpots as $coursemodule=>$hotpot) {
+            if ($hotpot->section!=0 && $hotpot->section!=$displaysection) {
+                unset($hotpots[$coursemodule]);
+            }
+        }
+    }
+
+    if (empty($hotpots)) {
+        notice("There are no $strmodulenameplural", $next_url);
+        exit;
+    }
+
+    // get list of hotpot ids
+    $hotpotids = array();
+    foreach ($hotpots as $cmid=>$hotpot) {
+        $hotpotids[] = $hotpot->id;
+    }
+    $hotpotids = implode(',', $hotpotids);
+
+    if (isadmin()) {
+
+        // get regrade settings, if any
+        $regrade = optional_param("regrade");
+        $confirm = optional_param("confirm");
+
+        // check regrade is valid
+        unset($regrade_cmid);
+        if (isset($regrade)) {
+            foreach ($hotpots as $cmid=>$hotpot) {
+                $found = false;
+                if ($hotpot->id==$regrade) {
+                    $regrade_cmid = $cmid;
+                }
+            }
+        }
+
+        // regrade, if necessary
+        if (isset($regrade_cmid)) {
+
+            if (empty($confirm)) {
+
+                $strregradecheck = get_string('regradecheck', 'hotpot', $hotpots[$regrade_cmid]->name);
+
+                print_simple_box_start("center", "60%", "#FFAAAA", 20, "noticebox");
+                print_heading($strregradecheck);
+                print ''
+                .   '<table border="0"><tr><td>'
+                .   '<form target="_parent" method="post" action="'.$ME.'">'
+                .   '<input type="hidden" name="id" value="'.$course->id.'">'
+                .   '<input type="hidden" name="regrade" value="'.$regrade.'" />'
+                .   '<input type="hidden" name="confirm" value="1" />'
+                .   $sesskey
+                .   '<input type="submit" value="'.get_string("yes").'" />'
+                .   '</form>'
+                .   '</td><td> &nbsp; </td><td>'
+                .   '<form target="_parent" method="post" action="'.$ME.'">'
+                .   '<input type="hidden" name="id" value="'.$course->id.'">'
+                .   $sesskey
+                .   '<input type="submit" value="'.get_string("no").'" />'
+                .   '</form>'
+                .   '</td></tr></table>'
+                ;
+                print_simple_box_end();
+                print_footer($course);
+                exit;
+
+            } else { // regrade has been confirmed, so proceed
+
+                if ($regrade=='all') {
+                    $select = "hotpot IN ($hotpotids)";
+                } else {
+                    $select = "hotpot=$regrade";
+                }
+
+                $questionids = array();
+                if ($questions = get_records_select("hotpot_questions", $select)) {
+                    $questionids = array_keys($questions);
+                }
+                $questionids = implode(',', $questionids);
+
+                if ($questionids) {
+                    hotpot_delete_and_notify('hotpot_questions', "id IN ($questionids)", get_string('question', 'quiz'));
+                    hotpot_delete_and_notify('hotpot_responses', "question IN ($questionids)", get_string('answer', 'quiz'));
+                }
+
+                if ($attempts = get_records_select('hotpot_attempts', $select)) {
+
+                    // start counter and timer
+                    $start = microtime();
+                    $count = 0;
+
+                    // use while loop instead of foreach loop
+                    // to allow the possibility of splitting a regrade 
+                    // and so avoid "maximum script time exceeded" errors
+                    $attemptids = array_keys($attempts);
+                    $i_max = count($attemptids);
+                    $i = 0;
+                    while ($i<$i_max) {
+
+                        $attemptid = $attemptids[$i];
+                        $attempt =&$attempts[$attemptid];
+
+                        $attempt->details = get_field('hotpot_details', 'details', 'attempt', $attemptid);
+                        if ($attempt->details) {
+
+                            hotpot_add_attempt_details($attempt);
+                            if (! update_record('hotpot_attempts', $attempt)) {
+                                error("Could not update attempt record: ".$db->ErrorMsg(), $next_url);
+                            }
+                        }
+                        $count++;
+                        $i++;
+                    }
+                    if ($count) {
+                        notify(get_string('added', 'moodle', "$count x ".get_string('attempts', 'quiz')));
+                    }
+                    $msg = get_string('regradecomplete', 'quiz');
+                    if (!empty($CFG->hotpot_showtimes)) {
+                        $duration = format_time(sprintf("%0.2f", microtime_diff($start, microtime())));
+                        $msg .= " ($duration)";
+                    }
+                    notify($msg);
+                }
+            }
+        } // end regrade
+
+        //print '<center><form action="'.$ME.'" method="post">';
+        //print '<input type="hidden" name="id" value="'.$course->id.'">';
+        //print '<input type="submit" name="regrade" value="'.get_string('regrade', 'quiz').'">';
+        //print '</form></center>'."\n";
+
+
+        // get duplicate hotpot-name questions
+        //  - JMatch LHS is longer than 255 bytes
+        //  - JQuiz question text is longer than 255 bytes
+        //  - other unidentified situations ?!?
+
+        $field = '';
+        $questions = false;
+        $regradehotpots = array();
+
+        switch (strtolower($CFG->dbtype)) {
+            case 'mysql' : 
+                $field = "CONCAT(hotpot, '_', name)";
+                break;
+            case 'postgres7' :
+                $field = "hotpot||'_'||name";
+                break;
+        }
+        if ($field) {
+            $questions = get_records_sql("
+                SELECT $field, COUNT(*), hotpot, name
+                FROM {$CFG->prefix}hotpot_questions 
+                WHERE hotpot IN ($hotpotids)
+                GROUP BY hotpot, name 
+                HAVING COUNT(*) >1
+            ");
+        }
+        if ($questions) {
+            foreach ($questions as $question) {
+                $regradehotpots[] = $question->hotpot;
+            }
+            $regradehotpots = array_unique($regradehotpots);
+            sort($regradehotpots);
+        }
+    }
+
+    // start timer
+    $start = microtime();
+
+    // get total number of attempts, users and details for these hotpots
+    $tables = "{$CFG->prefix}hotpot_attempts AS a";
+    $fields = "
+        a.hotpot AS hotpot,
+        COUNT(DISTINCT a.clickreportid) AS attemptcount,
+        COUNT(DISTINCT a.userid) AS usercount,
+        MAX(a.score) AS maxscore
+    ";
+    $select = "a.hotpot IN ($hotpotids)";
+    if (isteacher($course->id)) {
+        // do nothing (=get all users)
+    } else {
+        // restrict results to this user only
+        $select .= " AND a.userid='$USER->id'";
+    }
+    $usejoin = 1;
+    if (isadmin() && $usejoin) {
+        // join attempts table and details table
+        $tables .= ",{$CFG->prefix}hotpot_details AS d";
+        $fields .= ',COUNT(DISTINCT d.id) AS detailcount';
+        $select .= " AND a.id=d.attempt";
+
+        // this may take about twice as long as getting the gradecounts separately :-(
+        // so this operation could be done after getting the $totals from the attempts table
+    }
+    $totals = get_records_sql("SELECT $fields FROM $tables WHERE $select GROUP BY a.hotpot");
+
+    if (isadmin() && empty($usejoin)) {
+        foreach ($hotpots as $hotpot) {
+            $totals[$hotpot->id]->detailcount = 0;
+            if ($ids = get_records('hotpot_attempts', 'hotpot', $hotpot->id)) {
+                $ids = join(',', array_keys($ids));
+                $totals[$hotpot->id]->detailcount = count_records_select('hotpot_details', "attempt IN ($ids)");
+            }
+        }
+    }
+
+    // message strings for main table
+    $strusers  = get_string('users');
+    $strupdate = get_string('update');
+    $strregrade = get_string('regrade', 'hotpot');
+    $strneverclosed = get_string('neverclosed', 'hotpot');
+    $strregraderequired = get_string('regraderequired', 'hotpot');
+
+    // column headings and attributes
+    $table->head = array();
+    $table->align = array();
+
+    if (!empty($CFG->hotpot_showtimes)) {
+        print '<H3>'.sprintf("%0.3f", microtime_diff($start, microtime())).' secs'."</H3>\n";
+    }
+
+    switch ($course->format) {
+        case 'weeks' : 
+            $title = get_string("week");
+            break;
+        case 'topics' : 
+            $title = get_string("topic");
+            break;
+        default : 
+            $title = '';
+            break;
+    }
+    if ($title) {
+        array_push($table->head, $title); 
+        array_push($table->align, "center");
+    }
+    if (isteacheredit($course->id)) {
+        array_push($table->head, $strupdate);
+        array_push($table->align, "center");
+    }
+    array_push($table->head, 
+        get_string("name"), 
+        get_string("quizcloses", "quiz"), 
+        get_string("bestgrade", "quiz"), 
+        get_string("attempts", "quiz")
+    );
+    array_push($table->align, 
+        "left", "left", "center", "left"
+    );
+    if (isadmin()) {
+        array_push($table->head, $strregrade);
+        array_push($table->align, "center");
+    }
+
+    $currentsection = -1;
+    foreach ($hotpots as $hotpot) {
+
+        $printsection = "";
+        if ($hotpot->section != $currentsection) {
+            if ($hotpot->section) {
+                $printsection = $hotpot->section;
+                if ($course->format=='weeks' || $course->format=='topics') {
+                    // Show the zoom boxes
+                    if ($displaysection==$hotpot->section) {
+                        $strshowall = get_string('showall'.$course->format);
+                        $printsection .= '<br /><a href="index.php?id='.$course->id.'&section=all" title="'.$strshowall.'"><img src="'.$CFG->pixpath.'/i/all.gif" height=25 width=16 border=0></a><br />';
+                    } else {
+                        $strshowone = get_string('showonly'.preg_replace('|s$|', '', $course->format, 1), '', $hotpot->section);
+                        $printsection .=  '<br /><a href="index.php?id='.$course->id.'&section='.$hotpot->section.'" title="'.$strshowone.'"><img src="'.$CFG->pixpath.'/i/one.gif" height=16 width=16 border=0></a><br />';
+                    }
+                }
+            }
+            if ($currentsection>=0) {
+                $table->data[] = 'hr';
+            }
+            $currentsection = $hotpot->section;
+        }
+
+        $class = ($hotpot->visible) ? '' : 'class="dimmed" ';
+        $quizname = '<a '.$class.'href="view.php?id='.$hotpot->coursemodule.'">'.$hotpot->name.'</A>';
+        $quizclose = empty($hotpot->timeclose) ? $strneverclosed : userdate($hotpot->timeclose);
+
+        // are there any totals for this hotpot?
+        if (empty($totals[$hotpot->id]->attemptcount)) {
+            $report = "&nbsp;";
+            $bestscore = "&nbsp;";
+
+        } else {
+            // report number of attempts and users
+            $report = get_string("viewallreports","quiz", $totals[$hotpot->id]->attemptcount);
+            if (isteacher($course->id)) {
+                $report .= " (".$totals[$hotpot->id]->usercount." $strusers)";
+            }
+            $report = '<a href="report.php?hp='.$hotpot->id.'">'.$report.'</a>';
+
+            // get best score
+            if (is_numeric($totals[$hotpot->id]->maxscore)) {
+                $bestscore = $totals[$hotpot->id]->maxscore." / $hotpot->grade";
+            } else {
+                $bestscore = "&nbsp;";
+            }
+        }
+
+        if (isadmin()) {
+            if (in_array($hotpot->id, $regradehotpots)) {
+                $report .= ' <font color="red">'.$strregraderequired.'</font>';
+            }
+        }
+
+        $data = array ();
+
+        if ($course->format=="weeks" || $course->format=="topics") {
+            array_push($data, $printsection);
+        }
+
+        if (isteacheredit($course->id)) {
+            $updatebutton = ''
+            .   '<form target="'.$CFG->framename.'" method="get" action="'.$CFG->wwwroot.'/course/mod.php">'
+            .   '<input type="hidden" name="update" value="'.$hotpot->coursemodule.'" />'
+            .   $sesskey
+            .   '<input type="submit" value="'.$strupdate.'" />'
+            .   '</form>'
+            ;
+            array_push($data, $updatebutton);
+        }
+
+        array_push($data, $quizname, $quizclose, $bestscore, $report);
+
+        if (isadmin()) {
+            if (empty($totals[$hotpot->id]->detailcount)) {
+                // no details records for this hotpot, so disable regrade
+                $regradebutton = '&nbsp;';
+            } else {
+                $strregradecheck = get_string('regradecheck', 'hotpot', strtr($hotpot->name, $quotes));
+                $regradebutton = ''
+                .   '<form target="_parent" method="post" action="'.$ME.'" onsubmit="var x=window.confirm('."'$strregradecheck'".');this.confirm.value=x;return x;">'
+                .   '<input type="hidden" name="id" value="'.$course->id.'">'
+                .   '<input type="hidden" name="regrade" value="'.$hotpot->id.'" />'
+                .   '<input type="hidden" name="confirm" value="" />'
+                .   $sesskey
+                .   '<input type="submit" value="'.$strregrade.'" />'
+                .   '</form>'
+                ;
+            }
+            array_push($data, $regradebutton);
+        }
+
+        $table->data[] = $data;
+    }
+
+    echo "<br />";
+
+    print_table($table);
+
+    // Finish the page
+    print_footer($course);
 ?>
index a14ddc72d2aa7252843c0535c7dd93832cac3e10..a7d2b4582bd2b485db4226b7ac4c6dbceca5ecef 100644 (file)
@@ -4,10 +4,10 @@
 /// CONFIGURATION settings
 
 if (!isset($CFG->hotpot_showtimes)) {
-       set_config("hotpot_showtimes", 0);
+    set_config("hotpot_showtimes", 0);
 }
 if (!isset($CFG->hotpot_excelencodings)) {
-       set_config("hotpot_excelencodings", "");
+    set_config("hotpot_excelencodings", "");
 }
 
 //////////////////////////////////
@@ -31,8 +31,8 @@ define("HOTPOT_LOCATION_COURSEFILES", "0");
 define("HOTPOT_LOCATION_SITEFILES",   "1");
 
 $HOTPOT_LOCATION = array (
-       HOTPOT_LOCATION_COURSEFILES => get_string("coursefiles"),
-       HOTPOT_LOCATION_SITEFILES   => get_string("sitefiles"),
+    HOTPOT_LOCATION_COURSEFILES => get_string("coursefiles"),
+    HOTPOT_LOCATION_SITEFILES   => get_string("sitefiles"),
 );
 
 define("HOTPOT_OUTPUTFORMAT_BEST",     "1");
@@ -46,34 +46,34 @@ define("HOTPOT_OUTPUTFORMAT_FLASH",   "20");
 define("HOTPOT_OUTPUTFORMAT_MOBILE",  "30");
 
 $HOTPOT_OUTPUTFORMAT = array (
-       HOTPOT_OUTPUTFORMAT_BEST    => get_string("outputformat_best", "hotpot"),
-       HOTPOT_OUTPUTFORMAT_V6_PLUS => get_string("outputformat_v6_plus", "hotpot"),
-       HOTPOT_OUTPUTFORMAT_V6      => get_string("outputformat_v6", "hotpot"),
-       HOTPOT_OUTPUTFORMAT_V5_PLUS => get_string("outputformat_v5_plus", "hotpot"),
-       HOTPOT_OUTPUTFORMAT_V5      => get_string("outputformat_v5", "hotpot"),
-       HOTPOT_OUTPUTFORMAT_V4      => get_string("outputformat_v4", "hotpot"),
-       HOTPOT_OUTPUTFORMAT_V3      => get_string("outputformat_v3", "hotpot"),
-       HOTPOT_OUTPUTFORMAT_FLASH   => get_string("outputformat_flash", "hotpot"),
-       HOTPOT_OUTPUTFORMAT_MOBILE  => get_string("outputformat_mobile", "hotpot"),
+    HOTPOT_OUTPUTFORMAT_BEST    => get_string("outputformat_best", "hotpot"),
+    HOTPOT_OUTPUTFORMAT_V6_PLUS => get_string("outputformat_v6_plus", "hotpot"),
+    HOTPOT_OUTPUTFORMAT_V6      => get_string("outputformat_v6", "hotpot"),
+    HOTPOT_OUTPUTFORMAT_V5_PLUS => get_string("outputformat_v5_plus", "hotpot"),
+    HOTPOT_OUTPUTFORMAT_V5      => get_string("outputformat_v5", "hotpot"),
+    HOTPOT_OUTPUTFORMAT_V4      => get_string("outputformat_v4", "hotpot"),
+    HOTPOT_OUTPUTFORMAT_V3      => get_string("outputformat_v3", "hotpot"),
+    HOTPOT_OUTPUTFORMAT_FLASH   => get_string("outputformat_flash", "hotpot"),
+    HOTPOT_OUTPUTFORMAT_MOBILE  => get_string("outputformat_mobile", "hotpot"),
 );
 $HOTPOT_OUTPUTFORMAT_DIR = array (
-       HOTPOT_OUTPUTFORMAT_V6_PLUS => 'v6',
-       HOTPOT_OUTPUTFORMAT_V6      => 'v6',
-       HOTPOT_OUTPUTFORMAT_V5_PLUS => 'v5',
-       HOTPOT_OUTPUTFORMAT_V5      => 'v5',
-       HOTPOT_OUTPUTFORMAT_V4      => 'v4',
-       HOTPOT_OUTPUTFORMAT_V3      => 'v3',
-       HOTPOT_OUTPUTFORMAT_FLASH   => 'flash',
-       HOTPOT_OUTPUTFORMAT_MOBILE  => 'mobile',
+    HOTPOT_OUTPUTFORMAT_V6_PLUS => 'v6',
+    HOTPOT_OUTPUTFORMAT_V6      => 'v6',
+    HOTPOT_OUTPUTFORMAT_V5_PLUS => 'v5',
+    HOTPOT_OUTPUTFORMAT_V5      => 'v5',
+    HOTPOT_OUTPUTFORMAT_V4      => 'v4',
+    HOTPOT_OUTPUTFORMAT_V3      => 'v3',
+    HOTPOT_OUTPUTFORMAT_FLASH   => 'flash',
+    HOTPOT_OUTPUTFORMAT_MOBILE  => 'mobile',
 );
 foreach ($HOTPOT_OUTPUTFORMAT_DIR as $format=>$dir) {
-       if (is_file("$CFG->hotpottemplate/$dir.php") && is_dir("$CFG->hotpottemplate/$dir")) {
-               // do nothing ($format is available)
-       } else {
-               // $format is not available, so remove it
-               unset($HOTPOT_OUTPUTFORMAT[$format]);
-               unset($HOTPOT_OUTPUTFORMAT_DIR[$format]);
-       }
+    if (is_file("$CFG->hotpottemplate/$dir.php") && is_dir("$CFG->hotpottemplate/$dir")) {
+        // do nothing ($format is available)
+    } else {
+        // $format is not available, so remove it
+        unset($HOTPOT_OUTPUTFORMAT[$format]);
+        unset($HOTPOT_OUTPUTFORMAT_DIR[$format]);
+    }
 }
 define("HOTPOT_NAVIGATION_BAR",     "1");
 define("HOTPOT_NAVIGATION_FRAME",   "2");
@@ -83,12 +83,12 @@ define("HOTPOT_NAVIGATION_GIVEUP",  "5");
 define("HOTPOT_NAVIGATION_NONE",    "6");
 
 $HOTPOT_NAVIGATION = array (
-       HOTPOT_NAVIGATION_BAR     => get_string("navigation_bar", "hotpot"),
-       HOTPOT_NAVIGATION_FRAME   => get_string("navigation_frame", "hotpot"),
-       HOTPOT_NAVIGATION_IFRAME  => get_string("navigation_iframe", "hotpot"),
-       HOTPOT_NAVIGATION_BUTTONS => get_string("navigation_buttons", "hotpot"),
-       HOTPOT_NAVIGATION_GIVEUP  => get_string("navigation_give_up", "hotpot"),
-       HOTPOT_NAVIGATION_NONE    => get_string("navigation_none", "hotpot"),
+    HOTPOT_NAVIGATION_BAR     => get_string("navigation_bar", "hotpot"),
+    HOTPOT_NAVIGATION_FRAME   => get_string("navigation_frame", "hotpot"),
+    HOTPOT_NAVIGATION_IFRAME  => get_string("navigation_iframe", "hotpot"),
+    HOTPOT_NAVIGATION_BUTTONS => get_string("navigation_buttons", "hotpot"),
+    HOTPOT_NAVIGATION_GIVEUP  => get_string("navigation_give_up", "hotpot"),
+    HOTPOT_NAVIGATION_NONE    => get_string("navigation_none", "hotpot"),
 );
 
 define("HOTPOT_JCB",    "1");
@@ -101,14 +101,14 @@ define("HOTPOT_TEXTOYS_RHUBARB",   "7");
 define("HOTPOT_TEXTOYS_SEQUITUR",  "8");
 
 $HOTPOT_QUIZTYPE = array(
-       HOTPOT_JCB    => 'JCB',
-       HOTPOT_JCLOZE => 'JCloze',
-       HOTPOT_JCROSS => 'JCross',
-       HOTPOT_JMATCH => 'JMatch',
-       HOTPOT_JMIX   => 'JMix',
-       HOTPOT_JQUIZ  => 'JQuiz',
-       HOTPOT_TEXTOYS_RHUBARB  => 'Rhubarb',
-       HOTPOT_TEXTOYS_SEQUITUR => 'Sequitur'
+    HOTPOT_JCB    => 'JCB',
+    HOTPOT_JCLOZE => 'JCloze',
+    HOTPOT_JCROSS => 'JCross',
+    HOTPOT_JMATCH => 'JMatch',
+    HOTPOT_JMIX   => 'JMix',
+    HOTPOT_JQUIZ  => 'JQuiz',
+    HOTPOT_TEXTOYS_RHUBARB  => 'Rhubarb',
+    HOTPOT_TEXTOYS_SEQUITUR => 'Sequitur'
 );
 
 define("HOTPOT_JQUIZ_MULTICHOICE", "1");
@@ -122,10 +122,10 @@ define("HOTPOT_GRADEMETHOD_FIRST",   "3");
 define("HOTPOT_GRADEMETHOD_LAST",    "4");
 
 $HOTPOT_GRADEMETHOD = array (
-       HOTPOT_GRADEMETHOD_HIGHEST => get_string("gradehighest", "quiz"),
-       HOTPOT_GRADEMETHOD_AVERAGE => get_string("gradeaverage", "quiz"),
-       HOTPOT_GRADEMETHOD_FIRST   => get_string("attemptfirst", "quiz"),
-       HOTPOT_GRADEMETHOD_LAST    => get_string("attemptlast",  "quiz"),
+    HOTPOT_GRADEMETHOD_HIGHEST => get_string("gradehighest", "quiz"),
+    HOTPOT_GRADEMETHOD_AVERAGE => get_string("gradeaverage", "quiz"),
+    HOTPOT_GRADEMETHOD_FIRST   => get_string("attemptfirst", "quiz"),
+    HOTPOT_GRADEMETHOD_LAST    => get_string("attemptlast",  "quiz"),
 );
 
 define("HOTPOT_STATUS_INPROGRESS", "1");
@@ -134,10 +134,10 @@ define("HOTPOT_STATUS_ABANDONED",  "3");
 define("HOTPOT_STATUS_COMPLETED",  "4");
 
 $HOTPOT_STATUS = array (
-       HOTPOT_STATUS_INPROGRESS => get_string("inprogress", "hotpot"),
-       HOTPOT_STATUS_TIMEDOUT   => get_string("timedout",   "hotpot"),
-       HOTPOT_STATUS_ABANDONED  => get_string("abandoned",  "hotpot"),
-       HOTPOT_STATUS_COMPLETED  => get_string("completed",  "hotpot"),
+    HOTPOT_STATUS_INPROGRESS => get_string("inprogress", "hotpot"),
+    HOTPOT_STATUS_TIMEDOUT   => get_string("timedout",   "hotpot"),
+    HOTPOT_STATUS_ABANDONED  => get_string("abandoned",  "hotpot"),
+    HOTPOT_STATUS_COMPLETED  => get_string("completed",  "hotpot"),
 );
 
 define("HOTPOT_FEEDBACK_NONE", "0");
@@ -147,14 +147,14 @@ define("HOTPOT_FEEDBACK_MOODLEFORUM", "3");
 define("HOTPOT_FEEDBACK_MOODLEMESSAGING", "4");
 
 $HOTPOT_FEEDBACK = array (
-       HOTPOT_FEEDBACK_NONE => get_string("feedbacknone", "hotpot"),
-       HOTPOT_FEEDBACK_WEBPAGE => get_string("feedbackwebpage",  "hotpot"),
-       HOTPOT_FEEDBACK_FORMMAIL => get_string("feedbackformmail", "hotpot"),
-       HOTPOT_FEEDBACK_MOODLEFORUM => get_string("feedbackmoodleforum", "hotpot"),
-       HOTPOT_FEEDBACK_MOODLEMESSAGING => get_string("feedbackmoodlemessaging", "hotpot"),
+    HOTPOT_FEEDBACK_NONE => get_string("feedbacknone", "hotpot"),
+    HOTPOT_FEEDBACK_WEBPAGE => get_string("feedbackwebpage",  "hotpot"),
+    HOTPOT_FEEDBACK_FORMMAIL => get_string("feedbackformmail", "hotpot"),
+    HOTPOT_FEEDBACK_MOODLEFORUM => get_string("feedbackmoodleforum", "hotpot"),
+    HOTPOT_FEEDBACK_MOODLEMESSAGING => get_string("feedbackmoodlemessaging", "hotpot"),
 );
 if (empty($CFG->messaging)) { // Moodle 1.4 (and less)
-       unset($HOTPOT_FEEDBACK[HOTPOT_FEEDBACK_MOODLEMESSAGING]);
+    unset($HOTPOT_FEEDBACK[HOTPOT_FEEDBACK_MOODLEMESSAGING]);
 }
 
 define("HOTPOT_DISPLAYNEXT_QUIZ",   "0");
@@ -175,662 +175,662 @@ define("HOTPOT_DISPLAYNEXT_INDEX",  "2");
 
 // $hp is an object containing the values of the form in mod.html
 // i.e. all the fields in the 'hotpot' table, plus the following:
-//     $hp->course       : an id in the 'course' table
-//     $hp->coursemodule : an id in the 'course_modules' table
-//     $hp->section      : an id in the 'course_sections' table
-//     $hp->module       : an id in the 'modules' table
-//     $hp->modulename   : always 'hotpot'
-//     $hp->instance     : an id in the 'hotpot' table
-//     $hp->mode         : 'add' or 'update'
-//     $hp->sesskey      : unique string required for Moodle's session management
+//  $hp->course       : an id in the 'course' table
+//  $hp->coursemodule : an id in the 'course_modules' table
+//  $hp->section      : an id in the 'course_sections' table
+//  $hp->module       : an id in the 'modules' table
+//  $hp->modulename   : always 'hotpot'
+//  $hp->instance     : an id in the 'hotpot' table
+//  $hp->mode         : 'add' or 'update'
+//  $hp->sesskey      : unique string required for Moodle's session management
 
 function hotpot_add_instance(&$hp) {
-       if (hotpot_set_form_values($hp)) {
-               $result = insert_record("hotpot", $hp);
-       } else {
-               $result=  false;
-       }
-       return $result;
+    if (hotpot_set_form_values($hp)) {
+        $result = insert_record("hotpot", $hp);
+    } else {
+        $result=  false;
+    }
+    return $result;
 }
 
 function hotpot_update_instance(&$hp) {
-       if (hotpot_set_form_values($hp)) {
-               $hp->id = $hp->instance;
-               $result = update_record("hotpot", $hp);
-       } else {
-               $result=  false;
-       }
-       return $result;
+    if (hotpot_set_form_values($hp)) {
+        $hp->id = $hp->instance;
+        $result = update_record("hotpot", $hp);
+    } else {
+        $result=  false;
+    }
+    return $result;
 }
 
 function hotpot_set_form_values(&$hp) {
-       $ok = true;
-       $hp->errors = array(); // these will be reported by moderr.html
-
-       if (empty($hp->reference)) {
-               $ok = false;
-               $hp->errors['reference']= get_string('error_nofilename', 'hotpot');
-       }
-
-       if ($hp->studentfeedbackurl=='http://') {
-               $hp->studentfeedbackurl = '';
-       }
-
-       if (empty($hp->studentfeedbackurl)) {
-               switch ($hp->studentfeedback) {
-                       case HOTPOT_FEEDBACK_WEBPAGE:
-                               $ok = false;
-                               $hp->errors['studentfeedbackurl']= get_string('error_nofeedbackurlwebpage', 'hotpot');
-                       break;
-                       case HOTPOT_FEEDBACK_FORMMAIL:
-                               $ok = false;
-                               $hp->errors['studentfeedbackurl']= get_string('error_nofeedbackurlformmail', 'hotpot');
-                       break;
-               }
-       }
-
-       $time = time();
-       $hp->timecreated = $time;
-       $hp->timemodified = $time;
-
-       if (empty($hp->enabletimeopen)) {
-               $hp->timeopen = 0;
-       } else {
-               $hp->timeopen = make_timestamp(
-                       $hp->openyear, $hp->openmonth, $hp->openday,
-                       $hp->openhour, $hp->openminute, 0
-               );
-       }
-
-       if (empty($hp->enabletimeclose)) {
-               $hp->timeclose = 0;
-       } else {
-               $hp->timeclose = make_timestamp(
-                       $hp->closeyear, $hp->closemonth, $hp->closeday,
-                       $hp->closehour, $hp->closeminute, 0
-               );
-       }
-
-       if ($hp->quizchain==HOTPOT_YES) {
-               switch ($hp->mode) {
-                       case 'add':
-                               $ok = hotpot_add_chain($hp);
-                       break;
-                       case 'update':
-                               $ok = hotpot_update_chain($hp);
-                       break;
-               }
-       } else { // $hp->quizchain==HOTPOT_NO
-               hotpot_set_name_summary_reference($hp);
-       }
-
-       switch ($hp->displaynext) {
-               // N.B. redirection only works for Moodle 1.5+
-               case HOTPOT_DISPLAYNEXT_COURSE:
-                       $hp->redirect = true;
-                       $hp->redirecturl = "view.php?id=$hp->course";
-                       break;
-               case HOTPOT_DISPLAYNEXT_INDEX:
-                       $hp->redirect = true;
-                       $hp->redirecturl = "../mod/hotpot/index.php?id=$hp->course";
-                       break;
-               default:
-                       // use Moodle default action (i.e. go on to display the hotpot quiz)
-       }
-
-       // if ($ok && $hp->setdefaults) {
-       if ($ok) {
-               set_user_preference('hotpot_timeopen', $hp->timeopen);
-               set_user_preference('hotpot_timeclose', $hp->timeclose);
-               set_user_preference('hotpot_navigation', $hp->navigation);
-               set_user_preference('hotpot_outputformat', $hp->outputformat);
-               set_user_preference('hotpot_studentfeedback', $hp->studentfeedback);
-               set_user_preference('hotpot_studentfeedbackurl', $hp->studentfeedbackurl);
-               set_user_preference('hotpot_forceplugins', $hp->forceplugins);
-               set_user_preference('hotpot_shownextquiz', $hp->shownextquiz);
-               set_user_preference('hotpot_review', $hp->review);
-               set_user_preference('hotpot_grade', $hp->grade);
-               set_user_preference('hotpot_grademethod', $hp->grademethod);
-               set_user_preference('hotpot_attempts', $hp->attempts);
-               set_user_preference('hotpot_subnet', $hp->subnet);
-               set_user_preference('hotpot_displaynext', $hp->displaynext);
-               if ($hp->mode=='add') {
-                       set_user_preference('hotpot_quizchain', $hp->quizchain);
-                       set_user_preference('hotpot_namesource', $hp->namesource);
-                       set_user_preference('hotpot_summarysource', $hp->summarysource);
-               }
-       }
-       return $ok;
+    $ok = true;
+    $hp->errors = array(); // these will be reported by moderr.html
+
+    if (empty($hp->reference)) {
+        $ok = false;
+        $hp->errors['reference']= get_string('error_nofilename', 'hotpot');
+    }
+
+    if ($hp->studentfeedbackurl=='http://') {
+        $hp->studentfeedbackurl = '';
+    }
+
+    if (empty($hp->studentfeedbackurl)) {
+        switch ($hp->studentfeedback) {
+            case HOTPOT_FEEDBACK_WEBPAGE:
+                $ok = false;
+                $hp->errors['studentfeedbackurl']= get_string('error_nofeedbackurlwebpage', 'hotpot');
+            break;
+            case HOTPOT_FEEDBACK_FORMMAIL:
+                $ok = false;
+                $hp->errors['studentfeedbackurl']= get_string('error_nofeedbackurlformmail', 'hotpot');
+            break;
+        }
+    }
+
+    $time = time();
+    $hp->timecreated = $time;
+    $hp->timemodified = $time;
+
+    if (empty($hp->enabletimeopen)) {
+        $hp->timeopen = 0;
+    } else {
+        $hp->timeopen = make_timestamp(
+            $hp->openyear, $hp->openmonth, $hp->openday,
+            $hp->openhour, $hp->openminute, 0
+        );
+    }
+
+    if (empty($hp->enabletimeclose)) {
+        $hp->timeclose = 0;
+    } else {
+        $hp->timeclose = make_timestamp(
+            $hp->closeyear, $hp->closemonth, $hp->closeday,
+            $hp->closehour, $hp->closeminute, 0
+        );
+    }
+
+    if ($hp->quizchain==HOTPOT_YES) {
+        switch ($hp->mode) {
+            case 'add':
+                $ok = hotpot_add_chain($hp);
+            break;
+            case 'update':
+                $ok = hotpot_update_chain($hp);
+            break;
+        }
+    } else { // $hp->quizchain==HOTPOT_NO
+        hotpot_set_name_summary_reference($hp);
+    }
+
+    switch ($hp->displaynext) {
+        // N.B. redirection only works for Moodle 1.5+
+        case HOTPOT_DISPLAYNEXT_COURSE:
+            $hp->redirect = true;
+            $hp->redirecturl = "view.php?id=$hp->course";
+            break;
+        case HOTPOT_DISPLAYNEXT_INDEX:
+            $hp->redirect = true;
+            $hp->redirecturl = "../mod/hotpot/index.php?id=$hp->course";
+            break;
+        default:
+            // use Moodle default action (i.e. go on to display the hotpot quiz)
+    }
+
+    // if ($ok && $hp->setdefaults) {
+    if ($ok) {
+        set_user_preference('hotpot_timeopen', $hp->timeopen);
+        set_user_preference('hotpot_timeclose', $hp->timeclose);
+        set_user_preference('hotpot_navigation', $hp->navigation);
+        set_user_preference('hotpot_outputformat', $hp->outputformat);
+        set_user_preference('hotpot_studentfeedback', $hp->studentfeedback);
+        set_user_preference('hotpot_studentfeedbackurl', $hp->studentfeedbackurl);
+        set_user_preference('hotpot_forceplugins', $hp->forceplugins);
+        set_user_preference('hotpot_shownextquiz', $hp->shownextquiz);
+        set_user_preference('hotpot_review', $hp->review);
+        set_user_preference('hotpot_grade', $hp->grade);
+        set_user_preference('hotpot_grademethod', $hp->grademethod);
+        set_user_preference('hotpot_attempts', $hp->attempts);
+        set_user_preference('hotpot_subnet', $hp->subnet);
+        set_user_preference('hotpot_displaynext', $hp->displaynext);
+        if ($hp->mode=='add') {
+            set_user_preference('hotpot_quizchain', $hp->quizchain);
+            set_user_preference('hotpot_namesource', $hp->namesource);
+            set_user_preference('hotpot_summarysource', $hp->summarysource);
+        }
+    }
+    return $ok;
 }
 function hotpot_get_chain(&$cm) {
-       // get details of course_modules in this section
-       $course_module_ids = get_field('course_sections', 'sequence', 'id', $cm->section);
-       if (empty($course_module_ids)) {
-               $hotpot_modules = array();
-       } else {
-               $hotpot_modules = get_records_select('course_modules', "id IN ($course_module_ids) AND module=$cm->module");
-               if (empty($hotpot_modules)) {
-                       $hotpot_modules = array();
-               }
-       }
-
-       // get ids of hotpot modules in this section
-       $ids = array();
-       foreach ($hotpot_modules as $hotpot_module) {
-               $ids[] = $hotpot_module->instance;
-       }
-
-       // get details of hotpots in this section
-       if (empty($ids)) {
-               $hotpots = array();
-       } else {
-               $hotpots = get_records_list('hotpot', 'id', implode(',', $ids));
-       }
-
-       $found = false;
-       $chain = array();
-
-       // loop through course_modules in this section
-       $ids = explode(',', $course_module_ids);
-       foreach ($ids as $id) {
-
-               // check this course_module is a hotpot activity
-               if (isset($hotpot_modules[$id])) {
-
-                       // store details of this course module and hotpot activity
-                       $hotpot_id = $hotpot_modules[$id]->instance;
-                       $chain[$id] = &$hotpot_modules[$id];
-                       $chain[$id]->hotpot = &$hotpots[$hotpot_id];
-
-                       // set $found, if this is the course module we're looking for
-                       if (isset($cm->coursemodule)) {
-                               if ($id==$cm->coursemodule) {
-                                       $found = true;
-                               }
-                       } else {
-                               if ($id==$cm->id) {
-                                       $found = true;
-                               }
-                       }
-
-                       // is this the end of a chain
-                       if (empty($hotpots[$hotpot_id]->shownextquiz)) {
-                               if ($found) {
-                                       break; // out of loop
-                               } else {
-                                       // restart chain (target cm has not been found yet)
-                                       $chain = array();
-                               }
-                       }
-               }
-       } // end foreach $ids
-
-       return $found ? $chain : false;
+    // get details of course_modules in this section
+    $course_module_ids = get_field('course_sections', 'sequence', 'id', $cm->section);
+    if (empty($course_module_ids)) {
+        $hotpot_modules = array();
+    } else {
+        $hotpot_modules = get_records_select('course_modules', "id IN ($course_module_ids) AND module=$cm->module");
+        if (empty($hotpot_modules)) {
+            $hotpot_modules = array();
+        }
+    }
+
+    // get ids of hotpot modules in this section
+    $ids = array();
+    foreach ($hotpot_modules as $hotpot_module) {
+        $ids[] = $hotpot_module->instance;
+    }
+
+    // get details of hotpots in this section
+    if (empty($ids)) {
+        $hotpots = array();
+    } else {
+        $hotpots = get_records_list('hotpot', 'id', implode(',', $ids));
+    }
+
+    $found = false;
+    $chain = array();
+
+    // loop through course_modules in this section
+    $ids = explode(',', $course_module_ids);
+    foreach ($ids as $id) {
+
+        // check this course_module is a hotpot activity
+        if (isset($hotpot_modules[$id])) {
+
+            // store details of this course module and hotpot activity
+            $hotpot_id = $hotpot_modules[$id]->instance;
+            $chain[$id] = &$hotpot_modules[$id];
+            $chain[$id]->hotpot = &$hotpots[$hotpot_id];
+
+            // set $found, if this is the course module we're looking for
+            if (isset($cm->coursemodule)) {
+                if ($id==$cm->coursemodule) {
+                    $found = true;
+                }
+            } else {
+                if ($id==$cm->id) {
+                    $found = true;
+                }
+            }
+
+            // is this the end of a chain
+            if (empty($hotpots[$hotpot_id]->shownextquiz)) {
+                if ($found) {
+                    break; // out of loop
+                } else {
+                    // restart chain (target cm has not been found yet)
+                    $chain = array();
+                }
+            }
+        }
+    } // end foreach $ids
+
+    return $found ? $chain : false;
 }
 function hotpot_is_visible(&$cm) {
-       if (!isset($cm->sectionvisible)) {
-               if ($section = get_record('course_sections', 'id', $cm->section)) {
-                       $cm->sectionvisible = $section->visible;
-               } else {
-                       error('Course module record contains invalid section');
-               }
-       }
-
-       if (empty($cm->sectionvisible)) {
-               $visible = HOTPOT_NO;
-       } else {
-               $visible = HOTPOT_YES;
-               if (empty($cm->visible)) {
-                       if ($chain = hotpot_get_chain($cm)) {
-                               $startofchain = array_shift($chain);
-                               $visible = $startofchain->visible;
-                       }
-               }
-       }
-       return $visible;
+    if (!isset($cm->sectionvisible)) {
+        if ($section = get_record('course_sections', 'id', $cm->section)) {
+            $cm->sectionvisible = $section->visible;
+        } else {
+            error('Course module record contains invalid section');
+        }
+    }
+
+    if (empty($cm->sectionvisible)) {
+        $visible = HOTPOT_NO;
+    } else {
+        $visible = HOTPOT_YES;
+        if (empty($cm->visible)) {
+            if ($chain = hotpot_get_chain($cm)) {
+                $startofchain = array_shift($chain);
+                $visible = $startofchain->visible;
+            }
+        }
+    }
+    return $visible;
 }
 function hotpot_add_chain(&$hp) {
 /// add a chain of hotpot actiivities
 
-       global $CFG, $course;
-
-       $ok = true;
-       $hp->names = array();
-       $hp->summaries = array();
-       $hp->references = array();
-
-       $xml_quiz = new hotpot_xml_quiz($hp, false, false, false, false, false);
-
-       if (isset($xml_quiz->error)) {
-               $hp->errors['reference'] = $xml_quiz->error;
-               $ok = false;
-
-       } else if (is_dir($xml_quiz->filepath)) {
-
-               // get list of hotpot files in this folder
-               if ($dh = @opendir($xml_quiz->filepath)) {
-                       while ($file = @readdir($dh)) {
-                               if (preg_match('/\.(jbc|jcl|jcw|jmt|jmx|jqz|htm|html)$/', $file)) {
-                                       $hp->references[] = "$xml_quiz->reference/$file";
-                               }
-                       }
-                       closedir($dh);
-
-                       // get titles
-                       foreach ($hp->references as $i=>$reference) {
-                               $filepath = $xml_quiz->fileroot.'/'.$reference;
-                               hotpot_get_titles_and_next_ex($hp, $filepath);
-                               $hp->names[$i] = $hp->exercisetitle;
-                               $hp->summaries[$i] = $hp->exercisesubtitle;
-                       }
-
-               } else {
-                       $ok = false;
-                       $hp->errors['reference'] = get_string('error_couldnotopenfolder', 'hotpot', $hp->reference);
-               }
-
-       } else if (is_file($xml_quiz->filepath)) {
-
-               $filerootlength = strlen($xml_quiz->fileroot) + 1;
-
-               while ($xml_quiz->filepath) {
-                       hotpot_get_titles_and_next_ex($hp, $xml_quiz->filepath, true);
-                       $hp->names[] = $hp->exercisetitle;
-                       $hp->summaries[] = $hp->exercisesubtitle;
-                       $hp->references[] = substr($xml_quiz->filepath, $filerootlength);
-
-                       if ($hp->nextexercise) {
-                               $filepath = $xml_quiz->fileroot.'/'.$xml_quiz->filesubdir.$hp->nextexercise;
-
-                               // check file is not already in chain
-                               $reference = substr($filepath, $filerootlength);
-                               if (in_array($reference, $hp->references)) {
-                                       $filepath = '';
-                               }
-                       } else {
-                               $filepath = '';
-                       }
-                       if ($filepath && file_exists($filepath) && is_file($filepath) && is_readable($filepath)) {
-                               $xml_quiz->filepath = $filepath;
-                       } else {
-                               $xml_quiz->filepath = false; // finish while loop
-                       }
-               } // end while
-
-       } else {
-               $ok = false;
-               $hp->errors['reference'] = get_string('error_notfileorfolder', 'hotpot', $hp->reference);
-       }
-
-       if (empty($hp->references) && empty($hp->errors['reference'])) {
-               $ok = false;
-               $hp->errors['reference'] = get_string('error_noquizzesfound', 'hotpot', $hp->reference);
-       }
-
-       if ($ok) {
-               $hp->visible = HOTPOT_YES;
-
-               if (trim($hp->name)=='') {
-                       $hp->name = get_string("modulename", $hp->modulename);
-               }
-               $hp->specificname = $hp->name;
-               $hp->specificsummary = $hp->summary;
-
-               // add all except last activity in chain
-
-               $i_max = count($hp->references)-1;
-               for ($i=0; $i<$i_max; $i++) {
-
-                       hotpot_set_name_summary_reference($hp, $i);
-                       $hp->reference = addslashes($hp->reference);
-
-                       if (!$hp->instance = insert_record("hotpot", $hp)) {
-                               error("Could not add a new instance of $hp->modulename", "view.php?id=$hp->course");
-                       }
-
-                       // store (hotpot table) id of start of chain
-                       if ($i==0) {
-                               $hp->startofchain = $hp->instance;
-                       }
-
-                       if (isset($course->groupmode)) {
-                               $hp->groupmode = $course->groupmode;
-                       }
-
-                       if (! $hp->coursemodule = add_course_module($hp)) {
-                               error("Could not add a new course module");
-                       }
-                       if (! $sectionid = add_mod_to_section($hp) ) {
-                               error("Could not add the new course module to that section");
-                       }
-
-                       if (! set_field("course_modules", "section", $sectionid, "id", $hp->coursemodule)) {
-                               error("Could not update the course module with the correct section");
-                       }
-
-                       add_to_log($hp->course, "course", "add mod",
-                               "../mod/$hp->modulename/view.php?id=$hp->coursemodule",
-                               "$hp->modulename $hp->instance"
-                       );
-                       add_to_log($hp->course, $hp->modulename, "add",
-                               "view.php?id=$hp->coursemodule",
-                               "$hp->instance", $hp->coursemodule
-                       );
-
-                       // hide tail of chain
-                       if ($hp->shownextquiz==HOTPOT_YES) {
-                               $hp->visible = HOTPOT_NO;
-                       }
-               } // end for ($hp->references)
-
-               // settings for final activity in chain
-               hotpot_set_name_summary_reference($hp, $i);
-               $hp->reference = addslashes($hp->references[$i]);
-               $hp->shownextquiz = HOTPOT_NO;
-
-               if (isset($hp->startofchain)) {
-                       // redirection only works for Moodle 1.5+
-                       $hp->redirect = true;
-                       $hp->redirecturl = "$CFG->wwwroot/mod/hotpot/view.php?hp=$hp->startofchain";
-               }
-       } // end if $ok
-
-       return $ok;
+    global $CFG, $course;
+
+    $ok = true;
+    $hp->names = array();
+    $hp->summaries = array();
+    $hp->references = array();
+
+    $xml_quiz = new hotpot_xml_quiz($hp, false, false, false, false, false);
+
+    if (isset($xml_quiz->error)) {
+        $hp->errors['reference'] = $xml_quiz->error;
+        $ok = false;
+
+    } else if (is_dir($xml_quiz->filepath)) {
+
+        // get list of hotpot files in this folder
+        if ($dh = @opendir($xml_quiz->filepath)) {
+            while ($file = @readdir($dh)) {
+                if (preg_match('/\.(jbc|jcl|jcw|jmt|jmx|jqz|htm|html)$/', $file)) {
+                    $hp->references[] = "$xml_quiz->reference/$file";
+                }
+            }
+            closedir($dh);
+
+            // get titles
+            foreach ($hp->references as $i=>$reference) {
+                $filepath = $xml_quiz->fileroot.'/'.$reference;
+                hotpot_get_titles_and_next_ex($hp, $filepath);
+                $hp->names[$i] = $hp->exercisetitle;
+                $hp->summaries[$i] = $hp->exercisesubtitle;
+            }
+
+        } else {
+            $ok = false;
+            $hp->errors['reference'] = get_string('error_couldnotopenfolder', 'hotpot', $hp->reference);
+        }
+
+    } else if (is_file($xml_quiz->filepath)) {
+
+        $filerootlength = strlen($xml_quiz->fileroot) + 1;
+
+        while ($xml_quiz->filepath) {
+            hotpot_get_titles_and_next_ex($hp, $xml_quiz->filepath, true);
+            $hp->names[] = $hp->exercisetitle;
+            $hp->summaries[] = $hp->exercisesubtitle;
+            $hp->references[] = substr($xml_quiz->filepath, $filerootlength);
+
+            if ($hp->nextexercise) {
+                $filepath = $xml_quiz->fileroot.'/'.$xml_quiz->filesubdir.$hp->nextexercise;
+
+                // check file is not already in chain
+                $reference = substr($filepath, $filerootlength);
+                if (in_array($reference, $hp->references)) {
+                    $filepath = '';
+                }
+            } else {
+                $filepath = '';
+            }
+            if ($filepath && file_exists($filepath) && is_file($filepath) && is_readable($filepath)) {
+                $xml_quiz->filepath = $filepath;
+            } else {
+                $xml_quiz->filepath = false; // finish while loop
+            }
+        } // end while
+
+    } else {
+        $ok = false;
+        $hp->errors['reference'] = get_string('error_notfileorfolder', 'hotpot', $hp->reference);
+    }
+
+    if (empty($hp->references) && empty($hp->errors['reference'])) {
+        $ok = false;
+        $hp->errors['reference'] = get_string('error_noquizzesfound', 'hotpot', $hp->reference);
+    }
+
+    if ($ok) {
+        $hp->visible = HOTPOT_YES;
+
+        if (trim($hp->name)=='') {
+            $hp->name = get_string("modulename", $hp->modulename);
+        }
+        $hp->specificname = $hp->name;
+        $hp->specificsummary = $hp->summary;
+
+        // add all except last activity in chain
+
+        $i_max = count($hp->references)-1;
+        for ($i=0; $i<$i_max; $i++) {
+
+            hotpot_set_name_summary_reference($hp, $i);
+            $hp->reference = addslashes($hp->reference);
+
+            if (!$hp->instance = insert_record("hotpot", $hp)) {
+                error("Could not add a new instance of $hp->modulename", "view.php?id=$hp->course");
+            }
+
+            // store (hotpot table) id of start of chain
+            if ($i==0) {
+                $hp->startofchain = $hp->instance;
+            }
+
+            if (isset($course->groupmode)) {
+                $hp->groupmode = $course->groupmode;
+            }
+
+            if (! $hp->coursemodule = add_course_module($hp)) {
+                error("Could not add a new course module");
+            }
+            if (! $sectionid = add_mod_to_section($hp) ) {
+                error("Could not add the new course module to that section");
+            }
+
+            if (! set_field("course_modules", "section", $sectionid, "id", $hp->coursemodule)) {
+                error("Could not update the course module with the correct section");
+            }
+
+            add_to_log($hp->course, "course", "add mod",
+                "../mod/$hp->modulename/view.php?id=$hp->coursemodule",
+                "$hp->modulename $hp->instance"
+            );
+            add_to_log($hp->course, $hp->modulename, "add",
+                "view.php?id=$hp->coursemodule",
+                "$hp->instance", $hp->coursemodule
+            );
+
+            // hide tail of chain
+            if ($hp->shownextquiz==HOTPOT_YES) {
+                $hp->visible = HOTPOT_NO;
+            }
+        } // end for ($hp->references)
+
+        // settings for final activity in chain
+        hotpot_set_name_summary_reference($hp, $i);
+        $hp->reference = addslashes($hp->references[$i]);
+        $hp->shownextquiz = HOTPOT_NO;
+
+        if (isset($hp->startofchain)) {
+            // redirection only works for Moodle 1.5+
+            $hp->redirect = true;
+            $hp->redirecturl = "$CFG->wwwroot/mod/hotpot/view.php?hp=$hp->startofchain";
+        }
+    } // end if $ok
+
+    return $ok;
 }
 function hotpot_set_name_summary_reference(&$hp, $chain_index=NULL) {
 
-       $xml_quiz = NULL;
-
-       $textfields = array('name', 'summary');
-       foreach ($textfields as $textfield) {
-
-               $textsource = $textfield.'source';
-
-               // are we adding a chain?
-               if (isset($chain_index)) {
-
-                       switch ($hp->$textsource) {
-                               case HOTPOT_TEXTSOURCE_QUIZ:
-                                       if ($textfield=='name') {
-                                               $hp->exercisetitle = $hp->names[$chain_index];
-                                       } else if ($textfield=='summary') {
-                                               $hp->exercisesubtitle = $hp->summaries[$chain_index];
-                                       }
-                                       break;
-                               case HOTPOT_TEXTSOURCE_SPECIFIC:
-                                       $specifictext = 'specific'.$textfield;
-                                       if (empty($hp->$specifictext) && trim($hp->$specifictext)=='') {
-                                               $hp->$textfield = '';
-                                       } else {
-                                               $hp->$textfield = $hp->$specifictext.' ('.($chain_index+1).')';
-                                       }
-                                       break;
-                       }
-                       $hp->reference = $hp->references[$chain_index];
-               }
-
-               if ($hp->$textsource==HOTPOT_TEXTSOURCE_QUIZ) {
-                       if (empty($xml_quiz) && !isset($chain_index)) {
-                               $xml_quiz = new hotpot_xml_quiz($hp, false, false, false, false, false);
-                               hotpot_get_titles_and_next_ex($hp, $xml_quiz->filepath);
-                       }
-                       if ($textfield=='name') {
-                               $hp->$textfield = addslashes($hp->exercisetitle);
-                       } else if ($textfield=='summary') {
-                               $hp->$textfield = addslashes($hp->exercisesubtitle);
-                       }
-               }
-               switch ($hp->$textsource) {
-                       case HOTPOT_TEXTSOURCE_FILENAME:
-                               $hp->$textfield = basename($hp->reference);
-                               break;
-                       case HOTPOT_TEXTSOURCE_FILEPATH:
-                               $hp->$textfield = '';
-                               // continue to next lines
-                       default:
-                               if (empty($hp->$textfield)) {
-                                       $hp->$textfield = str_replace('/', ' ', $hp->reference);
-                               }
-               } // end switch
-       } // end foreach
+    $xml_quiz = NULL;
+
+    $textfields = array('name', 'summary');
+    foreach ($textfields as $textfield) {
+
+        $textsource = $textfield.'source';
+
+        // are we adding a chain?
+        if (isset($chain_index)) {
+
+            switch ($hp->$textsource) {
+                case HOTPOT_TEXTSOURCE_QUIZ:
+                    if ($textfield=='name') {
+                        $hp->exercisetitle = $hp->names[$chain_index];
+                    } else if ($textfield=='summary') {
+                        $hp->exercisesubtitle = $hp->summaries[$chain_index];
+                    }
+                    break;
+                case HOTPOT_TEXTSOURCE_SPECIFIC:
+                    $specifictext = 'specific'.$textfield;
+                    if (empty($hp->$specifictext) && trim($hp->$specifictext)=='') {
+                        $hp->$textfield = '';
+                    } else {
+                        $hp->$textfield = $hp->$specifictext.' ('.($chain_index+1).')';
+                    }
+                    break;
+            }
+            $hp->reference = $hp->references[$chain_index];
+        }
+
+        if ($hp->$textsource==HOTPOT_TEXTSOURCE_QUIZ) {
+            if (empty($xml_quiz) && !isset($chain_index)) {
+                $xml_quiz = new hotpot_xml_quiz($hp, false, false, false, false, false);
+                hotpot_get_titles_and_next_ex($hp, $xml_quiz->filepath);
+            }
+            if ($textfield=='name') {
+                $hp->$textfield = addslashes($hp->exercisetitle);
+            } else if ($textfield=='summary') {
+                $hp->$textfield = addslashes($hp->exercisesubtitle);
+            }
+        }
+        switch ($hp->$textsource) {
+            case HOTPOT_TEXTSOURCE_FILENAME:
+                $hp->$textfield = basename($hp->reference);
+                break;
+            case HOTPOT_TEXTSOURCE_FILEPATH:
+                $hp->$textfield = '';
+                // continue to next lines
+            default:
+                if (empty($hp->$textfield)) {
+                    $hp->$textfield = str_replace('/', ' ', $hp->reference);
+                }
+        } // end switch
+    } // end foreach
 }
 function hotpot_get_titles_and_next_ex(&$hp, $filepath, $get_next=false) {
 
-       $hp->exercisetitle = '';
-       $hp->exercisesubtitle = '';
-       $hp->nextexercise = '';
-
-       // read the quiz file source
-       if ($source = file_get_contents($filepath)) {
-
-               $next = '';
-               $title = '';
-               $subtitle = '';
-
-               if (preg_match('|\.html?$|', $filepath)) {
-                       // html file
-                       if (preg_match('|<h2[^>]*class="ExerciseTitle"[^>]*>(.*?)</h2>|is', $source, $matches)) {
-                               $title = trim(strip_tags($matches[1]));
-                       }
-                       if (empty($title)) {
-                               if (preg_match('|<title[^>]*>(.*?)</title>|is', $source, $matches)) {
-                                       $title = trim(strip_tags($matches[1]));
-                               }
-                       }
-                       if (preg_match('|<h3[^>]*class="ExerciseSubtitle"[^>]*>(.*?)</h3>|is', $source, $matches)) {
-                               $subtitle = trim(strip_tags($matches[1]));
-                       }
-                       if ($get_next) {
-                               if (preg_match('|<div[^>]*class="NavButtonBar"[^>]*>(.*?)</div>|is', $source, $matches)) {
-                                       $navbuttonbar = $matches[1];
-                                       if (preg_match_all('|<button[^>]*class="NavButton"[^>]*onclick="'."location='([^']*)'".'[^"]*"[^>]*>|is', $navbuttonbar, $matches)) {
-                                               $lastbutton = count($matches[0])-1;
-                                               $next = $matches[1][$lastbutton];
-                                       }
-                               }
-                       }
-
-               } else {
-                       // xml file (...maybe)
-                       $xml_tree = new hotpot_xml_tree($source);
-                       $xml_tree->filetype = '';
-
-                       $keys = array_keys($xml_tree->xml);
-                       foreach ($keys as $key) {
-                               if (preg_match('/^(hotpot|textoys)-(\w+)-file$/i', $key, $matches)) {
-                                       $xml_tree->filetype = 'xml';
-                                       $xml_tree->xml_root = "['$key']['#']";
-                                       $xml_tree->quiztype = strtolower($matches[2]);
-                                       break;
-                               }
-                       }
-                       if ($xml_tree->filetype=='xml') {
-
-                               $title = strip_tags($xml_tree->xml_value('data,title'));
-                               $subtitle = $xml_tree->xml_value('hotpot-config-file,'.$xml_tree->quiztype.',exercise-subtitle');
-
-                               if ($get_next) {
-                                       $include = $xml_tree->xml_value('hotpot-config-file,global,include-next-ex');
-                                       if (!empty($include)) {
-                                               $next = $xml_tree->xml_value("hotpot-config-file,$xml_tree->quiztype,next-ex-url");
-                                               if (is_array($next)) {
-                                                       $next = $next[0]; // in case "next-ex-url" was repeated in the xml file
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               $hp->nextexercise = $next;
-               $hp->exercisetitle = (empty($title) || is_array($title)) ? basename($filepath) : $title;
-               $hp->exercisesubtitle = (empty($subtitle) || is_array($subtitle)) ? $hp->exercisetitle : $subtitle;
-       }
+    $hp->exercisetitle = '';
+    $hp->exercisesubtitle = '';
+    $hp->nextexercise = '';
+
+    // read the quiz file source
+    if ($source = file_get_contents($filepath)) {
+
+        $next = '';
+        $title = '';
+        $subtitle = '';
+
+        if (preg_match('|\.html?$|', $filepath)) {
+            // html file
+            if (preg_match('|<h2[^>]*class="ExerciseTitle"[^>]*>(.*?)</h2>|is', $source, $matches)) {
+                $title = trim(strip_tags($matches[1]));
+            }
+            if (empty($title)) {
+                if (preg_match('|<title[^>]*>(.*?)</title>|is', $source, $matches)) {
+                    $title = trim(strip_tags($matches[1]));
+                }
+            }
+            if (preg_match('|<h3[^>]*class="ExerciseSubtitle"[^>]*>(.*?)</h3>|is', $source, $matches)) {
+                $subtitle = trim(strip_tags($matches[1]));
+            }
+            if ($get_next) {
+                if (preg_match('|<div[^>]*class="NavButtonBar"[^>]*>(.*?)</div>|is', $source, $matches)) {
+                    $navbuttonbar = $matches[1];
+                    if (preg_match_all('|<button[^>]*class="NavButton"[^>]*onclick="'."location='([^']*)'".'[^"]*"[^>]*>|is', $navbuttonbar, $matches)) {
+                        $lastbutton = count($matches[0])-1;
+                        $next = $matches[1][$lastbutton];
+                    }
+                }
+            }
+
+        } else {
+            // xml file (...maybe)
+            $xml_tree = new hotpot_xml_tree($source);
+            $xml_tree->filetype = '';
+
+            $keys = array_keys($xml_tree->xml);
+            foreach ($keys as $key) {
+                if (preg_match('/^(hotpot|textoys)-(\w+)-file$/i', $key, $matches)) {
+                    $xml_tree->filetype = 'xml';
+                    $xml_tree->xml_root = "['$key']['#']";
+                    $xml_tree->quiztype = strtolower($matches[2]);
+                    break;
+                }
+            }
+            if ($xml_tree->filetype=='xml') {
+
+                $title = strip_tags($xml_tree->xml_value('data,title'));
+                $subtitle = $xml_tree->xml_value('hotpot-config-file,'.$xml_tree->quiztype.',exercise-subtitle');
+
+                if ($get_next) {
+                    $include = $xml_tree->xml_value('hotpot-config-file,global,include-next-ex');
+                    if (!empty($include)) {
+                        $next = $xml_tree->xml_value("hotpot-config-file,$xml_tree->quiztype,next-ex-url");
+                        if (is_array($next)) {
+                            $next = $next[0]; // in case "next-ex-url" was repeated in the xml file
+                        }
+                    }
+                }
+            }
+        }
+
+        $hp->nextexercise = $next;
+        $hp->exercisetitle = (empty($title) || is_array($title)) ? basename($filepath) : $title;
+        $hp->exercisesubtitle = (empty($subtitle) || is_array($subtitle)) ? $hp->exercisetitle : $subtitle;
+    }
 }
 function hotpot_get_all_instances_in_course($modulename, $course) {
 /// called from index.php
 
-       global $CFG;
-       $instances = array();
-
-       if (isset($CFG->release) && substr($CFG->release, 0, 3)>=1.2) {
-               $groupmode = 'cm.groupmode,';
-       } else {
-               $groupmode = '';
-       }
-
-       $query = "
-               SELECT
-                       cm.id AS coursemodule,
-                       cm.course AS course,
-                       cm.module AS module,
-                       cm.instance AS instance,
-                       -- cm.section AS section,
-                       cm.visible AS visible,
-                       $groupmode
-                       -- cs.section AS sectionnumber,
-                       cs.section AS section,
-                       cs.sequence AS sequence,
-                       cs.visible AS sectionvisible,
-                       thismodule.*
-               FROM
-                       {$CFG->prefix}course_modules AS cm,
-                       {$CFG->prefix}course_sections AS cs,
-                       {$CFG->prefix}modules AS m,
-                       {$CFG->prefix}$modulename AS thismodule
-               WHERE
-                       m.name = '$modulename' AND
-                       m.id = cm.module AND
-                       cm.course = '$course->id' AND
-                       cm.section = cs.id AND
-                       cm.instance = thismodule.id
-       ";
-       if ($rawmods = get_records_sql($query)) {
-
-               // cache $isteacher setting
-               $isteacher = isteacher($course->id);
-
-               $explodesection = array();
-               $order = array();
-
-               foreach ($rawmods as $rawmod) {
-
-                       if (empty($explodesection[$rawmod->section])) {
-                               $explodesection[$rawmod->section] = true;
-
-                               $coursemodules = explode(',', $rawmod->sequence);
-                               foreach ($coursemodules as $i=>$coursemodule) {
-                                       $order[$coursemodule] = sprintf('%d.%04d', $rawmod->section, $i);
-                               }
-                       }
-
-                       if ($isteacher) {
-                               $visible = true;
-                       } else if ($modulename=='hotpot') {
-                               $visible = hotpot_is_visible($rawmod);
-                       } else {
-                               $visible = $rawmod->visible;
-                       }
-
-                       if ($visible) {
-                               $instances[$order[$rawmod->coursemodule]] = $rawmod;
-                       }
-
-               } // end foreach $modinfo
-
-               ksort($instances);
-               $instances = array_values($instances);
-       }
-
-       return $instances;
+    global $CFG;
+    $instances = array();
+
+    if (isset($CFG->release) && substr($CFG->release, 0, 3)>=1.2) {
+        $groupmode = 'cm.groupmode,';
+    } else {
+        $groupmode = '';
+    }
+
+    $query = "
+        SELECT
+            cm.id AS coursemodule,
+            cm.course AS course,
+            cm.module AS module,
+            cm.instance AS instance,
+            -- cm.section AS section,
+            cm.visible AS visible,
+            $groupmode
+            -- cs.section AS sectionnumber,
+            cs.section AS section,
+            cs.sequence AS sequence,
+            cs.visible AS sectionvisible,
+            thismodule.*
+        FROM
+            {$CFG->prefix}course_modules AS cm,
+            {$CFG->prefix}course_sections AS cs,
+            {$CFG->prefix}modules AS m,
+            {$CFG->prefix}$modulename AS thismodule
+        WHERE
+            m.name = '$modulename' AND
+            m.id = cm.module AND
+            cm.course = '$course->id' AND
+            cm.section = cs.id AND
+            cm.instance = thismodule.id
+    ";
+    if ($rawmods = get_records_sql($query)) {
+
+        // cache $isteacher setting
+        $isteacher = isteacher($course->id);
+
+        $explodesection = array();
+        $order = array();
+
+        foreach ($rawmods as $rawmod) {
+
+            if (empty($explodesection[$rawmod->section])) {
+                $explodesection[$rawmod->section] = true;
+
+                $coursemodules = explode(',', $rawmod->sequence);
+                foreach ($coursemodules as $i=>$coursemodule) {
+                    $order[$coursemodule] = sprintf('%d.%04d', $rawmod->section, $i);
+                }
+            }
+
+            if ($isteacher) {
+                $visible = true;
+            } else if ($modulename=='hotpot') {
+                $visible = hotpot_is_visible($rawmod);
+            } else {
+                $visible = $rawmod->visible;
+            }
+
+            if ($visible) {
+                $instances[$order[$rawmod->coursemodule]] = $rawmod;
+            }
+
+        } // end foreach $modinfo
+
+        ksort($instances);
+        $instances = array_values($instances);
+    }
+
+    return $instances;
 }
 
 function hotpot_update_chain(&$hp) {
 /// update a chain of hotpot actiivities
 
-       $ok = true;
-       if ($hotpot_modules = hotpot_get_chain($hp)) {
-
-               // skip updating of these fields
-               $skipfields = array('id', 'course', 'name', 'reference', 'summary', 'shownextquiz');
-               $fields = array();
-
-               foreach ($hotpot_modules as $hotpot_module) {
-
-                       if ($hp->instance==$hotpot_module->id) {
-                               // don't need to update this hotpot
-
-                       } else {
-                               // shortcut to hotpot record
-                               $hotpot = &$hotpot_module->hotpot;
-
-                               // get a list of fields to update (first time only)
-                               if (empty($fields)) {
-                                       $fields = array_keys(get_object_vars($hotpot));
-                               }
-
-                               // assume update is NOT required
-                               $require_update = false;
-
-                               // update field values (except $skipfields)
-                               foreach($fields as $field) {
-                                       if (in_array($field, $skipfields) || $hotpot->$field==$hp->$field) {
-                                               // update not required for this field
-                                       } else {
-                                               $require_update = true;
-                                               $hotpot->$field = $hp->$field;
-                                       }
-                               }
-
-                               // update this $hotpot, if required
-                               if ($require_update && !update_record("hotpot", $hotpot)) {
-                                       error("Could not update the $hp->modulename", "view.php?id=$hp->course");
-                               }
-                       }
-               } // end foreach $ids
-       }
-       return $ok;
+    $ok = true;
+    if ($hotpot_modules = hotpot_get_chain($hp)) {
+
+        // skip updating of these fields
+        $skipfields = array('id', 'course', 'name', 'reference', 'summary', 'shownextquiz');
+        $fields = array();
+
+        foreach ($hotpot_modules as $hotpot_module) {
+
+            if ($hp->instance==$hotpot_module->id) {
+                // don't need to update this hotpot
+
+            } else {
+                // shortcut to hotpot record
+                $hotpot = &$hotpot_module->hotpot;
+
+                // get a list of fields to update (first time only)
+                if (empty($fields)) {
+                    $fields = array_keys(get_object_vars($hotpot));
+                }
+
+                // assume update is NOT required
+                $require_update = false;
+
+                // update field values (except $skipfields)
+                foreach($fields as $field) {
+                    if (in_array($field, $skipfields) || $hotpot->$field==$hp->$field) {
+                        // update not required for this field
+                    } else {
+                        $require_update = true;
+                        $hotpot->$field = $hp->$field;
+                    }
+                }
+
+                // update this $hotpot, if required
+                if ($require_update && !update_record("hotpot", $hotpot)) {
+                    error("Could not update the $hp->modulename", "view.php?id=$hp->course");
+                }
+            }
+        } // end foreach $ids
+    }
+    return $ok;
 }
 function hotpot_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.
 
-       $result = false;
-       if (delete_records("hotpot", "id", "$id")) {
-               $result = true;
-               delete_records("hotpot_questions", "hotpot", "$id");
-               if ($attempts = get_records_select("hotpot_attempts", "hotpot='$id'")) {
-                       $ids = implode(',', array_keys($attempts));
-                       delete_records_select("hotpot_attempts",  "id IN ($ids)");
-                       delete_records_select("hotpot_details",   "attempt IN ($ids)");
-                       delete_records_select("hotpot_responses", "attempt IN ($ids)");
-               }
-       }
-       return $result;
+    $result = false;
+    if (delete_records("hotpot", "id", "$id")) {
+        $result = true;
+        delete_records("hotpot_questions", "hotpot", "$id");
+        if ($attempts = get_records_select("hotpot_attempts", "hotpot='$id'")) {
+            $ids = implode(',', array_keys($attempts));
+            delete_records_select("hotpot_attempts",  "id IN ($ids)");
+            delete_records_select("hotpot_details",   "attempt IN ($ids)");
+            delete_records_select("hotpot_responses", "attempt IN ($ids)");
+        }
+    }
+    return $result;
 }
 function hotpot_delete_and_notify($table, $select, $strtable) {
-       $count = max(0, count_records_select($table, $select));
-       if ($count) {
-               delete_records_select($table, $select);
-               $count -= max(0, count_records_select($table, $select));
-               if ($count) {
-                       notify(get_string('deleted')." $count x $strtable");
-               }
-       }
+    $count = max(0, count_records_select($table, $select));
+    if ($count) {
+        delete_records_select($table, $select);
+        $count -= max(0, count_records_select($table, $select));
+        if ($count) {
+            notify(get_string('deleted')." $count x $strtable");
+        }
+    }
 }
 
 function hotpot_user_complete($course, $user, $mod, $hp) {
 /// Print a detailed representation of what a  user has done with
 /// a given particular instance of this module, for user activity reports.
 
-       $report = hotpot_user_outline($course, $user, $mod, $hp);
-       if (empty($report)) {
-               print get_string("noactivity", "hotpot");
-       } else {
-               $date = userdate($report->time, get_string('strftimerecentfull'));
-               print $report->info.' '.get_string('mostrecently').': '.$date;
-       }
-       return true;
+    $report = hotpot_user_outline($course, $user, $mod, $hp);
+    if (empty($report)) {
+        print get_string("noactivity", "hotpot");
+    } else {
+        $date = userdate($report->time, get_string('strftimerecentfull'));
+        print $report->info.' '.get_string('mostrecently').': '.$date;
+    }
+    return true;
 }
 
 function hotpot_user_outline($course, $user, $mod, $hp) {
@@ -840,43 +840,43 @@ function hotpot_user_outline($course, $user, $mod, $hp) {
 /// $report->time = the time they did it
 /// $report->info = a short text description
 
-       $report = NULL;
-       if ($records = get_records_select("hotpot_attempts", "hotpot='$hp->id' AND userid='$user->id'", "timestart ASC", "*")) {
-               $scores = array();
-               foreach ($records as $record){
-                       if (empty($report->time)) {
-                               $report->time = $record->timestart;
-                       }
-                       $scores[] = hotpot_format_score($record);
-               }
-               if (empty($scores)) {
-                       $report->time = 0;
-                       $report->info = get_string('noactivity', 'hotpot');
-               } else {
-                       $report->info = get_string('score', 'quiz').': '.implode(', ', $scores);
-               }
-       }
-       return $report;
+    $report = NULL;
+    if ($records = get_records_select("hotpot_attempts", "hotpot='$hp->id' AND userid='$user->id'", "timestart ASC", "*")) {
+        $scores = array();
+        foreach ($records as $record){
+            if (empty($report->time)) {
+                $report->time = $record->timestart;
+            }
+            $scores[] = hotpot_format_score($record);
+        }
+        if (empty($scores)) {
+            $report->time = 0;
+            $report->info = get_string('noactivity', 'hotpot');
+        } else {
+            $report->info = get_string('score', 'quiz').': '.implode(', ', $scores);
+        }
+    }
+    return $report;
 }
 
 function hotpot_format_score($record, $undefined='&nbsp;') {
-       if (isset($record->score)) {
-               $score = $record->score;
-       } else {
-               $score = $undefined;
-       }
-       return $score;
+    if (isset($record->score)) {
+        $score = $record->score;
+    } else {
+        $score = $undefined;
+    }
+    return $score;
 }
 
 function hotpot_format_status($record, $undefined='&nbsp;') {
-       global $HOTPOT_STATUS;
-
-       if (isset($record->status) || isset($HOTPOT_STATUS[$record->status])) {
-               $status = $HOTPOT_STATUS[$record->status];
-       } else {
-               $status = $undefined;
-       }
-       return $status;
+    global $HOTPOT_STATUS;
+
+    if (isset($record->status) || isset($HOTPOT_STATUS[$record->status])) {
+        $status = $HOTPOT_STATUS[$record->status];
+    } else {
+        $status = $undefined;
+    }
+    return $status;
 }
 
 function hotpot_print_recent_activity($course, $isteacher, $timestart) {
@@ -884,162 +884,162 @@ function hotpot_print_recent_activity($course, $isteacher, $timestart) {
 /// that has occurred in hotpot activities and print it out.
 /// Return true if there was output, or false is there was none.
 
-       global $CFG;
-
-       $result = false;
-       if($isteacher){
-
-               $records = get_records_sql("
-                       SELECT
-                               h.id AS id,
-                               h.name AS name,
-                               COUNT(*) AS count_attempts
-                       FROM
-                               {$CFG->prefix}hotpot AS h,
-                               {$CFG->prefix}hotpot_attempts AS a
-                       WHERE
-                               h.course = $course->id
-                               AND h.id = a.hotpot
-                               AND a.id = a.clickreportid
-                               AND a.starttime > $timestart
-                       GROUP  BY
-                               h.id, h.name
-               ");
-               // note that PostGreSQL requires h.name in the GROUP BY clause
-
-               if($records) {
-
-                       $names = array();
-                       foreach ($records as $id => $record){
-                               $href = "$CFG->wwwroot/mod/hotpot/view.php?hp=$id";
-                               $name = '&nbsp;<a href="'.$href.'">'.$record->name.'</a>';
-                               if ($record->count_attempts > 1) {
-                                       $name .= " ($record->count_attempts)";
-                               }
-                               $names[] = $name;
-                       }
-
-                       print_headline(get_string('modulenameplural', 'hotpot').':');
-
-                       if ($CFG->version >= 2005050500) { // Moodle 1.5+
-                               echo '<div class="head"><div class="name">'.implode('<br />', $names).'</div></div>';
-                       } else { // Moodle 1.4.x (or less)
-                               echo '<font size="1">'.implode('<br />', $names).'</font>';
-                       }
-
-                       $result = true;
-               }
-       }
-       return $result;  //  True if anything was printed, otherwise false
+    global $CFG;
+
+    $result = false;
+    if($isteacher){
+
+        $records = get_records_sql("
+            SELECT
+                h.id AS id,
+                h.name AS name,
+                COUNT(*) AS count_attempts
+            FROM
+                {$CFG->prefix}hotpot AS h,
+                {$CFG->prefix}hotpot_attempts AS a
+            WHERE
+                h.course = $course->id
+                AND h.id = a.hotpot
+                AND a.id = a.clickreportid
+                AND a.starttime > $timestart
+            GROUP  BY
+                h.id, h.name
+        ");
+        // note that PostGreSQL requires h.name in the GROUP BY clause
+
+        if($records) {
+
+            $names = array();
+            foreach ($records as $id => $record){
+                $href = "$CFG->wwwroot/mod/hotpot/view.php?hp=$id";
+                $name = '&nbsp;<a href="'.$href.'">'.$record->name.'</a>';
+                if ($record->count_attempts > 1) {
+                    $name .= " ($record->count_attempts)";
+                }
+                $names[] = $name;
+            }
+
+            print_headline(get_string('modulenameplural', 'hotpot').':');
+
+            if ($CFG->version >= 2005050500) { // Moodle 1.5+
+                echo '<div class="head"><div class="name">'.implode('<br />', $names).'</div></div>';
+            } else { // Moodle 1.4.x (or less)
+                echo '<font size="1">'.implode('<br />', $names).'</font>';
+            }
+
+            $result = true;
+        }
+    }
+    return $result;  //  True if anything was printed, otherwise false
 }
 
 function hotpot_get_recent_mod_activity(&$activities, &$index, $sincetime, $courseid, $cmid="", $userid="", $groupid="") {
 // Returns all quizzes since a given time.
 
-       global $CFG;
-
-       // If $cmid or $userid are specified, then this restricts the results
-       $cm_select = empty($cmid) ? "" : " AND cm.id = '$cmid'";
-       $user_select = empty($userid) ? "" : " AND u.id = '$userid'";
-
-       $records = get_records_sql("
-               SELECT
-                       a.*,
-                       h.name, h.course,
-                       cm.instance, cm.section,
-                       u.firstname, u.lastname, u.picture
-               FROM
-                       {$CFG->prefix}hotpot_attempts AS a,
-                       {$CFG->prefix}hotpot AS h,
-                       {$CFG->prefix}course_modules AS cm,
-                       {$CFG->prefix}user AS u
-               WHERE
-                       a.timefinish > '$sincetime'
-                       AND a.id = a.clickreportid
-                       AND a.userid = u.id $user_select
-                       AND a.hotpot = h.id $cm_select
-                       AND cm.instance = h.id
-                       AND cm.course = '$courseid'
-                       AND h.course = cm.course
-               ORDER BY
-                       a.timefinish ASC
-       ");
-
-       if (!empty($records)) {
-               foreach ($records as $record) {
-                       if (empty($groupid) || ismember($groupid, $record->userid)) {
-
-                               unset($activity);
-
-                               $activity->type = "hotpot";
-                               $activity->defaultindex = $index;
-                               $activity->instance = $record->hotpot;
-
-                               $activity->name = $record->name;
-                               $activity->section = $record->section;
-
-                               $activity->content->attemptid = $record->id;
-                               $activity->content->attempt = $record->attempt;
-                               $activity->content->score = $record->score;
-                               $activity->content->timestart = $record->timestart;
-                               $activity->content->timefinish = $record->timefinish;
-
-                               $activity->user->userid = $record->userid;
-                               $activity->user->fullname = fullname($record);
-                               $activity->user->picture = $record->picture;
-
-                               $activity->timestamp = $record->timefinish;
-
-                               $activities[] = $activity;
-
-                               $index++;
-                       }
-               } // end foreach
-       }
+    global $CFG;
+
+    // If $cmid or $userid are specified, then this restricts the results
+    $cm_select = empty($cmid) ? "" : " AND cm.id = '$cmid'";
+    $user_select = empty($userid) ? "" : " AND u.id = '$userid'";
+
+    $records = get_records_sql("
+        SELECT
+            a.*,
+            h.name, h.course,
+            cm.instance, cm.section,
+            u.firstname, u.lastname, u.picture
+        FROM
+            {$CFG->prefix}hotpot_attempts AS a,
+            {$CFG->prefix}hotpot AS h,
+            {$CFG->prefix}course_modules AS cm,
+            {$CFG->prefix}user AS u
+        WHERE
+            a.timefinish > '$sincetime'
+            AND a.id = a.clickreportid
+            AND a.userid = u.id $user_select
+            AND a.hotpot = h.id $cm_select
+            AND cm.instance = h.id
+            AND cm.course = '$courseid'
+            AND h.course = cm.course
+        ORDER BY
+            a.timefinish ASC
+    ");
+
+    if (!empty($records)) {
+        foreach ($records as $record) {
+            if (empty($groupid) || ismember($groupid, $record->userid)) {
+
+                unset($activity);
+
+                $activity->type = "hotpot";
+                $activity->defaultindex = $index;
+                $activity->instance = $record->hotpot;
+
+                $activity->name = $record->name;
+                $activity->section = $record->section;
+
+                $activity->content->attemptid = $record->id;
+                $activity->content->attempt = $record->attempt;
+                $activity->content->score = $record->score;
+                $activity->content->timestart = $record->timestart;
+                $activity->content->timefinish = $record->timefinish;
+
+                $activity->user->userid = $record->userid;
+                $activity->user->fullname = fullname($record);
+                $activity->user->picture = $record->picture;
+
+                $activity->timestamp = $record->timefinish;
+
+                $activities[] = $activity;
+
+                $index++;
+            }
+        } // end foreach
+    }
 }
 
 function hotpot_print_recent_mod_activity($activity, $course, $detail=false) {
 /// Basically, this function prints the results of "hotpot_get_recent_activity"
 
-       global $CFG, $THEME, $USER;
+    global $CFG, $THEME, $USER;
 
-       print '<table border="0" cellpadding="3" cellspacing="0">';
+    print '<table border="0" cellpadding="3" cellspacing="0">';
 
-       print '<tr><td bgcolor="'.$THEME->cellcontent2.'" class="forumpostpicture" width="35" valign="top">';
-       print_user_picture($activity->user->userid, $course, $activity->user->picture);
-       print '</td><td width="100%"><font size="2">';
+    print '<tr><td bgcolor="'.$THEME->cellcontent2.'" class="forumpostpicture" width="35" valign="top">';
+    print_user_picture($activity->user->userid, $course, $activity->user->picture);
+    print '</td><td width="100%"><font size="2">';
 
-       if ($detail) {
-               // activity icon
-               $src = "$CFG->modpixpath/$activity->type/icon.gif";
-               print '<img src="'.$src.'" height="16" width="16" alt="'.$activity->type.'" /> ';
+    if ($detail) {
+        // activity icon
+        $src = "$CFG->modpixpath/$activity->type/icon.gif";
+        print '<img src="'.$src.'" height="16" width="16" alt="'.$activity->type.'" /> ';
 
-               // link to activity
-               $href = "$CFG->wwwroot/mod/hotpot/view.php?hp=$activity->instance";
-               print '<a href="'.$href.'">'.$activity->name.'</a> - ';
-       }
-       if (isteacher($course)) {
-               // score (with link to attempt details)
-               $href = "$CFG->wwwroot/mod/hotpot/review.php?hp=$activity->instance&attempt=".$activity->content->attemptid;
-               print '<a href="'.$href.'">('.hotpot_format_score($activity->content).')</a> ';
+        // link to activity
+        $href = "$CFG->wwwroot/mod/hotpot/view.php?hp=$activity->instance";
+        print '<a href="'.$href.'">'.$activity->name.'</a> - ';
+    }
+    if (isteacher($course)) {
+        // score (with link to attempt details)
+        $href = "$CFG->wwwroot/mod/hotpot/review.php?hp=$activity->instance&attempt=".$activity->content->attemptid;
+        print '<a href="'.$href.'">('.hotpot_format_score($activity->content).')</a> ';
 
-               // attempt number
-               print get_string('attempt', 'quiz').' - '.$activity->content->attempt.'<br />';
-       }
+        // attempt number
+        print get_string('attempt', 'quiz').' - '.$activity->content->attempt.'<br />';
+    }
 
-       // link to user
-       $href = "$CFG->wwwroot/user/view.php?id=$activity->user->userid&course=$course";
-       print '<a href="'.$href.'">'.$activity->user->fullname.'</a> ';
+    // link to user
+    $href = "$CFG->wwwroot/user/view.php?id=$activity->user->userid&course=$course";
+    print '<a href="'.$href.'">'.$activity->user->fullname.'</a> ';
 
-       // time and date
-       print ' - ' . userdate($activity->timestamp);
+    // time and date
+    print ' - ' . userdate($activity->timestamp);
 
-       // duration
-       $duration = format_time($activity->content->timestart - $activity->content->timefinish);
-       print " &nbsp; ($duration)";
+    // duration
+    $duration = format_time($activity->content->timestart - $activity->content->timefinish);
+    print " &nbsp; ($duration)";
 
-       print "</font></td></tr>";
-       print "</table>";
+    print "</font></td></tr>";
+    print "</table>";
 }
 
 function hotpot_cron () {
@@ -1047,77 +1047,77 @@ function hotpot_cron () {
 /// This function searches for things that need to be done, such
 /// as sending out mail, toggling flags etc ...
 
-       global $CFG;
+    global $CFG;
 
-       return true;
+    return true;
 }
 
 function hotpot_grades($hotpotid) {
 /// Must return an array of grades for a given instance of this module,
 /// indexed by user.  It also returns a maximum allowed grade.
 
-       $hotpot = get_record('hotpot', 'id', $hotpotid);
-       $return->grades = hotpot_get_grades($hotpot);
-       $return->maxgrade = $hotpot->grade;
+    $hotpot = get_record('hotpot', 'id', $hotpotid);
+    $return->grades = hotpot_get_grades($hotpot);
+    $return->maxgrade = $hotpot->grade;
 
-       return $return;
+    return $return;
 }
 function hotpot_get_grades($hotpot, $user_ids='') {
-       global $CFG;
-
-       $grades = array();
-
-       $weighting = $hotpot->grade / 100;
-       $precision = hotpot_get_precision($hotpot);
-
-       // set the SQL string to determine the $grade
-       $grade = "";
-       switch ($hotpot->grademethod) {
-               case HOTPOT_GRADEMETHOD_HIGHEST:
-                       $grade = "ROUND(MAX(score) * $weighting, $precision) AS grade";
-                       break;
-               case HOTPOT_GRADEMETHOD_AVERAGE:
-                       // the 'AVG' function skips abandoned quizzes, so use SUM(score)/COUNT(id)
-                       $grade = "ROUND(SUM(score)/COUNT(id) * $weighting, $precision) AS grade";
-                       break;
-               case HOTPOT_GRADEMETHOD_FIRST:
-                       if ($CFG->dbtype=='postgres7') {
-                               $grade = "MIN(timestart||'_'||(CASE WHEN (score IS NULL) THEN '' ELSE TRIM(ROUND(score * $weighting, $precision)) END)) AS grade";
-                       } else {
-                               $grade = "MIN(CONCAT(timestart, '_', IF(score IS NULL, '', ROUND(score * $weighting, $precision)))) AS grade";
-                       }
-                       break;
-               case HOTPOT_GRADEMETHOD_LAST:
-                       if ($CFG->dbtype=='postgres7') {
-                               $grade = "MAX(timestart||'_'||(CASE WHEN (score IS NULL) THEN '' ELSE TRIM(ROUND(score * $weighting, $precision)) END)) AS grade";
-                       } else {
-                               $grade = "MAX(CONCAT(timestart, '_', IF(score IS NULL, '', ROUND(score * $weighting, $precision)))) AS grade";
-                       }
-                       break;
-       }
-
-       if ($grade) {
-               $userid_condition = empty($user_ids) ? '' : "AND userid IN ($user_ids) ";
-               $grades = get_records_sql_menu("
-                       SELECT userid, $grade
-                       FROM {$CFG->prefix}hotpot_attempts
-                       WHERE timefinish>0 AND hotpot='$hotpot->id' $userid_condition
-                       GROUP BY userid
-               ");
-               if ($grades) {
-                       if ($hotpot->grademethod==HOTPOT_GRADEMETHOD_FIRST || $hotpot->grademethod==HOTPOT_GRADEMETHOD_LAST) {
-                               // remove left hand characters in $grade (up to and including the underscore)
-                               foreach ($grades as $userid=>$grade) {
-                                       $grades[$userid] = substr($grades[$userid], strpos($grades[$userid], '_')+1);
-                               }
-                       }
-               }
-       }
-
-       return $grades;
+    global $CFG;
+
+    $grades = array();
+
+    $weighting = $hotpot->grade / 100;
+    $precision = hotpot_get_precision($hotpot);
+
+    // set the SQL string to determine the $grade
+    $grade = "";
+    switch ($hotpot->grademethod) {
+        case HOTPOT_GRADEMETHOD_HIGHEST:
+            $grade = "ROUND(MAX(score) * $weighting, $precision) AS grade";
+            break;
+        case HOTPOT_GRADEMETHOD_AVERAGE:
+            // the 'AVG' function skips abandoned quizzes, so use SUM(score)/COUNT(id)
+            $grade = "ROUND(SUM(score)/COUNT(id) * $weighting, $precision) AS grade";
+            break;
+        case HOTPOT_GRADEMETHOD_FIRST:
+            if ($CFG->dbtype=='postgres7') {
+                $grade = "MIN(timestart||'_'||(CASE WHEN (score IS NULL) THEN '' ELSE TRIM(ROUND(score * $weighting, $precision)) END)) AS grade";
+            } else {
+                $grade = "MIN(CONCAT(timestart, '_', IF(score IS NULL, '', ROUND(score * $weighting, $precision)))) AS grade";
+            }
+            break;
+        case HOTPOT_GRADEMETHOD_LAST:
+            if ($CFG->dbtype=='postgres7') {
+                $grade = "MAX(timestart||'_'||(CASE WHEN (score IS NULL) THEN '' ELSE TRIM(ROUND(score * $weighting, $precision)) END)) AS grade";
+            } else {
+                $grade = "MAX(CONCAT(timestart, '_', IF(score IS NULL, '', ROUND(score * $weighting, $precision)))) AS grade";
+            }
+            break;
+    }
+
+    if ($grade) {
+        $userid_condition = empty($user_ids) ? '' : "AND userid IN ($user_ids) ";
+        $grades = get_records_sql_menu("
+            SELECT userid, $grade
+            FROM {$CFG->prefix}hotpot_attempts
+            WHERE timefinish>0 AND hotpot='$hotpot->id' $userid_condition
+            GROUP BY userid
+        ");
+        if ($grades) {
+            if ($hotpot->grademethod==HOTPOT_GRADEMETHOD_FIRST || $hotpot->grademethod==HOTPOT_GRADEMETHOD_LAST) {
+                // remove left hand characters in $grade (up to and including the underscore)
+                foreach ($grades as $userid=>$grade) {
+                    $grades[$userid] = substr($grades[$userid], strpos($grades[$userid], '_')+1);
+                }
+            }
+        }
+    }
+
+    return $grades;
 }
 function hotpot_get_precision(&$hotpot) {
-       return ($hotpot->grademethod==HOTPOT_GRADEMETHOD_AVERAGE || $hotpot->grade<100) ? 1 : 0;
+    return ($hotpot->grademethod==HOTPOT_GRADEMETHOD_AVERAGE || $hotpot->grade<100) ? 1 : 0;
 }
 
 function hotpot_get_participants($hotpotid) {
@@ -1125,18 +1125,18 @@ function hotpot_get_participants($hotpotid) {
 //for a given instance of hotpot. Must include every user involved
 //in the instance, independient of his role (student, teacher, admin...)
 //See other modules as example.
-       global $CFG;
-
-       return get_records_sql("
-               SELECT DISTINCT
-                       u.id, u.id
-               FROM
-                       {$CFG->prefix}user u,
-                       {$CFG->prefix}hotpot_attempts a
-               WHERE
-                       u.id = a.userid
-                       AND a.hotpot = '$hotpotid'
-       ");
+    global $CFG;
+
+    return get_records_sql("
+        SELECT DISTINCT
+            u.id, u.id
+        FROM
+            {$CFG->prefix}user u,
+            {$CFG->prefix}hotpot_attempts a
+        WHERE
+            u.id = a.userid
+            AND a.hotpot = '$hotpotid'
+    ");
 }
 
 function hotpot_scale_used ($hotpotid, $scaleid) {
@@ -1145,15 +1145,15 @@ function hotpot_scale_used ($hotpotid, $scaleid) {
 //modified if necessary. See forum, glossary or journal modules
 //as reference.
 
-       $report = false;
+    $report = false;
 
-       //$rec = get_record("hotpot","id","$hotpotid","scale","-$scaleid");
-       //
-       //if (!empty($rec)  && !empty($scaleid)) {
-       //      $report = true;
-       //}
+    //$rec = get_record("hotpot","id","$hotpotid","scale","-$scaleid");
+    //
+    //if (!empty($rec)  && !empty($scaleid)) {
+    //  $report = true;
+    //}
 
-       return $report;
+    return $report;
 }
 
 //////////////////////////////////////////////////////////
@@ -1162,83 +1162,83 @@ function hotpot_scale_used ($hotpotid, $scaleid) {
 
 
 function hotpot_add_attempt($hotpotid) {
-       global $db, $CFG, $USER;
-       $time = time();
-       switch (strtolower($CFG->dbtype)) {
-               case 'mysql':
-                       $timefinish = "IF(a.timefinish IS NULL, '$time', a.timefinish)";
-                       $clickreportid = "IF(a.clickreportid IS NULL, a.id, a.clickreportid)";
-                       break;
-               case 'postgres7':
-                       $timefinish = "WHEN(a.timefinish IS NULL) THEN '$time' ELSE a.timefinish";
-                       $clickreportid = "WHEN(a.clickreportid IS NULL) THEN a.id ELSE a.clickreportid";
-                       break;
-       }
-
-       // set all previous "in progress" attempts at this quiz to "abandoned"
-       $db->Execute("
-               UPDATE
-                       {$CFG->prefix}hotpot_attempts as a
-               SET
-                       a.timefinish = $timefinish,
-                       a.status = '".HOTPOT_STATUS_ABANDONED."',
-                       a.clickreportid = $clickreportid
-               WHERE
-                       a.hotpot='$hotpotid'
-                       AND a.userid='$USER->id'
-                       AND a.status='".HOTPOT_STATUS_INPROGRESS."'
-       ");
-
-       // create and add new attempt record
-       $attempt->hotpot = $hotpotid;
-       $attempt->userid = $USER->id;
-       $attempt->attempt = hotpot_get_next_attempt($hotpotid);
-       $attempt->timestart = time();
-
-       return insert_record("hotpot_attempts", $attempt);
+    global $db, $CFG, $USER;
+    $time = time();
+    switch (strtolower($CFG->dbtype)) {
+        case 'mysql':
+            $timefinish = "IF(a.timefinish IS NULL, '$time', a.timefinish)";
+            $clickreportid = "IF(a.clickreportid IS NULL, a.id, a.clickreportid)";
+            break;
+        case 'postgres7':
+            $timefinish = "WHEN(a.timefinish IS NULL) THEN '$time' ELSE a.timefinish";
+            $clickreportid = "WHEN(a.clickreportid IS NULL) THEN a.id ELSE a.clickreportid";
+            break;
+    }
+
+    // set all previous "in progress" attempts at this quiz to "abandoned"
+    $db->Execute("
+        UPDATE
+            {$CFG->prefix}hotpot_attempts as a
+        SET
+            a.timefinish = $timefinish,
+            a.status = '".HOTPOT_STATUS_ABANDONED."',
+            a.clickreportid = $clickreportid
+        WHERE
+            a.hotpot='$hotpotid'
+            AND a.userid='$USER->id'
+            AND a.status='".HOTPOT_STATUS_INPROGRESS."'
+    ");
+
+    // create and add new attempt record
+    $attempt->hotpot = $hotpotid;
+    $attempt->userid = $USER->id;
+    $attempt->attempt = hotpot_get_next_attempt($hotpotid);
+    $attempt->timestart = time();
+
+    return insert_record("hotpot_attempts", $attempt);
 }
 function hotpot_get_next_attempt($hotpotid) {
-       global $USER;
+    global $USER;
 
-       // get max attempt so far
-       $i = count_records_select('hotpot_attempts', "hotpot='$hotpotid' AND userid='$USER->id'", 'MAX(attempt)');
+    // get max attempt so far
+    $i = count_records_select('hotpot_attempts', "hotpot='$hotpotid' AND userid='$USER->id'", 'MAX(attempt)');
 
-       return empty($i) ? 1 : ($i+1);
+    return empty($i) ? 1 : ($i+1);
 }
 function hotpot_get_question_name($question) {
-       $name = '';
-       if (isset($question->text)) {
-               $name = hotpot_strings($question->text);
-       }
-       if (empty($name)) {
-               $name = $question->name;
-       }
-       return $name;
+    $name = '';
+    if (isset($question->text)) {
+        $name = hotpot_strings($question->text);
+    }
+    if (empty($name)) {
+        $name = $question->name;
+    }
+    return $name;
 }
 function hotpot_strings($ids) {
 
-       // array of ids of empty strings
-       static $HOTPOT_EMPTYSTRINGS;
-
-       if (!isset($HOTPOT_EMPTYSTRINGS)) { // first time only
-               // get ids of empty strings
-               $emptystrings = get_records_select('hotpot_strings', 'LENGTH(TRIM(string))=0');
-               $HOTPOT_EMPTYSTRINGS = empty($emptystrings) ? array() : array_keys($emptystrings);
-       }
-
-       $strings = array();
-       if (!empty($ids)) {
-               $ids = explode(',', $ids);
-               foreach ($ids as $id) {
-                       if (!in_array($id, $HOTPOT_EMPTYSTRINGS)) {
-                               $strings[] = hotpot_string($id);
-                       }
-               }
-       }
-       return implode(',', $strings);
+    // array of ids of empty strings
+    static $HOTPOT_EMPTYSTRINGS;
+
+    if (!isset($HOTPOT_EMPTYSTRINGS)) { // first time only
+        // get ids of empty strings
+        $emptystrings = get_records_select('hotpot_strings', 'LENGTH(TRIM(string))=0');
+        $HOTPOT_EMPTYSTRINGS = empty($emptystrings) ? array() : array_keys($emptystrings);
+    }
+
+    $strings = array();
+    if (!empty($ids)) {
+        $ids = explode(',', $ids);
+        foreach ($ids as $id) {
+            if (!in_array($id, $HOTPOT_EMPTYSTRINGS)) {
+                $strings[] = hotpot_string($id);
+            }
+        }
+    }
+    return implode(',', $strings);
 }
 function hotpot_string($id) {
-       return get_field('hotpot_strings', 'string', 'id', $id);
+    return get_field('hotpot_strings', 'string', 'id', $id);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////
@@ -1251,575 +1251,575 @@ require_once("$CFG->libdir/xmlize.php");
 require_once("$CFG->hotpottemplate/default.php");
 
 class hotpot_xml_tree {
-       function hotpot_xml_tree($str, $xml_root='') {
-               if (empty($str)) {
-                       $this->xml =  array();
-               } else {
-                       if (empty($CFG->unicodedb)) {
-                               $str = utf8_encode($str);
-                       }
-                       $this->xml =  xmlize($str, 0);
-               }
-               $this->xml_root = $xml_root;
-       }
-       function xml_value($tags, $more_tags="[0]['#']") {
-
-               $tags = empty($tags) ? '' : "['".str_replace(",", "'][0]['#']['", $tags)."']";
-               eval('$value = &$this->xml'.$this->xml_root.$tags.$more_tags.';');
-
-               if (is_string($value)) {
-                       if (empty($CFG->unicodedb)) {
-                               $value = utf8_decode($value);
-                       }
-
-                       // decode angle brackets
-                       $value = strtr($value, array('&#x003C;'=>'<', '&#x003E;'=>'>', '&#x0026;'=>'&'));
-
-                       // remove white space between <table>, <ul|OL|DL> and <OBJECT|EMBED> parts
-                       // (so it doesn't get converted to <br />)
-                       $htmltags = '('
-                       .       'TABLE|/?CAPTION|/?COL|/?COLGROUP|/?TBODY|/?TFOOT|/?THEAD|/?TD|/?TH|/?TR'
-                       .       '|OL|UL|/?LI'
-                       .       '|DL|/?DT|/?DD'
-                       .       '|EMBED|OBJECT|APPLET|/?PARAM'
-                       //.     '|SELECT|/?OPTION'
-                       //.     '|FIELDSET|/?LEGEND'
-                       //.     '|FRAMESET|/?FRAME'
-                       .       ')'
-                       ;
-
-                       $space = '(\s|(<br[^>]*>))+';
-                       $search = '#(<'.$htmltags.'[^>]*'.'>)'.$space.'(?='.'<)#is';
-                       $value = preg_replace($search, '\\1', $value);
-
-                       // replace remaining newlines with <br />
-                       $value = str_replace("\n", '<br />', $value);
-
-                       // encode unicode characters as HTML entities
-                       // (in particular, accented charaters that have not been encoded by HP)
-
-                       // unicode characters can be detected by checking the hex value of a character
-                       //      00 - 7F : ascii char (roman alphabet + punctuation)
-                       //      80 - BF : byte 2, 3 or 4 of a unicode char
-                       //      C0 - DF : 1st byte of 2-byte char
-                       //      E0 - EF : 1st byte of 3-byte char
-                       //      F0 - FF : 1st byte of 4-byte char
-                       // if the string doesn't match the above, it might be
-                       //      80 - FF : single-byte, non-ascii char
-                       $search = '#('.'[\xc0-\xdf][\x80-\xbf]'.'|'.'[\xe0-\xef][\x80-\xbf]{2}'.'|'.'[\xf0-\xff][\x80-\xbf]{3}'.'|'.'[\x80-\xff]'.')#se';
-                       $value = preg_replace($search, "hotpot_utf8_to_html_entity('\\1')", $value);
-               }
-               return $value;
-       }
-       function xml_values($tags) {
-               $i = 0;
-               $values = array();
-               while ($value = $this->xml_value($tags, "[$i]['#']")) {
-                       $values[$i++] = $value;
-               }
-               return $values;
-       }
-       function obj_value(&$obj, $name) {
-               return is_object($obj) ? @$obj->$name : (is_array($obj) ? @$obj[$name] : NULL);
-       }
-       function encode_cdata(&$str, $tag) {
-
-               // conversion tables
-               static $HTML_ENTITIES = array(
-                       '&apos;' => "'",
-                       '&quot;' => '"',
-                       '&lt;'   => '<',
-                       '&gt;'   => '>',
-                       '&amp;'  => '&',
-               );
-               static $ILLEGAL_STRINGS = array(
-                       "\r\n"  => '&lt;br /&gt;',
-                       "\r"    => '&lt;br /&gt;',
-                       "\n"    => '&lt;br /&gt;',
-                       '['     => '&#91;',
-                       ']'     => '&#93;'
-               );
-
-               // extract the $tag from the $str(ing), if possible
-               $pattern = '|(^.*<'.$tag.'[^>]*)(>.*<)(/'.$tag.'>.*$)|is';
-               if (preg_match($pattern, $str, $matches)) {
-
-                       // encode problematic CDATA chars and strings
-                       $matches[2] = strtr($matches[2], $ILLEGAL_STRINGS);
-
-                       // if there are any ampersands in "open text"
-                       // surround them by CDATA start and end markers
-                       // (and convert HTML entities to plain text)
-                       $search = '/>([^<]*&[^<]*)</e';
-                       $replace = '"><![CDATA[".strtr("$1", $HTML_ENTITIES)."]]><"';
-                       $matches[2] = preg_replace($search, $replace, $matches[2]);
-
-                       $str = $matches[1].$matches[2].$matches[3];
-               }
-       }
+    function hotpot_xml_tree($str, $xml_root='') {
+        if (empty($str)) {
+            $this->xml =  array();
+        } else {
+            if (empty($CFG->unicodedb)) {
+                $str = utf8_encode($str);
+            }
+            $this->xml =  xmlize($str, 0);
+        }
+        $this->xml_root = $xml_root;
+    }
+    function xml_value($tags, $more_tags="[0]['#']") {
+
+        $tags = empty($tags) ? '' : "['".str_replace(",", "'][0]['#']['", $tags)."']";
+        eval('$value = &$this->xml'.$this->xml_root.$tags.$more_tags.';');
+
+        if (is_string($value)) {
+            if (empty($CFG->unicodedb)) {
+                $value = utf8_decode($value);
+            }
+
+            // decode angle brackets
+            $value = strtr($value, array('&#x003C;'=>'<', '&#x003E;'=>'>', '&#x0026;'=>'&'));
+
+            // remove white space between <table>, <ul|OL|DL> and <OBJECT|EMBED> parts
+            // (so it doesn't get converted to <br />)
+            $htmltags = '('
+            .   'TABLE|/?CAPTION|/?COL|/?COLGROUP|/?TBODY|/?TFOOT|/?THEAD|/?TD|/?TH|/?TR'
+            .   '|OL|UL|/?LI'
+            .   '|DL|/?DT|/?DD'
+            .   '|EMBED|OBJECT|APPLET|/?PARAM'
+            //. '|SELECT|/?OPTION'
+            //. '|FIELDSET|/?LEGEND'
+            //. '|FRAMESET|/?FRAME'
+            .   ')'
+            ;
+
+            $space = '(\s|(<br[^>]*>))+';
+            $search = '#(<'.$htmltags.'[^>]*'.'>)'.$space.'(?='.'<)#is';
+            $value = preg_replace($search, '\\1', $value);
+
+            // replace remaining newlines with <br />
+            $value = str_replace("\n", '<br />', $value);
+
+            // encode unicode characters as HTML entities
+            // (in particular, accented charaters that have not been encoded by HP)
+
+            // unicode characters can be detected by checking the hex value of a character
+            //  00 - 7F : ascii char (roman alphabet + punctuation)
+            //  80 - BF : byte 2, 3 or 4 of a unicode char
+            //  C0 - DF : 1st byte of 2-byte char
+            //  E0 - EF : 1st byte of 3-byte char
+            //  F0 - FF : 1st byte of 4-byte char
+            // if the string doesn't match the above, it might be
+            //  80 - FF : single-byte, non-ascii char
+            $search = '#('.'[\xc0-\xdf][\x80-\xbf]'.'|'.'[\xe0-\xef][\x80-\xbf]{2}'.'|'.'[\xf0-\xff][\x80-\xbf]{3}'.'|'.'[\x80-\xff]'.')#se';
+            $value = preg_replace($search, "hotpot_utf8_to_html_entity('\\1')", $value);
+        }
+        return $value;
+    }
+    function xml_values($tags) {
+        $i = 0;
+        $values = array();
+        while ($value = $this->xml_value($tags, "[$i]['#']")) {
+            $values[$i++] = $value;
+        }
+        return $values;
+    }
+    function obj_value(&$obj, $name) {
+        return is_object($obj) ? @$obj->$name : (is_array($obj) ? @$obj[$name] : NULL);
+    }
+    function encode_cdata(&$str, $tag) {
+
+        // conversion tables
+        static $HTML_ENTITIES = array(
+            '&apos;' => "'",
+            '&quot;' => '"',
+            '&lt;'   => '<',
+            '&gt;'   => '>',
+            '&amp;'  => '&',
+        );
+        static $ILLEGAL_STRINGS = array(
+            "\r\n"  => '&lt;br /&gt;',
+            "\r"    => '&lt;br /&gt;',
+            "\n"    => '&lt;br /&gt;',
+            '['     => '&#91;',
+            ']'     => '&#93;'
+        );
+
+        // extract the $tag from the $str(ing), if possible
+        $pattern = '|(^.*<'.$tag.'[^>]*)(>.*<)(/'.$tag.'>.*$)|is';
+        if (preg_match($pattern, $str, $matches)) {
+
+            // encode problematic CDATA chars and strings
+            $matches[2] = strtr($matches[2], $ILLEGAL_STRINGS);
+
+            // if there are any ampersands in "open text"
+            // surround them by CDATA start and end markers
+            // (and convert HTML entities to plain text)
+            $search = '/>([^<]*&[^<]*)</e';
+            $replace = '"><![CDATA[".strtr("$1", $HTML_ENTITIES)."]]><"';
+            $matches[2] = preg_replace($search, $replace, $matches[2]);
+
+            $str = $matches[1].$matches[2].$matches[3];
+        }
+    }
 }
 
 class hotpot_xml_quiz extends hotpot_xml_tree {
 
-       // constructor function
-       function hotpot_xml_quiz(&$obj, $read_file=true, $parse_xml=true, $convert_urls=true, $report_errors=true, $create_html=true) {
-               // obj can be the $_GET array or a form object/array
-
-               global $CFG, $HOTPOT_OUTPUTFORMAT, $HOTPOT_OUTPUTFORMAT_DIR;
-
-               // check xmlize functions are available
-               if (! function_exists("xmlize")) {
-                       error('xmlize functions are not available');
-               }
-
-               $this->read_file = $read_file;
-               $this->parse_xml = $parse_xml;
-               $this->convert_urls = $convert_urls;
-               $this->report_errors = $report_errors;
-               $this->create_html = $create_html;
-
-               // extract fields from $obj
-               //      course     : the course id
-               //      reference       : the filename within the files folder
-               //      location         : "site" files folder or "course" files folder
-               //      navigation   : type of navigation required in quiz
-               //      forceplugins : force Moodle compatible media players
-               $this->course = $this->obj_value($obj, 'course');
-               $this->reference = $this->obj_value($obj, 'reference');
-               $this->location = $this->obj_value($obj, 'location');
-               $this->navigation = $this->obj_value($obj, 'navigation');
-               $this->forceplugins = $this->obj_value($obj, 'forceplugins');
-
-               // can't continue if there is no course or reference
-               if (empty($this->course) || empty($this->reference)) {
-                       $this->error = get_string('error_nocourseorfilename', 'hotpot');
-                       if ($this->report_errors) {
-                               error($this->error);
-                       }
-                       return;
-               }
-
-               $this->course_homeurl = "$CFG->wwwroot/course/view.php?id=$this->course";
-
-               // set filedir, filename and filepath
-               switch ($this->location) {
-                       case HOTPOT_LOCATION_SITEFILES:
-                               $site = get_site();
-                               $this->filedir = $site->id;
-                               break;
-
-                       case HOTPOT_LOCATION_COURSEFILES:
-                       default:
-                               $this->filedir = $this->course;
-                               break;
-               }
-               $this->filesubdir = dirname($this->reference);
-               if ($this->filesubdir=='.') {
-                       $this->filesubdir = '';
-               }
-               if ($this->filesubdir) {
-                       $this->filesubdir .= '/';
-               }
-               $this->filename = basename($this->reference);
-               $this->fileroot = "$CFG->dataroot/$this->filedir";
-               $this->filepath = "$this->fileroot/$this->reference";
-
-               // read the file, if required
-               if ($this->read_file) {
-
-                       if (!file_exists($this->filepath) || !is_readable($this->filepath)) {
-                               $this->error = get_string('error_couldnotopensourcefile', 'hotpot', $this->filepath);
-                               if ($this->report_errors) {
-                                       error($this->error, $this->course_homeurl);
-                               }
-                               return;
-                       }
-
-                       // read in the XML source
-                       $this->source = file_get_contents($this->filepath);
-
-                       // convert relative URLs to absolute URLs
-                       if ($this->convert_urls) {
-                               $this->hotpot_convert_relative_urls($this->source);
-                       }
-
-                       $this->html = '';
-                       $this->quiztype = '';
-                       $this->outputformat = 0;
-
-                       // is this an html file?
-                       if (preg_match('|\.html?$|', $this->filename)) {
-
-                               $this->filetype = 'html';
-                               $this->html = &$this->source;
-
-                               // relative URLs in stylesheets
-                               $search = '|'.'(<style[^>]*>)'.'(.*?)'.'(</style>)'.'|ise';
-                               $replace = "stripslashes('\\1').hotpot_convert_stylesheets_urls('".$this->get_baseurl()."','".$this->reference."','\\2'.'\\3')";
-                               $this->source = preg_replace($search, $replace, $this->source);
-
-                               // relative URLs in "PreloadImages(...);"
-                               $search = '|'.'(?<='.'PreloadImages'.'\('.')'."([^)]+?)".'(?='.'\);'.')'.'|se';
-                               $replace = "hotpot_convert_preloadimages_urls('".$this->get_baseurl()."','".$this->reference."','\\1')";
-                               $this->source = preg_replace($search, $replace, $this->source);
-
-                               // relative URLs in <button class="NavButton" ... onclick="location='...'">
-                               $search = '|'.'(?<='.'onclick="'."location='".')'."([^']*)".'(?='."'; return false;".'")'.'|ise';
-                               $replace = "hotpot_convert_navbutton_url('".$this->get_baseurl()."','".$this->reference."','\\1','".$this->course."')";
-                               $this->source = preg_replace($search, $replace, $this->source);
-
-                       } else {
-                               if ($this->parse_xml) {
-
-                                       $this->filetype = 'xml';
-
-                                       // encode "gap fill" text in JCloze exercise
-                                       $this->encode_cdata($this->source, 'gap-fill');
-
-                                       // convert source to xml tree
-                                       $this->hotpot_xml_tree($this->source);
-
-                                       $keys = array_keys($this->xml);
-                                       foreach ($keys as $key) {
-                                               if (preg_match('/^(hotpot|textoys)-(\w+)-file$/i', $key, $matches)) {
-                                                       $this->quiztype = strtolower($matches[2]);
-                                                       $this->xml_root = "['$key']['#']";
-                                                       break;
-                                               }
-                                       }
-                               }
-
-                               if ($this->create_html) {
-
-                                       // set the real output format from the requested output format
-                                       $this->real_outputformat = $this->obj_value($obj, 'outputformat');
-                                       $this->draganddrop = '';
-                                       if (
-                                               empty($this->real_outputformat) ||
-                                               $this->real_outputformat==HOTPOT_OUTPUTFORMAT_BEST ||
-                                               empty($HOTPOT_OUTPUTFORMAT_DIR[$this->real_outputformat])
-                                       ) {
-                                               if ($CFG->hotpotismobile && isset($HOTPOT_OUTPUTFORMAT_DIR[HOTPOT_OUTPUTFORMAT_MOBILE])) {
-                                                               $this->real_outputformat = HOTPOT_OUTPUTFORMAT_MOBILE;
-                                               } else { // PC
-                                                       if ($this->quiztype=='jmatch' || $this->quiztype=='jmix') {
-                                                               $this->real_outputformat = HOTPOT_OUTPUTFORMAT_V6_PLUS;
-                                                       } else {
-                                                               $this->real_outputformat = HOTPOT_OUTPUTFORMAT_V6;
-                                                       }
-                                               }
-                                       }
-
-                                       if ($this->real_outputformat==HOTPOT_OUTPUTFORMAT_V6_PLUS) {
-                                               if ($this->quiztype=='jmatch' || $this->quiztype=='jmix') {
-                                                       $this->draganddrop = 'd'; // prefix for templates (can also be "f" ?)
-                                               }
-                                               $this->real_outputformat = HOTPOT_OUTPUTFORMAT_V6;
-                                       }
-
-                                       // set path(s) to template
-                                       $this->template_dir = $HOTPOT_OUTPUTFORMAT_DIR[$this->real_outputformat];
-                                       $this->template_dirpath = $CFG->hotpottemplate.'/'.$this->template_dir;
-                                       $this->template_filepath = $CFG->hotpottemplate.'/'.$this->template_dir.'.php';
-
-                                       // check template class exists
-                                       if (!file_exists($this->template_filepath) || !is_readable($this->template_filepath)) {
-                                               $this->error = get_string('error_couldnotopentemplate', 'hotpot', $this->template_dir);
-                                               if ($this->report_errors) {
-                                                       error($this->error, $this->course_homeurl);
-                                               }
-                                               return;
-                                       }
-
-                                       // get default and output-specfic template classes
-                                       include($this->template_filepath);
-
-                                       // create html (using the template for the specified output format)
-                                       $this->template = new hotpot_xml_quiz_template($this);
-                                       $this->html = &$this->template->html;
-
-                               } // end $this->create_html
-                       } // end if html/xml file
-               } // end if $this->read_file
-       } // end constructor function
-
-       function hotpot_convert_relative_urls(&$str) {
-               $tagopen = '(?:(<)|(&lt;)|(&amp;#x003C;))'; // left angle bracket
-               $tagclose = '(?(2)>|(?(3)&gt;|(?(4)&amp;#x003E;)))'; //  right angle bracket (to match left angle bracket)
-
-               $space = '\s+'; // at least one space
-               $anychar = '(?:[^>]*?)'; // any character
-
-               $quoteopen = '("|&quot;|&amp;quot;)'; // open quote
-               $quoteclose = '\\5'; //  close quote (to match open quote)
-
-               $replace = "hotpot_convert_relative_url('".$this->get_baseurl()."', '".$this->reference."', '\\1', '\\6', '\\7')";
-
-               $tags = array('script'=>'src', 'link'=>'href', 'a'=>'href','img'=>'src','param'=>'value', 'object'=>'data', 'embed'=>'src');
-               foreach ($tags as $tag=>$attribute) {
-                       if ($tag=='param') {
-                               $url = '\S+?\.\S+?'; // must include a filename and have no spaces
-                       } else {
-                               $url = '.*?';
-                       }
-                       $search = "%($tagopen$tag$space$anychar$attribute=$quoteopen)($url)($quoteclose$anychar$tagclose)%ise";
-                       $str = preg_replace($search, $replace, $str);
-               }
-       }
-
-       function get_baseurl() {
-               // set the url base (first time only)
-               if (!isset($this->baseurl)) {
-                       global $CFG;
-                       if ($CFG->slasharguments) {
-                               $this->baseurl = "$CFG->wwwroot/file.php/$this->filedir/";
-                       } else {
-                               $this->baseurl = "$CFG->wwwroot/file.php?file=/$this->filedir/";
-                       }
-               }
-               return $this->baseurl;
-       }
-
-
-       // insert forms and messages
-
-       function remove_nav_buttons() {
-               $search = '#<!-- Begin(Top|Bottom)NavButtons -->(.*?)<!-- End(Top|Bottom)NavButtons -->#s';
-               $this->html = preg_replace($search, '', $this->html);
-       }
-       function insert_script($src=HOTPOT_JS) {
-               $script = '<script src="'.$src.'" type="text/javascript" language="javascript"></script>'."\n";
-               $this->html = preg_replace('|</head>|i', $script.'</head>', $this->html, 1);
-       }
-       function insert_submission_form($attemptid, $startblock, $endblock, $keep_contents=false) {
-               $form_name = 'store';
-               $form_fields = ''
-               .       '<input type="hidden" name="attemptid" value="'.$attemptid.'" />'
-               .       '<input type="hidden" name="starttime" value="" />'
-               .       '<input type="hidden" name="endtime" value="" />'
-               .       '<input type="hidden" name="mark" value="" />'
-               .       '<input type="hidden" name="detail" value="" />'
-               .       '<input type="hidden" name="status" value="" />'
-               ;
-               $this->insert_form($startblock, $endblock, $form_name, $form_fields, $keep_contents);
-       }
-       function insert_giveup_form($attemptid, $startblock, $endblock, $keep_contents=false) {
-               $form_name = ''; // no <form> tag will be generated
-               $form_fields = ''
-               .       '<button onclick="Finish('.HOTPOT_STATUS_ABANDONED.')" class="FuncButton" '
-               .       'onfocus="FuncBtnOver(this)" onblur="FuncBtnOut(this)" '
-               .       'onmouseover="FuncBtnOver(this)" onmouseout="FuncBtnOut(this)" '
-               .       'onmousedown="FuncBtnDown(this)" onmouseup="FuncBtnOut(this)">'
-               .       get_string('giveup', 'hotpot').'</button>'
-               ;
-               $this->insert_form($startblock, $endblock, $form_name, $form_fields, $keep_contents, true);
-       }
-       function insert_form($startblock, $endblock, $form_name, $form_fields, $keep_contents, $center=false) {
-               global $CFG;
-               $search = '#('.preg_quote($startblock).')(.*?)('.preg_quote($endblock).')#s';
-               $replace = $form_fields;
-               if ($keep_contents) {
-                       $replace .= '\\2';
-               }
-               if ($form_name) {
-                       $replace = '<form action="'.$CFG->wwwroot.'/mod/hotpot/attempt.php" method="POST" name="'.$form_name.'" target="'.$CFG->framename.'">'.$replace.'</form>';
-               }
-               if ($center) {
-                       $replace = '<div style="margin-left:auto; margin-right:auto; text-align: center;">'.$replace.'</div>';
-               }
-               $replace = '\\1'.$replace.'\\3';
-               $this->html = preg_replace($search, $replace, $this->html, 1);
-       }
-       function insert_message($start_str, $message, $color='red', $align='center') {
-               $message = '<p align="'.$align.'" style="text-align:'.$align.'"><b><font color="'.$color.'">'.$message."</font></b></p>\n";
-               $this->html = preg_replace('|'.preg_quote($start_str).'|', $start_str.$message, $this->html, 1);
-       }
-
-       function adjust_media_urls() {
-
-               if ($this->forceplugins) {
-
-                       // make sure the Moodle media plugin is available
-                       global $CFG;
-                       include_once "$CFG->dirroot/filter/mediaplugin/filter.php";
-
-                       // exclude swf files from the filter
-                       //$CFG->filter_mediaplugin_ignore_swf = true;
-
-                       $space = '\s(?:.+\s)?';
-                       $quote = '["'."']?"; // single, double, or no quote
-
-                       // patterns to media files types and paths
-                       $filetype = "avi|mpeg|mpg|mp3|mov|wmv";
-                       $filepath = ".*?\.($filetype)";
-
-                       $tagopen = '(?:(<)|(\\\\u003C))'; // left angle-bracket (uses two parenthese)
-                       $tagclose = '(?(1)>|(?(2)\\\\u003E))'; // right angle-bracket (to match the left one)
-                       $tagreopen = '(?(1)<|(?(2)\\\\u003C))'; // another left angle-bracket (to match the first one)
-
-                       // pattern to match <PARAM> tags which contain the file path
-                       //      wmp        : url
-                       //      quicktime  : src
-                       //      realplayer : src
-                       //      flash      : movie (doesn't need replacing)
-                       $param_url = "/{$tagopen}param{$space}name=$quote(?:movie|src|url)$quote{$space}value=$quote($filepath)$quote.*?$tagclose/is";
-
-                       // pattern to match <a> tags which link to multimedia files
-                       $link_url = "/{$tagopen}a{$space}href=$quote($filepath)$quote.*?$tagclose.*?$tagreopen\/A$tagclose/is";
-
-                       // extract <object> tags
-                       preg_match_all("/{$tagopen}object\s.*?{$tagclose}(.*?){$tagreopen}\/object{$tagclose}/is", $this->html, $objects);
-
-                       $i_max = count($objects[0]);
-                       for ($i=0; $i<$i_max; $i++) {
-
-                               // extract URL from <PARAM> or <A> 
-                               $url = '';
-                               if (preg_match($param_url, $objects[3][$i], $matches) || preg_match($link_url, $objects[3][$i], $matches)) {
-                                       $url = $matches[3];
-                               }
-
-                               if ($url) {
-                                       // strip inner tags (e.g. <embed>)
-                                       $txt = preg_replace("/$tagopen.*?$tagclose/", '', $objects[3][$i]);
-
-                                       // if url is in the query string, remove the leading characters
-                                       $url = preg_replace('/^[^?]*\?([^=]+=[^&]*&)*[^=]+=([^&]*)$/', '$2', $url, 1);
-                                       $link = '<a href="'.$url.'">'.$txt.'</a>';
-
-                                       $new_object = mediaplugin_filter($this->filedir, $link);
-                                       $new_object = str_replace($link, '', $new_object);
-                                       $new_object = str_replace('&amp;', '&', $new_object);
-
-                                       $this->html = str_replace($objects[0][$i], $new_object, $this->html);
-                               }
-                       }
-               }
-       }
+    // constructor function
+    function hotpot_xml_quiz(&$obj, $read_file=true, $parse_xml=true, $convert_urls=true, $report_errors=true, $create_html=true) {
+        // obj can be the $_GET array or a form object/array
+
+        global $CFG, $HOTPOT_OUTPUTFORMAT, $HOTPOT_OUTPUTFORMAT_DIR;
+
+        // check xmlize functions are available
+        if (! function_exists("xmlize")) {
+            error('xmlize functions are not available');
+        }
+
+        $this->read_file = $read_file;
+        $this->parse_xml = $parse_xml;
+        $this->convert_urls = $convert_urls;
+        $this->report_errors = $report_errors;
+        $this->create_html = $create_html;
+
+        // extract fields from $obj
+        //  course     : the course id
+        //  reference   : the filename within the files folder
+        //  location     : "site" files folder or "course" files folder
+        //  navigation   : type of navigation required in quiz
+        //  forceplugins : force Moodle compatible media players
+        $this->course = $this->obj_value($obj, 'course');
+        $this->reference = $this->obj_value($obj, 'reference');
+        $this->location = $this->obj_value($obj, 'location');
+        $this->navigation = $this->obj_value($obj, 'navigation');
+        $this->forceplugins = $this->obj_value($obj, 'forceplugins');
+
+        // can't continue if there is no course or reference
+        if (empty($this->course) || empty($this->reference)) {
+            $this->error = get_string('error_nocourseorfilename', 'hotpot');
+            if ($this->report_errors) {
+                error($this->error);
+            }
+            return;
+        }
+
+        $this->course_homeurl = "$CFG->wwwroot/course/view.php?id=$this->course";
+
+        // set filedir, filename and filepath
+        switch ($this->location) {
+            case HOTPOT_LOCATION_SITEFILES:
+                $site = get_site();
+                $this->filedir = $site->id;
+                break;
+
+            case HOTPOT_LOCATION_COURSEFILES:
+            default:
+                $this->filedir = $this->course;
+                break;
+        }
+        $this->filesubdir = dirname($this->reference);
+        if ($this->filesubdir=='.') {
+            $this->filesubdir = '';
+        }
+        if ($this->filesubdir) {
+            $this->filesubdir .= '/';
+        }
+        $this->filename = basename($this->reference);
+        $this->fileroot = "$CFG->dataroot/$this->filedir";
+        $this->filepath = "$this->fileroot/$this->reference";
+
+        // read the file, if required
+        if ($this->read_file) {
+
+            if (!file_exists($this->filepath) || !is_readable($this->filepath)) {
+                $this->error = get_string('error_couldnotopensourcefile', 'hotpot', $this->filepath);
+                if ($this->report_errors) {
+                    error($this->error, $this->course_homeurl);
+                }
+                return;
+            }
+
+            // read in the XML source
+            $this->source = file_get_contents($this->filepath);
+
+            // convert relative URLs to absolute URLs
+            if ($this->convert_urls) {
+                $this->hotpot_convert_relative_urls($this->source);
+            }
+
+            $this->html = '';
+            $this->quiztype = '';
+            $this->outputformat = 0;
+
+            // is this an html file?
+            if (preg_match('|\.html?$|', $this->filename)) {
+
+                $this->filetype = 'html';
+                $this->html = &$this->source;
+
+                // relative URLs in stylesheets
+                $search = '|'.'(<style[^>]*>)'.'(.*?)'.'(</style>)'.'|ise';
+                $replace = "stripslashes('\\1').hotpot_convert_stylesheets_urls('".$this->get_baseurl()."','".$this->reference."','\\2'.'\\3')";
+                $this->source = preg_replace($search, $replace, $this->source);
+
+                // relative URLs in "PreloadImages(...);"
+                $search = '|'.'(?<='.'PreloadImages'.'\('.')'."([^)]+?)".'(?='.'\);'.')'.'|se';
+                $replace = "hotpot_convert_preloadimages_urls('".$this->get_baseurl()."','".$this->reference."','\\1')";
+                $this->source = preg_replace($search, $replace, $this->source);
+
+                // relative URLs in <button class="NavButton" ... onclick="location='...'">
+                $search = '|'.'(?<='.'onclick="'."location='".')'."([^']*)".'(?='."'; return false;".'")'.'|ise';
+                $replace = "hotpot_convert_navbutton_url('".$this->get_baseurl()."','".$this->reference."','\\1','".$this->course."')";
+                $this->source = preg_replace($search, $replace, $this->source);
+
+            } else {
+                if ($this->parse_xml) {
+
+                    $this->filetype = 'xml';
+
+                    // encode "gap fill" text in JCloze exercise
+                    $this->encode_cdata($this->source, 'gap-fill');
+
+                    // convert source to xml tree
+                    $this->hotpot_xml_tree($this->source);
+
+                    $keys = array_keys($this->xml);
+                    foreach ($keys as $key) {
+                        if (preg_match('/^(hotpot|textoys)-(\w+)-file$/i', $key, $matches)) {
+                            $this->quiztype = strtolower($matches[2]);
+                            $this->xml_root = "['$key']['#']";
+                            break;
+                        }
+                    }
+                }
+
+                if ($this->create_html) {
+
+                    // set the real output format from the requested output format
+                    $this->real_outputformat = $this->obj_value($obj, 'outputformat');
+                    $this->draganddrop = '';
+                    if (
+                        empty($this->real_outputformat) ||
+                        $this->real_outputformat==HOTPOT_OUTPUTFORMAT_BEST ||
+                        empty($HOTPOT_OUTPUTFORMAT_DIR[$this->real_outputformat])
+                    ) {
+                        if ($CFG->hotpotismobile && isset($HOTPOT_OUTPUTFORMAT_DIR[HOTPOT_OUTPUTFORMAT_MOBILE])) {
+                                $this->real_outputformat = HOTPOT_OUTPUTFORMAT_MOBILE;
+                        } else { // PC
+                            if ($this->quiztype=='jmatch' || $this->quiztype=='jmix') {
+                                $this->real_outputformat = HOTPOT_OUTPUTFORMAT_V6_PLUS;
+                            } else {
+                                $this->real_outputformat = HOTPOT_OUTPUTFORMAT_V6;
+                            }
+                        }
+                    }
+
+                    if ($this->real_outputformat==HOTPOT_OUTPUTFORMAT_V6_PLUS) {
+                        if ($this->quiztype=='jmatch' || $this->quiztype=='jmix') {
+                            $this->draganddrop = 'd'; // prefix for templates (can also be "f" ?)
+                        }
+                        $this->real_outputformat = HOTPOT_OUTPUTFORMAT_V6;
+                    }
+
+                    // set path(s) to template
+                    $this->template_dir = $HOTPOT_OUTPUTFORMAT_DIR[$this->real_outputformat];
+                    $this->template_dirpath = $CFG->hotpottemplate.'/'.$this->template_dir;
+                    $this->template_filepath = $CFG->hotpottemplate.'/'.$this->template_dir.'.php';
+
+                    // check template class exists
+                    if (!file_exists($this->template_filepath) || !is_readable($this->template_filepath)) {
+                        $this->error = get_string('error_couldnotopentemplate', 'hotpot', $this->template_dir);
+                        if ($this->report_errors) {
+                            error($this->error, $this->course_homeurl);
+                        }
+                        return;
+                    }
+
+                    // get default and output-specfic template classes
+                    include($this->template_filepath);
+
+                    // create html (using the template for the specified output format)
+                    $this->template = new hotpot_xml_quiz_template($this);
+                    $this->html = &$this->template->html;
+
+                } // end $this->create_html
+            } // end if html/xml file
+        } // end if $this->read_file
+    } // end constructor function
+
+    function hotpot_convert_relative_urls(&$str) {
+        $tagopen = '(?:(<)|(&lt;)|(&amp;#x003C;))'; // left angle bracket
+        $tagclose = '(?(2)>|(?(3)&gt;|(?(4)&amp;#x003E;)))'; //  right angle bracket (to match left angle bracket)
+
+        $space = '\s+'; // at least one space
+        $anychar = '(?:[^>]*?)'; // any character
+
+        $quoteopen = '("|&quot;|&amp;quot;)'; // open quote
+        $quoteclose = '\\5'; //  close quote (to match open quote)
+
+        $replace = "hotpot_convert_relative_url('".$this->get_baseurl()."', '".$this->reference."', '\\1', '\\6', '\\7')";
+
+        $tags = array('script'=>'src', 'link'=>'href', 'a'=>'href','img'=>'src','param'=>'value', 'object'=>'data', 'embed'=>'src');
+        foreach ($tags as $tag=>$attribute) {
+            if ($tag=='param') {
+                $url = '\S+?\.\S+?'; // must include a filename and have no spaces
+            } else {
+                $url = '.*?';
+            }
+            $search = "%($tagopen$tag$space$anychar$attribute=$quoteopen)($url)($quoteclose$anychar$tagclose)%ise";
+            $str = preg_replace($search, $replace, $str);
+        }
+    }
+
+    function get_baseurl() {
+        // set the url base (first time only)
+        if (!isset($this->baseurl)) {
+            global $CFG;
+            if ($CFG->slasharguments) {
+                $this->baseurl = "$CFG->wwwroot/file.php/$this->filedir/";
+            } else {
+                $this->baseurl = "$CFG->wwwroot/file.php?file=/$this->filedir/";
+            }
+        }
+        return $this->baseurl;
+    }
+
+
+    // insert forms and messages
+
+    function remove_nav_buttons() {
+        $search = '#<!-- Begin(Top|Bottom)NavButtons -->(.*?)<!-- End(Top|Bottom)NavButtons -->#s';
+        $this->html = preg_replace($search, '', $this->html);
+    }
+    function insert_script($src=HOTPOT_JS) {
+        $script = '<script src="'.$src.'" type="text/javascript" language="javascript"></script>'."\n";
+        $this->html = preg_replace('|</head>|i', $script.'</head>', $this->html, 1);
+    }
+    function insert_submission_form($attemptid, $startblock, $endblock, $keep_contents=false) {
+        $form_name = 'store';
+        $form_fields = ''
+        .   '<input type="hidden" name="attemptid" value="'.$attemptid.'" />'
+        .   '<input type="hidden" name="starttime" value="" />'
+        .   '<input type="hidden" name="endtime" value="" />'
+        .   '<input type="hidden" name="mark" value="" />'
+        .   '<input type="hidden" name="detail" value="" />'
+        .   '<input type="hidden" name="status" value="" />'
+        ;
+        $this->insert_form($startblock, $endblock, $form_name, $form_fields, $keep_contents);
+    }
+    function insert_giveup_form($attemptid, $startblock, $endblock, $keep_contents=false) {
+        $form_name = ''; // no <form> tag will be generated
+        $form_fields = ''
+        .   '<button onclick="Finish('.HOTPOT_STATUS_ABANDONED.')" class="FuncButton" '
+        .   'onfocus="FuncBtnOver(this)" onblur="FuncBtnOut(this)" '
+        .   'onmouseover="FuncBtnOver(this)" onmouseout="FuncBtnOut(this)" '
+        .   'onmousedown="FuncBtnDown(this)" onmouseup="FuncBtnOut(this)">'
+        .   get_string('giveup', 'hotpot').'</button>'
+        ;
+        $this->insert_form($startblock, $endblock, $form_name, $form_fields, $keep_contents, true);
+    }
+    function insert_form($startblock, $endblock, $form_name, $form_fields, $keep_contents, $center=false) {
+        global $CFG;
+        $search = '#('.preg_quote($startblock).')(.*?)('.preg_quote($endblock).')#s';
+        $replace = $form_fields;
+        if ($keep_contents) {
+            $replace .= '\\2';
+        }
+        if ($form_name) {
+            $replace = '<form action="'.$CFG->wwwroot.'/mod/hotpot/attempt.php" method="POST" name="'.$form_name.'" target="'.$CFG->framename.'">'.$replace.'</form>';
+        }
+        if ($center) {
+            $replace = '<div style="margin-left:auto; margin-right:auto; text-align: center;">'.$replace.'</div>';
+        }
+        $replace = '\\1'.$replace.'\\3';
+        $this->html = preg_replace($search, $replace, $this->html, 1);
+    }
+    function insert_message($start_str, $message, $color='red', $align='center') {
+        $message = '<p align="'.$align.'" style="text-align:'.$align.'"><b><font color="'.$color.'">'.$message."</font></b></p>\n";
+        $this->html = preg_replace('|'.preg_quote($start_str).'|', $start_str.$message, $this->html, 1);
+    }
+
+    function adjust_media_urls() {
+
+        if ($this->forceplugins) {
+
+            // make sure the Moodle media plugin is available
+            global $CFG;
+            include_once "$CFG->dirroot/filter/mediaplugin/filter.php";
+
+            // exclude swf files from the filter
+            //$CFG->filter_mediaplugin_ignore_swf = true;
+
+            $space = '\s(?:.+\s)?';
+            $quote = '["'."']?"; // single, double, or no quote
+
+            // patterns to media files types and paths
+            $filetype = "avi|mpeg|mpg|mp3|mov|wmv";
+            $filepath = ".*?\.($filetype)";
+
+            $tagopen = '(?:(<)|(\\\\u003C))'; // left angle-bracket (uses two parenthese)
+            $tagclose = '(?(1)>|(?(2)\\\\u003E))'; // right angle-bracket (to match the left one)
+            $tagreopen = '(?(1)<|(?(2)\\\\u003C))'; // another left angle-bracket (to match the first one)
+
+            // pattern to match <PARAM> tags which contain the file path
+            //  wmp        : url
+            //  quicktime  : src
+            //  realplayer : src
+            //  flash      : movie (doesn't need replacing)
+            $param_url = "/{$tagopen}param{$space}name=$quote(?:movie|src|url)$quote{$space}value=$quote($filepath)$quote.*?$tagclose/is";
+
+            // pattern to match <a> tags which link to multimedia files
+            $link_url = "/{$tagopen}a{$space}href=$quote($filepath)$quote.*?$tagclose.*?$tagreopen\/A$tagclose/is";
+
+            // extract <object> tags
+            preg_match_all("/{$tagopen}object\s.*?{$tagclose}(.*?){$tagreopen}\/object{$tagclose}/is", $this->html, $objects);
+
+            $i_max = count($objects[0]);
+            for ($i=0; $i<$i_max; $i++) {
+
+                // extract URL from <PARAM> or <A> 
+                $url = '';
+                if (preg_match($param_url, $objects[3][$i], $matches) || preg_match($link_url, $objects[3][$i], $matches)) {
+                    $url = $matches[3];
+                }
+
+                if ($url) {
+                    // strip inner tags (e.g. <embed>)
+                    $txt = preg_replace("/$tagopen.*?$tagclose/", '', $objects[3][$i]);
+
+                    // if url is in the query string, remove the leading characters
+                    $url = preg_replace('/^[^?]*\?([^=]+=[^&]*&)*[^=]+=([^&]*)$/', '$2', $url, 1);
+                    $link = '<a href="'.$url.'">'.$txt.'</a>';
+
+                    $new_object = mediaplugin_filter($this->filedir, $link);
+                    $new_object = str_replace($link, '', $new_object);
+                    $new_object = str_replace('&amp;', '&', $new_object);
+
+                    $this->html = str_replace($objects[0][$i], $new_object, $this->html);
+                }
+            }
+        }
+    }
 
 } // end class
 
 function hotpot_convert_stylesheets_urls($baseurl, $reference, $css, $stripslashes=true) {
-       if ($stripslashes) {
-               $css = stripslashes($css);
-       }
-       $search = '|'.'(?<='.'url'.'\('.')'."(.+?)".'(?='.'\)'.')'.'|ise';
-       $replace = "hotpot_convert_url('".$baseurl."','".$reference."','\\1')";
-       return preg_replace($search, $replace, $css);
+    if ($stripslashes) {
+        $css = stripslashes($css);
+    }
+    $search = '|'.'(?<='.'url'.'\('.')'."(.+?)".'(?='.'\)'.')'.'|ise';
+    $replace = "hotpot_convert_url('".$baseurl."','".$reference."','\\1')";
+    return preg_replace($search, $replace, $css);
 }
 function hotpot_convert_preloadimages_urls($baseurl, $reference, $urls, $stripslashes=true) {
-       if ($stripslashes) {
-               $urls = stripslashes($urls);
-       }
-       $search = '|(?<=["'."'])([^,'".'"]*?)(?=["'."'])|ise";
-       $replace = "hotpot_convert_url('".$baseurl."','".$reference."','\\1')";
-       return preg_replace($search, $replace, $urls);
+    if ($stripslashes) {
+        $urls = stripslashes($urls);
+    }
+    $search = '|(?<=["'."'])([^,'".'"]*?)(?=["'."'])|ise";
+    $replace = "hotpot_convert_url('".$baseurl."','".$reference."','\\1')";
+    return preg_replace($search, $replace, $urls);
 }
 function hotpot_convert_navbutton_url($baseurl, $reference, $url, $course, $stripslashes=true) {
-       global $CFG;
-
-       if ($stripslashes) {
-               $url = stripslashes($url);
-       }
-       $url = hotpot_convert_url($baseurl, $reference, $url, false);
-
-       // is this a $url for another hotpot in this course ?
-       if (preg_match("|^$baseurl(.*)$|", $url, $matches)) {
-               if ($records = get_records_select('hotpot', "course='$course' AND reference='".$matches[1]."'")) {
-                       $ids = array_keys($records);
-                       $url = "$CFG->wwwroot/mod/hotpot/view.php?hp=".$ids[0];
-               }
-       }
-
-       return $url;
+    global $CFG;
+
+    if ($stripslashes) {
+        $url = stripslashes($url);
+    }
+    $url = hotpot_convert_url($baseurl, $reference, $url, false);
+
+    // is this a $url for another hotpot in this course ?
+    if (preg_match("|^$baseurl(.*)$|", $url, $matches)) {
+        if ($records = get_records_select('hotpot', "course='$course' AND reference='".$matches[1]."'")) {
+            $ids = array_keys($records);
+            $url = "$CFG->wwwroot/mod/hotpot/view.php?hp=".$ids[0];
+        }
+    }
+
+    return $url;
 }
 
 function hotpot_convert_relative_url($baseurl, $reference, $opentag, $url, $closetag, $stripslashes=true) {
-       if ($stripslashes) {
-               $opentag = stripslashes($opentag);
-               $url = stripslashes($url);
-               $closetag = stripslashes($closetag);
-       }
-
-       // catch <PARAM name="FlashVars" value="TheSound=soundfile.mp3">
-       //      ampersands can appear as "&", "&amp;" or "&amp;#x0026;amp;"
-       if (preg_match('|^'.'\w+=[^&]+'.'('.'&((amp;#x0026;)?amp;)?'.'\w+=[^&]+)*'.'$|', $url)) {
-               $query = $url;
-               $url = '';
-               $fragment = '';
-
-       // parse the $url into $matches
-       //      [1] path
-       //      [2] query string, if any
-       //      [3] anchor fragment, if any
-       } else if (preg_match('|^'.'([^?]*)'.'((?:\\?[^#]*)?)'.'((?:#.*)?)'.'$|', $url, $matches)) {
-               $url = $matches[1];
-               $query = $matches[2];
-               $fragment = $matches[3];
-
-       // these appears to be no query or fragment in this url
-       } else {
-               $query = '';
-               $fragment = '';
-       }
-
-       if ($url) {
-               $url = hotpot_convert_url($baseurl, $reference, $url, false);
-       }
-
-       if ($query) {
-               $search = '#'.'(file|src|thesound)='."([^&]+)".'#ise';
-               $replace = "'\\1='.hotpot_convert_url('".$baseurl."','".$reference."','\\2')";
-               $query = preg_replace($search, $replace, $query);
-       }
-
-       $url = $opentag.$url.$query.$fragment.$closetag;
-
-       return $url;
+    if ($stripslashes) {
+        $opentag = stripslashes($opentag);
+        $url = stripslashes($url);
+        $closetag = stripslashes($closetag);
+    }
+
+    // catch <PARAM name="FlashVars" value="TheSound=soundfile.mp3">
+    //  ampersands can appear as "&", "&amp;" or "&amp;#x0026;amp;"
+    if (preg_match('|^'.'\w+=[^&]+'.'('.'&((amp;#x0026;)?amp;)?'.'\w+=[^&]+)*'.'$|', $url)) {
+        $query = $url;
+        $url = '';
+        $fragment = '';
+
+    // parse the $url into $matches
+    //  [1] path
+    //  [2] query string, if any
+    //  [3] anchor fragment, if any
+    } else if (preg_match('|^'.'([^?]*)'.'((?:\\?[^#]*)?)'.'((?:#.*)?)'.'$|', $url, $matches)) {
+        $url = $matches[1];
+        $query = $matches[2];
+        $fragment = $matches[3];
+
+    // these appears to be no query or fragment in this url
+    } else {
+        $query = '';
+        $fragment = '';
+    }
+
+    if ($url) {
+        $url = hotpot_convert_url($baseurl, $reference, $url, false);
+    }
+
+    if ($query) {
+        $search = '#'.'(file|src|thesound)='."([^&]+)".'#ise';
+        $replace = "'\\1='.hotpot_convert_url('".$baseurl."','".$reference."','\\2')";
+        $query = preg_replace($search, $replace, $query);
+    }
+
+    $url = $opentag.$url.$query.$fragment.$closetag;
+
+    return $url;
 }
 
 function hotpot_convert_url($baseurl, $reference, $url, $stripslashes=true) {
-       // maintain a cache of converted urls
-       static $HOTPOT_RELATIVE_URLS = array();
-
-       if ($stripslashes) {
-               $url = stripslashes($url);
-       }
-
-       // is this an absolute url? (or javascript pseudo url)
-       if (preg_match('%^(http://|/|javascript:)%i', $url)) {
-               // do nothing
-
-       // has this relative url already been converted?
-       } else if (isset($HOTPOT_RELATIVE_URLS[$url])) {
-               $url = $HOTPOT_RELATIVE_URLS[$url];
-
-       } else {
-               $relativeurl = $url;
-
-               // get the subdirectory, $dir, of the quiz $reference
-               $dir = dirname($reference);
-
-               // allow for leading "./" and "../"
-               while (preg_match('|^(\.{1,2})/(.*)$|', $url, $matches)) {
-                       if ($matches[1]=='..') {
-                               $dir = dirname($dir);
-                       }
-                       $url = $matches[2];
-               }
-
-               // add subdirectory, $dir, to $baseurl, if necessary
-               if ($dir && $dir<>'.') {
-                       $baseurl .= "$dir/";
-               }
-
-               // prefix $url with $baseurl
-               $url = "$baseurl$url";
-
-               // add url to cache
-               $HOTPOT_RELATIVE_URLS[$relativeurl] = $url;
-       }
-       return $url;
+    // maintain a cache of converted urls
+    static $HOTPOT_RELATIVE_URLS = array();
+
+    if ($stripslashes) {
+        $url = stripslashes($url);
+    }
+
+    // is this an absolute url? (or javascript pseudo url)
+    if (preg_match('%^(http://|/|javascript:)%i', $url)) {
+        // do nothing
+
+    // has this relative url already been converted?
+    } else if (isset($HOTPOT_RELATIVE_URLS[$url])) {
+        $url = $HOTPOT_RELATIVE_URLS[$url];
+
+    } else {
+        $relativeurl = $url;
+
+        // get the subdirectory, $dir, of the quiz $reference
+        $dir = dirname($reference);
+
+        // allow for leading "./" and "../"
+        while (preg_match('|^(\.{1,2})/(.*)$|', $url, $matches)) {
+            if ($matches[1]=='..') {
+                $dir = dirname($dir);
+            }
+            $url = $matches[2];
+        }
+
+        // add subdirectory, $dir, to $baseurl, if necessary
+        if ($dir && $dir<>'.') {
+            $baseurl .= "$dir/";
+        }
+
+        // prefix $url with $baseurl
+        $url = "$baseurl$url";
+
+        // add url to cache
+        $HOTPOT_RELATIVE_URLS[$relativeurl] = $url;
+    }
+    return $url;
 }
 
 // ===================================================
@@ -1828,481 +1828,481 @@ function hotpot_convert_url($baseurl, $reference, $url, $stripslashes=true) {
 
 function hotpot_add_attempt_details(&$attempt) {
 
-       // encode ampersands so that HTML entities are preserved in the XML parser
-       // N.B. ampersands inside <![CDATA[ ]]> blocks do NOT need to be encoded
-
-       $old = &$attempt->details; // shortcut to "old" details
-       $new = '';
-       $str_start = 0;
-       while (($cdata_start = strpos($old, '<![CDATA[', $str_start)) && ($cdata_end = strpos($old, ']]>', $cdata_start))) {
-               $cdata_end += 3;
-               $new .= str_replace('&', '&amp;', substr($old, $str_start, $cdata_start-$str_start)).substr($old, $cdata_start, $cdata_end-$cdata_start);
-               $str_start = $cdata_end;
-       }
-       $new .= str_replace('&', '&amp;', substr($old, $str_start));
-       unset($old);
-
-       // parse the attempt details as xml
-       $details = new hotpot_xml_tree($new, "['hpjsresult']['#']");
-
-       $num = -1;
-       $q_num = -1;
-       $question = NULL;
-       $reponse = NULL;
-
-       $i = 0;
-       $tags = 'fields,field';
-
-       while (($field="[$i]['#']") && $details->xml_value($tags, $field)) {
-
-               $name = $details->xml_value($tags, $field."['fieldname'][0]['#']");
-               $data = $details->xml_value($tags, $field."['fielddata'][0]['#']");
-
-               // parse the field name into $matches
-               //      [1] quiz type
-               //      [2] attempt detail name
-               if (preg_match('/^(\w+?)_(\w+)$/', $name, $matches)) {
-                       $quiztype = strtolower($matches[1]);
-                       $name = strtolower($matches[2]);
-
-                       // parse the attempt detail $name into $matches
-                       //      [1] question number
-                       //      [2] question detail name
-                       if (preg_match('/^q(\d+)_(\w+)$/', $name, $matches)) {
-                               $num = $matches[1];
-                               $name = strtolower($matches[2]);
-                               $data = addslashes($data);
-
-                               // adjust JCross question numbers
-                               if (preg_match('/^(across|down)(.*)$/', $name, $matches)) {
-                                       $num .= '_'.$matches[1]; // e.g. 01_across, 02_down
-                                       $name = $matches[2];
-                                       if (substr($name, 0, 1)=='_') {
-                                               $name = substr($name, 1); // remove leading '_'
-                                       }
-                               }
-
-                               // is this a new question (or the first one)?
-                               if ($q_num<>$num) {
-
-                                       // add previous question and response, if any
-                                       hotpot_add_response($attempt, $question, $response);
-
-                                       // initialize question object
-                                       $question = NULL;
-                                       $question->name = '';
-                                       $question->text = '';
-                                       $question->hotpot = $attempt->hotpot;
-
-                                       // initialize response object
-                                       $response = NULL;
-                                       $response->attempt = $attempt->id;
-
-                                       // update question number
-                                       $q_num = $num;
-                               }
-
-                               // adjust field name and value, and set question type
-                               // (may not be necessary one day)
-                               hotpot_adjust_response_field($quiztype, $question, $num, $name, $data);
-
-                               // add $data to the question/response details
-                               switch ($name) {
-                                       case 'name':
-                                       case 'type':
-                                               $question->$name = $data;
-                                               break;
-                                       case 'text':
-                                               $question->$name = hotpot_string_id($data);
-                                               break;
-
-                                       case 'correct':
-                                       case 'ignored':
-                                       case 'wrong':
-                                               $response->$name = hotpot_string_ids($data);
-                                               break;
-
-                                       case 'score':
-                                       case 'weighting':
-                                       case 'hints':
-                                       case 'clues':
-                                       case 'checks':
-                                               $response->$name = intval($data);
-                                               break;
-                               }
-
-                       } else { // attempt details
-
-                               // adjust field name and value
-                               hotpot_adjust_response_field($quiztype, $question, $num='', $name, $data);
-
-                               // add $data to the attempt details
-                               if ($name=='penalties') {
-                                       $attempt->$name = intval($data);
-                               }
-                       }
-               }
-
-               $i++;
-       } // end while
-
-       // add the final question and response, if any
-       hotpot_add_response($attempt, $question, $response);
+    // encode ampersands so that HTML entities are preserved in the XML parser
+    // N.B. ampersands inside <![CDATA[ ]]> blocks do NOT need to be encoded
+
+    $old = &$attempt->details; // shortcut to "old" details
+    $new = '';
+    $str_start = 0;
+    while (($cdata_start = strpos($old, '<![CDATA[', $str_start)) && ($cdata_end = strpos($old, ']]>', $cdata_start))) {
+        $cdata_end += 3;
+        $new .= str_replace('&', '&amp;', substr($old, $str_start, $cdata_start-$str_start)).substr($old, $cdata_start, $cdata_end-$cdata_start);
+        $str_start = $cdata_end;
+    }
+    $new .= str_replace('&', '&amp;', substr($old, $str_start));
+    unset($old);
+
+    // parse the attempt details as xml
+    $details = new hotpot_xml_tree($new, "['hpjsresult']['#']");
+
+    $num = -1;
+    $q_num = -1;
+    $question = NULL;
+    $reponse = NULL;
+
+    $i = 0;
+    $tags = 'fields,field';
+
+    while (($field="[$i]['#']") && $details->xml_value($tags, $field)) {
+
+        $name = $details->xml_value($tags, $field."['fieldname'][0]['#']");
+        $data = $details->xml_value($tags, $field."['fielddata'][0]['#']");
+
+        // parse the field name into $matches
+        //  [1] quiz type
+        //  [2] attempt detail name
+        if (preg_match('/^(\w+?)_(\w+)$/', $name, $matches)) {
+            $quiztype = strtolower($matches[1]);
+            $name = strtolower($matches[2]);
+
+            // parse the attempt detail $name into $matches
+            //  [1] question number
+            //  [2] question detail name
+            if (preg_match('/^q(\d+)_(\w+)$/', $name, $matches)) {
+                $num = $matches[1];
+                $name = strtolower($matches[2]);
+                $data = addslashes($data);
+
+                // adjust JCross question numbers
+                if (preg_match('/^(across|down)(.*)$/', $name, $matches)) {
+                    $num .= '_'.$matches[1]; // e.g. 01_across, 02_down
+                    $name = $matches[2];
+                    if (substr($name, 0, 1)=='_') {
+                        $name = substr($name, 1); // remove leading '_'
+                    }
+                }
+
+                // is this a new question (or the first one)?
+                if ($q_num<>$num) {
+
+                    // add previous question and response, if any
+                    hotpot_add_response($attempt, $question, $response);
+
+                    // initialize question object
+                    $question = NULL;
+                    $question->name = '';
+                    $question->text = '';
+                    $question->hotpot = $attempt->hotpot;
+
+                    // initialize response object
+                    $response = NULL;
+                    $response->attempt = $attempt->id;
+
+                    // update question number
+                    $q_num = $num;
+                }
+
+                // adjust field name and value, and set question type
+                // (may not be necessary one day)
+                hotpot_adjust_response_field($quiztype, $question, $num, $name, $data);
+
+                // add $data to the question/response details
+                switch ($name) {
+                    case 'name':
+                    case 'type':
+                        $question->$name = $data;
+                        break;
+                    case 'text':
+                        $question->$name = hotpot_string_id($data);
+                        break;
+
+                    case 'correct':
+                    case 'ignored':
+                    case 'wrong':
+                        $response->$name = hotpot_string_ids($data);
+                        break;
+
+                    case 'score':
+                    case 'weighting':
+                    case 'hints':
+                    case 'clues':
+                    case 'checks':
+                        $response->$name = intval($data);
+                        break;
+                }
+
+            } else { // attempt details
+
+                // adjust field name and value
+                hotpot_adjust_response_field($quiztype, $question, $num='', $name, $data);
+
+                // add $data to the attempt details
+                if ($name=='penalties') {
+                    $attempt->$name = intval($data);
+                }
+            }
+        }
+
+        $i++;
+    } // end while
+
+    // add the final question and response, if any
+    hotpot_add_response($attempt, $question, $response);
 }
 function hotpot_add_response(&$attempt, &$question, &$response) {
-       global $db, $next_url;
+    global $db, $next_url;
 
-       $loopcount = 1;
+    $loopcount = 1;
 
-       $looping = isset($question) && isset($question->name) && isset($response);
-       while ($looping) {
+    $looping = isset($question) && isset($question->name) && isset($response);
+    while ($looping) {
 
-               if ($loopcount==1) {
-                       $questionname = $question->name;
-               }
+        if ($loopcount==1) {
+            $questionname = $question->name;
+        }
 
-               if (!$question->id = get_field('hotpot_questions', 'id', 'name', $question->name, 'hotpot', $attempt->hotpot)) {
-                       // add question record
-                       if (!$question->id = insert_record('hotpot_questions', $question)) {
-                               error("Could not add question record (attempt_id=$attempt->id): ".$db->ErrorMsg(), $next_url);
-                       }
-               }
+        if (!$question->id = get_field('hotpot_questions', 'id', 'name', $question->name, 'hotpot', $attempt->hotpot)) {
+            // add question record
+            if (!$question->id = insert_record('hotpot_questions', $question)) {
+                error("Could not add question record (attempt_id=$attempt->id): ".$db->ErrorMsg(), $next_url);
+            }
+        }
 
-               if (record_exists('hotpot_responses', 'attempt', $attempt->id, 'question', $question->id)) {
-                       // there is already a response to this question for this attempt
-                       // probably because this quiz has two questions with the same text
-                       //      e.g. Which one of these answers is correct?
+        if (record_exists('hotpot_responses', 'attempt', $attempt->id, 'question', $question->id)) {
+            // there is already a response to this question for this attempt
+            // probably because this quiz has two questions with the same text
+            //  e.g. Which one of these answers is correct?
 
-                       // To workaround this, we create new question names
-                       //      e.g. Which one of these answers is correct? (2)
-                       // until we get a question name for which there is no response yet on this attempt
+            // To workaround this, we create new question names
+            //  e.g. Which one of these answers is correct? (2)
+            // until we get a question name for which there is no response yet on this attempt
 
-                       $loopcount++;
-                       $question->name = "$questionname ($loopcount)";
+            $loopcount++;
+            $question->name = "$questionname ($loopcount)";
 
-                       // This method fails to correctly identify questions in
-                       // quizzes which allow questions to be shuffled or omitted.
-                       // As yet, there is no workaround for such cases.
+            // This method fails to correctly identify questions in
+            // quizzes which allow questions to be shuffled or omitted.
+            // As yet, there is no workaround for such cases.
 
-               } else {
-                       $response->question = $question->id;
+        } else {
+            $response->question = $question->id;
 
-                       // add response record
-                       if(!$response->id = insert_record('hotpot_responses', $response)) {
-                               error("Could not add response record (attempt_id=$attempt->id, question_id=$question->id): ".$db->ErrorMsg(), $next_url);
-                       }
+            // add response record
+            if(!$response->id = insert_record('hotpot_responses', $response)) {
+                error("Could not add response record (attempt_id=$attempt->id, question_id=$question->id): ".$db->ErrorMsg(), $next_url);
+            }
 
-                       // we can stop looping now
-                       $looping = false;
-               }
-       } // end while
+            // we can stop looping now
+            $looping = false;
+        }
+    } // end while
 }
 function hotpot_adjust_response_field($quiztype, &$question, &$num, &$name, &$data) {
-       switch ($quiztype) {
-               case 'jbc':
-                       $question->type = HOTPOT_JCB;
-                       switch ($name) {
-                               case 'right':
-                                       $name = 'correct';
-                               break;
-                       }
-                       break;
-               case 'jcloze':
-                       $question->type = HOTPOT_JCLOZE;
-                       if (is_numeric($num)) {
-                               $question->name = $num;
-                       }
-                       switch ($name) {
-                               case 'penalties':
-                                       if (is_numeric($num)) {
-                                               $name = 'checks';
-                                               if (is_numeric($data)) {
-                                                       $data++;
-                                               }
-                                       }
-                                       break;
-                               case 'clue_shown':
-                                       $name = 'clues';
-                                       $data = ($data=='YES' ? 1 : 0);
-                                       break;
-                               case 'clue_text':
-                                       $name = 'text';
-                                       break;
-                       }
-                       break;
-               case 'jcross':
-                       $question->type = HOTPOT_JCROSS;
-                       $question->name = $num;
-                       switch ($name) {
-                               case '': // HotPot v2.0.x
-                                       $name = 'correct';
-                                       break;
-                               case 'clue':
-                                       $name = 'text';
-                                       break;
-                       }
-                       break;
-               case 'jmatch':
-                       $question->type = HOTPOT_JMATCH;
-                       switch ($name) {
-                               case 'attempts':
-                                       $name = 'penalties';
-                                       if (is_numeric($data) && $data>0) {
-                                               $data--;
-                                       }
-                               break;
-                               case 'lhs':
-                                       $name = 'name';
-                               break;
-                               case 'rhs':
-                                       $name = 'correct';
-                               break;
-                       }
-                       break;
-               case 'jmix':
-                       $question->type = HOTPOT_JMIX;
-                       $question->name = $num;
-                       switch ($name) {
-                               // keep these in for "restore" of courses
-                               // which were backed up with HotPot v2.0.x
-                               case 'wrongguesses':
-                                       $name = 'checks';
-                                       if (is_numeric($data)) {
-                                               $data++;
-                                       }
-                               break;
-                               case 'right':
-                                       $name = 'correct';
-                               break;
-                       }
-                       break;
-                       break;
-               case 'jquiz':
-                       switch ($name) {
-                               case 'type':
-                                       $data = HOTPOT_JQUIZ;
-                                       switch ($data) {
-                                               case 'multiple-choice':
-                                                       $data .= '.'.HOTPOT_JQUIZ_MULTICHOICE;
-                                               break;
-                                               case 'short-answer':
-                                                       $data .= '.'.HOTPOT_JQUIZ_SHORTANSWER;
-                                               break;
-                                               case 'hybrid':
-                                                       $data .= '.'.HOTPOT_JQUIZ_HYBRID;
-                                               break;
-                                               case 'multi-select':
-                                                       $data .= '.'.HOTPOT_JQUIZ_MULTISELECT;
-                                               case 'n/a':
-                                               default:
-                                                       // do nothing more
-                                               break;
-                                       }
-                               break;
-                               case 'question':
-                                       $name = 'name';
-                               break;
-                       }
-                       break;
-
-               case 'rhubarb':
-                       $question->type = HOTPOT_TEXTOYS_RHUBARB;
-                       if (empty($question->name)) {
-                               $question->name = $num;
-                       }
-                       break;
-
-               case 'sequitur':
-                       $question->type = HOTPOT_TEXTOYS_SEQUITUR;
-                       break;
-       }
+    switch ($quiztype) {
+        case 'jbc':
+            $question->type = HOTPOT_JCB;
+            switch ($name) {
+                case 'right':
+                    $name = 'correct';
+                break;
+            }
+            break;
+        case 'jcloze':
+            $question->type = HOTPOT_JCLOZE;
+            if (is_numeric($num)) {
+                $question->name = $num;
+            }
+            switch ($name) {
+                case 'penalties':
+                    if (is_numeric($num)) {
+                        $name = 'checks';
+                        if (is_numeric($data)) {
+                            $data++;
+                        }
+                    }
+                    break;
+                case 'clue_shown':
+                    $name = 'clues';
+                    $data = ($data=='YES' ? 1 : 0);
+                    break;
+                case 'clue_text':
+                    $name = 'text';
+                    break;
+            }
+            break;
+        case 'jcross':
+            $question->type = HOTPOT_JCROSS;
+            $question->name = $num;
+            switch ($name) {
+                case '': // HotPot v2.0.x
+                    $name = 'correct';
+                    break;
+                case 'clue':
+                    $name = 'text';
+                    break;
+            }
+            break;
+        case 'jmatch':
+            $question->type = HOTPOT_JMATCH;
+            switch ($name) {
+                case 'attempts':
+                    $name = 'penalties';
+                    if (is_numeric($data) && $data>0) {
+                        $data--;
+                    }
+                break;
+                case 'lhs':
+                    $name = 'name';
+                break;
+                case 'rhs':
+                    $name = 'correct';
+                break;
+            }
+            break;
+        case 'jmix':
+            $question->type = HOTPOT_JMIX;
+            $question->name = $num;
+            switch ($name) {
+                // keep these in for "restore" of courses
+                // which were backed up with HotPot v2.0.x
+                case 'wrongguesses':
+                    $name = 'checks';
+                    if (is_numeric($data)) {
+                        $data++;
+                    }
+                break;
+                case 'right':
+                    $name = 'correct';
+                break;
+            }
+            break;
+            break;
+        case 'jquiz':
+            switch ($name) {
+                case 'type':
+                    $data = HOTPOT_JQUIZ;
+                    switch ($data) {
+                        case 'multiple-choice':
+                            $data .= '.'.HOTPOT_JQUIZ_MULTICHOICE;
+                        break;
+                        case 'short-answer':
+                            $data .= '.'.HOTPOT_JQUIZ_SHORTANSWER;
+                        break;
+                        case 'hybrid':
+                            $data .= '.'.HOTPOT_JQUIZ_HYBRID;
+                        break;
+                        case 'multi-select':
+                            $data .= '.'.HOTPOT_JQUIZ_MULTISELECT;
+                        case 'n/a':
+                        default:
+                            // do nothing more
+                        break;
+                    }
+                break;
+                case 'question':
+                    $name = 'name';
+                break;
+            }
+            break;
+
+        case 'rhubarb':
+            $question->type = HOTPOT_TEXTOYS_RHUBARB;
+            if (empty($question->name)) {
+                $question->name = $num;
+            }
+            break;
+
+        case 'sequitur':
+            $question->type = HOTPOT_TEXTOYS_SEQUITUR;
+            break;
+    }
 }
 function hotpot_string_ids($field_value) {
-       $ids = array();
-       $strings = explode(',', $field_value);
-       foreach($strings as $str) {
-               if ($id = hotpot_string_id($str)) {
-                       $ids[] = $id;
-               }
-       }
-       return implode(',', $ids);
+    $ids = array();
+    $strings = explode(',', $field_value);
+    foreach($strings as $str) {
+        if ($id = hotpot_string_id($str)) {
+            $ids[] = $id;
+        }
+    }
+    return implode(',', $ids);
 }
 function hotpot_string_id($str) {
-       $id = '';
-       if (isset($str) && $str<>'') {
-
-               // get the id from the table if it is already there
-               if (!$id = get_field('hotpot_strings', 'id', 'string', $str)) {
-
-                       // create a string record
-                       $record = NULL;
-                       $record->string = $str;
-
-                       // try and add the new string record
-                       if (!$id = insert_record('hotpot_strings', $record)) {
-                               global $db;
-                               error("Could not add string record for '".htmlspecialchars($str)."': ".$db->ErrorMsg());
-                       }
-               }
-       }
-       return $id;
+    $id = '';
+    if (isset($str) && $str<>'') {
+
+        // get the id from the table if it is already there
+        if (!$id = get_field('hotpot_strings', 'id', 'string', $str)) {
+
+            // create a string record
+            $record = NULL;
+            $record->string = $str;
+
+            // try and add the new string record
+            if (!$id = insert_record('hotpot_strings', $record)) {
+                global $db;
+                error("Could not add string record for '".htmlspecialchars($str)."': ".$db->ErrorMsg());
+            }
+        }
+    }
+    return $id;
 }
 
 if (!function_exists('file_get_contents')) {
-       // add this function for php version<4.3
-       function file_get_contents($filepath) {
-               $contents = file($filepath);
-               if (is_array($contents)) {
-                        $contents = implode('', $contents);
-               }
-               return $contents;
-       }
+    // add this function for php version<4.3
+    function file_get_contents($filepath) {
+        $contents = file($filepath);
+        if (is_array($contents)) {
+             $contents = implode('', $contents);
+        }
+        return $contents;
+    }
 }
 if (!function_exists('html_entity_decode')) {
-       // add this function for php version<4.3
-       function html_entity_decode($str) {
-               $t = get_html_translation_table(HTML_ENTITIES);
-               $t = array_flip($t);
-               return strtr($str, $t);
-       }
+    // add this function for php version<4.3
+    function html_entity_decode($str) {
+        $t = get_html_translation_table(HTML_ENTITIES);
+        $t = array_flip($t);
+        return strtr($str, $t);
+    }
 
 }
 
 // required for Moodle 1.x
 if (!isset($CFG->pixpath)) {
-       $CFG->pixpath = "$CFG->wwwroot/pix";
+    $CFG->pixpath = "$CFG->wwwroot/pix";
 }
 
 if (!function_exists('fullname')) {
-       // add this function for Moodle 1.x
-       function fullname($user) {
-               return "$user->firstname $user->lastname";
-       }
+    // add this function for Moodle 1.x
+    function fullname($user) {
+        return "$user->firstname $user->lastname";
+    }
 }
 if (!function_exists('get_user_preferences')) {
-       // add this function for Moodle 1.x
-       function get_user_preferences($name=NULL, $default=NULL, $userid=NULL) {
-               return $default;
-       }
+    // add this function for Moodle 1.x
+    function get_user_preferences($name=NULL, $default=NULL, $userid=NULL) {
+        return $default;
+    }
 }
 if (!function_exists('set_user_preference')) {
-       // add this function for Moodle 1.x
-       function set_user_preference($name, $value, $otheruser=NULL) {
-               return false;
-       }
+    // add this function for Moodle 1.x
+    function set_user_preference($name, $value, $otheruser=NULL) {
+        return false;
+    }
 }
 function hotpot_utf8_to_html_entity($char) {
-       // http://www.zend.com/codex.php?id=835&single=1
-
-       // array used to figure what number to decrement from character order value
-       // according to number of characters used to map unicode to ascii by utf-8
-       static $HOTPOT_UTF8_DECREMENT = array(
-               1=>0, 2=>192, 3=>224, 4=>240
-       );
-
-       // the number of bits to shift each character by
-       static $HOTPOT_UTF8_SHIFT = array(
-               1=>array(0=>0),
-               2=>array(0=>6,  1=>0),
-               3=>array(0=>12, 1=>6,  2=>0),
-               4=>array(0=>18, 1=>12, 2=>6, 3=>0)
-       );
-
-       $dec = 0;
-       $len = strlen($char);
-       for ($pos=0; $pos<$len; $pos++) {
-               $ord = ord ($char{$pos});
-               $ord -= ($pos ? 128 : $HOTPOT_UTF8_DECREMENT[$len]);
-               $dec += ($ord << $HOTPOT_UTF8_SHIFT[$len][$pos]);
-       }
-       return '&#x'.sprintf('%04X', $dec).';';
+    // http://www.zend.com/codex.php?id=835&single=1
+
+    // array used to figure what number to decrement from character order value
+    // according to number of characters used to map unicode to ascii by utf-8
+    static $HOTPOT_UTF8_DECREMENT = array(
+        1=>0, 2=>192, 3=>224, 4=>240
+    );
+
+    // the number of bits to shift each character by
+    static $HOTPOT_UTF8_SHIFT = array(
+        1=>array(0=>0),
+        2=>array(0=>6,  1=>0),
+        3=>array(0=>12, 1=>6,  2=>0),
+        4=>array(0=>18, 1=>12, 2=>6, 3=>0)
+    );
+
+    $dec = 0;
+    $len = strlen($char);
+    for ($pos=0; $pos<$len; $pos++) {
+        $ord = ord ($char{$pos});
+        $ord -= ($pos ? 128 : $HOTPOT_UTF8_DECREMENT[$len]);
+        $dec += ($ord << $HOTPOT_UTF8_SHIFT[$len][$pos]);
+    }
+    return '&#x'.sprintf('%04X', $dec).';';
 }
 
 function hotpot_print_show_links($course, $location, $reference, $actions='', $spacer=' &nbsp; ', $new_window=false) {
-       global $CFG;
-       if (is_string($actions)) {
-               if (empty($actions)) {
-                       $actions = 'showxmlsource,showxmltree,showhtmlsource';
-               }
-               $actions = explode(',', $actions);
-       }
-       $strenterafilename = get_string('enterafilename', 'hotpot');
-       $html = <<<END_OF_SCRIPT
+    global $CFG;
+    if (is_string($actions)) {
+        if (empty($actions)) {
+            $actions = 'showxmlsource,showxmltree,showhtmlsource';
+        }
+        $actions = explode(',', $actions);
+    }
+    $strenterafilename = get_string('enterafilename', 'hotpot');
+    $html = <<<END_OF_SCRIPT
 <script type="text/javascript" language="javascript">
 <!--
-       function setLink(lnk) {
-               var form = document.forms['form'];
-               return setLinkAttribute(lnk, 'reference', form) && setLinkAttribute(lnk, 'location', form);
-       }
-       function setLinkAttribute(lnk, name, form) {
-               // set link attribute value using
-               // f(orm) name and e(lement) name
-
-               var r = true; // result
-
-               var obj = (form) ? form.elements[name] : null;
-               if (obj) {
-                       r = false;
-                       var v = getObjValue(obj);
-                       if (v=='') {
-                               alert('$strenterafilename');
-                       } else {
-                               var s = lnk.href;
-                               var i = s.indexOf('?');
-                               if (i>=0) {
-                                       i = s.indexOf(name+'=', i+1);
-                                       if (i>=0) {
-                                               i += name.length+1;
-                                               var ii = s.indexOf('&', i);
-                                               if (ii<0) {
-                                                       ii = s.length;
-                                               }
-                                               lnk.href = s.substring(0, i) + v + s.substring(ii);
-                                               r = true;
-                                       }
-                               }
-                       }
-               }
-               return r;
-       }
-       function getObjValue(obj) {
-               var v = ''; // the value
-               var t = (obj && obj.type) ? obj.type : "";
-               if (t=="text" || t=="textarea" || t=="hidden") {
-                       v = obj.value;
-               } else if (t=="select-one" || t=="select-multiple") {
-                       var l = obj.options.length;
-                       for (var i=0; i<l; i++) {
-                               if (obj.options[i].selected) {
-                                       v += (v=="" ? "" : ",") + obj.options[i].value;
-                               }
-                       }
-               }
-               return v;
-       }
-       function getDir(s) {
-               if (s.charAt(0)!='/') {
-                       s = '/' + s;
-               }
-               var i = s.lastIndexOf('/');
-               return s.substring(0, i);
-       }
+    function setLink(lnk) {
+        var form = document.forms['form'];
+        return setLinkAttribute(lnk, 'reference', form) && setLinkAttribute(lnk, 'location', form);
+    }
+    function setLinkAttribute(lnk, name, form) {
+        // set link attribute value using
+        // f(orm) name and e(lement) name
+
+        var r = true; // result
+
+        var obj = (form) ? form.elements[name] : null;
+        if (obj) {
+            r = false;
+            var v = getObjValue(obj);
+            if (v=='') {
+                alert('$strenterafilename');
+            } else {
+                var s = lnk.href;
+                var i = s.indexOf('?');
+                if (i>=0) {
+                    i = s.indexOf(name+'=', i+1);
+                    if (i>=0) {
+                        i += name.length+1;
+                        var ii = s.indexOf('&', i);
+                        if (ii<0) {
+                            ii = s.length;
+                        }
+                        lnk.href = s.substring(0, i) + v + s.substring(ii);
+                        r = true;
+                    }
+                }
+            }
+        }
+        return r;
+    }
+    function getObjValue(obj) {
+        var v = ''; // the value
+        var t = (obj && obj.type) ? obj.type : "";
+        if (t=="text" || t=="textarea" || t=="hidden") {
+            v = obj.value;
+        } else if (t=="select-one" || t=="select-multiple") {
+            var l = obj.options.length;
+            for (var i=0; i<l; i++) {
+                if (obj.options[i].selected) {
+                    v += (v=="" ? "" : ",") + obj.options[i].value;
+                }
+            }
+        }
+        return v;
+    }
+    function getDir(s) {
+        if (s.charAt(0)!='/') {
+            s = '/' + s;
+        }
+        var i = s.lastIndexOf('/');
+        return s.substring(0, i);
+    }
 //-->
 </script>
 END_OF_SCRIPT;
 
-       foreach ($actions as $action) {
-               $html .= $spacer
-               .       '<a href="'
-               .                       $CFG->wwwroot.'/mod/hotpot/show.php'
-               .                       '?course='.$course.'&location='.$location.'&reference='.urlencode($reference).'&action='.$action
-               .               '"'
-               .               ' onclick="return setLink(this);"'
-               .               ($new_window ? ' target="_blank"' : '')
-               .       '>'.get_string($action, 'hotpot').'</a>'
-               ;
-       }
-       print '<span class="helplink">'.$html.'</span>';
+    foreach ($actions as $action) {
+        $html .= $spacer
+        .   '<a href="'
+        .           $CFG->wwwroot.'/mod/hotpot/show.php'
+        .           '?course='.$course.'&location='.$location.'&reference='.urlencode($reference).'&action='.$action
+        .       '"'
+        .       ' onclick="return setLink(this);"'
+        .       ($new_window ? ' target="_blank"' : '')
+        .   '>'.get_string($action, 'hotpot').'</a>'
+        ;
+    }
+    print '<span class="helplink">'.$html.'</span>';
 }
 
 ?>
index 7941e2345990dda081ee6d69a8db2f59d4ad4ce8..a296bdf0d19b66ee1cec451c8e94f2b3fe1d9005 100644 (file)
@@ -11,309 +11,309 @@ set_form_fields($form);
 
 // commonly used array of <select> options
 $yes_no_options = array(
-       HOTPOT_NO => get_string("no"), 
-       HOTPOT_YES => get_string("yes")
+    HOTPOT_NO => get_string("no"), 
+    HOTPOT_YES => get_string("yes")
 );
 $text_source_options = array(
-       HOTPOT_TEXTSOURCE_QUIZ => get_string("textsourcequiz", "hotpot"), 
-       HOTPOT_TEXTSOURCE_FILENAME => get_string("textsourcefilename", "hotpot"),
-       HOTPOT_TEXTSOURCE_FILEPATH => get_string("textsourcefilepath", "hotpot"),
-       HOTPOT_TEXTSOURCE_SPECIFIC => get_string("textsourcespecific", "hotpot")
+    HOTPOT_TEXTSOURCE_QUIZ => get_string("textsourcequiz", "hotpot"), 
+    HOTPOT_TEXTSOURCE_FILENAME => get_string("textsourcefilename", "hotpot"),
+    HOTPOT_TEXTSOURCE_FILEPATH => get_string("textsourcefilepath", "hotpot"),
+    HOTPOT_TEXTSOURCE_SPECIFIC => get_string("textsourcespecific", "hotpot")
 );
 ?>
 <center>
 <form name="form" method="post" action="mod.php">
 <table cellpadding="5">
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("name") ?>:</b></td>
-               <td align="left"><?PHP
-                       if ($form->mode=='add') {
-                               choose_from_menu($text_source_options, "namesource", "$form->namesource", "");
-                       } else {
-                               print '<input type="hidden" name="namesource" value="'.HOTPOT_TEXTSOURCE_SPECIFIC.'">';
-                       }
-                       print '<span id="nameSPAN">';
-                       print '<input type="text" name="name" size=40 value="'.$form->name.'">';
-                       print '</span>';
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right">
-                       <b><?PHP 
-                               print_string("summary") 
-                       ?>:</b><br />
-                       <FONT size="1"><?PHP
-                               helpbutton("summary", get_string("summary"), "resource", true, true);
-                               print '<br />';
-                               helpbutton("writing", get_string("helpwriting"), "moodle", true, true);
-                               print '<br />';
-                               if (isset($usehtmleditor) && $usehtmleditor) {
-                                       helpbutton("richtext", get_string("helprichtext"), "moodle", true, true);
-                                       print '<br />';
-                               } else {
-                                       helpbutton("text", get_string("helptext"), "moodle", true, true); 
-                                       print '<br />';
-                                       emoticonhelpbutton("form", "description");
-                                       print '<br />';
-                               }
-                       ?></FONT>
-               </td>
-               <td align="left"><?PHP 
-                       if ($form->mode=='add') {
-                               choose_from_menu($text_source_options, "summarysource", "$form->summarysource", "");
-                       } else {
-                               print '<input type="hidden" name="summarysource" value="'.HOTPOT_TEXTSOURCE_SPECIFIC.'">';
-                       }
-                       print '<span id="summarySPAN">';
-                       if (function_exists("print_textarea") && isset($usehtmleditor)) {
-                               print_textarea($usehtmleditor, 10, 65, 680, 400, "summary", $form->summary);
-                       } else {
-                               // Moodle 1.1.1 (original size was rows="5" cols="50")
-                               print '<textarea name="summary" rows="10" cols="65" wrap="virtual">'.$form->summary.'</textarea>';
-                       }
-                       print '</span>';
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("quizopen", "quiz") ?>:</b></td>
-               <td align="left"><?PHP
-                       $options = array(
-                               HOTPOT_NO => get_string("alwaysopen", "hotpot"), 
-                               HOTPOT_YES => get_string("specifictime", "hotpot")
-                       );
-                       choose_from_menu($options, "enabletimeopen", "$form->enabletimeopen", "");
-                       print '<span id="timeopenSPAN">';
-                       print ' &nbsp; ';
-                       if (!$form->timeopen && $course->format == "weeks") {
-                               $form->timeopen= $course->startdate + (($form->section - 1) * 608400);
-                       }
-                       print_date_selector("openday", "openmonth", "openyear", $form->timeopen);
-                       print ' - ';
-                       print_time_selector("openhour", "openminute", $form->timeopen);
-                       helpbutton("timeopen", get_string("quizopen","quiz"), "quiz");
-                       print '</span>';
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("quizclose", "quiz") ?>:</b></td>
-               <td align="left"><?PHP
-                       $options = array(
-                               HOTPOT_NO => get_string("neverclosed", "hotpot"), 
-                               HOTPOT_YES => get_string("specifictime", "hotpot")
-                       );
-                       choose_from_menu($options, "enabletimeclose", "$form->enabletimeclose", "");
-                       print '<span id="timecloseSPAN">';
-                       print ' &nbsp; ';
-                       if (!$form->timeclose && $course->format == "weeks") {
-                               $form->timeclose= $course->startdate + (($form->section) * 608400);
-                       }
-                       print_date_selector("closeday", "closemonth", "closeyear", $form->timeclose);
-                       print ' - ';
-                       print_time_selector("closehour", "closeminute", $form->timeclose);
-                       helpbutton("timeopen", get_string("quizclose","quiz"), "quiz");
-                       print '</span>';
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right" nowrap>
-                       <b><?PHP print get_string("location","hotpot") ?>:</b>
-               </td>
-               <td align="left"><?PHP
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("name") ?>:</b></td>
+        <td align="left"><?PHP
+            if ($form->mode=='add') {
+                choose_from_menu($text_source_options, "namesource", "$form->namesource", "");
+            } else {
+                print '<input type="hidden" name="namesource" value="'.HOTPOT_TEXTSOURCE_SPECIFIC.'">';
+            }
+            print '<span id="nameSPAN">';
+            print '<input type="text" name="name" size=40 value="'.$form->name.'">';
+            print '</span>';
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right">
+            <b><?PHP 
+                print_string("summary") 
+            ?>:</b><br />
+            <FONT size="1"><?PHP
+                helpbutton("summary", get_string("summary"), "resource", true, true);
+                print '<br />';
+                helpbutton("writing", get_string("helpwriting"), "moodle", true, true);
+                print '<br />';
+                if (isset($usehtmleditor) && $usehtmleditor) {
+                    helpbutton("richtext", get_string("helprichtext"), "moodle", true, true);
+                    print '<br />';
+                } else {
+                    helpbutton("text", get_string("helptext"), "moodle", true, true); 
+                    print '<br />';
+                    emoticonhelpbutton("form", "description");
+                    print '<br />';
+                }
+            ?></FONT>
+        </td>
+        <td align="left"><?PHP 
+            if ($form->mode=='add') {
+                choose_from_menu($text_source_options, "summarysource", "$form->summarysource", "");
+            } else {
+                print '<input type="hidden" name="summarysource" value="'.HOTPOT_TEXTSOURCE_SPECIFIC.'">';
+            }
+            print '<span id="summarySPAN">';
+            if (function_exists("print_textarea") && isset($usehtmleditor)) {
+                print_textarea($usehtmleditor, 10, 65, 680, 400, "summary", $form->summary);
+            } else {
+                // Moodle 1.1.1 (original size was rows="5" cols="50")
+                print '<textarea name="summary" rows="10" cols="65" wrap="virtual">'.$form->summary.'</textarea>';
+            }
+            print '</span>';
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("quizopen", "quiz") ?>:</b></td>
+        <td align="left"><?PHP
+            $options = array(
+                HOTPOT_NO => get_string("alwaysopen", "hotpot"), 
+                HOTPOT_YES => get_string("specifictime", "hotpot")
+            );
+            choose_from_menu($options, "enabletimeopen", "$form->enabletimeopen", "");
+            print '<span id="timeopenSPAN">';
+            print ' &nbsp; ';
+            if (!$form->timeopen && $course->format == "weeks") {
+                $form->timeopen= $course->startdate + (($form->section - 1) * 608400);
+            }
+            print_date_selector("openday", "openmonth", "openyear", $form->timeopen);
+            print ' - ';
+            print_time_selector("openhour", "openminute", $form->timeopen);
+            helpbutton("timeopen", get_string("quizopen","quiz"), "quiz");
+            print '</span>';
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("quizclose", "quiz") ?>:</b></td>
+        <td align="left"><?PHP
+            $options = array(
+                HOTPOT_NO => get_string("neverclosed", "hotpot"), 
+                HOTPOT_YES => get_string("specifictime", "hotpot")
+            );
+            choose_from_menu($options, "enabletimeclose", "$form->enabletimeclose", "");
+            print '<span id="timecloseSPAN">';
+            print ' &nbsp; ';
+            if (!$form->timeclose && $course->format == "weeks") {
+                $form->timeclose= $course->startdate + (($form->section) * 608400);
+            }
+            print_date_selector("closeday", "closemonth", "closeyear", $form->timeclose);
+            print ' - ';
+            print_time_selector("closehour", "closeminute", $form->timeclose);
+            helpbutton("timeopen", get_string("quizclose","quiz"), "quiz");
+            print '</span>';
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right" nowrap>
+            <b><?PHP print get_string("location","hotpot") ?>:</b>
+        </td>
+        <td align="left"><?PHP
 
 
-                       if (isadmin()) {
-                               $site = get_site();
-                               if ($course->id==$site->id) {
-                                       $id = $site->id;
-                                       $location = HOTPOT_LOCATION_SITEFILES;
-                               } else {
-                                       $id = "'+(getObjValue(this.form.location)==".HOTPOT_LOCATION_SITEFILES."?".$site->id.":".$course->id.")+'";
-                                       $location = '';
-                               }
-                       } else { // ordinary teacher or content creator
-                                       $id = $course->id;
-                                       $location = HOTPOT_LOCATION_COURSEFILES;
-                       }
+            if (isadmin()) {
+                $site = get_site();
+                if ($course->id==$site->id) {
+                    $id = $site->id;
+                    $location = HOTPOT_LOCATION_SITEFILES;
+                } else {
+                    $id = "'+(getObjValue(this.form.location)==".HOTPOT_LOCATION_SITEFILES."?".$site->id.":".$course->id.")+'";
+                    $location = '';
+                }
+            } else { // ordinary teacher or content creator
+                    $id = $course->id;
+                    $location = HOTPOT_LOCATION_COURSEFILES;
+            }
 
-                       if (array_key_exists($location, $HOTPOT_LOCATION)) {
-                               print '<input type="hidden" name="location" value="'.$location.'" />';
-                               print '<i><font size="-1">'.$HOTPOT_LOCATION[$location].'</font></i> &nbsp; ';
+            if (array_key_exists($location, $HOTPOT_LOCATION)) {
+                print '<input type="hidden" name="location" value="'.$location.'" />';
+                print '<i><font size="-1">'.$HOTPOT_LOCATION[$location].'</font></i> &nbsp; ';
 
-                       } else { // admin can select from "site" or "course" files
-                               choose_from_menu($HOTPOT_LOCATION, "location", "$form->location", "");
-                       }
+            } else { // admin can select from "site" or "course" files
+                choose_from_menu($HOTPOT_LOCATION, "location", "$form->location", "");
+            }
 
 
-                       if (function_exists("button_to_popup_window")) {
+            if (function_exists("button_to_popup_window")) {
 
-                               // use javascript to extract wdir from the reference field
-                               $wdir = "'+getDir(getObjValue(this.form.reference))+'";
+                // use javascript to extract wdir from the reference field
+                $wdir = "'+getDir(getObjValue(this.form.reference))+'";
 
-                               // set button url depending on Moodle version
-                               if ($CFG->version < 2004083125) { // version may need refining
-                                       // up to and including Moodle 1.4.1
-                                       $url = "/mod/resource/coursefiles.php?id=$id&wdir=$wdir";
-                               } else {
-                                       // Moodle 1.4.2 and beyond
-                                       $url = "/files/index.php?id=$id&wdir=$wdir&choose=form.reference";
-                               }
+                // set button url depending on Moodle version
+                if ($CFG->version < 2004083125) { // version may need refining
+                    // up to and including Moodle 1.4.1
+                    $url = "/mod/resource/coursefiles.php?id=$id&wdir=$wdir";
+                } else {
+                    // Moodle 1.4.2 and beyond
+                    $url = "/files/index.php?id=$id&wdir=$wdir&choose=form.reference";
+                }
 
-                               $strchooseafile = get_string("chooseafile", "resource");
-                               button_to_popup_window ($url, 'coursefiles', $strchooseafile, 500, 750, $strchooseafile);
-                       }
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right" nowrap>
-                       <b><?PHP print_string("filename", "resource") ?>:</b>
-               </td>
-               <td align="left"><?PHP
-                       if (function_exists("button_to_popup_window")) {
-                               print '<input name="reference" size="50" value="'.$form->reference.'">&nbsp;';
+                $strchooseafile = get_string("chooseafile", "resource");
+                button_to_popup_window ($url, 'coursefiles', $strchooseafile, 500, 750, $strchooseafile);
+            }
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right" nowrap>
+            <b><?PHP print_string("filename", "resource") ?>:</b>
+        </td>
+        <td align="left"><?PHP
+            if (function_exists("button_to_popup_window")) {
+                print '<input name="reference" size="50" value="'.$form->reference.'">&nbsp;';
 
-                       } else if (function_exists("get_directory_list")) {
-                               // Moodle 1.1 (and perhaps some others)
-                               $dirs = get_directory_list("$CFG->dataroot/$course->id");
-                               $options = array();
-                               foreach ($dirs as $dir) {
-                                       $options["$dir"] = $dir;
-                               }
-                               choose_from_menu ($options, "reference", $form->reference);
+            } else if (function_exists("get_directory_list")) {
+                // Moodle 1.1 (and perhaps some others)
+                $dirs = get_directory_list("$CFG->dataroot/$course->id");
+                $options = array();
+                foreach ($dirs as $dir) {
+                    $options["$dir"] = $dir;
+                }
+                choose_from_menu ($options, "reference", $form->reference);
 
-                       } else {
-                               // a very old Moodle (may be none left :-)
-                               print '<input name="reference" size="50" value="'.$form->reference.'">&nbsp;';
-                       }
-                       print '<br />';
-                       hotpot_print_show_links($form->course, $form->location, $form->reference, '', ' &nbsp; ', true);
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP 
-                       $quizchain = "{$form->mode}quizchain";
-                       print_string($quizchain, "hotpot"); 
-               ?>:</b></td>
-               <td align="left"><?PHP
-                       choose_from_menu($yes_no_options, "quizchain", $form->quizchain, "");
-                       helpbutton($quizchain, get_string($quizchain,"hotpot"), "hotpot");
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("outputformat", "hotpot") ?>:</b></td>
-               <td align="left"><?PHP
-                       choose_from_menu($HOTPOT_OUTPUTFORMAT, "outputformat", "$form->outputformat", "");
-                       helpbutton("outputformat", get_string("outputformat","hotpot"), "hotpot");
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("navigation", "hotpot") ?>:</b></td>
-               <td align="left"><?PHP
-                       choose_from_menu($HOTPOT_NAVIGATION, "navigation", "$form->navigation", "");
-                       helpbutton("navigation", get_string("navigation","hotpot"), "hotpot");
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("studentfeedback", "hotpot") ?>:</b></td>
-               <td align="left"><?PHP
-                       choose_from_menu($HOTPOT_FEEDBACK, "studentfeedback", "$form->studentfeedback", "");
-                       print "<input name=\"studentfeedbackurl\" size=\"50\" value=\"$form->studentfeedbackurl\">";
-                       helpbutton("studentfeedback", get_string("studentfeedback","hotpot"), "hotpot");
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("forceplugins", "hotpot") ?>:</b></td>
-               <td align="left"><?PHP
-                       choose_from_menu($yes_no_options, "forceplugins", "$form->forceplugins", "");
-                       helpbutton("forceplugins", get_string("forceplugins","hotpot"), "hotpot");
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("shownextquiz", "hotpot") ?>:</b></td>
-               <td align="left"><?PHP
-                       choose_from_menu($yes_no_options, "shownextquiz", "$form->shownextquiz", "");
-                       helpbutton("shownextquiz", get_string("shownextquiz","hotpot"), "hotpot");
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("allowreview", "quiz") ?>:</b></td>
-               <td align="left"><?PHP
-                       choose_from_menu($yes_no_options, "review", "$form->review", "");
-                       helpbutton("review", get_string("allowreview","quiz"), "quiz");
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("maximumgrade") ?>:</b></td>
-               <td align="left"><?PHP
-                       $options = array();
-                       for ($i=100; $i>=1; $i--) {
-                               $options[$i] = $i;
-                       }
-                       $options[0] = get_string("nograde");
+            } else {
+                // a very old Moodle (may be none left :-)
+                print '<input name="reference" size="50" value="'.$form->reference.'">&nbsp;';
+            }
+            print '<br />';
+            hotpot_print_show_links($form->course, $form->location, $form->reference, '', ' &nbsp; ', true);
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP 
+            $quizchain = "{$form->mode}quizchain";
+            print_string($quizchain, "hotpot"); 
+        ?>:</b></td>
+        <td align="left"><?PHP
+            choose_from_menu($yes_no_options, "quizchain", $form->quizchain, "");
+            helpbutton($quizchain, get_string($quizchain,"hotpot"), "hotpot");
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("outputformat", "hotpot") ?>:</b></td>
+        <td align="left"><?PHP
+            choose_from_menu($HOTPOT_OUTPUTFORMAT, "outputformat", "$form->outputformat", "");
+            helpbutton("outputformat", get_string("outputformat","hotpot"), "hotpot");
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("navigation", "hotpot") ?>:</b></td>
+        <td align="left"><?PHP
+            choose_from_menu($HOTPOT_NAVIGATION, "navigation", "$form->navigation", "");
+            helpbutton("navigation", get_string("navigation","hotpot"), "hotpot");
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("studentfeedback", "hotpot") ?>:</b></td>
+        <td align="left"><?PHP
+            choose_from_menu($HOTPOT_FEEDBACK, "studentfeedback", "$form->studentfeedback", "");
+            print "<input name=\"studentfeedbackurl\" size=\"50\" value=\"$form->studentfeedbackurl\">";
+            helpbutton("studentfeedback", get_string("studentfeedback","hotpot"), "hotpot");
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("forceplugins", "hotpot") ?>:</b></td>
+        <td align="left"><?PHP
+            choose_from_menu($yes_no_options, "forceplugins", "$form->forceplugins", "");
+            helpbutton("forceplugins", get_string("forceplugins","hotpot"), "hotpot");
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("shownextquiz", "hotpot") ?>:</b></td>
+        <td align="left"><?PHP
+            choose_from_menu($yes_no_options, "shownextquiz", "$form->shownextquiz", "");
+            helpbutton("shownextquiz", get_string("shownextquiz","hotpot"), "hotpot");
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("allowreview", "quiz") ?>:</b></td>
+        <td align="left"><?PHP
+            choose_from_menu($yes_no_options, "review", "$form->review", "");
+            helpbutton("review", get_string("allowreview","quiz"), "quiz");
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("maximumgrade") ?>:</b></td>
+        <td align="left"><?PHP
+            $options = array();
+            for ($i=100; $i>=1; $i--) {
+                $options[$i] = $i;
+            }
+            $options[0] = get_string("nograde");
 
-                       choose_from_menu($options, "grade", "$form->grade", "");
-                       helpbutton("maxgrade", get_string("maximumgrade"), "quiz");
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("grademethod", "quiz") ?>:</b></td>
-               <td align="left"><?PHP
-                       choose_from_menu($HOTPOT_GRADEMETHOD, "grademethod", "$form->grademethod", "");
-                       helpbutton("grademethod", get_string("grademethod","quiz"), "quiz");
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("attemptsallowed", "quiz") ?>:</b></td>
-               <td align="left"><?PHP
-                       $options = array(
-                               0 => get_string("attemptsunlimited", "quiz"),
-                               1 => '1 '.strtolower(get_string("attempt", "quiz"))
-                       );
-                       for ($i=2; $i<=10; $i++) {
-                               $options[$i] = "$i ".strtolower(get_string("attempts", "quiz"));
-                       }
-                       choose_from_menu($options, "attempts", "$form->attempts", "");
-                       helpbutton("attempts", get_string("attemptsallowed","quiz"), "quiz");
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("requirepassword", "quiz") ?>:</b></td>
-               <td align="left">
-                       <input type="text" name="password" size=40 value="<?PHP p($form->password) ?>">
-                       <?PHP helpbutton("requirepassword", get_string("requirepassword", "quiz"), "quiz"); ?>
-               </td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("requiresubnet", "quiz") ?>:</b></td>
-               <td align="left">
-                       <input type="text" name="subnet" size=40 value="<?PHP p($form->subnet) ?>">
-                       <?PHP helpbutton("requiresubnet", get_string("requiresubnet", "quiz"), "quiz"); ?>
-               </td>
-       </tr>
-       <tr valign="top">
-               <td align="right"><b><?PHP print_string("clickreporting", "hotpot") ?>:</b></td>
-               <td align="left"><?PHP
-                       choose_from_menu($yes_no_options, "clickreporting", "$form->clickreporting", "");
-                       helpbutton("clickreporting", get_string("clickreporting","hotpot"), "hotpot");
-               ?></td>
-       </tr>
-       <tr valign="top">
-               <td align="right">&nbsp;</td>
-               <td align="left">
-                       <!-- buttons -->
-                       <input type="submit" value="<?PHP print_string("savechanges") ?>"> &nbsp; &nbsp;
-                       <input type="submit" name="cancel" value="<?PHP print_string("cancel") ?>" /><br />
-                       <?PHP
-                               if (isset($CFG->release) && substr($CFG->release, 0, 3)>=1.5) {
-                                       $options = array(
-                                               HOTPOT_DISPLAYNEXT_QUIZ => get_string("displayhotpotnext", "hotpot"),
-                                               HOTPOT_DISPLAYNEXT_COURSE => get_string("displaycoursenext", "hotpot"),
-                                               HOTPOT_DISPLAYNEXT_INDEX => get_string("displayindexnext", "hotpot")
-                                       );
-                                       choose_from_menu($options, "displaynext", "$form->displaynext", "");
-                               } else {
-                                       print '<input type="hidden" name="displaynext" value="'.HOTPOT_NO.'">'."\n";
-                               }
-                       ?>
+            choose_from_menu($options, "grade", "$form->grade", "");
+            helpbutton("maxgrade", get_string("maximumgrade"), "quiz");
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("grademethod", "quiz") ?>:</b></td>
+        <td align="left"><?PHP
+            choose_from_menu($HOTPOT_GRADEMETHOD, "grademethod", "$form->grademethod", "");
+            helpbutton("grademethod", get_string("grademethod","quiz"), "quiz");
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("attemptsallowed", "quiz") ?>:</b></td>
+        <td align="left"><?PHP
+            $options = array(
+                0 => get_string("attemptsunlimited", "quiz"),
+                1 => '1 '.strtolower(get_string("attempt", "quiz"))
+            );
+            for ($i=2; $i<=10; $i++) {
+                $options[$i] = "$i ".strtolower(get_string("attempts", "quiz"));
+            }
+            choose_from_menu($options, "attempts", "$form->attempts", "");
+            helpbutton("attempts", get_string("attemptsallowed","quiz"), "quiz");
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("requirepassword", "quiz") ?>:</b></td>
+        <td align="left">
+            <input type="text" name="password" size=40 value="<?PHP p($form->password) ?>">
+            <?PHP helpbutton("requirepassword", get_string("requirepassword", "quiz"), "quiz"); ?>
+        </td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("requiresubnet", "quiz") ?>:</b></td>
+        <td align="left">
+            <input type="text" name="subnet" size=40 value="<?PHP p($form->subnet) ?>">
+            <?PHP helpbutton("requiresubnet", get_string("requiresubnet", "quiz"), "quiz"); ?>
+        </td>
+    </tr>
+    <tr valign="top">
+        <td align="right"><b><?PHP print_string("clickreporting", "hotpot") ?>:</b></td>
+        <td align="left"><?PHP
+            choose_from_menu($yes_no_options, "clickreporting", "$form->clickreporting", "");
+            helpbutton("clickreporting", get_string("clickreporting","hotpot"), "hotpot");
+        ?></td>
+    </tr>
+    <tr valign="top">
+        <td align="right">&nbsp;</td>
+        <td align="left">
+            <!-- buttons -->
+            <input type="submit" value="<?PHP print_string("savechanges") ?>"> &nbsp; &nbsp;
+            <input type="submit" name="cancel" value="<?PHP print_string("cancel") ?>" /><br />
+            <?PHP
+                if (isset($CFG->release) && substr($CFG->release, 0, 3)>=1.5) {
+                    $options = array(
+                        HOTPOT_DISPLAYNEXT_QUIZ => get_string("displayhotpotnext", "hotpot"),
+                        HOTPOT_DISPLAYNEXT_COURSE => get_string("displaycoursenext", "hotpot"),
+                        HOTPOT_DISPLAYNEXT_INDEX => get_string("displayindexnext", "hotpot")
+                    );
+                    choose_from_menu($options, "displaynext", "$form->displaynext", "");
+                } else {
+                    print '<input type="hidden" name="displaynext" value="'.HOTPOT_NO.'">'."\n";
+                }
+            ?>
 </table>
 
 <!-- hidden fields -->
@@ -333,121 +333,121 @@ $text_source_options = array(
 
 <script type="text/javascript" language="javascript">
 <!--
-       function hpShowHideStudentFeedbackUrl() {
-               var frm = document.forms['form'];
-               if (frm) {
-                       var obj = frm.elements['studentfeedback'];
-                       var url = frm.elements['studentfeedbackurl'];
-                       if (obj && obj.type=='select-one' && url && url.style) {
-                               if (obj.onchange==null) {
-                                       obj.onchange = hpShowHideStudentFeedbackUrl;
-                               }
-                               var v = obj.options[obj.selectedIndex].value;
-                               url.style.display = (v==1 || v==2) ? 'inline' : 'none';
-                       }
-               }
-       }
-       hpShowHideStudentFeedbackUrl();
+    function hpShowHideStudentFeedbackUrl() {
+        var frm = document.forms['form'];
+        if (frm) {
+            var obj = frm.elements['studentfeedback'];
+            var url = frm.elements['studentfeedbackurl'];
+            if (obj && obj.type=='select-one' && url && url.style) {
+                if (obj.onchange==null) {
+                    obj.onchange = hpShowHideStudentFeedbackUrl;
+                }
+                var v = obj.options[obj.selectedIndex].value;
+                url.style.display = (v==1 || v==2) ? 'inline' : 'none';
+            }
+        }
+    }
+    hpShowHideStudentFeedbackUrl();
 
-       function hpShowHideTime(s) {
-               var frm = document.forms['form'];
-               if (frm) {
-                       var obj = frm.elements['enabletime'+s];
-                       if (obj && obj.type=='select-one' && document.getElementById) {
-                               if (obj.onchange==null) {
-                                       obj.onchange = new Function("hpShowHideTime('"+s+"')");
-                               }
-                               var v = obj.options[obj.selectedIndex].value;
-                               var obj = document.getElementById('time'+s+'SPAN');
-                               if (obj && obj.style) {
-                                       obj.style.display = (v==0) ? 'none' : 'inline';
-                               }
-                       }
-               }
-       }
-       hpShowHideTime('open');
-       hpShowHideTime('close');
+    function hpShowHideTime(s) {
+        var frm = document.forms['form'];
+        if (frm) {
+            var obj = frm.elements['enabletime'+s];
+            if (obj && obj.type=='select-one' && document.getElementById) {
+                if (obj.onchange==null) {
+                    obj.onchange = new Function("hpShowHideTime('"+s+"')");
+                }
+                var v = obj.options[obj.selectedIndex].value;
+                var obj = document.getElementById('time'+s+'SPAN');
+                if (obj && obj.style) {
+                    obj.style.display = (v==0) ? 'none' : 'inline';
+                }
+            }
+        }
+    }
+    hpShowHideTime('open');
+    hpShowHideTime('close');
 
-       function hpShowHideTextSource(s) {
-               var frm = document.forms['form'];
-               if (frm) {
-                       var obj = frm.elements[s+'source'];
-                       if (obj && obj.type=='select-one' && document.getElementById) {
-                               if (obj.onchange==null) {
-                                       obj.onchange = new Function("hpShowHideTextSource('"+s+"')");
-                               }
-                               var v = obj.options[obj.selectedIndex].value;
-                               var obj = document.getElementById(s+'SPAN');
-                               if (obj && obj.style) {
-                                       obj.style.display = (v==0 || v==1 || v==2) ? 'none' : 'inline';
-                               }
-                       }
-               }
-               return true;
-       }
-       hpShowHideTextSource('name');
-       //hpShowHideTextSource('summary');
+    function hpShowHideTextSource(s) {
+        var frm = document.forms['form'];
+        if (frm) {
+            var obj = frm.elements[s+'source'];
+            if (obj && obj.type=='select-one' && document.getElementById) {
+                if (obj.onchange==null) {
+                    obj.onchange = new Function("hpShowHideTextSource('"+s+"')");
+                }
+                var v = obj.options[obj.selectedIndex].value;
+                var obj = document.getElementById(s+'SPAN');
+                if (obj && obj.style) {
+                    obj.style.display = (v==0 || v==1 || v==2) ? 'none' : 'inline';
+                }
+            }
+        }
+        return true;
+    }
+    hpShowHideTextSource('name');
+    //hpShowHideTextSource('summary');
 
 // override the standard Moodle "setfocus" function, 
 // which gives a js error if the "name" field is hidden
 function setfocus() {
-       var f = document.form;
-       if (f) {
-               if (canfocus(f, 'namesource')) {
-                       f.namesource.focus();
-               } else if (canfocus(f, 'name')) {
-                       f.name.focus();
-               }
-       }
+    var f = document.form;
+    if (f) {
+        if (canfocus(f, 'namesource')) {
+            f.namesource.focus();
+        } else if (canfocus(f, 'name')) {
+            f.name.focus();
+        }
+    }
 }
 function canfocus(f, name) {
-       var obj = eval('f.'+name);
-       return (obj==null || obj.type=='hidden' || obj.focus==null || (obj.style && obj.style.display=='none')) ? false : true;
+    var obj = eval('f.'+name);
+    return (obj==null || obj.type=='hidden' || obj.focus==null || (obj.style && obj.style.display=='none')) ? false : true;
 }
 //-->
 </script>
 <?PHP
 
 // ======================
-//     functions
+//  functions
 // ======================
 
 function set_form_fields(&$form) {
-       set_form_field($form, 'name');
-       set_form_field($form, 'summary');
-       set_form_field($form, 'timeopen', get_user_preferences('hotpot_timeopen', 0));
-       set_form_field($form, 'enabletimeopen', empty($form->timeopen) ? HOTPOT_NO : HOTPOT_YES);
-       set_form_field($form, 'timeclose', get_user_preferences('hotpot_timeclose', 0));
-       set_form_field($form, 'enabletimeclose', empty($form->timeclose) ? HOTPOT_NO : HOTPOT_YES);
-       set_form_field($form, 'location', HOTPOT_LOCATION_COURSEFILES);
-       set_form_field($form, 'reference');
-       set_form_field($form, 'navigation', get_user_preferences('hotpot_navigation', HOTPOT_NAVIGATION_BAR));
-       set_form_field($form, 'outputformat', get_user_preferences('hotpot_outputformat', HOTPOT_OUTPUTFORMAT_BEST));
-       set_form_field($form, 'studentfeedback', get_user_preferences('hotpot_studentfeedback', HOTPOT_FEEDBACK_NONE));
-       set_form_field($form, 'studentfeedbackurl', get_user_preferences('hotpot_studentfeedbackurl', 'http://'));
-       set_form_field($form, 'forceplugins', get_user_preferences('hotpot_forceplugins', HOTPOT_NO));
-       if ($form->mode=='add') {
-               set_form_field($form, 'namesource', get_user_preferences('hotpot_namesource', HOTPOT_TEXTSOURCE_QUIZ));
-               set_form_field($form, 'summarysource', get_user_preferences('hotpot_summarysource', HOTPOT_TEXTSOURCE_QUIZ));
-               $quizchain = get_user_preferences('hotpot_quizchain', HOTPOT_NO);
-       } else {
-               $quizchain = empty($form->quizchain) ? HOTPOT_NO : HOTPOT_YES;
-       }
-       set_form_field($form, 'quizchain', $quizchain);
-       set_form_field($form, 'shownextquiz', get_user_preferences('hotpot_shownextquiz', HOTPOT_NO));
-       set_form_field($form, 'review', get_user_preferences('hotpot_review', HOTPOT_YES));
-       set_form_field($form, 'grade', get_user_preferences('hotpot_grade', 100));
-       set_form_field($form, 'grademethod', get_user_preferences('hotpot_grademethod', HOTPOT_GRADEMETHOD_HIGHEST));
-       set_form_field($form, 'attempts', get_user_preferences('hotpot_attempts', 0)); // 0=unlimited
-       set_form_field($form, 'password');
-       set_form_field($form, 'subnet', get_user_preferences('hotpot_subnet'));
-       set_form_field($form, 'clickreporting', HOTPOT_NO);
-       set_form_field($form, 'displaynext', get_user_preferences('hotpot_displaynext', HOTPOT_DISPLAYNEXT_QUIZ));
+    set_form_field($form, 'name');
+    set_form_field($form, 'summary');
+    set_form_field($form, 'timeopen', get_user_preferences('hotpot_timeopen', 0));
+    set_form_field($form, 'enabletimeopen', empty($form->timeopen) ? HOTPOT_NO : HOTPOT_YES);
+    set_form_field($form, 'timeclose', get_user_preferences('hotpot_timeclose', 0));
+    set_form_field($form, 'enabletimeclose', empty($form->timeclose) ? HOTPOT_NO : HOTPOT_YES);
+    set_form_field($form, 'location', HOTPOT_LOCATION_COURSEFILES);
+    set_form_field($form, 'reference');
+    set_form_field($form, 'navigation', get_user_preferences('hotpot_navigation', HOTPOT_NAVIGATION_BAR));
+    set_form_field($form, 'outputformat', get_user_preferences('hotpot_outputformat', HOTPOT_OUTPUTFORMAT_BEST));
+    set_form_field($form, 'studentfeedback', get_user_preferences('hotpot_studentfeedback', HOTPOT_FEEDBACK_NONE));
+    set_form_field($form, 'studentfeedbackurl', get_user_preferences('hotpot_studentfeedbackurl', 'http://'));
+    set_form_field($form, 'forceplugins', get_user_preferences('hotpot_forceplugins', HOTPOT_NO));
+    if ($form->mode=='add') {
+        set_form_field($form, 'namesource', get_user_preferences('hotpot_namesource', HOTPOT_TEXTSOURCE_QUIZ));
+        set_form_field($form, 'summarysource', get_user_preferences('hotpot_summarysource', HOTPOT_TEXTSOURCE_QUIZ));
+        $quizchain = get_user_preferences('hotpot_quizchain', HOTPOT_NO);
+    } else {
+        $quizchain = empty($form->quizchain) ? HOTPOT_NO : HOTPOT_YES;
+    }
+    set_form_field($form, 'quizchain', $quizchain);
+    set_form_field($form, 'shownextquiz', get_user_preferences('hotpot_shownextquiz', HOTPOT_NO));
+    set_form_field($form, 'review', get_user_preferences('hotpot_review', HOTPOT_YES));
+    set_form_field($form, 'grade', get_user_preferences('hotpot_grade', 100));
+    set_form_field($form, 'grademethod', get_user_preferences('hotpot_grademethod', HOTPOT_GRADEMETHOD_HIGHEST));
+    set_form_field($form, 'attempts', get_user_preferences('hotpot_attempts', 0)); // 0=unlimited
+    set_form_field($form, 'password');
+    set_form_field($form, 'subnet', get_user_preferences('hotpot_subnet'));
+    set_form_field($form, 'clickreporting', HOTPOT_NO);
+    set_form_field($form, 'displaynext', get_user_preferences('hotpot_displaynext', HOTPOT_DISPLAYNEXT_QUIZ));
 }
 function set_form_field(&$form, $fieldname, $defaultvalue='') {
-       if (!isset($form->$fieldname)) {
-               $form->$fieldname = $defaultvalue;
-       }
+    if (!isset($form->$fieldname)) {
+        $form->$fieldname = $defaultvalue;
+    }
 }
 
 ?>
index b80056187987c95169ae6a655ce0f8dfdb67359c..7ad0b12d92a5603e48caa2177e96543faada782c 100644 (file)
         }
     }
 
-       // set homeurl of couse (for error messages)
-       $course_homeurl = "$CFG->wwwroot/course/view.php?id=$course->id";
-
-       require_login($course->id);
-
-       // get report mode
-       if (isteacher($course->id)) {
-               $mode = optional_param("mode", "overview");
-       } else {
-               // students have no choice
-               $mode = 'overview';
-       }
-
-       // assemble array of form data
-       $formdata = array(
-               'mode' => $mode,
-               'reportcourse'     => isadmin() ? optional_param('reportcourse', get_user_preferences('hotpot_reportcourse', 'this')) : 'this',
-               'reportusers'      => isteacher($course->id) ? optional_param('reportusers', get_user_preferences('hotpot_reportusers', 'all')) : 'this',
-               'reportattempts'   => optional_param('reportattempts', get_user_preferences('hotpot_reportattempts', 'all')),
-               'reportformat'     => optional_param('reportformat', 'htm'),
-               'reportshowlegend' => optional_param('reportshowlegend', get_user_preferences('hotpot_reportshowlegend', '0')),
-               'reportencoding'   => optional_param('reportencoding', get_user_preferences('hotpot_reportencoding', '')),
-               'reportwrapdata'   => optional_param('reportwrapdata', get_user_preferences('hotpot_reportwrapdata', '1')),
-       );
-
-       foreach ($formdata as $name=>$value) {
-               set_user_preference("hotpot_$name", $value);
-       }
+    // set homeurl of couse (for error messages)
+    $course_homeurl = "$CFG->wwwroot/course/view.php?id=$course->id";
+
+    require_login($course->id);
+
+    // get report mode
+    if (isteacher($course->id)) {
+        $mode = optional_param("mode", "overview");
+    } else {
+        // students have no choice
+        $mode = 'overview';
+    }
+
+    // assemble array of form data
+    $formdata = array(
+        'mode' => $mode,
+        'reportcourse'     => isadmin() ? optional_param('reportcourse', get_user_preferences('hotpot_reportcourse', 'this')) : 'this',
+        'reportusers'      => isteacher($course->id) ? optional_param('reportusers', get_user_preferences('hotpot_reportusers', 'all')) : 'this',
+        'reportattempts'   => optional_param('reportattempts', get_user_preferences('hotpot_reportattempts', 'all')),
+        'reportformat'     => optional_param('reportformat', 'htm'),
+        'reportshowlegend' => optional_param('reportshowlegend', get_user_preferences('hotpot_reportshowlegend', '0')),
+        'reportencoding'   => optional_param('reportencoding', get_user_preferences('hotpot_reportencoding', '')),
+        'reportwrapdata'   => optional_param('reportwrapdata', get_user_preferences('hotpot_reportwrapdata', '1')),
+    );
+
+    foreach ($formdata as $name=>$value) {
+        set_user_preference("hotpot_$name", $value);
+    }
 
 /// Start the report
 
-       add_to_log($course->id, "hotpot", "report", "report.php?id=$cm->id&mode=$mode", "$hotpot->id", "$cm->id");
-
-       // print page header. if required
-       if ($formdata['reportformat']=='htm') {
-               hotpot_print_report_heading($course, $cm, $hotpot, $mode);
-               if (isteacher($course->id)) {
-                       hotpot_print_report_selector($course, $hotpot, $formdata);
-               }
-       }
-
-       // delete selected attempts, if any
-       if (isteacher($course->id)) {
-               $del = optional_param("del", "");
-               hotpot_delete_selected_attempts($hotpot, $del);
-       }
-
-       $hotpot_ids = '';
-       $course_ids = '';
-       switch ($formdata['reportcourse']) {
-               case 'this':
-                       $course_ids = $course->id;
-                       $hotpot_ids = $hotpot->id;
-                       break;
-               case 'all' :
-                       $records = get_records_select_menu('user_teachers', "userid='$USER->id'", 'course', 'id, course');
-                       $course_ids = join(',', array_values($records));
-
-                       $records = get_records_select_menu('hotpot', "reference='$hotpot->reference'", 'reference', 'id, reference');
-                       $hotpot_ids = join(',', array_keys($records));
-                       break;
-       }
-
-       $user_ids = '';
-       $users = array();
-       switch ($formdata['reportusers']) {
-               case 'all':
-                       $admin_ids = get_records_select_menu('user_admins');
-                       if (is_array($admin_ids)) {
-                               $users = array_merge($users, $admin_ids);
-                       }
-                       $creator_ids = get_records_select_menu('user_coursecreators');
-                       if (is_array($creator_ids)) {
-                               $users = array_merge($users, $creator_ids);
-                       }
-                       $teacher_ids = get_records_select_menu('user_teachers', "course IN ($course_ids)", 'course', 'id, userid');
-                       if (is_array($teacher_ids)) {
-                               $users = array_merge($users, $teacher_ids);
-                       }
-                       $guest_id = get_records_select_menu('user', "username='guest'", '', 'id,id');
-                       if (is_array($guest_id)) {
-                               $users = array_merge($users, $guest_id);
-                       }
-                       // add students next
-
-               case 'students':
-                       $student_ids = get_records_select_menu('user_students', "course IN ($course_ids)", 'course', 'id, userid');
-                       if (is_array($student_ids)) {
-                               $users = array_merge($users, $student_ids);
-                       }
-                       $user_ids = array_values($users);
-                       sort($user_ids);
-                       $user_ids = join(',', array_unique($user_ids));
-                       break;
-
-               case 'this': // current user only
-                       $user_ids = $USER->id;
-                       break;
-
-               default: // specific user selected by teacher
-                       if (is_numeric($formdata['reportusers'])) {
-                               $user_ids = $formdata['reportusers'];
-                       }
-       }
-
-       if (empty($user_ids)) {
-               print_heading(get_string('nousersyet'));
-               exit;
-       }
-
-       // database table and selection conditions
-       $table = "{$CFG->prefix}hotpot_attempts AS a";
-       $select = "a.hotpot IN ($hotpot_ids) AND a.userid IN ($user_ids)";
-       if ($mode!='overview') {
-               $select .= ' AND a.status<>'.HOTPOT_STATUS_INPROGRESS;
-       }
-
-       // confine attempts if necessary
-       switch ($formdata['reportattempts']) {
-               case 'best':
-                       $function = 'MAX';
-                       $fieldnames = array('score', 'id', 'clickreportid');
-                       $defaultvalue = 0;
-                       break;
-               case 'first':
-                       $function = 'MIN';
-                       $fieldnames = array('timefinish', 'id', 'clickreportid');
-                       $default_value = time();
-                       break;
-               case 'last':
-                       $function = 'MAX';
-                       $fieldnames = array('timefinish', 'id', 'clickreportid');
-                       $defaultvalue = time();
-                       break;
-               default: // 'all' and any others
-                       $function = '';
-                       $fieldnames = array();
-                       $defaultvalue = '';
-                       break;
-       }
-       if (empty($function) || empty($fieldnames)) {
-               // do nothing (i.e. get ALL attempts)
-       } else {
-               $groupby = 'userid';
-               $records = hotpot_get_records_groupby($function, $fieldnames, $table, $select, $groupby);
-
-               $ids = array();
-               foreach ($records as $record) {
-                       $ids[] = $record->clickreportid;
-               }
-               $select = "a.clickreportid IN (".join(',', $ids).")";
-       }
-
-       // pick out last attempt in each clickreport series
-       $cr_attempts = hotpot_get_records_groupby('MAX', array('timefinish', 'id'), $table, $select, 'clickreportid');
-
-       $fields = 'a.*, u.firstname, u.lastname, u.picture';
-       if ($mode=='click') {
-               $fields .= ', u.idnumber';
-       } else { 
-               // overview, simple and detailed reports 
-               // get last attempt record in clickreport series
-               $ids = array();
-               foreach ($cr_attempts as $cr_attempt) {
-                       $ids[] = $cr_attempt->id;
-               }
-               if (empty($ids)) {
-                       $select = "";
-               } else {
-                       $ids = array_unique($ids);
-                       sort($ids);
-                       $select = "a.id IN (".join(',', $ids).")";
-               }
-       }
-
-       $attempts = array();
-
-       if ($select) {
-               // add user information to SQL query
-               $select .= ' AND a.userid = u.id';
-               $table .= ", {$CFG->prefix}user AS u";
-               $order = "u.lastname, a.attempt, a.timefinish";
-               // get the attempts (at last!)
-               $attempts = get_records_sql("SELECT $fields FROM $table WHERE $select ORDER BY $order");
-       }
-
-       // stop now if no attempts were found
-       if (empty($attempts)) {
-               print_heading(get_string('noattempts','quiz'));
-               exit;
-       }
-
-       // get the questions
-       if (!$questions = get_records_select('hotpot_questions', "hotpot='$hotpot->id'")) {
-               $questions = array();
-       }
-
-       // get grades
-       $grades = hotpot_get_grades($hotpot, $user_ids);
-
-       // get list of attempts by user and set reference to last attempt in clickreport series
-       $users = array();
-       foreach ($attempts as $id=>$attempt) {
-
-               $userid = $attempt->userid;
-
-               if (!isset($users[$userid])) {
-                       $users[$userid]->grade = isset($grades[$userid]) ? $grades[$userid] : '&nbsp;';
-                       $users[$userid]->attempts = array();
-               }
-
-               $users[$userid]->attempts[] = &$attempts[$id];
-
-               if ($mode=='click' && isset($cr_attempts[$id])) {
-                       $attempts[$id]->cr_lastclick = $cr_attempts[$id]->id;
-                       $attempts[$id]->cr_timefinish = $cr_attempts[$id]->timefinish;
-               }
-       }
-
-       if ($mode!='overview') {
-
-               // initialise details of responses to questions in these attempts
-               foreach ($attempts as $a=>$attempt) {
-                       $attempts[$a]->responses = array();
-               }
-               foreach ($questions as $q=>$question) {
-                       $questions[$q]->attempts = array();
-               }
-
-               // get reponses to these attempts
-               $attempt_ids = join(',',array_keys($attempts));
-               if (!$responses = get_records_sql("SELECT * FROM {$CFG->prefix}hotpot_responses WHERE attempt IN ($attempt_ids)")) {
-                       $responses = array();
-               }
-
-               // ids of questions used in these responses
-               $questionids = array();
-
-               foreach ($responses as $response) {
-                       // shortcuts to the attempt and question ids
-                       $a = $response->attempt;
-                       $q = $response->question;
-
-                       // check the attempt and question objects exist
-                       // (if they don't exist, something is very wrong!)
-                       if (isset($attempts[$a]) || isset($questions[$q])) {
-
-                               // add the response for this attempt
-                               $attempts[$a]->responses[$q] = $response;
-
-                               // add a reference from the question to the attempt which includes this question
-                               $questions[$q]->attempts[] = &$attempts[$a];
-
-                               // flag this id as being used
-                               $questionids[$q] = true;
-                       }
-               }
-
-               // remove unused questions
-               $questionids = array_keys($questionids);
-               foreach ($questions as $id=>$question) {
-                       if (!in_array($id, $questionids)) {
-                               unset($questions[$id]);
-                       }
-               }
-       }
+    add_to_log($course->id, "hotpot", "report", "report.php?id=$cm->id&mode=$mode", "$hotpot->id", "$cm->id");
+
+    // print page header. if required
+    if ($formdata['reportformat']=='htm') {
+        hotpot_print_report_heading($course, $cm, $hotpot, $mode);
+        if (isteacher($course->id)) {
+            hotpot_print_report_selector($course, $hotpot, $formdata);
+        }
+    }
+
+    // delete selected attempts, if any
+    if (isteacher($course->id)) {
+        $del = optional_param("del", "");
+        hotpot_delete_selected_attempts($hotpot, $del);
+    }
+
+    $hotpot_ids = '';
+    $course_ids = '';
+    switch ($formdata['reportcourse']) {
+        case 'this':
+            $course_ids = $course->id;
+            $hotpot_ids = $hotpot->id;
+            break;
+        case 'all' :
+            $records = get_records_select_menu('user_teachers', "userid='$USER->id'", 'course', 'id, course');
+            $course_ids = join(',', array_values($records));
+
+            $records = get_records_select_menu('hotpot', "reference='$hotpot->reference'", 'reference', 'id, reference');
+            $hotpot_ids = join(',', array_keys($records));
+            break;
+    }
+
+    $user_ids = '';
+    $users = array();
+    switch ($formdata['reportusers']) {
+        case 'all':
+            $admin_ids = get_records_select_menu('user_admins');
+            if (is_array($admin_ids)) {
+                $users = array_merge($users, $admin_ids);
+            }
+            $creator_ids = get_records_select_menu('user_coursecreators');
+            if (is_array($creator_ids)) {
+                $users = array_merge($users, $creator_ids);
+            }
+            $teacher_ids = get_records_select_menu('user_teachers', "course IN ($course_ids)", 'course', 'id, userid');
+            if (is_array($teacher_ids)) {
+                $users = array_merge($users, $teacher_ids);
+            }
+            $guest_id = get_records_select_menu('user', "username='guest'", '', 'id,id');
+            if (is_array($guest_id)) {
+                $users = array_merge($users, $guest_id);
+            }
+            // add students next
+
+        case 'students':
+            $student_ids = get_records_select_menu('user_students', "course IN ($course_ids)", 'course', 'id, userid');
+            if (is_array($student_ids)) {
+                $users = array_merge($users, $student_ids);
+            }
+            $user_ids = array_values($users);
+            sort($user_ids);
+            $user_ids = join(',', array_unique($user_ids));
+            break;
+
+        case 'this': // current user only
+            $user_ids = $USER->id;
+            break;
+
+        default: // specific user selected by teacher
+            if (is_numeric($formdata['reportusers'])) {
+                $user_ids = $formdata['reportusers'];
+            }
+    }
+
+    if (empty($user_ids)) {
+        print_heading(get_string('nousersyet'));
+        exit;
+    }
+
+    // database table and selection conditions
+    $table = "{$CFG->prefix}hotpot_attempts AS a";
+    $select = "a.hotpot IN ($hotpot_ids) AND a.userid IN ($user_ids)";
+    if ($mode!='overview') {
+        $select .= ' AND a.status<>'.HOTPOT_STATUS_INPROGRESS;
+    }
+
+    // confine attempts if necessary
+    switch ($formdata['reportattempts']) {
+        case 'best':
+            $function = 'MAX';
+            $fieldnames = array('score', 'id', 'clickreportid');
+            $defaultvalue = 0;
+            break;
+        case 'first':
+            $function = 'MIN';
+            $fieldnames = array('timefinish', 'id', 'clickreportid');
+            $default_value = time();
+            break;
+        case 'last':
+            $function = 'MAX';
+            $fieldnames = array('timefinish', 'id', 'clickreportid');
+            $defaultvalue = time();
+            break;
+        default: // 'all' and any others
+            $function = '';
+            $fieldnames = array();
+            $defaultvalue = '';
+            break;
+    }
+    if (empty($function) || empty($fieldnames)) {
+        // do nothing (i.e. get ALL attempts)
+    } else {
+        $groupby = 'userid';
+        $records = hotpot_get_records_groupby($function, $fieldnames, $table, $select, $groupby);
+
+        $ids = array();
+        foreach ($records as $record) {
+            $ids[] = $record->clickreportid;
+        }
+        $select = "a.clickreportid IN (".join(',', $ids).")";
+    }
+
+    // pick out last attempt in each clickreport series
+    $cr_attempts = hotpot_get_records_groupby('MAX', array('timefinish', 'id'), $table, $select, 'clickreportid');
+
+    $fields = 'a.*, u.firstname, u.lastname, u.picture';
+    if ($mode=='click') {
+        $fields .= ', u.idnumber';
+    } else { 
+        // overview, simple and detailed reports 
+        // get last attempt record in clickreport series
+        $ids = array();
+        foreach ($cr_attempts as $cr_attempt) {
+            $ids[] = $cr_attempt->id;
+        }
+        if (empty($ids)) {
+            $select = "";
+        } else {
+            $ids = array_unique($ids);
+            sort($ids);
+            $select = "a.id IN (".join(',', $ids).")";
+        }
+    }
+
+    $attempts = array();
+
+    if ($select) {
+        // add user information to SQL query
+        $select .= ' AND a.userid = u.id';
+        $table .= ", {$CFG->prefix}user AS u";
+        $order = "u.lastname, a.attempt, a.timefinish";
+        // get the attempts (at last!)
+        $attempts = get_records_sql("SELECT $fields FROM $table WHERE $select ORDER BY $order");
+    }
+
+    // stop now if no attempts were found
+    if (empty($attempts)) {
+        print_heading(get_string('noattempts','quiz'));
+        exit;
+    }
+
+    // get the questions
+    if (!$questions = get_records_select('hotpot_questions', "hotpot='$hotpot->id'")) {
+        $questions = array();
+    }
+
+    // get grades
+    $grades = hotpot_get_grades($hotpot, $user_ids);
+
+    // get list of attempts by user and set reference to last attempt in clickreport series
+    $users = array();
+    foreach ($attempts as $id=>$attempt) {
+
+        $userid = $attempt->userid;
+
+        if (!isset($users[$userid])) {
+            $users[$userid]->grade = isset($grades[$userid]) ? $grades[$userid] : '&nbsp;';
+            $users[$userid]->attempts = array();
+        }
+
+        $users[$userid]->attempts[] = &$attempts[$id];
+
+        if ($mode=='click' && isset($cr_attempts[$id])) {
+            $attempts[$id]->cr_lastclick = $cr_attempts[$id]->id;
+            $attempts[$id]->cr_timefinish = $cr_attempts[$id]->timefinish;
+        }
+    }
+
+    if ($mode!='overview') {
+
+        // initialise details of responses to questions in these attempts
+        foreach ($attempts as $a=>$attempt) {
+            $attempts[$a]->responses = array();
+        }
+        foreach ($questions as $q=>$question) {
+            $questions[$q]->attempts = array();
+        }
+
+        // get reponses to these attempts
+        $attempt_ids = join(',',array_keys($attempts));
+        if (!$responses = get_records_sql("SELECT * FROM {$CFG->prefix}hotpot_responses WHERE attempt IN ($attempt_ids)")) {
+            $responses = array();
+        }
+
+        // ids of questions used in these responses
+        $questionids = array();
+
+        foreach ($responses as $response) {
+            // shortcuts to the attempt and question ids
+            $a = $response->attempt;
+            $q = $response->question;
+
+            // check the attempt and question objects exist
+            // (if they don't exist, something is very wrong!)
+            if (isset($attempts[$a]) || isset($questions[$q])) {
+
+                // add the response for this attempt
+                $attempts[$a]->responses[$q] = $response;
+
+                // add a reference from the question to the attempt which includes this question
+                $questions[$q]->attempts[] = &$attempts[$a];
+
+                // flag this id as being used
+                $questionids[$q] = true;
+            }
+        }
+
+        // remove unused questions
+        $questionids = array_keys($questionids);
+        foreach ($questions as $id=>$question) {
+            if (!in_array($id, $questionids)) {
+                unset($questions[$id]);
+            }
+        }
+    }
 
 /// Open the selected hotpot report and display it
 
-       $mode = clean_param($mode, PARAM_SAFEDIR);
+    $mode = clean_param($mode, PARAM_SAFEDIR);
 
-       if (! is_readable("report/$mode/report.php")) {
-               error("Report not known (".clean_text($mode).")", $course_homeurl);
-       }
+    if (! is_readable("report/$mode/report.php")) {
+        error("Report not known (".clean_text($mode).")", $course_homeurl);
+    }
 
-       include("report/default.php");  // Parent class
-       include("report/$mode/report.php");
+    include("report/default.php");  // Parent class
+    include("report/$mode/report.php");
 
-       $report = new hotpot_report();
+    $report = new hotpot_report();
 
-       if (! $report->display($hotpot, $cm, $course, $users, $attempts, $questions, $formdata)) {
-               error("Error occurred during report processing!", $course_homeurl);
-       }
+    if (! $report->display($hotpot, $cm, $course, $users, $attempts, $questions, $formdata)) {
+        error("Error occurred during report processing!", $course_homeurl);
+    }
 
-       if ($formdata['reportformat']=='htm') {
-               print_footer($course);
-       }
+    if ($formdata['reportformat']=='htm') {
+        print_footer($course);
+    }
 //////////////////////////////////////////////
 /// functions to delete attempts and responses
 
 function hotpot_grade_heading($hotpot, $formdata) {
 
-       global $HOTPOT_GRADEMETHOD;
-       $grademethod = $HOTPOT_GRADEMETHOD[$hotpot->grademethod];
-
-       if ($hotpot->grade!=100) {
-               $grademethod = "$hotpot->grade x $grademethod/100";
-       }
-       if ($formdata['reportformat']=='htm') {
-               $grademethod = '<font size="1">'.$grademethod.'</font>';
-       }
-       $nl = $formdata['reportformat']=='htm' ? '<br />' : "\n";
-       return get_string('grade')."$nl($grademethod)";
+    global $HOTPOT_GRADEMETHOD;
+    $grademethod = $HOTPOT_GRADEMETHOD[$hotpot->grademethod];
+
+    if ($hotpot->grade!=100) {
+        $grademethod = "$hotpot->grade x $grademethod/100";
+    }
+    if ($formdata['reportformat']=='htm') {
+        $grademethod = '<font size="1">'.$grademethod.'</font>';
+    }
+    $nl = $formdata['reportformat']=='htm' ? '<br />' : "\n";
+    return get_string('grade')."$nl($grademethod)";
 }
 function hotpot_delete_selected_attempts(&$hotpot, $del) {
 
-       $select = '';
-       switch ($del) {
-               case 'all' :
-                       $select = "hotpot='$hotpot->id'";
-                       break;
-               case 'abandoned':
-                       $select = "hotpot='$hotpot->id' AND status=".HOTPOT_STATUS_ABANDONED;
-                       break;
-               case 'selection':
-                       $ids = (array)data_submitted();
-                       unset($ids['del']);
-                       unset($ids['id']);
-                       if (!empty($ids)) {
-                               $select = "hotpot='$hotpot->id' AND clickreportid IN (".implode(',', $ids).")";
-                       }
-                       break;
-       }
-
-       // delete attempts using $select, if it is set
-       if ($select) {
-
-               $table = 'hotpot_attempts';
-               if ($attempts = get_records_select($table, $select)) {
-
-                       hotpot_delete_and_notify($table, $select, get_string('attempts', 'quiz'));
-
-                       $select = 'attempt IN ('.implode(',', array_keys($attempts)).')';
-                       hotpot_delete_and_notify('hotpot_details', $select, get_string('rawdetails', 'hotpot'));
-                       hotpot_delete_and_notify('hotpot_responses', $select, get_string('answer', 'quiz'));
-               }
-       }
+    $select = '';
+    switch ($del) {
+        case 'all' :
+            $select = "hotpot='$hotpot->id'";
+            break;
+        case 'abandoned':
+            $select = "hotpot='$hotpot->id' AND status=".HOTPOT_STATUS_ABANDONED;
+            break;
+        case 'selection':
+            $ids = (array)data_submitted();
+            unset($ids['del']);
+            unset($ids['id']);
+            if (!empty($ids)) {
+                $select = "hotpot='$hotpot->id' AND clickreportid IN (".implode(',', $ids).")";
+            }
+            break;
+    }
+
+    // delete attempts using $select, if it is set
+    if ($select) {
+
+        $table = 'hotpot_attempts';
+        if ($attempts = get_records_select($table, $select)) {
+
+            hotpot_delete_and_notify($table, $select, get_string('attempts', 'quiz'));
+
+            $select = 'attempt IN ('.implode(',', array_keys($attempts)).')';
+            hotpot_delete_and_notify('hotpot_details', $select, get_string('rawdetails', 'hotpot'));
+            hotpot_delete_and_notify('hotpot_responses', $select, get_string('answer', 'quiz'));
+        }
+    }
 
 }
 
@@ -376,239 +376,239 @@ function hotpot_delete_selected_attempts(&$hotpot, $del) {
 /// report selector menus
 
 function hotpot_print_report_heading(&$course, &$cm, &$hotpot, &$mode) {
-       $strmodulenameplural = get_string("modulenameplural", "hotpot");
-       $strmodulename  = get_string("modulename", "hotpot");
-
-       $title = "$course->shortname: $hotpot->name";
-       $heading = "$course->fullname";
-
-       $navigation = "<a href=index.php?id=$course->id>$strmodulenameplural</a> -> ";
-       $navigation .= "<a href=\"view.php?id=$cm->id\">$hotpot->name</a> -> ";
-       if (isteacher($course->id)) {
-               if ($mode=='overview' || $mode=='simplestat' || $mode=='fullstat') {
-                       $module = "quiz";
-               } else {
-                       $module = "hotpot";
-               }
-               $navigation .= get_string("report$mode", $module);
-
-       } else {
-               $navigation .= get_string("report", "quiz");
-       }
-       if ($course->category) {
-               $navigation = "<a href=\"../../course/view.php?id=$course->id\">$course->shortname</a> -> $navigation";
-       }
-       $button = update_module_button($cm->id, $course->id, $strmodulename);
-
-       print_header($title, $heading, $navigation, "", "", true, $button, navmenu($course, $cm));
-
-       print_heading($hotpot->name);
+    $strmodulenameplural = get_string("modulenameplural", "hotpot");
+    $strmodulename  = get_string("modulename", "hotpot");
+
+    $title = "$course->shortname: $hotpot->name";
+    $heading = "$course->fullname";
+
+    $navigation = "<a href=index.php?id=$course->id>$strmodulenameplural</a> -> ";
+    $navigation .= "<a href=\"view.php?id=$cm->id\">$hotpot->name</a> -> ";
+    if (isteacher($course->id)) {
+        if ($mode=='overview' || $mode=='simplestat' || $mode=='fullstat') {
+            $module = "quiz";
+        } else {
+            $module = "hotpot";
+        }
+        $navigation .= get_string("report$mode", $module);
+
+    } else {
+        $navigation .= get_string("report", "quiz");
+    }
+    if ($course->category) {
+        $navigation = "<a href=\"../../course/view.php?id=$course->id\">$course->shortname</a> -> $navigation";
+    }
+    $button = update_module_button($cm->id, $course->id, $strmodulename);
+
+    print_header($title, $heading, $navigation, "", "", true, $button, navmenu($course, $cm));
+
+    print_heading($hotpot->name);
 }
 function hotpot_print_report_selector(&$course, &$hotpot, &$formdata) {
 
-       global $CFG;
-
-       $reports = hotpot_get_report_names('overview,simplestat,fullstat');
-
-       print '<form method="post" action="'."$CFG->wwwroot/mod/hotpot/report.php?hp=$hotpot->id".'">';
-       print '<table cellpadding="2" align="center">';
-
-       $menus = array();
-
-       $menus['mode'] = array();
-       foreach ($reports as $name) {
-               if ($name=='overview' || $name=='simplestat' || $name=='fullstat') {
-                       $module = "quiz";   // standard reports
-               } else if ($name=='click' && empty($hotpot->clickreporting)) {
-                       $module =  "";      // clickreporting is disabled
-               } else {
-                       $module = "hotpot"; // custom reports
-               }
-               if ($module) {
-                       $menus['mode'][$name] = get_string("report$name", $module);
-               }
-       }
-       if (isadmin()) {
-               $menus['reportcourse'] = array(
-                       'this' => get_string('thiscourse', 'hotpot'), // $course->shortname,
-                       'all' => get_string('allmycourses', 'hotpot')
-               );
-       }
-       $menus['reportusers'] = array(
-               'all' => get_string('allparticipants'),
-               'students' => get_string('students')
-       );
-       $users = get_records_sql("
-               SELECT 
-                       u.*
-               FROM 
-                       {$CFG->prefix}user AS u,
-                       {$CFG->prefix}user_students AS us
-               WHERE
-                       u.id = us.userid AND us.course=$course->id
-               ORDER BY
-                       u.lastname
-       ");
-       if ($users) {
-               $menus['reportusers'][''] = '------'; // separator
-               foreach ($users as $id=>$user) {
-                               $menus['reportusers']["$id"] = fullname($user);
-               }
-       }
-       $menus['reportattempts'] = array(
-               'all' => get_string('attemptsall', 'hotpot'),
-               'best' => get_string('attemptsbest', 'hotpot'),
-               'first' => get_string('attemptsfirst', 'hotpot'),
-               'last' => get_string('attemptslast', 'hotpot')
-       );
-
-       print '<tr><td>';
-       helpbutton('reportcontent', get_string('reportcontent', 'hotpot'), 'hotpot');
-       print '</td><th align="right">'.get_string('reportcontent', 'hotpot').':</th><td colspan="7">';
-       foreach ($menus as $name => $options) {
-               $value = $formdata[$name];
-               print choose_from_menu($options, $name, $value, "", "", 0, true);
-       };
-       print '<input type="submit" value="'.get_string('reportbutton', 'hotpot').'"></td></tr>';
-
-       $menus = array();
-
-       $menus['reportformat'] = array();
-       $menus['reportformat']['htm'] = get_string('reportformathtml', 'hotpot');
-       if (file_exists("$CFG->libdir/excel") || file_exists("$CFG->libdir/excellib.class.php")) {
-               $menus['reportformat']['xls'] = get_string('reportformatexcel', 'hotpot');
-       }
-       $menus['reportformat']['txt'] = get_string('reportformattext', 'hotpot');
-
-       if (trim($CFG->hotpot_excelencodings)) {
-               $menus['reportencoding'] = array(get_string('none')=>'');
-
-               $encodings = explode(',', $CFG->hotpot_excelencodings);
-               foreach ($encodings as $encoding) {
-
-                       $encoding = trim($encoding);
-                       if ($encoding) {
-                               $menus['reportencoding'][$encoding] = $encoding;
-                       }
-               }
-       }
-       $menus['reportwrapdata'] = array(
-               '1' => get_string('yes'),
-               '0'  => get_string('no'),
-       );
-       $menus['reportshowlegend'] = array(
-               '1' => get_string('yes'),
-               '0'  => get_string('no'),
-       );
-
-       print '<tr><td>';
-       helpbutton('reportformat', get_string('reportformat', 'hotpot'), 'hotpot');
-       print '</td>';
-       foreach ($menus as $name => $options) {
-               $value = $formdata[$name];
-               print '<th align="right">'.get_string($name, 'hotpot').':</th><td>'.choose_from_menu($options, $name, $value, "", "", 0, true).'</td>';
-       }
-       print '</tr>';
-
-       print '</table>';
-
-       print '<hr size="1" noshade="noshade" />';
-       print '</form>'."\n";
+    global $CFG;
+
+    $reports = hotpot_get_report_names('overview,simplestat,fullstat');
+
+    print '<form method="post" action="'."$CFG->wwwroot/mod/hotpot/report.php?hp=$hotpot->id".'">';
+    print '<table cellpadding="2" align="center">';
+
+    $menus = array();
+
+    $menus['mode'] = array();
+    foreach ($reports as $name) {
+        if ($name=='overview' || $name=='simplestat' || $name=='fullstat') {
+            $module = "quiz";   // standard reports
+        } else if ($name=='click' && empty($hotpot->clickreporting)) {
+            $module =  "";      // clickreporting is disabled
+        } else {
+            $module = "hotpot"; // custom reports
+        }
+        if ($module) {
+            $menus['mode'][$name] = get_string("report$name", $module);
+        }
+    }
+    if (isadmin()) {
+        $menus['reportcourse'] = array(
+            'this' => get_string('thiscourse', 'hotpot'), // $course->shortname,
+            'all' => get_string('allmycourses', 'hotpot')
+        );
+    }
+    $menus['reportusers'] = array(
+        'all' => get_string('allparticipants'),
+        'students' => get_string('students')
+    );
+    $users = get_records_sql("
+        SELECT 
+            u.*
+        FROM 
+            {$CFG->prefix}user AS u,
+            {$CFG->prefix}user_students AS us
+        WHERE
+            u.id = us.userid AND us.course=$course->id
+        ORDER BY
+            u.lastname
+    ");
+    if ($users) {
+        $menus['reportusers'][''] = '------'; // separator
+        foreach ($users as $id=>$user) {
+                $menus['reportusers']["$id"] = fullname($user);
+        }
+    }
+    $menus['reportattempts'] = array(
+        'all' => get_string('attemptsall', 'hotpot'),
+        'best' => get_string('attemptsbest', 'hotpot'),
+        'first' => get_string('attemptsfirst', 'hotpot'),
+        'last' => get_string('attemptslast', 'hotpot')
+    );
+
+    print '<tr><td>';
+    helpbutton('reportcontent', get_string('reportcontent', 'hotpot'), 'hotpot');
+    print '</td><th align="right">'.get_string('reportcontent', 'hotpot').':</th><td colspan="7">';
+    foreach ($menus as $name => $options) {
+        $value = $formdata[$name];
+        print choose_from_menu($options, $name, $value, "", "", 0, true);
+    };
+    print '<input type="submit" value="'.get_string('reportbutton', 'hotpot').'"></td></tr>';
+
+    $menus = array();
+
+    $menus['reportformat'] = array();
+    $menus['reportformat']['htm'] = get_string('reportformathtml', 'hotpot');
+    if (file_exists("$CFG->libdir/excel") || file_exists("$CFG->libdir/excellib.class.php")) {
+        $menus['reportformat']['xls'] = get_string('reportformatexcel', 'hotpot');
+    }
+    $menus['reportformat']['txt'] = get_string('reportformattext', 'hotpot');
+
+    if (trim($CFG->hotpot_excelencodings)) {
+        $menus['reportencoding'] = array(get_string('none')=>'');
+
+        $encodings = explode(',', $CFG->hotpot_excelencodings);
+        foreach ($encodings as $encoding) {
+
+            $encoding = trim($encoding);
+            if ($encoding) {
+                $menus['reportencoding'][$encoding] = $encoding;
+            }
+        }
+    }
+    $menus['reportwrapdata'] = array(
+        '1' => get_string('yes'),
+        '0'  => get_string('no'),
+    );
+    $menus['reportshowlegend'] = array(
+        '1' => get_string('yes'),
+        '0'  => get_string('no'),
+    );
+
+    print '<tr><td>';
+    helpbutton('reportformat', get_string('reportformat', 'hotpot'), 'hotpot');
+    print '</td>';
+    foreach ($menus as $name => $options) {
+        $value = $formdata[$name];
+        print '<th align="right">'.get_string($name, 'hotpot').':</th><td>'.choose_from_menu($options, $name, $value, "", "", 0, true).'</td>';
+    }
+    print '</tr>';
+
+    print '</table>';
+
+    print '<hr size="1" noshade="noshade" />';
+    print '</form>'."\n";
 }
 function hotpot_get_report_names($names='') {
-       // $names : optional list showing required order reports names
+    // $names : optional list showing required order reports names
 
-       $reports = array();
+    $reports = array();
 
-       // convert $names to an array, if necessary (usually is)
-       if (!is_array($names)) {
-               $names = explode(',', $names);
-       }
+    // convert $names to an array, if necessary (usually is)
+    if (!is_array($names)) {
+        $names = explode(',', $names);
+    }
 
-       $plugins = get_list_of_plugins('mod/hotpot/report');
-       foreach($names as $name) {
-               if (is_numeric($i = array_search($name, $plugins))) {
-                       $reports[] = $name;
-                       unset($plugins[$i]);
-               }
-       }
+    $plugins = get_list_of_plugins('mod/hotpot/report');
+    foreach($names as $name) {
+        if (is_numeric($i = array_search($name, $plugins))) {
+            $reports[] = $name;
+            unset($plugins[$i]);
+        }
+    }
 
-       // append remaining plugins
-       $reports = array_merge($reports, $plugins);
+    // append remaining plugins
+    $reports = array_merge($reports, $plugins);
 
-       return $reports;
+    return $reports;
 }
 function hotpot_get_report_users($course_ids, $formdata) {
-       $users = array();
-
-       /// Check to see if groups are being used in this module
-       $currentgroup = false;
-       if ($groupmode = groupmode($course, $cm)) {   // Groups are being used
-               $currentgroup = setup_and_print_groups($course, $groupmode, "report.php?id=$cm->id&mode=simple");
-       }
-
-       $sort = "u.lastname ASC";
-
-       switch ($formdata['reportusers']) {
-               case 'students':
-                       if ($currentgroup) {
-                               $users = get_group_students($currentgroup, $sort);
-                       } else {
-                               $users = get_course_students($course->id, $sort);
-                       }
-                       break;
-               case 'all':
-                       if ($currentgroup) {
-                               $users = get_group_users($currentgroup, $sort);
-                       } else {
-                               $users = get_course_users($course->id, $sort);
-                       }
-                       break;
-       }
-
-       return $users;
+    $users = array();
+
+    /// Check to see if groups are being used in this module
+    $currentgroup = false;
+    if ($groupmode = groupmode($course, $cm)) {   // Groups are being used
+        $currentgroup = setup_and_print_groups($course, $groupmode, "report.php?id=$cm->id&mode=simple");
+    }
+
+    $sort = "u.lastname ASC";
+
+    switch ($formdata['reportusers']) {
+        case 'students':
+            if ($currentgroup) {
+                $users = get_group_students($currentgroup, $sort);
+            } else {
+                $users = get_course_students($course->id, $sort);
+            }
+            break;
+        case 'all':
+            if ($currentgroup) {
+                $users = get_group_users($currentgroup, $sort);
+            } else {
+                $users = get_course_users($course->id, $sort);
+            }
+            break;
+    }
+
+    return $users;
 }
 function hotpot_get_records_groupby($function, $fieldnames, $table, $select, $groupby) {
-       // $function is an SQL aggregate function (MAX or MIN)
-
-       global $CFG;
-
-       switch (strtolower($CFG->dbtype)) {
-               case 'mysql':
-                       $fields = "$groupby, $function(CONCAT(".join(",'_',", $fieldnames).")) AS joinedvalues";
-                       break;
-               case 'postgres7':
-                       $fields = "$groupby, $function(".join("||'_'||", $fieldnames).") AS joinedvalues";
-                       break;
-               default:
-                       $fields = "";
-                       break;
-       }
-
-       if ($fields) {
-               $records = get_records_sql("SELECT $fields FROM $table WHERE $select GROUP BY $groupby");
-       }
-
-       if (empty($fields) || empty($records)) {
-               $records = array();
-       }
-
-       $fieldcount = count($fieldnames);
-
-       foreach ($records as $id=>$record) {
-               if (empty($record->joinedvalues)) {
-                       unset($records[$id]);
-               } else {
-                       $formdata = explode('_', $record->joinedvalues);
-
-                       for ($i=0; $i<$fieldcount; $i++) {
-                               $fieldname = $fieldnames[$i];
-                               $records[$id]->$fieldname = $formdata[$i];
-                       }
-               }
-               unset($record->joinedvalues);
-       }
-
-       return $records;
+    // $function is an SQL aggregate function (MAX or MIN)
+
+    global $CFG;
+
+    switch (strtolower($CFG->dbtype)) {
+        case 'mysql':
+            $fields = "$groupby, $function(CONCAT(".join(",'_',", $fieldnames).")) AS joinedvalues";
+            break;
+        case 'postgres7':
+            $fields = "$groupby, $function(".join("||'_'||", $fieldnames).") AS joinedvalues";
+            break;
+        default:
+            $fields = "";
+            break;
+    }
+
+    if ($fields) {
+        $records = get_records_sql("SELECT $fields FROM $table WHERE $select GROUP BY $groupby");
+    }
+
+    if (empty($fields) || empty($records)) {
+        $records = array();
+    }
+
+    $fieldcount = count($fieldnames);
+
+    foreach ($records as $id=>$record) {
+        if (empty($record->joinedvalues)) {
+            unset($records[$id]);
+        } else {
+            $formdata = explode('_', $record->joinedvalues);
+
+            for ($i=0; $i<$fieldcount; $i++) {
+                $fieldname = $fieldnames[$i];
+                $records[$id]->$fieldname = $formdata[$i];
+            }
+        }
+        unset($record->joinedvalues);
+    }
+
+    return $records;
 }
 ?>
index 998362d3f06a5ec8ee03ec1c3b8fc682a3185055..c89423e2c5cd80d9f0a6482320355011dd255c17 100644 (file)
@@ -2,7 +2,7 @@
 
 ////////////////////////////////////////////////////////////////////
 /// Default class for report plugins
-///                                                                                                                       
+///                                                            
 /// Doesn't do anything on it's own -- it needs to be extended.   
 /// This class displays quiz reports.  Because it is called from 
 /// within /mod/quiz/report.php you can assume that the page header
 
 class hotpot_default_report {
 
-       function display($hotpot, $cm, $course, $users, $attempts, $questions, $options) {       
-               /// This function just displays the report
-               // it is replaced by the "display" functions in the scripts in the "report" folder
-               return true;
-       }
-
-       function add_question_headings(&$questions, &$table, $align='center', $size=50, $wrap=false, $fontsize=0) {
-               $count = count($questions);
-               for ($i=0; $i<$count; $i++) {
-                       $table->head[] = get_string('questionshort', 'hotpot', $i+1);
-                       if (isset($table->align)) {
-                               $table->align[] = $align;
-                       }
-                       if (isset($table->size)) {
-                               $table->size[] = $size;
-                       }
-                       if (isset($table->wrap)) {
-                               $table->wrap[] = $wrap;
-                       }
-                       if (isset($table->fontsize)) {
-                               $table->fontsize[] = $fontsize;
-                       }
-               }
-
-       }
-
-       function set_legend(&$table, &$q, &$value, &$question) {
-               // $q is the question number
-               // $value is the value (=text) of the answer
-
-               // check the legend is required
-               if (isset($table->legend) && isset($value)) {
-
-                       // create question details array, if necessary
-                       if (empty($table->legend[$q])) {
-                               $table->legend[$q] = array(
-                                       'name' => hotpot_get_question_name($question),
-                                       'answers' => array()
-                               );
-                       }
-
-                       // search for this $value in answers array for this $q(uestion)
-                       $i_max = count($table->legend[$q]['answers']);
-                       for ($i=0; $i<$i_max; $i++) {
-                               if ($table->legend[$q]['answers'][$i]==$value) {
-                                       break;
-                               }
-                       }
-
-                       // add $value to answers array, if it was not there
-                       if ($i==$i_max) {
-                               $table->legend[$q]['answers'][$i] = $value; 
-                       }
-
-                       // convert $value to alphabetic index (A, B ... AA, AB ...)
-                       $value = $this->dec_to_ALPHA($i);
-               }
-       }
-       function create_legend_table(&$tables, &$table) {
-
-               if (isset($table->legend)) {
-
-                       $legend->width = '*';
-                       $legend->tablealign = '*';
-                       $legend->border = isset($table->border) ? $table->border : NULL;
-                       $legend->cellpadding = isset($table->cellpadding) ? $table->cellpadding : NULL;
-                       $legend->cellspacing = isset($table->cellspacing) ? $table->cellspacing : NULL;
-                       $legend->tableclass = isset($table->tableclass) ? $table->tableclass : NULL;
-
-                       $legend->caption = get_string('reportlegend', 'hotpot');
-                       $legend->align = array('right', 'left');
-                       $legend->statheadercols = array(0);
-
-                       $legend->stat = array();
-
-                       // put the questions in order
-                       sort($table->legend);
-
-                       foreach($table->legend as $q=>$question) {
-
-                               $legend->stat[] = array(
-                                       get_string('questionshort', 'hotpot', $q+1), 
-                                       $question['name']
-                               );
-                               foreach($question['answers'] as $a=>$answer) {
-                                       $legend->stat[] = array(
-                                               $this->dec_to_ALPHA($a), 
-                                               $answer
-                                       );
-                               }
-                       }
-
-                       unset($table->legend);
-                       $tables[] = $legend;
-               }
-       }
-       function dec_to_ALPHA($dec) {
-               if ($dec < 26) {
-                       return chr(ord('A') + $dec);
-               } else {
-                       return $this->dec_to_ALPHA(intval($dec/26)-1).$this->dec_to_ALPHA($dec % 26);
-               }
-       }
-       function remove_column(&$table, $target_col) {
-
-               if (is_array($table)) {
-                       unset($table[$target_col]);
-                       $table = array_values($table);
-
-               } else if (is_object($table)) {
-                       $vars = get_object_vars($table);
-                       foreach ($vars as $name=>$value) {
-                               switch ($name) {
-                                       case 'data' :
-                                       case 'stat' :
-                                       case 'foot' :
-                                               $skipcol = array();
-                                               $cells = &$table->$name;
-
-                                               $row_max = count($cells);
-                                               for ($row=0; $row<$row_max; $row++) {
-
-                                                       $col = 0;
-                                                       $col_max = count($cells[$row]);
-
-                                                       $current_col = 0;
-                                                       while ($current_col<$target_col && $col<$col_max) {
-
-                                                               if (empty($skipcol[$current_col])) {
-
-                                                                       $cell = $cells[$row][$col++];
-                                                                       if (is_object($cell)) {
-                                                                               if (isset($cell->rowspan) && is_numeric($cell->rowspan) && ($cell->rowspan>0)) {
-                                                                                       // skip cells below this one
-                                                                                       $skipcol[$current_col] = $cell->rowspan-1;
-                                                                               }
-                                                                               if (isset($cell->colspan) && is_numeric($cell->colspan) && ($cell->colspan>0)) {
-                                                                                       // skip cells to the right of this one
-                                                                                       for ($c=1; $c<$cell->colspan; $c++) {
-                                                                                               if (empty($skipcol[$current_col+$c])) {
-                                                                                                       $skipcol[$current_col+$c] = 1;
-                                                                                               } else {
-                                                                                                       $skipcol[$current_col+$c] ++;
-                                                                                               }
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               } else {
-                                                                       $skipcol[$current_col]--;
-                                                               }
-                                                               $current_col++;
-                                                       }
-                                                       if ($current_col==$target_col && $col<$col_max) {
-                                                               $this->remove_column($cells[$row], $col);
-                                                       }
-                                               } // end for $row
-                                               break;
-                                       case 'head' :
-                                       case 'align' :
-                                       case 'class' :
-                                       case 'fontsize' :
-                                       case 'size' :
-                                       case 'wrap' :
-                                               $this->remove_column($table->$name, $target_col);
-                                               break;
-                                       case 'statheadercols' :
-                                               $array = &$table->$name;
-                                               $count = count($array);
-                                               for ($i=0; $i<$count; $i++) {
-                                                       if ($array[$i]>=$target_col) {
-                                                               $array[$i] --;
-                                                       }
-                                               }
-                                               break;
-                               } // end switch
-                       } // end foreach
-               } // end if
-       } // end function
-
-
-       function expand_spans(&$table, $zone) {
-               // expand multi-column and multi-row cells in a specified $zone of a $table
-
-               // do nothing if this $zone is empty
-               if (empty($table->$zone)) return;
-
-               // shortcut to rows in this $table $zone
-               $rows = &$table->{$zone};
-
-               // loop through the rows
-               foreach ($rows as $row=>$cells) {
-
-                       // check this is an array
-                       if (is_array($cells)) {
-
-                               // loop through the cells in this row
-                               foreach ($cells as $col=>$cell) {
-
-                                       if (is_object($cell)) {
-                                               if (isset($cell->rowspan) && is_numeric($cell->rowspan) && ($cell->rowspan>1)) {
-                                                       // fill in cells below this one
-                                                       $new_cell = array($cell->text);
-                                                       for ($r=1; $r<$cell->rowspan; $r++) {
-                                                               array_splice($rows[$row+$r], $col, 0, $new_cell);
-                                                       }
-                                               }
-                                               if (isset($cell->colspan) && is_numeric($cell->colspan) && ($cell->colspan>1)) {
-                                                       // fill in cells to the right of this one
-                                                       $new_cells = array();
-                                                       for ($c=1; $c<$cell->colspan; $c++) {
-                                                               $new_cells[] = $cell->text;
-                                                       }
-                                                       array_splice($rows[$row], $col, 0, $new_cells);
-                                               }
-                                               // replace $cell object with plain text
-                                               $rows[$row][$col] = $cell->text;
-                                       }
-                               }
-                       }
-               }
-       }
+    function display($hotpot, $cm, $course, $users, $attempts, $questions, $options) {   
+        /// This function just displays the report
+        // it is replaced by the "display" functions in the scripts in the "report" folder
+        return true;
+    }
+
+    function add_question_headings(&$questions, &$table, $align='center', $size=50, $wrap=false, $fontsize=0) {
+        $count = count($questions);
+        for ($i=0; $i<$count; $i++) {
+            $table->head[] = get_string('questionshort', 'hotpot', $i+1);
+            if (isset($table->align)) {
+                $table->align[] = $align;
+            }
+            if (isset($table->size)) {
+                $table->size[] = $size;
+            }
+            if (isset($table->wrap)) {
+                $table->wrap[] = $wrap;
+            }
+            if (isset($table->fontsize)) {
+                $table->fontsize[] = $fontsize;
+            }
+        }
+
+    }
+
+    function set_legend(&$table, &$q, &$value, &$question) {
+        // $q is the question number
+        // $value is the value (=text) of the answer
+
+        // check the legend is required
+        if (isset($table->legend) && isset($value)) {
+
+            // create question details array, if necessary
+            if (empty($table->legend[$q])) {
+                $table->legend[$q] = array(
+                    'name' => hotpot_get_question_name($question),
+                    'answers' => array()
+                );
+            }
+
+            // search for this $value in answers array for this $q(uestion)
+            $i_max = count($table->legend[$q]['answers']);
+            for ($i=0; $i<$i_max; $i++) {
+                if ($table->legend[$q]['answers'][$i]==$value) {
+                    break;
+                }
+            }
+
+            // add $value to answers array, if it was not there
+            if ($i==$i_max) {
+                $table->legend[$q]['answers'][$i] = $value; 
+            }
+
+            // convert $value to alphabetic index (A, B ... AA, AB ...)
+            $value = $this->dec_to_ALPHA($i);
+        }
+    }
+    function create_legend_table(&$tables, &$table) {
+
+        if (isset($table->legend)) {
+
+            $legend->width = '*';
+            $legend->tablealign = '*';
+            $legend->border = isset($table->border) ? $table->border : NULL;
+            $legend->cellpadding = isset($table->cellpadding) ? $table->cellpadding : NULL;
+            $legend->cellspacing = isset($table->cellspacing) ? $table->cellspacing : NULL;
+            $legend->tableclass = isset($table->tableclass) ? $table->tableclass : NULL;
+
+            $legend->caption = get_string('reportlegend', 'hotpot');
+            $legend->align = array('right', 'left');
+            $legend->statheadercols = array(0);
+
+            $legend->stat = array();
+
+            // put the questions in order
+            sort($table->legend);
+
+            foreach($table->legend as $q=>$question) {
+
+                $legend->stat[] = array(
+                    get_string('questionshort', 'hotpot', $q+1), 
+                    $question['name']
+                );
+                foreach($question['answers'] as $a=>$answer) {
+                    $legend->stat[] = array(
+                        $this->dec_to_ALPHA($a), 
+                        $answer
+                    );
+                }
+            }
+
+            unset($table->legend);
+            $tables[] = $legend;
+        }
+    }
+    function dec_to_ALPHA($dec) {
+        if ($dec < 26) {
+            return chr(ord('A') + $dec);
+        } else {
+            return $this->dec_to_ALPHA(intval($dec/26)-1).$this->dec_to_ALPHA($dec % 26);
+        }
+    }
+    function remove_column(&$table, $target_col) {
+
+        if (is_array($table)) {
+            unset($table[$target_col]);
+            $table = array_values($table);
+
+        } else if (is_object($table)) {
+            $vars = get_object_vars($table);
+            foreach ($vars as $name=>$value) {
+                switch ($name) {
+                    case 'data' :
+                    case 'stat' :
+                    case 'foot' :
+                        $skipcol = array();
+                        $cells = &$table->$name;
+
+                        $row_max = count($cells);
+                        for ($row=0; $row<$row_max; $row++) {
+
+                            $col = 0;
+                            $col_max = count($cells[$row]);
+
+                            $current_col = 0;
+                            while ($current_col<$target_col && $col<$col_max) {
+
+                                if (empty($skipcol[$current_col])) {
+
+                                    $cell = $cells[$row][$col++];
+                                    if (is_object($cell)) {
+                                        if (isset($cell->rowspan) && is_numeric($cell->rowspan) && ($cell->rowspan>0)) {
+                                            // skip cells below this one
+                                            $skipcol[$current_col] = $cell->rowspan-1;
+                                        }
+                                        if (isset($cell->colspan) && is_numeric($cell->colspan) && ($cell->colspan>0)) {
+                                            // skip cells to the right of this one
+                                            for ($c=1; $c<$cell->colspan; $c++) {
+                                                if (empty($skipcol[$current_col+$c])) {
+                                                    $skipcol[$current_col+$c] = 1;
+                                                } else {
+                                                    $skipcol[$current_col+$c] ++;
+                                                }
+                                            }
+                                        }
+                                    }
+                                } else {
+                                    $skipcol[$current_col]--;
+                                }
+                                $current_col++;
+                            }
+                            if ($current_col==$target_col && $col<$col_max) {
+                                $this->remove_column($cells[$row], $col);
+                            }
+                        } // end for $row
+                        break;
+                    case 'head' :
+                    case 'align' :
+                    case 'class' :
+                    case 'fontsize' :
+                    case 'size' :
+                    case 'wrap' :
+                        $this->remove_column($table->$name, $target_col);
+                        break;
+                    case 'statheadercols' :
+                        $array = &$table->$name;
+                        $count = count($array);
+                        for ($i=0; $i<$count; $i++) {
+                            if ($array[$i]>=$target_col) {
+                                $array[$i] --;
+                            }
+                        }
+                        break;
+                } // end switch
+            } // end foreach
+        } // end if
+    } // end function
+
+
+    function expand_spans(&$table, $zone) {
+        // expand multi-column and multi-row cells in a specified $zone of a $table
+
+        // do nothing if this $zone is empty
+        if (empty($table->$zone)) return;
+
+        // shortcut to rows in this $table $zone
+        $rows = &$table->{$zone};
+
+        // loop through the rows
+        foreach ($rows as $row=>$cells) {
+
+            // check this is an array
+            if (is_array($cells)) {
+
+                // loop through the cells in this row
+                foreach ($cells as $col=>$cell) {
+
+                    if (is_object($cell)) {
+                        if (isset($cell->rowspan) && is_numeric($cell->rowspan) && ($cell->rowspan>1)) {
+                            // fill in cells below this one
+                            $new_cell = array($cell->text);
+                            for ($r=1; $r<$cell->rowspan; $r++) {
+                                array_splice($rows[$row+$r], $col, 0, $new_cell);
+                            }
+                        }
+                        if (isset($cell->colspan) && is_numeric($cell->colspan) && ($cell->colspan>1)) {
+                            // fill in cells to the right of this one
+                            $new_cells = array();
+                            for ($c=1; $c<$cell->colspan; $c++) {
+                                $new_cells[] = $cell->text;
+                            }
+                            array_splice($rows[$row], $col, 0, $new_cells);
+                        }
+                        // replace $cell object with plain text
+                        $rows[$row][$col] = $cell->text;
+                    }
+                }
+            }
+        }
+    }
 
 /////////////////////////////////////////////////
 /// print a report in html, text or Excel format
@@ -246,592 +246,592 @@ class hotpot_default_report {
 // the stuff to print is contained in $table
 // which has the following properties:
 
-//      $table->border         border width for the table
-//      $table->cellpadding    padding on each cell
-//      $table->cellspacing    spacing between cells
-//      $table->tableclass     class for table
-//      $table->width          table width
-
-//      $table->align    is an array of column alignments
-//      $table->class    is an array of column classes
-//      $table->size     is an array of column sizes
-//      $table->wrap     is an array of column wrap/nowrap switches
-//      $table->fontsize is an array of fontsizes
-
-//      $table->caption is a caption (=title) for the report
-//      $table->head    is an array of headings (all TH cells)
-//      $table->data[]  is an array of arrays containing the data (all TD cells)
-//                     if a row is given as "hr", a "tabledivider" is inserted
-//                     if a cell is a string, it is assumed to be the cell content
-//                     a cell can also be an object, thus:
-//                             $cell->text : the content of the cell
-//                             $cell->rowspan : the row span of this cell
-//                             $cell->colspan : the column span of this cell
-//                     if rowspan or colspan are specified, neighboring cells are shifted accordingly
-//      $table->stat[]  is an array of arrays containing the statistics rows (TD and TH cells)
-//      $table->foot[]  is an array of arrays containing the footer rows (all TH cells)
-
-//      $table->statheadercols is an array of column numbers which are headers
+//   $table->border     border width for the table
+//   $table->cellpadding    padding on each cell
+//   $table->cellspacing    spacing between cells
+//   $table->tableclass class for table
+//   $table->width      table width
+
+//   $table->align    is an array of column alignments
+//   $table->class    is an array of column classes
+//   $table->size     is an array of column sizes
+//   $table->wrap     is an array of column wrap/nowrap switches
+//   $table->fontsize is an array of fontsizes
+
+//   $table->caption is a caption (=title) for the report
+//   $table->head    is an array of headings (all TH cells)
+//   $table->data[]  is an array of arrays containing the data (all TD cells)
+//          if a row is given as "hr", a "tabledivider" is inserted
+//          if a cell is a string, it is assumed to be the cell content
+//          a cell can also be an object, thus:
+//              $cell->text : the content of the cell
+//              $cell->rowspan : the row span of this cell
+//              $cell->colspan : the column span of this cell
+//          if rowspan or colspan are specified, neighboring cells are shifted accordingly
+//   $table->stat[]  is an array of arrays containing the statistics rows (TD and TH cells)
+//   $table->foot[]  is an array of arrays containing the footer rows (all TH cells)
+
+//   $table->statheadercols is an array of column numbers which are headers
 
 
 //////////////////////////////////////////
 /// print a report
 
-       function print_report(&$course, &$hotpot, &$tables, &$options) {
-               switch ($options['reportformat']) {
-                       case 'txt':
-                               $this->print_text_report($course, $hotpot, $tables, $options);
-                               break;
-                       case 'xls':
-                               $this->print_excel_report($course, $hotpot, $tables, $options);
-                               break;
-                       default: // 'htm' (and anything else)
-                               $this->print_html_report($tables);
-                               break;
-               }
-       }
-
-       function print_report_start(&$course, &$hotpot, &$options, &$table) {
-               switch ($options['reportformat']) {
-                       case 'txt':
-                               $this->print_text_start($course, $hotpot, $options);
-                               break;
-                       case 'xls':
-                               $this->print_excel_start($course, $hotpot, $options);
-                               break;
-
-                       case 'htm':
-                               $this->print_html_start($course, $hotpot, $options);
-                               break;
-               }
-       }
-
-       function print_report_cells(&$table, &$options, $zone) {
-               switch ($options['reportformat']) {
-                       case 'txt':
-                               $fmt = 'text';
-                               break;
-                       case 'xls':
-                               $fmt = 'excel';
-                               break;
-                       default: // 'htm' (and anything else)
-                               $fmt = 'html';
-                               break;
-               }
-               $fn = "print_{$fmt}_{$zone}";
-               $this->$fn($table, $options);
-       }
-
-       function print_report_finish(&$course, &$hotpot, &$options) {
-               switch ($options['reportformat']) {
-                       case 'txt' : 
-                               // do nothing
-                               break;
-                       case 'xls':
-                               $this->print_excel_finish($course, $hotpot, $options);
-                               break;
-                       case 'htm':
-                               $this->print_html_finish($course, $hotpot, $options);
-                               break;
-               }
-       }
+    function print_report(&$course, &$hotpot, &$tables, &$options) {
+        switch ($options['reportformat']) {
+            case 'txt':
+                $this->print_text_report($course, $hotpot, $tables, $options);
+                break;
+            case 'xls':
+                $this->print_excel_report($course, $hotpot, $tables, $options);
+                break;
+            default: // 'htm' (and anything else)
+                $this->print_html_report($tables);
+                break;
+        }
+    }
+
+    function print_report_start(&$course, &$hotpot, &$options, &$table) {
+        switch ($options['reportformat']) {
+            case 'txt':
+                $this->print_text_start($course, $hotpot, $options);
+                break;
+            case 'xls':
+                $this->print_excel_start($course, $hotpot, $options);
+                break;
+
+            case 'htm':
+                $this->print_html_start($course, $hotpot, $options);
+                break;
+        }
+    }
+
+    function print_report_cells(&$table, &$options, $zone) {
+        switch ($options['reportformat']) {
+            case 'txt':
+                $fmt = 'text';
+                break;
+            case 'xls':
+                $fmt = 'excel';
+                break;
+            default: // 'htm' (and anything else)
+                $fmt = 'html';
+                break;
+        }
+        $fn = "print_{$fmt}_{$zone}";
+        $this->$fn($table, $options);
+    }
+
+    function print_report_finish(&$course, &$hotpot, &$options) {
+        switch ($options['reportformat']) {
+            case 'txt' : 
+                // do nothing
+                break;
+            case 'xls':
+                $this->print_excel_finish($course, $hotpot, $options);
+                break;
+            case 'htm':
+                $this->print_html_finish($course, $hotpot, $options);
+                break;
+        }
+    }
 
 //////////////////////////////////////////
 /// print an html report
 
-       function print_html_report(&$tables) {
-               $count = count($tables);
-               foreach($tables as $i=>$table) {
-
-                       $this->print_html_start($table);
-                       $this->print_html_head($table);
-                       $this->print_html_data($table);
-                       $this->print_html_stat($table);
-                       $this->print_html_foot($table);
-                       $this->print_html_finish($table);
-
-                       if (($i+1)<$count) {
-                               print_spacer(30, 10, true);
-                       }
-               }
-       }
-       function print_html_start(&$table) {
-
-               // default class for the table
-               if (empty($table->tableclass)) {
-                       $table->tableclass = 'generaltable';
-               }
-
-               // default classes for TD and TH
-               $d = $table->tableclass.'cell';
-               $h = $table->tableclass.'header';
-
-               $table->th_side = '<th valign="top" align="right" class="'.$h.'">';
-
-               $table->td = array();
-               $table->th_top = array();
-
-               if (empty($table->colspan)) {
-                       if (isset($table->head)) {
-                               $table->colspan = count($table->head);
-                       } else if (isset($table->data)) {
-                               $table->colspan = count($table->data[0]);
-                       } else if (isset($table->stat)) {
-                               $table->colspan = count($table->stat);
-                       } else if (isset($table->foot)) {
-                               $table->colspan = count($table->foot);
-                       } else {
-                               $table->colspan = 0;
-                       }
-               }
-
-               for ($i=0; $i<$table->colspan; $i++) {
-
-                       $align = empty($table->align[$i]) ? '' : ' align="'.$table->align[$i].'"';
-                       $class = empty($table->class[$i]) ? $d : ' class="'.$table->class[$i].'"';
-                       $size  = empty($table->size[$i])  ? '' : ' width="'.$table->size[$i].'"';
-                       $wrap  = empty($table->wrap[$i])  ? '' : ' nowrap="nowrap"';
-
-                       $table->th_top[$i] = '<th align="center"'.$size.' class="'.$h.'" nowrap="nowrap">';
-
-                       $table->td[$i] = '<td valign="top"'.$align.$class.$wrap.'>';
-
-                       if (!empty($table->fontsize[$i])) {
-                               $table->td[$i] .= '<font size="'.$table->fontsize[$i].'">';
-                       }
-               }
-
-               if (empty($table->border)) {
-                       $table->border = 0;
-               }
-               if (empty($table->cellpadding)) {
-                       $table->cellpadding = 5;
-               }
-               if (empty($table->cellspacing)) {
-                       $table->cellspacing = 1;
-               }
-               if (empty($table->width)) {
-                       $table->width = "80%"; // actually the width of the "simple box"
-               }
-               if (empty($table->tablealign)) {
-                       $table->tablealign = "center";
-               }
-
-               if (isset($table->start)) {
-                       print $table->start."\n";
-               }
-
-               print_simple_box_start("$table->tablealign", "$table->width", "#ffffff", 0);
-               print '<table width="100%" border="'.$table->border.'" valign="top" align="center"  cellpadding="'.$table->cellpadding.'" cellspacing="'.$table->cellspacing.'" class="'.$table->tableclass.'">'."\n";
-
-               if (isset($table->caption)) {
-                       print '<tr><td colspan="'.$table->colspan.'" class="'.$table->tableclass.'header"><b>'.$table->caption.'</b></td></tr>'."\n";
-               }
-
-       }
-       function print_html_head(&$table) {
-               if (isset($table->head)) {
-                       print "<tr>\n";
-                       foreach ($table->head as $i=>$cell) {
-                               $th = $table->th_top[$i];
-                               print $th.$cell."</th>\n";
-                       }
-                       print "</tr>\n";
-               }
-       }
-       function print_html_data(&$table) {
-               if (isset($table->data)) {
-                       $skipcol = array();
-                       foreach ($table->data as $cells) {
-                               print "<tr>\n";
-                               if (is_array($cells)) {
-                                       $i = 0; // index on $cells
-                                       $col = 0; // column index
-                                       while ($col<$table->colspan && isset($cells[$i])) {
-                                               if (empty($skipcol[$col])) {
-                                                       $cell = &$cells[$i++]; 
-                                                       $td = $table->td[$col];
-                                                       if (is_object($cell)) {
-                                                               $text = $cell->text;
-                                                               if (isset($cell->rowspan) && is_numeric($cell->rowspan) && ($cell->rowspan>0)) {
-                                                                       $td = '<td rowspan="'.$cell->rowspan.'"'.substr($td, 3);
-                                                                       // skip cells below this one
-                                                                       $skipcol[$col] = $cell->rowspan-1;
-                                                               }
-                                                               if (isset($cell->colspan) && is_numeric($cell->colspan) && ($cell->colspan>0)) {
-                                                                       $td = '<td colspan="'.$cell->colspan.'"'.substr($td, 3);
-                                                                       // skip cells to the right of this one
-                                                                       for ($c=1; $c<$cell->colspan; $c++) {
-                                                                               if (empty($skipcol[$col+$c])) {
-                                                                                       $skipcol[$col+$c] = 1;
-                                                                               } else {
-                                                                                       $skipcol[$col+$c] ++;
-                                                                               }
-                                                                       }
-                                                               }
-                                                       } else { // $cell is a string
-                                                               $text = $cell;
-                                                       }
-                                                       print $td.$text."</td>\n";
-                                               } else {
-                                                       $skipcol[$col]--;
-                                               }
-                                               $col++;
-                                       } // end while
-                               } else if ($cells=='hr') {
-                                       print '<td colspan="'.$table->colspan.'"><div class="tabledivider"></div></td>'."\n";
-                               }
-                               print "</tr>\n";
-                       }
-               }
-       }
-       function print_html_stat(&$table) {
-               if (isset($table->stat)) {
-                       if (empty($table->statheadercols)) {
-                               $table->statheadercols = array();
-                       }
-                       foreach ($table->stat as $cells) {
-                               print '<tr>';
-                               foreach ($cells as $i => $cell) {
-                                       if (in_array($i, $table->statheadercols)) {
-                                               $th = $table->th_side;
-                                               print $th.$cell."</th>\n";
-                                       } else {
-                                               $td = $table->td[$i];
-                                               print $td.$cell."</td>\n";
-                                       }
-                               }
-                               print "</tr>\n";
-                       }
-               }
-       }
-       function print_html_foot(&$table) {
-               if (isset($table->foot)) {
-                       foreach ($table->foot as $cells) {
-                               print "<tr>\n";
-                               foreach ($cells as $i => $cell) {
-                                       if ($i==0) {
-                                               $th = $table->th_side;
-                                               print $th.$cell."</th>\n";
-                                       } else {
-                                               $th = $table->th_top[$i];
-                                               print $th.$cell."</th>\n";
-                                       }
-                               }
-                               print "</tr>\n";
-                       }
-               }
-       }
-       function print_html_finish(&$table) {
-               print "</table>\n";
-               print_simple_box_end();
-
-               if (isset($table->finish)) {
-                       print $table->finish."\n";
-               }
-       }
+    function print_html_report(&$tables) {
+        $count = count($tables);
+        foreach($tables as $i=>$table) {
+
+            $this->print_html_start($table);
+            $this->print_html_head($table);
+            $this->print_html_data($table);
+            $this->print_html_stat($table);
+            $this->print_html_foot($table);
+            $this->print_html_finish($table);
+
+            if (($i+1)<$count) {
+                print_spacer(30, 10, true);
+            }
+        }
+    }
+    function print_html_start(&$table) {
+
+        // default class for the table
+        if (empty($table->tableclass)) {
+            $table->tableclass = 'generaltable';
+        }
+
+        // default classes for TD and TH
+        $d = $table->tableclass.'cell';
+        $h = $table->tableclass.'header';
+
+        $table->th_side = '<th valign="top" align="right" class="'.$h.'">';
+
+        $table->td = array();
+        $table->th_top = array();
+
+        if (empty($table->colspan)) {
+            if (isset($table->head)) {
+                $table->colspan = count($table->head);
+            } else if (isset($table->data)) {
+                $table->colspan = count($table->data[0]);
+            } else if (isset($table->stat)) {
+                $table->colspan = count($table->stat);
+            } else if (isset($table->foot)) {
+                $table->colspan = count($table->foot);
+            } else {
+                $table->colspan = 0;
+            }
+        }
+
+        for ($i=0; $i<$table->colspan; $i++) {
+
+            $align = empty($table->align[$i]) ? '' : ' align="'.$table->align[$i].'"';
+            $class = empty($table->class[$i]) ? $d : ' class="'.$table->class[$i].'"';
+            $size  = empty($table->size[$i])  ? '' : ' width="'.$table->size[$i].'"';
+            $wrap  = empty($table->wrap[$i])  ? '' : ' nowrap="nowrap"';
+
+            $table->th_top[$i] = '<th align="center"'.$size.' class="'.$h.'" nowrap="nowrap">';
+
+            $table->td[$i] = '<td valign="top"'.$align.$class.$wrap.'>';
+
+            if (!empty($table->fontsize[$i])) {
+                $table->td[$i] .= '<font size="'.$table->fontsize[$i].'">';
+            }
+        }
+
+        if (empty($table->border)) {
+            $table->border = 0;
+        }
+        if (empty($table->cellpadding)) {
+            $table->cellpadding = 5;
+        }
+        if (empty($table->cellspacing)) {
+            $table->cellspacing = 1;
+        }
+        if (empty($table->width)) {
+            $table->width = "80%"; // actually the width of the "simple box"
+        }
+        if (empty($table->tablealign)) {
+            $table->tablealign = "center";
+        }
+
+        if (isset($table->start)) {
+            print $table->start."\n";
+        }
+
+        print_simple_box_start("$table->tablealign", "$table->width", "#ffffff", 0);
+        print '<table width="100%" border="'.$table->border.'" valign="top" align="center"  cellpadding="'.$table->cellpadding.'" cellspacing="'.$table->cellspacing.'" class="'.$table->tableclass.'">'."\n";
+
+        if (isset($table->caption)) {
+            print '<tr><td colspan="'.$table->colspan.'" class="'.$table->tableclass.'header"><b>'.$table->caption.'</b></td></tr>'."\n";
+        }
+
+    }
+    function print_html_head(&$table) {
+        if (isset($table->head)) {
+            print "<tr>\n";
+            foreach ($table->head as $i=>$cell) {
+                $th = $table->th_top[$i];
+                print $th.$cell."</th>\n";
+            }
+            print "</tr>\n";
+        }
+    }
+    function print_html_data(&$table) {
+        if (isset($table->data)) {
+            $skipcol = array();
+            foreach ($table->data as $cells) {
+                print "<tr>\n";
+                if (is_array($cells)) {
+                    $i = 0; // index on $cells
+                    $col = 0; // column index
+                    while ($col<$table->colspan && isset($cells[$i])) {
+                        if (empty($skipcol[$col])) {
+                            $cell = &$cells[$i++]; 
+                            $td = $table->td[$col];
+                            if (is_object($cell)) {
+                                $text = $cell->text;
+                                if (isset($cell->rowspan) && is_numeric($cell->rowspan) && ($cell->rowspan>0)) {
+                                    $td = '<td rowspan="'.$cell->rowspan.'"'.substr($td, 3);
+                                    // skip cells below this one
+                                    $skipcol[$col] = $cell->rowspan-1;
+                                }
+                                if (isset($cell->colspan) && is_numeric($cell->colspan) && ($cell->colspan>0)) {
+                                    $td = '<td colspan="'.$cell->colspan.'"'.substr($td, 3);
+                                    // skip cells to the right of this one
+                                    for ($c=1; $c<$cell->colspan; $c++) {
+                                        if (empty($skipcol[$col+$c])) {
+                                            $skipcol[$col+$c] = 1;
+                                        } else {
+                                            $skipcol[$col+$c] ++;
+                                        }
+                                    }
+                                }
+                            } else { // $cell is a string
+                                $text = $cell;
+                            }
+                            print $td.$text."</td>\n";
+                        } else {
+                            $skipcol[$col]--;
+                        }
+                        $col++;
+                    } // end while
+                } else if ($cells=='hr') {
+                    print '<td colspan="'.$table->colspan.'"><div class="tabledivider"></div></td>'."\n";
+                }
+                print "</tr>\n";
+            }
+        }
+    }
+    function print_html_stat(&$table) {
+        if (isset($table->stat)) {
+            if (empty($table->statheadercols)) {
+                $table->statheadercols = array();
+            }
+            foreach ($table->stat as $cells) {
+                print '<tr>';
+                foreach ($cells as $i => $cell) {
+                    if (in_array($i, $table->statheadercols)) {
+                        $th = $table->th_side;
+                        print $th.$cell."</th>\n";
+                    } else {
+                        $td = $table->td[$i];
+                        print $td.$cell."</td>\n";
+                    }
+                }
+                print "</tr>\n";
+            }
+        }
+    }
+    function print_html_foot(&$table) {
+        if (isset($table->foot)) {
+            foreach ($table->foot as $cells) {
+                print "<tr>\n";
+                foreach ($cells as $i => $cell) {
+                    if ($i==0) {
+                        $th = $table->th_side;
+                        print $th.$cell."</th>\n";
+                    } else {
+                        $th = $table->th_top[$i];
+                        print $th.$cell."</th>\n";
+                    }
+                }
+                print "</tr>\n";
+            }
+        }
+    }
+    function print_html_finish(&$table) {
+        print "</table>\n";
+        print_simple_box_end();
+
+        if (isset($table->finish)) {
+            print $table->finish."\n";
+        }
+    }
 
 //////////////////////////////////////////
 /// print a text report
 
-       function print_text_report(&$course, &$hotpot, &$tables, &$options) {
-               $this->print_text_start($course, $hotpot, $options);
-               foreach ($tables as $table) {
-                       $this->print_text_head($table, $options);
-                       $this->print_text_data($table, $options);
-                       $this->print_text_stat($table, $options);
-                       $this->print_text_foot($table, $options);
-               }
-       }
-       function print_text_start(&$course, &$hotpot, &$options) {
-               $downloadfilename = clean_filename("$course->shortname $hotpot->name.txt");
-               header("Content-Type: application/download\n"); 
-               header("Content-Disposition: attachment; filename=$downloadfilename");
-               header("Expires: 0");
-               header("Cache-Control: must-revalidate, post-check=0,pre-check=0");
-               header("Pragma: public");
-       }
-       function print_text_head(&$table, &$options) {
-               if (isset($table->caption)) {
-                       $i = strlen($table->caption);
-                       $data = array(
-                               array(str_repeat('=', $i)),
-                               array($table->caption),
-                               array(str_repeat('=', $i)),
-                       );
-                       foreach($data as $cells) {
-                               $this->print_text_cells($cells, $options);
-                       }
-               }
-               if (isset($table->head)) {
-                       $this->expand_spans($table, 'head');
-                       $this->print_text_cells($table->head, $options);
-               }
-       }
-       function print_text_data(&$table, &$options) {
-               if (isset($table->data)) {
-                       $this->expand_spans($table, 'data');
-                       foreach ($table->data as $cells) {
-                               $this->print_text_cells($cells, $options);
-                       }
-               }
-       }
-       function print_text_stat(&$table, &$options) {
-               if (isset($table->stat)) {
-                       $this->expand_spans($table, 'stat');
-                       foreach ($table->stat as $cells) {
-                               $this->print_text_cells($cells, $options);
-                       }
-               }
-       }
-       function print_text_foot(&$table, &$options) {
-               if (isset($table->foot)) {
-                       $this->expand_spans($table, 'foot');
-                       foreach ($table->foot as $cells) {
-                               $this->print_text_cells($cells, $options);
-                       }
-               }
-       }
-       function print_text_cells(&$cells, &$options) {
-
-               // do nothing if there are no cells
-               if (empty($cells) || is_string($cells)) return;
-
-               // convert to tab-delimted string
-               $str = implode("\t", $cells);
-
-               // replace newlines in string
-               $str = preg_replace("/\n/", ",", $str);
-
-               // set best newline for this browser (if it hasn't been done already)
-               if (empty($this->nl)) {
-                       $s = &$_SERVER['HTTP_USER_AGENT'];
-                       $win = is_numeric(strpos($s, 'Win'));
-                       $mac = is_numeric(strpos($s, 'Mac')) && !is_numeric(strpos($s, 'OS X'));
-                       $this->nl = $win ? "\r\n" : ($mac ? "\r" : "\n");
-               }
-
-               print $str.$this->nl;
-       }
+    function print_text_report(&$course, &$hotpot, &$tables, &$options) {
+        $this->print_text_start($course, $hotpot, $options);
+        foreach ($tables as $table) {
+            $this->print_text_head($table, $options);
+            $this->print_text_data($table, $options);
+            $this->print_text_stat($table, $options);
+            $this->print_text_foot($table, $options);
+        }
+    }
+    function print_text_start(&$course, &$hotpot, &$options) {
+        $downloadfilename = clean_filename("$course->shortname $hotpot->name.txt");
+        header("Content-Type: application/download\n"); 
+        header("Content-Disposition: attachment; filename=$downloadfilename");
+        header("Expires: 0");
+        header("Cache-Control: must-revalidate, post-check=0,pre-check=0");
+        header("Pragma: public");
+    }
+    function print_text_head(&$table, &$options) {
+        if (isset($table->caption)) {
+            $i = strlen($table->caption);
+            $data = array(
+                array(str_repeat('=', $i)),
+                array($table->caption),
+                array(str_repeat('=', $i)),
+            );
+            foreach($data as $cells) {
+                $this->print_text_cells($cells, $options);
+            }
+        }
+        if (isset($table->head)) {
+            $this->expand_spans($table, 'head');
+            $this->print_text_cells($table->head, $options);
+        }
+    }
+    function print_text_data(&$table, &$options) {
+        if (isset($table->data)) {
+            $this->expand_spans($table, 'data');
+            foreach ($table->data as $cells) {
+                $this->print_text_cells($cells, $options);
+            }
+        }
+    }
+    function print_text_stat(&$table, &$options) {
+        if (isset($table->stat)) {
+            $this->expand_spans($table, 'stat');
+            foreach ($table->stat as $cells) {
+                $this->print_text_cells($cells, $options);
+            }
+        }
+    }
+    function print_text_foot(&$table, &$options) {
+        if (isset($table->foot)) {
+            $this->expand_spans($table, 'foot');
+            foreach ($table->foot as $cells) {
+                $this->print_text_cells($cells, $options);
+            }
+        }
+    }
+    function print_text_cells(&$cells, &$options) {
+
+        // do nothing if there are no cells
+        if (empty($cells) || is_string($cells)) return;
+
+        // convert to tab-delimted string
+        $str = implode("\t", $cells);
+
+        // replace newlines in string
+        $str = preg_replace("/\n/", ",", $str);
+
+        // set best newline for this browser (if it hasn't been done already)
+        if (empty($this->nl)) {
+            $s = &$_SERVER['HTTP_USER_AGENT'];
+            $win = is_numeric(strpos($s, 'Win'));
+            $mac = is_numeric(strpos($s, 'Mac')) && !is_numeric(strpos($s, 'OS X'));
+            $this->nl = $win ? "\r\n" : ($mac ? "\r" : "\n");
+        }
+
+        print $str.$this->nl;
+    }
 
 //////////////////////////////////////////
 /// print an Excel report
 
-       function print_excel_report(&$course, &$hotpot, &$tables, &$options) {
-               global $CFG;
-
-               // create Excel workbook
-               if (file_exists("$CFG->libdir/excellib.class.php")) {
-                       // Moodle >= 1.6
-                       require_once("$CFG->libdir/excellib.class.php");
-                       $wb = new MoodleExcelWorkbook("-");
-               } else {
-                       // Moodle <= 1.5
-                       require_once("$CFG->libdir/excel/Worksheet.php");
-                       require_once("$CFG->libdir/excel/Workbook.php");
-                       $wb = new Workbook("-");
-               }
-
-               // send HTTP headers
-               $this->print_excel_headers($wb, $course, $hotpot);
-
-               // create one worksheet for each table
-               foreach($tables as $table) {
-                       unset($ws);
-                       $ws = &$wb->add_worksheet(empty($table->caption) ? '' : strip_tags($table->caption)); 
-
-                       $row = 0;
-                       $this->print_excel_head($wb, $ws, $table, $row, $options);
-                       $this->print_excel_data($wb, $ws, $table, $row, $options);
-                       $this->print_excel_stat($wb, $ws, $table, $row, $options);
-                       $this->print_excel_foot($wb, $ws, $table, $row, $options);
-               }
-       
-               // close the workbook (and send it to the browser)
-               $wb->close();
-       }
-       function print_excel_headers(&$wb, &$course, &$hotpot) {
-               $downloadfilename = clean_filename("$course->shortname $hotpot->name.xls");
-               if (method_exists($wb, 'send')) {
-                       // Moodle >=1.6
-                       $wb->send($downloadfilename);
-               } else {
-                       // Moodle <=1.5
-                       header("Content-type: application/vnd.ms-excel");
-                       header("Content-Disposition: attachment; filename=$downloadfilename" );
-                       header("Expires: 0");
-                       header("Cache-Control: must-revalidate, post-check=0,pre-check=0");
-                       header("Pragma: public");
-               }
-       }
-       function print_excel_head(&$wb, &$ws, &$table, &$row, &$options) {
-               // define format properties
-               $properties = array(
-                       'bold'=>1, 
-                       'align'=>'center', 
-                       'v_align'=>'bottom',
-                       'text_wrap'=>1
-               );
-
-               // expand multi-column and multi-row cells
-               $this->expand_spans($table, 'head');
-
-               // print the headings
-               $this->print_excel_cells($wb, $ws, $table, $row, $properties, $table->head, $options);
-       }
-       function print_excel_data(&$wb, &$ws, &$table, &$row, &$options) {
-               // do nothing if there are no cells
-               if (empty($table->data)) return;
-
-               // define format properties
-               $properties = array('text_wrap' => (empty($options['reportwrapdata']) ? 0 : 1));
-
-               // expand multi-column and multi-row cells
-               $this->expand_spans($table, 'data');
-
-               // print rows
-               foreach ($table->data as $cells) {
-                       $this->print_excel_cells($wb, $ws, $table, $row, $properties, $cells, $options);
-               }
-       }
-       function print_excel_stat(&$wb, &$ws, &$table, &$row, &$options) {
-               // do nothing if there are no cells
-               if (empty($table->stat)) return;
-
-               // define format properties
-               $properties = array('align'=>'right');
-
-               // expand multi-column and multi-row cells
-               $this->expand_spans($table, 'stat');
-
-               // print rows
-               $i_count = count($table->stat);
-               foreach ($table->stat as $i => $cells) {
-
-                       // set border on top and bottom row
-                       $properties['top'] = ($i==0) ? 1 : 0;
-                       $properties['bottom'] = ($i==($i_count-1)) ? 1 : 0;
-
-                       // print this row
-                       $this->print_excel_cells($wb, $ws, $table, $row, $properties, $cells, $options, $table->statheadercols);
-               }
-       }
-       function print_excel_foot(&$wb, &$ws, &$table, &$row, &$options) {
-               // do nothing if there are no cells
-               if (empty($table->foot)) return;
-
-               // define format properties
-               $properties = array('bold'=>1, 'align'=>'center');
-
-               // expand multi-column and multi-row cells
-               $this->expand_spans($table, 'foot');
-
-               // print rows
-               $i_count = count($table->foot);
-               foreach ($table->foot as $i => $cells) {
-
-                       // set border on top and bottom row
-                       $properties['top'] = ($i==0) ? 1 : 0;
-                       $properties['bottom'] = ($i==($i_count-1)) ? 1 : 0;
-
-                       // print this footer row
-                       $this->print_excel_cells($wb, $ws, $table, $row, $properties, $cells, $options);
-               }
-       }
-
-       function print_excel_cells(&$wb, &$ws, &$table, &$row, &$properties, &$cells, &$options, $statheadercols=NULL) {
-               // do nothing if there are no cells
-               if (empty($cells) || is_string($cells)) return;
-
-               // print cells
-               foreach($cells as $col => $cell) {
-
-                       unset($fmt_properties);
-                       $fmt_properties = $properties;
-
-                       if (empty($fmt_properties['text_wrap'])) {
-                               if (strlen("$cell")>=9) {
-                                       // long cell value
-                                       $fmt_properties['align'] = 'left';
-                               }
-                       } else {
-                               if (strlen("$cell")<9 && strpos("$cell", "\n")===false) {
-                                       // short cell value (wrapping not required)
-                                       $fmt_properties['text_wrap'] = 0;
-                               }
-                       }
-
-                       // set bold, if required (for stat)
-                       if (isset($statheadercols)) {
-                               $fmt_properties['bold'] = in_array($col, $statheadercols) ? 1 : 0;
-                               $fmt_properties['align'] = in_array($col, $statheadercols) ? 'right' : $table->align[$col];
-                       }
-
-                       // set align, if required
-                       if (isset($table->align[$col]) && empty($fmt_properties['align'])) {
-                               $fmt_properties['align'] =  $table->align[$col];
-                       }
-
-                       // check to see that an identical format object has not already been created
-                       unset($fmt);
-
-                       if (isset($wb->pear_excel_workbook)) {
-                               // Moodle >=1.6
-                               $fmt_properties_obj = (object)$fmt_properties;
-                               foreach ($wb->pear_excel_workbook->_formats as $id=>$format) {
-                                       if ($format==$fmt_properties_obj) {
-                                               $fmt = &$wb->pear_excel_workbook->_formats[$id];
-                                               break;
-                                       }
-                               }
-                       } else {
-                               // Moodle <=1.5
-                               foreach ($wb->formats as $id=>$format) {
-                                       if (isset($format->properties) && $format->properties==$fmt_properties) {
-                                               $fmt = &$wb->formats[$id];
-                                               break;
-                                       }
-                               }
-                               if (is_numeric($cell) || empty($options['reportencoding'])) {
-                                       // do nothing
-                               } else {
-                                       $in_charset = '';
-                                       if (function_exists('mb_convert_encoding')) {
-                                               $in_charset = mb_detect_encoding($cell, 'auto');
-                                       }
-                                       if (empty($in_charset)) {
-                                               $in_charset = get_string('thischarset');
-                                       }
-                                       if ($in_charset != 'ASCII' && function_exists('mb_convert_encoding')) {
-                                               $cell = mb_convert_encoding($cell, $options['reportencoding'], $in_charset);
-                                       }
-                               }
-                       }
-
-                       // create new format object, if necessary (to avoid "too many cell formats" error)
-                       if (!isset($fmt)) {
-                               $fmt = &$wb->add_format($fmt_properties);
-                               $fmt->properties = &$fmt_properties;
-
-                               // set vertical alignment
-                               if (isset($fmt->properties['v_align'])) {
-                                       $fmt->set_align($fmt->properties['v_align']);
-                               } else {
-                                       $fmt->set_align('top'); // default
-                               }
-                       }
-
-                       // write cell
-                       if (is_numeric($cell) && !preg_match("/^0./", $cell)) {
-                               $ws->write_number($row, $col, $cell, $fmt);
-                       } else {
-                               $ws->write_string($row, $col, $cell, $fmt);
-                       }
-               } // end foreach $col
-
-               // increment $row
-               $row++;
-       }
+    function print_excel_report(&$course, &$hotpot, &$tables, &$options) {
+        global $CFG;
+
+        // create Excel workbook
+        if (file_exists("$CFG->libdir/excellib.class.php")) {
+            // Moodle >= 1.6
+            require_once("$CFG->libdir/excellib.class.php");
+            $wb = new MoodleExcelWorkbook("-");
+        } else {
+            // Moodle <= 1.5
+            require_once("$CFG->libdir/excel/Worksheet.php");
+            require_once("$CFG->libdir/excel/Workbook.php");
+            $wb = new Workbook("-");
+        }
+
+        // send HTTP headers
+        $this->print_excel_headers($wb, $course, $hotpot);
+
+        // create one worksheet for each table
+        foreach($tables as $table) {
+            unset($ws);
+            $ws = &$wb->add_worksheet(empty($table->caption) ? '' : strip_tags($table->caption)); 
+
+            $row = 0;
+            $this->print_excel_head($wb, $ws, $table, $row, $options);
+            $this->print_excel_data($wb, $ws, $table, $row, $options);
+            $this->print_excel_stat($wb, $ws, $table, $row, $options);
+            $this->print_excel_foot($wb, $ws, $table, $row, $options);
+        }
+    
+        // close the workbook (and send it to the browser)
+        $wb->close();
+    }
+    function print_excel_headers(&$wb, &$course, &$hotpot) {
+        $downloadfilename = clean_filename("$course->shortname $hotpot->name.xls");
+        if (method_exists($wb, 'send')) {
+            // Moodle >=1.6
+            $wb->send($downloadfilename);
+        } else {
+            // Moodle <=1.5
+            header("Content-type: application/vnd.ms-excel");
+            header("Content-Disposition: attachment; filename=$downloadfilename" );
+            header("Expires: 0");
+            header("Cache-Control: must-revalidate, post-check=0,pre-check=0");
+            header("Pragma: public");
+        }
+    }
+    function print_excel_head(&$wb, &$ws, &$table, &$row, &$options) {
+        // define format properties
+        $properties = array(
+            'bold'=>1, 
+            'align'=>'center', 
+            'v_align'=>'bottom',
+            'text_wrap'=>1
+        );
+
+        // expand multi-column and multi-row cells
+        $this->expand_spans($table, 'head');
+
+        // print the headings
+        $this->print_excel_cells($wb, $ws, $table, $row, $properties, $table->head, $options);
+    }
+    function print_excel_data(&$wb, &$ws, &$table, &$row, &$options) {
+        // do nothing if there are no cells
+        if (empty($table->data)) return;
+
+        // define format properties
+        $properties = array('text_wrap' => (empty($options['reportwrapdata']) ? 0 : 1));
+
+        // expand multi-column and multi-row cells
+        $this->expand_spans($table, 'data');
+
+        // print rows
+        foreach ($table->data as $cells) {
+            $this->print_excel_cells($wb, $ws, $table, $row, $properties, $cells, $options);
+        }
+    }
+    function print_excel_stat(&$wb, &$ws, &$table, &$row, &$options) {
+        // do nothing if there are no cells
+        if (empty($table->stat)) return;
+
+        // define format properties
+        $properties = array('align'=>'right');
+
+        // expand multi-column and multi-row cells
+        $this->expand_spans($table, 'stat');
+
+        // print rows
+        $i_count = count($table->stat);
+        foreach ($table->stat as $i => $cells) {
+
+            // set border on top and bottom row
+            $properties['top'] = ($i==0) ? 1 : 0;
+            $properties['bottom'] = ($i==($i_count-1)) ? 1 : 0;
+
+            // print this row
+            $this->print_excel_cells($wb, $ws, $table, $row, $properties, $cells, $options, $table->statheadercols);
+        }
+    }
+    function print_excel_foot(&$wb, &$ws, &$table, &$row, &$options) {
+        // do nothing if there are no cells
+        if (empty($table->foot)) return;
+
+        // define format properties
+        $properties = array('bold'=>1, 'align'=>'center');
+
+        // expand multi-column and multi-row cells
+        $this->expand_spans($table, 'foot');
+
+        // print rows
+        $i_count = count($table->foot);
+        foreach ($table->foot as $i => $cells) {
+
+            // set border on top and bottom row
+            $properties['top'] = ($i==0) ? 1 : 0;
+            $properties['bottom'] = ($i==($i_count-1)) ? 1 : 0;
+
+            // print this footer row
+            $this->print_excel_cells($wb, $ws, $table, $row, $properties, $cells, $options);
+        }
+    }
+
+    function print_excel_cells(&$wb, &$ws, &$table, &$row, &$properties, &$cells, &$options, $statheadercols=NULL) {
+        // do nothing if there are no cells
+        if (empty($cells) || is_string($cells)) return;
+
+        // print cells
+        foreach($cells as $col => $cell) {
+
+            unset($fmt_properties);
+            $fmt_properties = $properties;
+
+            if (empty($fmt_properties['text_wrap'])) {
+                if (strlen("$cell")>=9) {
+                    // long cell value
+                    $fmt_properties['align'] = 'left';
+                }
+            } else {
+                if (strlen("$cell")<9 && strpos("$cell", "\n")===false) {
+                    // short cell value (wrapping not required)
+                    $fmt_properties['text_wrap'] = 0;
+                }
+            }
+
+            // set bold, if required (for stat)
+            if (isset($statheadercols)) {
+                $fmt_properties['bold'] = in_array($col, $statheadercols) ? 1 : 0;
+                $fmt_properties['align'] = in_array($col, $statheadercols) ? 'right' : $table->align[$col];
+            }
+
+            // set align, if required
+            if (isset($table->align[$col]) && empty($fmt_properties['align'])) {
+                $fmt_properties['align'] =  $table->align[$col];
+            }
+
+            // check to see that an identical format object has not already been created
+            unset($fmt);
+
+            if (isset($wb->pear_excel_workbook)) {
+                // Moodle >=1.6
+                $fmt_properties_obj = (object)$fmt_properties;
+                foreach ($wb->pear_excel_workbook->_formats as $id=>$format) {
+                    if ($format==$fmt_properties_obj) {
+                        $fmt = &$wb->pear_excel_workbook->_formats[$id];
+                        break;
+                    }
+                }
+            } else {
+                // Moodle <=1.5
+                foreach ($wb->formats as $id=>$format) {
+                    if (isset($format->properties) && $format->properties==$fmt_properties) {
+                        $fmt = &$wb->formats[$id];
+                        break;
+                    }
+                }
+                if (is_numeric($cell) || empty($options['reportencoding'])) {
+                    // do nothing
+                } else {
+                    $in_charset = '';
+                    if (function_exists('mb_convert_encoding')) {
+                        $in_charset = mb_detect_encoding($cell, 'auto');
+                    }
+                    if (empty($in_charset)) {
+                        $in_charset = get_string('thischarset');
+                    }
+                    if ($in_charset != 'ASCII' && function_exists('mb_convert_encoding')) {
+                        $cell = mb_convert_encoding($cell, $options['reportencoding'], $in_charset);
+                    }
+                }
+            }
+
+            // create new format object, if necessary (to avoid "too many cell formats" error)
+            if (!isset($fmt)) {
+                $fmt = &$wb->add_format($fmt_properties);
+                $fmt->properties = &$fmt_properties;
+
+                // set vertical alignment
+                if (isset($fmt->properties['v_align'])) {
+                    $fmt->set_align($fmt->properties['v_align']);
+                } else {
+                    $fmt->set_align('top'); // default
+                }
+            }
+
+            // write cell
+            if (is_numeric($cell) && !preg_match("/^0./", $cell)) {
+                $ws->write_number($row, $col, $cell, $fmt);
+            } else {
+                $ws->write_string($row, $col, $cell, $fmt);
+            }
+        } // end foreach $col
+
+        // increment $row
+        $row++;
+    }
 }
 
 ?>
index 8d2b8fcad89ea8a7b1dfd5adb3c2b173ff895812..06f1169654a70552f3b4c0995262298b8ee209f6 100644 (file)
 <?PHP // $Id$
 // This page prints a review of a particular quiz attempt
-       require_once("../../config.php");
-       require_once("lib.php");
-       $id = optional_param("id"); // Course Module ID, or
-       $hp = optional_param("hp"); // hotpot ID
-       $attempt = required_param("attempt"); // A particular attempt ID for review
-       if ($id) {
-               if (! $cm = get_coursemodule_from_id('hotpot', $id)) {
-                       error("Course Module ID was incorrect");
-               }
-               if (! $course = get_record("course", "id", $cm->course)) {
-                       error("Course is misconfigured");
-               }
-               if (! $hotpot = get_record("hotpot", "id", $cm->instance)) {
-                       error("Course module is incorrect");
-               }
-       } else {
-               if (! $hotpot = get_record("hotpot", "id", $hp)) {
-                       error("Course module is incorrect");
-               }
-               if (! $course = get_record("course", "id", $hotpot->course)) {
-                       error("Course is misconfigured");
-               }
-               if (! $cm = get_coursemodule_from_instance("hotpot", $hotpot->id, $course->id)) {
-                       error("Course Module ID was incorrect");
-               }
-       }
-       if (! $attempt = get_record("hotpot_attempts", "id", $attempt)) {
-               error("Attempt ID was incorrect");
-       }
-       require_login($course->id);
-       if (!isteacher($course->id)) {
-               if (!$hotpot->review) {
-                       error(get_string("noreview", "quiz"));
-               }
-               //if (time() < $hotpot->timeclose) {
-               //      error(get_string("noreviewuntil", "quiz", userdate($hotpot->timeclose)));
-               //}
-               if ($attempt->userid != $USER->id) {
-                       error("This is not your attempt!");
-               }
-       }
-       add_to_log($course->id, "hotpot", "review", "review.php?id=$cm->id&attempt=$attempt->id", "$hotpot->id", "$cm->id");
+    require_once("../../config.php");
+    require_once("lib.php");
+    $id = optional_param("id"); // Course Module ID, or
+    $hp = optional_param("hp"); // hotpot ID
+    $attempt = required_param("attempt"); // A particular attempt ID for review
+    if ($id) {
+        if (! $cm = get_coursemodule_from_id('hotpot', $id)) {
+            error("Course Module ID was incorrect");
+        }
+        if (! $course = get_record("course", "id", $cm->course)) {
+            error("Course is misconfigured");
+        }
+        if (! $hotpot = get_record("hotpot", "id", $cm->instance)) {
+            error("Course module is incorrect");
+        }
+    } else {
+        if (! $hotpot = get_record("hotpot", "id", $hp)) {
+            error("Course module is incorrect");
+        }
+        if (! $course = get_record("course", "id", $hotpot->course)) {
+            error("Course is misconfigured");
+        }
+        if (! $cm = get_coursemodule_from_instance("hotpot", $hotpot->id, $course->id)) {
+            error("Course Module ID was incorrect");
+        }
+    }
+    if (! $attempt = get_record("hotpot_attempts", "id", $attempt)) {
+        error("Attempt ID was incorrect");
+    }
+    require_login($course->id);
+    if (!isteacher($course->id)) {
+        if (!$hotpot->review) {
+            error(get_string("noreview", "quiz"));
+        }
+        //if (time() < $hotpot->timeclose) {
+        //  error(get_string("noreviewuntil", "quiz", userdate($hotpot->timeclose)));
+        //}
+        if ($attempt->userid != $USER->id) {
+            error("This is not your attempt!");
+        }
+    }
+    add_to_log($course->id, "hotpot", "review", "review.php?id=$cm->id&attempt=$attempt->id", "$hotpot->id", "$cm->id");
 // Print the page header
-       $strmodulenameplural = get_string("modulenameplural", "hotpot");
-       $strmodulename  = get_string("modulename", "hotpot");
-       // print header
-       $title = "$course->shortname: $hotpot->name";
-       $heading = "$course->fullname";
-       $navigation = "<a href=\"index.php?id=$course->id\">$strmodulenameplural</a> -> ".get_string("review", "quiz");
-       if ($course->category) {
-               $navigation = "<a href=\"../../course/view.php?id=$course->id\">$course->shortname</a> -> $navigation";
-       }
-       $button = update_module_button($cm->id, $course->id, $strmodulename);
-       print_header($title, $heading, $navigation, "", "", true, $button, navmenu($course, $cm));
-       print '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>'; // for overlib
-       print_heading($hotpot->name);
-       hotpot_print_attempt_summary($hotpot, $attempt);
-       hotpot_print_review_buttons($course, $hotpot, $attempt);
-       $action = isteacher($course->id) ? optional_param('action') : '';
-       if ($action) {
-               $xml = get_field('hotpot_details', 'details', 'attempt', $attempt->id);
-               print '<hr>';
-               switch ($action) {
-                       case 'showxmltree':
-                               print '<pre id="contents">';
-                               $xml_tree = new hotpot_xml_tree($xml, "['hpjsresult']['#']");
-                               print_r ($xml_tree->xml_value('fields'));
-                               print '</pre>';
-                               break;
-                       case 'showxmlsource':
-                               print htmlspecialchars($xml);
-                               break;
-                       default:
-                               print "Action '$action' not recognized";
-               }
-               print '<hr>';
-       } else {
-               hotpot_print_attempt_details($hotpot, $attempt);
-       }
-       hotpot_print_review_buttons($course, $hotpot, $attempt);
-       print_footer($course);
+    $strmodulenameplural = get_string("modulenameplural", "hotpot");
+    $strmodulename  = get_string("modulename", "hotpot");
+    // print header
+    $title = "$course->shortname: $hotpot->name";
+    $heading = "$course->fullname";
+    $navigation = "<a href=\"index.php?id=$course->id\">$strmodulenameplural</a> -> ".get_string("review", "quiz");
+    if ($course->category) {
+        $navigation = "<a href=\"../../course/view.php?id=$course->id\">$course->shortname</a> -> $navigation";
+    }
+    $button = update_module_button($cm->id, $course->id, $strmodulename);
+    print_header($title, $heading, $navigation, "", "", true, $button, navmenu($course, $cm));
+    print '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:1000;"></div>'; // for overlib
+    print_heading($hotpot->name);
+    hotpot_print_attempt_summary($hotpot, $attempt);
+    hotpot_print_review_buttons($course, $hotpot, $attempt);
+    $action = isteacher($course->id) ? optional_param('action') : '';
+    if ($action) {
+        $xml = get_field('hotpot_details', 'details', 'attempt', $attempt->id);
+        print '<hr>';
+        switch ($action) {
+            case 'showxmltree':
+                print '<pre id="contents">';
+                $xml_tree = new hotpot_xml_tree($xml, "['hpjsresult']['#']");
+                print_r ($xml_tree->xml_value('fields'));
+                print '</pre>';
+                break;
+            case 'showxmlsource':
+                print htmlspecialchars($xml);
+                break;
+            default:
+                print "Action '$action' not recognized";
+        }
+        print '<hr>';
+    } else {
+        hotpot_print_attempt_details($hotpot, $attempt);
+    }
+    hotpot_print_review_buttons($course, $hotpot, $attempt);
+    print_footer($course);
 ///////////////////////////
 //    functions
 ///////////////////////////
 function hotpot_print_attempt_summary(&$hotpot, &$attempt) {
-       // start table
-       print_simple_box_start("center", "80%", "#ffffff", 0);
-       print '<table width="100%" border="1" valign="top" align="center" cellpadding="2" cellspacing="2" class="generaltable">'."\n";
-       // add attempt properties
-       $fields = array('attempt', 'score', 'penalties', 'status', 'timetaken', 'timerecorded');
-       foreach ($fields as $field) {
-               switch ($field) {
-                       case 'score':
-                               $value = hotpot_format_score($attempt);
-                               break;
-                       case 'status':
-                               $value = hotpot_format_status($attempt);
-                               break;
-                       case 'timerecorded':
-                               $value = empty($attempt->timefinish) ? '-' : userdate($attempt->timefinish); 
-                               break;
-                       case 'timetaken':
-                               $value = empty($attempt->timefinish) ? '-' : format_time($attempt->timefinish - $attempt->timestart); 
-                               break;
-                       default:
-                               $value = isset($attempt->$field) ? $attempt->$field : NULL;
-               }
-               if (isset($value)) {
-                       switch ($field) {
-                               case 'status':
-                               case 'timerecorded':
-                                       $name = get_string('report'.$field, 'hotpot');
-                                       break;
-                               case 'penalties':
-                                       $name = get_string('penalties', 'hotpot');
-                                       break;
-                               default:
-                                       $name = get_string($field, 'quiz');
-                       }
-                       print '<tr><th align="right" width="100" class="generaltableheader">'.$name.':</th><td class="generaltablecell">'.$value.'</td></tr>';
-               }
-       }
-       // finish table
-       print '</table>';
-       print_simple_box_end();
+    // start table
+    print_simple_box_start("center", "80%", "#ffffff", 0);
+    print '<table width="100%" border="1" valign="top" align="center" cellpadding="2" cellspacing="2" class="generaltable">'."\n";
+    // add attempt properties
+    $fields = array('attempt', 'score', 'penalties', 'status', 'timetaken', 'timerecorded');
+    foreach ($fields as $field) {
+        switch ($field) {
+            case 'score':
+                $value = hotpot_format_score($attempt);
+                break;
+            case 'status':
+                $value = hotpot_format_status($attempt);
+                break;
+            case 'timerecorded':
+                $value = empty($attempt->timefinish) ? '-' : userdate($attempt->timefinish); 
+                break;
+            case 'timetaken':
+                $value = empty($attempt->timefinish) ? '-' : format_time($attempt->timefinish - $attempt->timestart); 
+                break;
+            default:
+                $value = isset($attempt->$field) ? $attempt->$field : NULL;
+        }
+        if (isset($value)) {
+            switch ($field) {
+                case 'status':
+                case 'timerecorded':
+                    $name = get_string('report'.$field, 'hotpot');
+                    break;
+                case 'penalties':
+                    $name = get_string('penalties', 'hotpot');
+                    break;
+                default:
+                    $name = get_string($field, 'quiz');
+            }
+            print '<tr><th align="right" width="100" class="generaltableheader">'.$name.':</th><td class="generaltablecell">'.$value.'</td></tr>';
+        }
+    }
+    // finish table
+    print '</table>';
+    print_simple_box_end();
 }
 function hotpot_print_review_buttons(&$course, &$hotpot, &$attempt) {
-       print "\n".'<table border="0" align="center" cellpadding="2" cellspacing="2" class="generaltable">';
-       print "\n<tr>\n".'<td align="center">';
-       print_single_button("report.php?hp=$hotpot->id", NULL, get_string('continue'), 'post');
-       if (isteacher($course->id) && record_exists('hotpot_details', 'attempt', $attempt->id)) {
-               print "</td>\n".'<td align="center">';
-               print_single_button("review.php?hp=$hotpot->id&attempt=$attempt->id&action=showxmlsource", NULL, get_string('showxmlsource', 'hotpot'), 'post');
-               print "</td>\n".'<td align="center">';
-               print_single_button("review.php?hp=$hotpot->id&attempt=$attempt->id&action=showxmltree", NULL, get_string('showxmltree', 'hotpot'), 'post');
-               $colspan = 3;
-       } else {
-               $colspan = 1;
-       }
-       print "</td>\n</tr>\n";
-       print '<tr><td colspan="'.$colspan.'">';
-       print_spacer(4, 1, false); // height=4, width=1, no <br />
-       print "</td></tr>\n";
-       print "</table>\n";
+    print "\n".'<table border="0" align="center" cellpadding="2" cellspacing="2" class="generaltable">';
+    print "\n<tr>\n".'<td align="center">';
+    print_single_button("report.php?hp=$hotpot->id", NULL, get_string('continue'), 'post');
+    if (isteacher($course->id) && record_exists('hotpot_details', 'attempt', $attempt->id)) {
+        print "</td>\n".'<td align="center">';
+        print_single_button("review.php?hp=$hotpot->id&attempt=$attempt->id&action=showxmlsource", NULL, get_string('showxmlsource', 'hotpot'), 'post');
+        print "</td>\n".'<td align="center">';
+        print_single_button("review.php?hp=$hotpot->id&attempt=$attempt->id&action=showxmltree", NULL, get_string('showxmltree', 'hotpot'), 'post');
+        $colspan = 3;
+    } else {
+        $colspan = 1;
+    }
+    print "</td>\n</tr>\n";
+    print '<tr><td colspan="'.$colspan.'">';
+    print_spacer(4, 1, false); // height=4, width=1, no <br />
+    print "</td></tr>\n";
+    print "</table>\n";
 }
 function hotpot_print_attempt_details(&$hotpot, &$attempt) {
-       // define fields to print
-       $textfields = array('correct', 'ignored', 'wrong');
-       $numfields = array('score', 'weighting', 'hints', 'clues', 'checks');
-       $fields = array_merge($textfields, $numfields);
-       $q = array(); // questions
-       $f = array(); // fields
-       foreach ($fields as $field) {
-               $name = get_string($field, 'hotpot');
-               $f[$field] = array('count'=>0, 'name'=>$name);
-       }
-       // get questions and responses for this attempt
-       $questions = get_records_select('hotpot_questions', "hotpot='$hotpot->id'", 'id');
-       $responses = get_records_select('hotpot_responses', "attempt='$attempt->id'", 'id');
-       if ($questions && $responses) {
-               foreach ($responses as $response) {
-                       $id = $response->question;
-                       foreach ($fields as $field) {
-                               if (!isset($f[$field])) {
-                                       $name = get_string($field, 'hotpot');
-                                       $f[$field] = array('count'=>0, 'name'=>$name);
-                               }
-                               if (isset($response->$field)) {
-                                       $f[$field]['count']++;
-                                       if (!isset($q[$id])) {
-                                               $name = hotpot_get_question_name($questions[$id]);
-                                               $q[$id] = array('name'=>$name);
-                                       }
-                                       $q[$id][$field] = $response->$field;
-                               }
-                       }
-               }
-       }
-       // count the number of columns required in the table
-       $colspan = 0;
-       foreach ($numfields as $field) {
-               if ($f[$field]['count']) {
-                       $colspan += 2;
-               }
-       }
-       $colspan = max(2, $colspan);
-       // start table of questions and responses
-       print_simple_box_start("center", "80%", "#ffffff", 0);
-       print '<table width="100%" border="1" valign="top" align="center" cellpadding="2" cellspacing="2" class="generaltable">'."\n";
-       if (empty($q)) {
-               print '<tr><td align="center" class="generaltablecell"><b>'.get_string("noresponses", "hotpot")."</b></td></tr>\n";
-       } else {
-               // flag to ensure separators are only printed before the 2nd and subsequent questions
-               $printseparator = false;
-               foreach ($q as $i=>$question) {
-                       // flag to ensure questions are only printed when there is at least one response
-                       $printedquestion = false;
-                       // add rows of text fields
-                       foreach ($textfields as $field) {
-                               if (isset($question[$field])) {
-                                       $text = hotpot_strings($question[$field]);
-                                       if (trim($text)) {
-                                               // print question if necessary
-                                               if (!$printedquestion) {
-                                                       if ($printseparator) {
-                                                               print '<tr><td colspan="'.$colspan.'"><div class="tabledivider"></div></td></tr>'."\n";
-                                                       }
-                                                       $printseparator = true;
-                                                       print '<tr><td colspan="'.$colspan.'" class="generaltablecell"><b>'.$question['name'].'</b></td></tr>'."\n";
-                                                       $printedquestion = true;
-                                               }
-                                               // print response
-                                               print '<tr><th align="right" width="100" class="generaltableheader">'.$f[$field]['name'].':</th><td colspan="'.($colspan-1).'" class="generaltablecell">'.$text.'</td></tr>'."\n";
-                                       }
-                               }
-                       }
-                       // add row of numeric fields
-                       print '<tr>';
-                       foreach ($numfields as $field) {
-                               if ($f[$field]['count']) {
-                                       // print question if necessary
-                                       if (!$printedquestion) {
-                                               print '<td colspan="'.$colspan.'" class="generaltablecell"><b>'.$question['name']."</b></td></tr>\n<tr>";
-                                               $printedquestion = true;
-                                       }
-                                       // print numeric response
-                                       $value = isset($question[$field]) ? $question[$field] : '-';
-                                       print '<th align="right" width="100" class="generaltableheader">'.$f[$field]['name'].':</th><td class="generaltablecell">'.$value.'</td>';
-                               }
-                       }
-                       print "</tr>\n";
-               } // foreach $q
-       }
-       // finish table
-       print "</table>\n";
-       print_simple_box_end();
+    // define fields to print
+    $textfields = array('correct', 'ignored', 'wrong');
+    $numfields = array('score', 'weighting', 'hints', 'clues', 'checks');
+    $fields = array_merge($textfields, $numfields);
+    $q = array(); // questions
+    $f = array(); // fields
+    foreach ($fields as $field) {
+        $name = get_string($field, 'hotpot');
+        $f[$field] = array('count'=>0, 'name'=>$name);
+    }
+    // get questions and responses for this attempt
+    $questions = get_records_select('hotpot_questions', "hotpot='$hotpot->id'", 'id');
+    $responses = get_records_select('hotpot_responses', "attempt='$attempt->id'", 'id');
+    if ($questions && $responses) {
+        foreach ($responses as $response) {
+            $id = $response->question;
+            foreach ($fields as $field) {
+                if (!isset($f[$field])) {
+                    $name = get_string($field, 'hotpot');
+                    $f[$field] = array('count'=>0, 'name'=>$name);
+                }
+                if (isset($response->$field)) {
+                    $f[$field]['count']++;
+                    if (!isset($q[$id])) {
+                        $name = hotpot_get_question_name($questions[$id]);
+                        $q[$id] = array('name'=>$name);
+                    }
+                    $q[$id][$field] = $response->$field;
+                }
+            }
+        }
+    }
+    // count the number of columns required in the table
+    $colspan = 0;
+    foreach ($numfields as $field) {
+        if ($f[$field]['count']) {
+            $colspan += 2;
+        }
+    }
+    $colspan = max(2, $colspan);
+    // start table of questions and responses
+    print_simple_box_start("center", "80%", "#ffffff", 0);
+    print '<table width="100%" border="1" valign="top" align="center" cellpadding="2" cellspacing="2" class="generaltable">'."\n";
+    if (empty($q)) {
+        print '<tr><td align="center" class="generaltablecell"><b>'.get_string("noresponses", "hotpot")."</b></td></tr>\n";
+    } else {
+        // flag to ensure separators are only printed before the 2nd and subsequent questions
+        $printseparator = false;
+        foreach ($q as $i=>$question) {
+            // flag to ensure questions are only printed when there is at least one response
+            $printedquestion = false;
+            // add rows of text fields
+            foreach ($textfields as $field) {
+                if (isset($question[$field])) {
+                    $text = hotpot_strings($question[$field]);
+                    if (trim($text)) {
+                        // print question if necessary
+                        if (!$printedquestion) {
+                            if ($printseparator) {
+                                print '<tr><td colspan="'.$colspan.'"><div class="tabledivider"></div></td></tr>'."\n";
+                            }
+                            $printseparator = true;
+                            print '<tr><td colspan="'.$colspan.'" class="generaltablecell"><b>'.$question['name'].'</b></td></tr>'."\n";
+                            $printedquestion = true;
+                        }
+                        // print response
+                        print '<tr><th align="right" width="100" class="generaltableheader">'.$f[$field]['name'].':</th><td colspan="'.($colspan-1).'" class="generaltablecell">'.$text.'</td></tr>'."\n";
+                    }
+                }
+            }
+            // add row of numeric fields
+            print '<tr>';
+            foreach ($numfields as $field) {
+                if ($f[$field]['count']) {
+                    // print question if necessary
+                    if (!$printedquestion) {
+                        print '<td colspan="'.$colspan.'" class="generaltablecell"><b>'.$question['name']."</b></td></tr>\n<tr>";
+                        $printedquestion = true;
+                    }
+                    // print numeric response
+                    $value = isset($question[$field]) ? $question[$field] : '-';
+                    print '<th align="right" width="100" class="generaltableheader">'.$f[$field]['name'].':</th><td class="generaltablecell">'.$value.'</td>';
+                }
+            }
+            print "</tr>\n";
+        } // foreach $q
+    }
+    // finish table
+    print "</table>\n";
+    print_simple_box_end();
 }
 ?>
index 923780f038d81a538c773b1a69ea44cb834b287f..2905ec256f5071a2ee0e10d3778c221fc640550c 100644 (file)
@@ -1,68 +1,68 @@
 <?php // $Id$
-       require_once("../../config.php");
-       require_once("lib.php");
-       require_login();
-       // fetch and clean the required $_GET parameters
-       // (script stops here if any parameters are missing)
-       unset($params);
-       $params->action = required_param('action');
-       $params->course = required_param('course');
-       $params->reference = required_param('reference');
-       require_login($params->course);
-       if (!isteacher($params->course)) {
-               error("You are not allowed to view this page!");
-       }
-       if (isadmin()) {
-               $params->location = optional_param('location', HOTPOT_LOCATION_COURSEFILES);
-       } else {
-               $params->location = HOTPOT_LOCATION_COURSEFILES;
-       }
-       $title = get_string($params->action, 'hotpot').': '.$params->reference;
-       print_header($title, $title);
-       hotpot_print_show_links($params->course, $params->location, $params->reference);
+    require_once("../../config.php");
+    require_once("lib.php");
+    require_login();
+    // fetch and clean the required $_GET parameters
+    // (script stops here if any parameters are missing)
+    unset($params);
+    $params->action = required_param('action');
+    $params->course = required_param('course');
+    $params->reference = required_param('reference');
+    require_login($params->course);
+    if (!isteacher($params->course)) {
+        error("You are not allowed to view this page!");
+    }
+    if (isadmin()) {
+        $params->location = optional_param('location', HOTPOT_LOCATION_COURSEFILES);
+    } else {
+        $params->location = HOTPOT_LOCATION_COURSEFILES;
+    }
+    $title = get_string($params->action, 'hotpot').': '.$params->reference;
+    print_header($title, $title);
+    hotpot_print_show_links($params->course, $params->location, $params->reference);
 ?>
 <script type="text/javascript" language="javascript">
 <!--
-       // http://www.krikkit.net/howto_javascript_copy_clipboard.html
-       function copy_contents(id) {
-               if (id==null) {
-                       id = 'contents';
-               }
-               var obj = null;
-               if (document.getElementById) {
-                       obj = document.getElementById(id);
-               }
-               if (obj && window.clipboardData) {
-                       window.clipboardData.setData("Text", obj.innerText);
-                       alert('<?php print_string('copiedtoclipboard', 'hotpot') ?>');
-               }
-       }
-       document.write('<span class="helplink"> &nbsp; <a href="javascript:copy_contents()"><?php print_string('copytoclipboard', 'hotpot') ?></A></span>');
+    // http://www.krikkit.net/howto_javascript_copy_clipboard.html
+    function copy_contents(id) {
+        if (id==null) {
+            id = 'contents';
+        }
+        var obj = null;
+        if (document.getElementById) {
+            obj = document.getElementById(id);
+        }
+        if (obj && window.clipboardData) {
+            window.clipboardData.setData("Text", obj.innerText);
+            alert('<?php print_string('copiedtoclipboard', 'hotpot') ?>');
+        }
+    }
+    document.write('<span class="helplink"> &nbsp; <a href="javascript:copy_contents()"><?php print_string('copytoclipboard', 'hotpot') ?></A></span>');
 -->
 </script>
 <?php
-       print_simple_box_start("center", "96%");
-       if($hp = new hotpot_xml_quiz($params)) {
-               print '<pre id="contents">';
-               switch ($params->action) {
-                       case 'showxmlsource':
-                               print htmlspecialchars($hp->source);
-                               break;
-                       case 'showxmltree':
-                               print_r($hp->xml);
-                               break;
-                       case 'showhtmlsource':
-                               print htmlspecialchars($hp->html);
-                               break;
-                       case 'showhtmlquiz':
-                               print $hp->html;
-                               break;
-               }
-               print '</pre>';
-       } else {
-               print_simple_box("Could not open Hot Potatoes XML file", "center", "", "#FFBBBB");
-       }
-       print_simple_box_end();
-       print '<br />';
-       close_window_button();
+    print_simple_box_start("center", "96%");
+    if($hp = new hotpot_xml_quiz($params)) {
+        print '<pre id="contents">';
+        switch ($params->action) {
+            case 'showxmlsource':
+                print htmlspecialchars($hp->source);
+                break;
+            case 'showxmltree':
+                print_r($hp->xml);
+                break;
+            case 'showhtmlsource':
+                print htmlspecialchars($hp->html);
+                break;
+            case 'showhtmlquiz':
+                print $hp->html;
+                break;
+        }
+        print '</pre>';
+    } else {
+        print_simple_box("Could not open Hot Potatoes XML file", "center", "", "#FFBBBB");
+    }
+    print_simple_box_end();
+    print '<br />';
+    close_window_button();
 ?>
index da38d63eb05ffaeed22931a6a3ed5c1365ee38ef..4f35b28e3f0c044f579a1a826bafceeafc88beaf 100644 (file)
 <?PHP
 class hotpot_xml_template_default {
-       function read_template($filename, $tag='temporary') {
-               // create the file path to the template
-               $filepath = $this->parent->template_dirpath.DIRECTORY_SEPARATOR.$filename;
-               // try and open the template file
-               if (!file_exists($filepath) || !is_readable($filepath)) {
-                       $msg = 'Could not open the '.$this->parent->template_dir.' template file &quot;'.$filepath.'&quot;';
-                       error($msg, $this->parent->course_homeurl);
-               }
-               // read in the template and close the file
-               $this->$tag = file_get_contents($filepath);
-               // expand the blocks and strings in the template
-               $this->expand_blocks($tag);
-               $this->expand_strings($tag);
-               if ($tag=='temporary') {
-                       $template = $this->$tag;
-                       $this->$tag = '';
-                       return $template;
-               }
-       }
-       function expand_blocks($tag) {
-               // get block $names
-               //      [1] the full block name (including optional leading 'str' or 'incl')
-               //      [2] leading 'incl' or 'str', if any
-               //      [3] the real block name ([1] without [2])
-               $search = '/\[\/((incl|str)?(\w+))\]/';
-               preg_match_all($search, $this->$tag, $names);
-               $i_max = count($names[0]);
-               for ($i=0; $i<$i_max; $i++) {
-                       $method = $this->parent->template_dir.'_expand_'.$names[3][$i];
-                       if (method_exists($this, $method)) {
-                               eval('$value=$this->'.$method.'();');
-                               $search = '/\['.$names[1][$i].'\](.*?)\[\/'.$names[1][$i].'\]/s';
-                               preg_match_all($search, $this->$tag, $blocks);
-                               $ii_max = count($blocks[0]);
-                               for ($ii=0; $ii<$ii_max; $ii++) {
-                                       $replace = empty($value) ? '' : $blocks[1][$ii];
-                                       $this->$tag = str_replace($blocks[0][$ii], $replace, $this->$tag);
-                               }
-                       } else {
-                               $msg = 'Template block expand method not found: &quot;'.$method.'&quot;';
-                               error($msg, $this->parent->course_homeurl);
-                       }
-               }
-       }
-       function expand_strings($tag, $search='') {
-               if (empty($search)) {
-                       // default $search $pattern
-                       $search = '/\[(?:bool|int|str)(\\w+)\]/';
-               }
-               preg_match_all($search, $this->$tag, $matches);
-               $i_max = count($matches[0]);
-               for ($i=0; $i<$i_max; $i++) {
-                       $method = $this->parent->template_dir.'_expand_'.$matches[1][$i];
-                       if (method_exists($this, $method)) {
-                               eval('$replace=$this->'.$method.'();');
-                               $this->$tag = str_replace($matches[0][$i], $replace, $this->$tag);
-                       }
-               }
-       }
-       function bool_value($tags, $more_tags="[0]['#']") {
-               $value = $this->parent->xml_value($tags, $more_tags);
-               return empty($value) ? 'false' : 'true';
-       }
-       function int_value($tags, $more_tags="[0]['#']") {
-               return intval($this->parent->xml_value($tags, $more_tags));
-       }
-       function js_value($tags, $more_tags="[0]['#']", $convert_to_unicode=false) {
-               return $this->js_safe($this->parent->xml_value($tags, $more_tags), $convert_to_unicode);
-       }
-       function js_safe($str, $convert_to_unicode=false) {
-               // encode a string for javascript
-               // decode "<" and ">" - not necesary as it was done by xml_value()
-               // $str  = strtr($str, array('&#x003C;' => '<', '&#x003E;' => '>'));
-               // escape single quotes and backslashes
-               $str = strtr($str, array("'"=>"\\'", '\\'=>'\\\\'));
-               // convert newlines (win = "\r\n", mac="\r", linix/unix="\n")
-               $nl = '\\n'; // javascript newline
-               $str = strtr($str, array("\r\n"=>$nl, "\r"=>$nl, "\n"=>$nl));
-               // convert (hex and decimal) html entities to unicode, if required
-               if ($convert_to_unicode) {
-                       $str = preg_replace('|&#x([0-9A-F]+);|i', '\\u\\1', $str);
-                       $str = preg_replace('|&#(\d+);|e', "'\\u'.sprintf('%04X', '\\1')", $str);
-               }
-               return $str;
-       }
-       function get_halfway_color($x, $y) {
-               // returns the $color that is half way between $x and $y
-               $color = $x; // default
-               $rgb = '/^\#?([0-9a-f])([0-9a-f])([0-9a-f])$/i';
-               $rrggbb = '/^\#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i';
-               if ((
-                       preg_match($rgb, $x, $x_matches) ||
-                       preg_match($rrggbb, $x, $x_matches) 
-               ) && (
-                       preg_match($rgb, $y, $y_matches) ||
-                       preg_match($rrggbb, $y, $y_matches)
-               )) {
-                       $color = '#';
-                       for ($i=1; $i<=3; $i++) {
-                               $x_dec = hexdec($x_matches[$i]);
-                               $y_dec = hexdec($y_matches[$i]);
-                               $color .= sprintf('%02x', min($x_dec, $y_dec) + abs($x_dec-$y_dec)/2);
-                       }
-               }
-               return $color;
-       }
+    function read_template($filename, $tag='temporary') {
+        // create the file path to the template
+        $filepath = $this->parent->template_dirpath.DIRECTORY_SEPARATOR.$filename;
+        // try and open the template file
+        if (!file_exists($filepath) || !is_readable($filepath)) {
+            $msg = 'Could not open the '.$this->parent->template_dir.' template file &quot;'.$filepath.'&quot;';
+            error($msg, $this->parent->course_homeurl);
+        }
+        // read in the template and close the file
+        $this->$tag = file_get_contents($filepath);
+        // expand the blocks and strings in the template
+        $this->expand_blocks($tag);
+        $this->expand_strings($tag);
+        if ($tag=='temporary') {
+            $template = $this->$tag;
+            $this->$tag = '';
+            return $template;
+        }
+    }
+    function expand_blocks($tag) {
+        // get block $names
+        //  [1] the full block name (including optional leading 'str' or 'incl')
+        //  [2] leading 'incl' or 'str', if any
+        //  [3] the real block name ([1] without [2])
+        $search = '/\[\/((incl|str)?(\w+))\]/';
+        preg_match_all($search, $this->$tag, $names);
+        $i_max = count($names[0]);
+        for ($i=0; $i<$i_max; $i++) {
+            $method = $this->parent->template_dir.'_expand_'.$names[3][$i];
+            if (method_exists($this, $method)) {
+                eval('$value=$this->'.$method.'();');
+                $search = '/\['.$names[1][$i].'\](.*?)\[\/'.$names[1][$i].'\]/s';
+                preg_match_all($search, $this->$tag, $blocks);
+                $ii_max = count($blocks[0]);
+                for ($ii=0; $ii<$ii_max; $ii++) {
+                    $replace = empty($value) ? '' : $blocks[1][$ii];
+                    $this->$tag = str_replace($blocks[0][$ii], $replace, $this->$tag);
+                }
+            } else {
+                $msg = 'Template block expand method not found: &quot;'.$method.'&quot;';
+                error($msg, $this->parent->course_homeurl);
+            }
+        }
+    }
+    function expand_strings($tag, $search='') {
+        if (empty($search)) {
+            // default $search $pattern
+            $search = '/\[(?:bool|int|str)(\\w+)\]/';
+        }
+        preg_match_all($search, $this->$tag, $matches);
+        $i_max = count($matches[0]);
+        for ($i=0; $i<$i_max; $i++) {
+            $method = $this->parent->template_dir.'_expand_'.$matches[1][$i];
+            if (method_exists($this, $method)) {
+                eval('$replace=$this->'.$method.'();');
+                $this->$tag = str_replace($matches[0][$i], $replace, $this->$tag);
+            }
+        }
+    }
+    function bool_value($tags, $more_tags="[0]['#']") {
+        $value = $this->parent->xml_value($tags, $more_tags);
+        return empty($value) ? 'false' : 'true';
+    }
+    function int_value($tags, $more_tags="[0]['#']") {
+        return intval($this->parent->xml_value($tags, $more_tags));
+    }
+    function js_value($tags, $more_tags="[0]['#']", $convert_to_unicode=false) {
+        return $this->js_safe($this->parent->xml_value($tags, $more_tags), $convert_to_unicode);
+    }
+    function js_safe($str, $convert_to_unicode=false) {
+        // encode a string for javascript
+        // decode "<" and ">" - not necesary as it was done by xml_value()
+        // $str  = strtr($str, array('&#x003C;' => '<', '&#x003E;' => '>'));
+        // escape single quotes and backslashes
+        $str = strtr($str, array("'"=>"\\'", '\\'=>'\\\\'));
+        // convert newlines (win = "\r\n", mac="\r", linix/unix="\n")
+        $nl = '\\n'; // javascript newline
+        $str = strtr($str, array("\r\n"=>$nl, "\r"=>$nl, "\n"=>$nl));
+        // convert (hex and decimal) html entities to unicode, if required
+        if ($convert_to_unicode) {
+            $str = preg_replace('|&#x([0-9A-F]+);|i', '\\u\\1', $str);
+            $str = preg_replace('|&#(\d+);|e', "'\\u'.sprintf('%04X', '\\1')", $str);
+        }
+        return $str;
+    }
+    function get_halfway_color($x, $y) {
+        // returns the $color that is half way between $x and $y
+        $color = $x; // default
+        $rgb = '/^\#?([0-9a-f])([0-9a-f])([0-9a-f])$/i';
+        $rrggbb = '/^\#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i';
+        if ((
+            preg_match($rgb, $x, $x_matches) ||
+            preg_match($rrggbb, $x, $x_matches) 
+        ) && (
+            preg_match($rgb, $y, $y_matches) ||
+            preg_match($rrggbb, $y, $y_matches)
+        )) {
+            $color = '#';
+            for ($i=1; $i<=3; $i++) {
+                $x_dec = hexdec($x_matches[$i]);
+                $y_dec = hexdec($y_matches[$i]);
+                $color .= sprintf('%02x', min($x_dec, $y_dec) + abs($x_dec-$y_dec)/2);
+            }
+        }
+        return $color;
+    }
 }
 ?>
index 02a0346ee1e3ed8ea43484355d5d21a930ce100d..4389b59da2e033bc4f78049ea0c210c3c505394d 100644 (file)
 \r
 class hotpot_xml_quiz_template extends hotpot_xml_template_default {\r
 \r
-       // constructor function for this class\r
-       function hotpot_xml_quiz_template(&$parent) {\r
-\r
-               $this->parent = &$parent;\r
-               \r
-               $get_js = optional_param('js', false);\r
-               $get_css = optional_param('css', false);\r
-\r
-               if (!empty($get_css)) {\r
-                       // set $this->css\r
-                       $this->v6_expand_StyleSheet(); \r
-\r
-               } else if (!empty($get_js)) {\r
-                       // set $this->js\r
-                       $this->read_template($this->parent->draganddrop.$this->parent->quiztype.'6.js_', 'js');\r
-\r
-               } else {\r
-                       // set $this->html\r
-                       $this->read_template($this->parent->draganddrop.$this->parent->quiztype.'6.ht_', 'html');\r
-               }\r
-\r
-               // expand special strings, if any\r
-               $pattern = '';\r
-               switch ($this->parent->quiztype) {\r
-                       case 'jcloze':\r
-                               $pattern = '/\[(PreloadImageList)\]/';\r
-                               break;\r
-                       case 'jcross':\r
-                               $pattern = '/\[(PreloadImageList|ShowHideClueList)\]/';\r
-                               break;\r
-                       case 'jmatch':\r
-                               $pattern = '/\[(PreloadImageList|QsToShow|FixedArray|DragArray)\]/';\r
-                               break;\r
-                       case 'jmix':\r
-                               $pattern = '/\[(PreloadImageList|SegmentArray|AnswerArray)\]/';\r
-                               break;\r
-                       case 'jquiz':\r
-                               $pattern = '/\[(PreloadImageList|QsToShow)\]/';\r
-                               break;\r
-               }\r
-               if (!empty($pattern)) {\r
-                       $this->expand_strings('html', $pattern);\r
-               }\r
-       }\r
-\r
-       // captions and messages\r
-\r
-       function v6_expand_AlsoCorrect() {\r
-               return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',also-correct');\r
-       }\r
-       function v6_expand_CapitalizeFirst() {\r
-               return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',capitalize-first-letter');\r
-       }\r
-       function v6_expand_CheckCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,check-caption');\r
-       }\r
-       function v6_expand_CorrectIndicator() {\r
-               return $this->js_value('hotpot-config-file,global,correct-indicator');\r
-       }\r
-       function v6_expand_Back() {\r
-               return $this->int_value('hotpot-config-file,global,include-back');\r
-       }\r
-       function v6_expand_BackCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,back-caption');\r
-       }\r
-       function v6_expand_ClickToAdd() {\r
-               return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',click-to-add');\r
-       }\r
-       function v6_expand_ClueCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,clue-caption');\r
-       }\r
-       function v6_expand_Clues() {\r
-               return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-clues');\r
-       }\r
-       function v6_expand_Contents() {\r
-               return $this->int_value('hotpot-config-file,global,include-contents');\r
-       }\r
-       function v6_expand_ContentsCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,contents-caption');\r
-       }\r
-       function v6_expand_GuessCorrect() {\r
-               return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guess-correct');\r
-       }\r
-       function v6_expand_GuessIncorrect() {\r
-               return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guess-incorrect');\r
-       }\r
-       function v6_expand_Hint() {\r
-               return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-hint');\r
-       }\r
-       function v6_expand_HintCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,hint-caption');\r
-       }\r
-       function v6_expand_IncorrectIndicator() {\r
-               return $this->js_value('hotpot-config-file,global,incorrect-indicator');\r
-       }\r
-       function v6_expand_LastQCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,last-q-caption');\r
-       }\r
-       function v6_expand_NextCorrect() {\r
-               $value = $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',next-correct-part');\r
-               if (empty($value)) { // jquiz\r
-                       $value = $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',next-correct-letter');\r
-               }\r
-               return $value;\r
-       }\r
-       function v6_expand_NextEx() {\r
-               return $this->int_value('hotpot-config-file,global,include-next-ex');\r
-       }\r
-       function v6_expand_NextExCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,next-ex-caption');\r
-       }\r
-       function v6_expand_NextQCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,next-q-caption');\r
-       }\r
-       function v6_expand_OKCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,ok-caption');\r
-       }\r
-       function v6_expand_Restart() {\r
-               return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-restart');\r
-       }\r
-       function v6_expand_RestartCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,restart-caption');\r
-       }\r
-       function v6_expand_ShowAllQuestionsCaption() {\r
-               return $this->js_value('hotpot-config-file,global,show-all-questions-caption');\r
-       }\r
-       function v6_expand_ShowOneByOneCaption() {\r
-               return $this->js_value('hotpot-config-file,global,show-one-by-one-caption');\r
-       }\r
-       function v6_expand_TheseAnswersToo() {\r
-               return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',also-correct');\r
-       }\r
-       function v6_expand_ThisMuch() {\r
-               return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',this-much-correct');\r
-       }\r
-       function v6_expand_Undo() {\r
-               return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-undo');\r
-       }\r
-       function v6_expand_UndoCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,undo-caption');\r
-       }\r
-       function v6_expand_YourScoreIs() {\r
-               return $this->js_value('hotpot-config-file,global,your-score-is');\r
-       }\r
-\r
-       // reading\r
-\r
-       function v6_expand_Reading() {\r
-               return $this->int_value('data,reading,include-reading');\r
-       }\r
-       function v6_expand_ReadingText() {\r
-               $title = $this->v6_expand_ReadingTitle();\r
-               $value = $this->parent->xml_value('data,reading,reading-text');\r
-               $value = empty($value) ? '' : ('<div class="ReadingText">'.$value.'</div>');\r
-               return $title.$value;\r
-       }\r
-       function v6_expand_ReadingTitle() {\r
-               $value = $this->parent->xml_value('data,reading,reading-title');\r
-               return empty($value) ? '' : ('<h3 class="ExerciseSubtitle">'.$value.'</h3>');\r
-       }\r
-\r
-       // timer \r
-\r
-       function v6_expand_Timer() {\r
-               return $this->int_value('data,timer,include-timer');\r
-       }\r
-       function v6_expand_JSTimer() {\r
-               return $this->read_template('hp6timer.js_');\r
-       }\r
-       function v6_expand_Seconds() {\r
-               return $this->parent->xml_value('data,timer,seconds');\r
-       }\r
-\r
-       // send results \r
-\r
-       function v6_expand_SendResults() {\r
-               return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',send-email');\r
-       }\r
-       function v6_expand_JSSendResults() {\r
-               return $this->read_template('hp6sendresults.js_');\r
-       }\r
-       function v6_expand_FormMailURL() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,formmail-url');\r
-       }\r
-       function v6_expand_EMail() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,email');\r
-       }\r
-       function v6_expand_NamePlease() {\r
-               return $this->js_value('hotpot-config-file,global,name-please');\r
-       }\r
-\r
-       // preload images\r
-\r
-       function v6_expand_PreloadImages() {\r
-               $value = $this->v6_expand_PreloadImageList();\r
-               return empty($value) ? false : true;\r
-       }\r
-       function v6_expand_PreloadImageList() {\r
-\r
-               // check it has not been set already\r
-               if (!isset($this->PreloadImageList)) {\r
-\r
-                       // the list of image urls\r
-                       $list = array();\r
-\r
-                       // extract <img> tags\r
-                       $img_tag = htmlspecialchars('|&#x003C;img.*?src="(.*?)".*?&#x003E;|is');\r
-                       if (preg_match_all($img_tag, $this->parent->source, $matches)) {\r
-                               $list = $matches[1];\r
-\r
-                               // remove duplicates\r
-                               $list = array_unique($list);\r
-                       }\r
-\r
-                       // convert to comma delimited string\r
-                       $this->PreloadImageList = empty($list) ? '' : "'".implode(',', $list)."'";\r
-               }\r
-               return $this->PreloadImageList;\r
-       }\r
-\r
-       // html files (all quiz types)\r
-\r
-       function v6_expand_PlainTitle() {\r
-               return $this->parent->xml_value('data,title');\r
-       }\r
-       function v6_expand_ExerciseSubtitle() {\r
-               return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',exercise-subtitle');\r
-       }\r
-       function v6_expand_Instructions() {\r
-               return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',instructions');\r
-       }\r
-       function v6_expand_DublinCoreMetadata() {\r
-               $dc = '<link rel="schema.DC" href="'.$this->parent->xml_value('', "['rdf:RDF'][0]['@']['xmlns:dc']").'" />'."\n";\r
-               if (is_string($this->parent->xml_value('rdf:RDF,rdf:Description'))) {\r
-                       // do nothing (there is no more dc info)\r
-               } else {\r
-                       $dc .= '<meta name="DC:Creator" content="'.$this->parent->xml_value('rdf:RDF,rdf:Description,dc:creator').'" />'."\n";\r
-                       $dc .= '<meta name="DC:Title" content="'.strip_tags($this->parent->xml_value('rdf:RDF,rdf:Description,dc:title')).'" />'."\n";\r
-               }\r
-               return $dc;\r
-       }\r
-       function v6_expand_FullVersionInfo() {\r
-               global $CFG;\r
-               require_once($CFG->hotpotroot.DIRECTORY_SEPARATOR.'version.php'); // set $module\r
-               return $this->parent->xml_value('version').'.x (Moodle '.$CFG->release.', hotpot-module '.$this->parent->obj_value($module, 'release').')';\r
-       }\r
-       function v6_expand_HeaderCode() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,header-code');\r
-       }\r
-       function v6_expand_StyleSheet() {\r
-               $this->read_template('hp6.cs_', 'css');\r
-               $this->css = hotpot_convert_stylesheets_urls($this->parent->get_baseurl(), $this->parent->reference, $this->css);\r
-               return $this->css;\r
-       }\r
-\r
-       // stylesheet (hp6.cs_)\r
-\r
-       function v6_expand_PageBGColor() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,page-bg-color');\r
-       }\r
-       function v6_expand_GraphicURL() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,graphic-url');\r
-       }\r
-       function v6_expand_ExBGColor() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,ex-bg-color');\r
-       }\r
-\r
-       function v6_expand_FontFace() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,font-face');\r
-       }\r
-       function v6_expand_FontSize() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,font-size');\r
-       }\r
-       function v6_expand_TextColor() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,text-color');\r
-       }\r
-       function v6_expand_TitleColor() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,title-color');\r
-       }\r
-       function v6_expand_LinkColor() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,link-color');\r
-       }\r
-       function v6_expand_VLinkColor() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,vlink-color');\r
-       }\r
-\r
-       function v6_expand_NavTextColor() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,page-bg-color');\r
-       }\r
-       function v6_expand_NavBarColor() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,nav-bar-color');\r
-       }\r
-       function v6_expand_NavLightColor() {\r
-               $color = $this->parent->xml_value('hotpot-config-file,global,nav-bar-color');\r
-               return $this->get_halfway_color($color, '#ffffff'); \r
-       }\r
-       function v6_expand_NavShadeColor() {\r
-               $color = $this->parent->xml_value('hotpot-config-file,global,nav-bar-color');\r
-               return $this->get_halfway_color($color, '#000000');\r
-       }\r
-\r
-       function v6_expand_FuncLightColor() { // top-left of buttons\r
-               $color = $this->parent->xml_value('hotpot-config-file,global,ex-bg-color');\r
-               return $this->get_halfway_color($color, '#ffffff');\r
-       }\r
-       function v6_expand_FuncShadeColor() { // bottom right of buttons\r
-               $color = $this->parent->xml_value('hotpot-config-file,global,ex-bg-color');\r
-               return $this->get_halfway_color($color, '#000000');\r
-       }\r
-\r
-       // navigation buttons\r
-\r
-       function v6_expand_NavButtons() {\r
-               $back = $this->v6_expand_Back();\r
-               $next_ex = $this->v6_expand_NextEx();\r
-               $contents = $this->v6_expand_Contents();\r
-               return (empty($back) && empty($next_ex) && empty($contents) ? false : true);\r
-       }\r
-       function v6_expand_NavBarJS() {\r
-               return $this->v6_expand_NavButtons();\r
-       }\r
-\r
-       // js files (all quiz types)\r
-\r
-       function v6_expand_JSBrowserCheck() {\r
-               return $this->read_template('hp6browsercheck.js_');\r
-       }\r
-       function v6_expand_JSButtons() {\r
-               return $this->read_template('hp6buttons.js_');\r
-       }\r
-       function v6_expand_JSCard() {\r
-               return $this->read_template('hp6card.js_');\r
-       }\r
-       function v6_expand_JSCheckShortAnswer() {\r
-               return $this->read_template('hp6checkshortanswer.js_');\r
-       }\r
-       function v6_expand_JSHotPotNet() {\r
-               return $this->read_template('hp6hotpotnet.js_');\r
-       }\r
-       function v6_expand_JSShowMessage() {\r
-               return $this->read_template('hp6showmessage.js_');\r
-       }\r
-       function v6_expand_JSUtilities() {\r
-               return $this->read_template('hp6utilities.js_');\r
-       }\r
-\r
-       // js files\r
-\r
-       function v6_expand_JSJCloze6() {\r
-               return $this->read_template('jcloze6.js_');\r
-       }\r
-       function v6_expand_JSJCross6() {\r
-               return $this->read_template('jcross6.js_');\r
-       }\r
-       function v6_expand_JSJMatch6() {\r
-               return $this->read_template('jmatch6.js_');\r
-       }\r
-       function v6_expand_JSJMix6() {\r
-               return $this->read_template('jmix6.js_');\r
-       }\r
-       function v6_expand_JSJQuiz6() {\r
-               return $this->read_template('jquiz6.js_');\r
-       }\r
-\r
-       // drag and drop\r
-\r
-       function v6_expand_JSDJMatch6() {\r
-               return $this->read_template('djmatch6.js_');\r
-       }\r
-       function v6_expand_JSDJMix6() {\r
-               return $this->read_template('djmix6.js_');\r
-       }\r
-\r
-       // what are these for?\r
-\r
-       function v6_expand_JSFJMatch6() {\r
-               return $this->read_template('fjmatch6.js_');\r
-       }\r
-       function v6_expand_JSFJMix6() {\r
-               return $this->read_template('fjmix6.js_');\r
-       }\r
-\r
-       // jmatch6.js_\r
-\r
-       function v6_expand_ShuffleQs() {\r
-               return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',shuffle-questions');\r
-       }\r
-       function v6_expand_QsToShow() {\r
-               $i = $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',show-limited-questions');\r
-               if ($i) {\r
-                       $i = $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',questions-to-show');\r
-               }\r
-               if (empty($i)) {\r
-                       $i = 0;\r
-                       switch ($this->parent->quiztype) {\r
-                               case 'jmatch':\r
-                                       $values = $this->parent->xml_values('data,matching-exercise,pair');\r
-                                       $i = count($values);\r
-                                       break;\r
-                               case 'jquiz':\r
-                                       while ($this->parent->xml_value('data,questions,question-record', "[$i]['#']['question'][0]['#']")) {\r
-                                               $i++;\r
-                                       }\r
-                                       break;\r
-                       } // end switch\r
-               }\r
-               return $i;\r
-       }\r
-       function v6_expand_MatchDivItems() {\r
-               $l_items = array();\r
-               $r_items = array();\r
-               $this->get_jmatch_items($l_items, $r_items);\r
-\r
-               $l_keys = $this->shuffle_jmatch_items($l_items);\r
-               $r_keys = $this->shuffle_jmatch_items($r_items);\r
-\r
-               $options = '<option value="x">'.$this->parent->xml_value('data,matching-exercise,default-right-item').'</option>';\r
-               foreach ($r_keys as $key) {\r
-                       $options .= '<option value="'.$key.'">'.$r_items[$key]['text'][0]['#'].'</option>'."\n";\r
-               }\r
-\r
-               $str = '';\r
-               foreach ($l_keys as $key) {\r
-                       $str .= '<tr><td class="LeftItem">'.$l_items[$key]['text'][0]['#'].'</td>';\r
-                       $str .= '<td class="RightItem"><select id="s'.$key.'_'.$key.'">'.$options.'</select></td>';\r
-                       $str .= '<td></td></tr>';\r
-               }\r
-               return $str;\r
-       }\r
-\r
-       // jmix6.js_\r
-\r
-       function v6_expand_Punctuation() {\r
-               $tags = 'data,jumbled-order-exercise';\r
-               $chars = array_merge(\r
-                       $this->jmix_Punctuation("$tags,main-order,segment"),\r
-                       $this->jmix_Punctuation("$tags,alternate")\r
-               );\r
-               $chars = array_unique($chars);\r
-               $chars = implode('', $chars);\r
-               $chars = $this->js_safe($chars, true);\r
-               return $chars;\r
-       }\r
-       function jmix_Punctuation($tags) {\r
-               $chars = array();\r
-\r
-               // all punctutation except '&#;' (because they are used in html entities)\r
-               $ENTITIES = $this->jmix_encode_punctuation('!"$%'."'".'()*+,-./:<=>?@[\]^_`{|}~');\r
-               $pattern = "/&#x([0-9A-F]+);/i";\r
-               $i = 0;\r
-\r
-               // get next segment (or alternate answer)\r
-               while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {\r
-\r
-                       // convert low-ascii punctuation to entities\r
-                       $value = strtr($value, $ENTITIES);\r
-\r
-                       // extract all hex HTML entities\r
-                       if (preg_match_all($pattern, $value, $matches)) {\r
-\r
-                               // loop through hex entities\r
-                               $m_max = count($matches[0]);\r
-                               for ($m=0; $m<$m_max; $m++) {\r
-\r
-                                       // convert to hex number\r
-                                       eval('$hex=0x'.$matches[1][$m].';');\r
-\r
-                                       // is this a punctuation character?\r
-                                       if (\r
-                                               ($hex>=0x0020 && $hex<=0x00BF) || // ascii punctuation\r
-                                               ($hex>=0x2000 && $hex<=0x206F) || // general punctuation\r
-                                               ($hex>=0x3000 && $hex<=0x303F) || // CJK punctuation\r
-                                               ($hex>=0xFE30 && $hex<=0xFE4F) || // CJK compatability\r
-                                               ($hex>=0xFE50 && $hex<=0xFE6F) || // small form variants\r
-                                               ($hex>=0xFF00 && $hex<=0xFF40) || // halfwidth and fullwidth forms (1)\r
-                                               ($hex>=0xFF5B && $hex<=0xFF65) || // halfwidth and fullwidth forms (2)\r
-                                               ($hex>=0xFFE0 && $hex<=0xFFEE)    // halfwidth and fullwidth forms (3)\r
-                                       ) {\r
-                                               // add this character\r
-                                               $chars[] = $matches[0][$m];\r
-                                       }\r
-                               }\r
-                       }\r
-                       $i++;\r
-               }\r
-\r
-               return $chars;\r
-       }\r
-       function v6_expand_OpenPunctuation() {\r
-               $tags = 'data,jumbled-order-exercise';\r
-               $chars = array_merge(\r
-                       $this->jmix_OpenPunctuation("$tags,main-order,segment"),\r
-                       $this->jmix_OpenPunctuation("$tags,alternate")\r
-               );\r
-               $chars = array_unique($chars);\r
-               $chars = implode('', $chars);\r
-               $chars = $this->js_safe($chars, true);\r
-               return $chars;\r
-       }\r
-       function jmix_OpenPunctuation($tags) {\r
-               $chars = array();\r
-\r
-               // unicode punctuation designations (pi="initial quote", ps="open")\r
-               //      http://www.sql-und-xml.de/unicode-database/pi.html\r
-               //      http://www.sql-und-xml.de/unicode-database/ps.html\r
-               $pi = '0022|0027|00AB|2018|201B|201C|201F|2039';\r
-               $ps = '0028|005B|007B|0F3A|0F3C|169B|201A|201E|2045|207D|208D|2329|23B4|2768|276A|276C|276E|2770|2772|2774|27E6|27E8|27EA|2983|2985|2987|2989|298B|298D|298F|2991|2993|2995|2997|29D8|29DA|29FC|3008|300A|300C|300E|3010|3014|3016|3018|301A|301D|FD3E|FE35|FE37|FE39|FE3B|FE3D|FE3F|FE41|FE43|FE47|FE59|FE5B|FE5D|FF08|FF3B|FF5B|FF5F|FF62';\r
-               $pattern = "/(&#x($pi|$ps);)/i";\r
-\r
-               $ENTITIES = $this->jmix_encode_punctuation('"'."'".'(<[{');\r
-\r
-               $i = 0;\r
-               while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {\r
-                       $value = strtr($value, $ENTITIES);\r
-                       if (preg_match_all($pattern, $value, $matches)) {\r
-                               $chars = array_merge($chars, $matches[0]);\r
-                       \r
-                       $i++;\r
-               }\r
-\r
-               return $chars;\r
-       }\r
-       function jmix_encode_punctuation($str) {\r
-               $ENTITIES = array();\r
-               $i_max = strlen($str);\r
-               for ($i=0; $i<$i_max; $i++) {\r
-                       $ENTITIES[$str{$i}] = '&#x'.sprintf('%04X', ord($str{$i})).';';\r
-               }\r
-               return $ENTITIES;\r
-       }\r
-       function v6_expand_ExerciseTitle() {\r
-               return $this->parent->xml_value('data,title');\r
-       }\r
-\r
-       // Jmix specials\r
-\r
-       function v6_expand_SegmentArray() {\r
-\r
-               $segments = array();\r
-               $values = array();\r
-               $VALUES = array();\r
-\r
-               // XML tags to the start of a segment\r
-               $tags = 'data,jumbled-order-exercise,main-order,segment';\r
-\r
-               $i = 0;\r
-               while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {\r
-                       $VALUE = strtoupper($value);\r
-                       $key = array_search($VALUE, $VALUES);\r
-                       if (is_numeric($key)) {\r
-                               $segments[] = $key;\r
-                       } else {\r
-                               $segments[] = $i;\r
-                               $values[$i] = $value;\r
-                               $VALUES[$i] = $VALUE;\r
-                       }\r
-                       $i++;\r
-               }\r
-\r
-               $this->seed_random_number_generator();\r
-               $keys = array_keys($segments);\r
-               shuffle($keys);\r
-\r
-               $str = '';\r
-               for($i=0; $i<count($keys); $i++) {\r
-                       $key = $segments[$keys[$i]];\r
-                       $str .= "Segments[$i] = new Array();\n";\r
-                       $str .= "Segments[$i][0] = '".$this->js_safe($values[$key], true)."';\n";\r
-                       $str .= "Segments[$i][1] = ".($key+1).";\n";\r
-                       $str .= "Segments[$i][2] = 0;\n";\r
-               }\r
-               return $str;\r
-       }\r
-       function v6_expand_AnswerArray() {\r
-\r
-               $segments = array();\r
-               $values = array();\r
-               $VALUES = array();\r
-               $escapedvalues = array();\r
-\r
-               // XML tags to the start of a segment\r
-               $tags = 'data,jumbled-order-exercise,main-order,segment';\r
-\r
-               $i = 0;\r
-               while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {\r
-                       $VALUE = strtoupper($value);\r
-                       $key = array_search($VALUE, $VALUES);\r
-                       if (is_numeric($key)) {\r
-                               $segments[] = $key+1;\r
-                       } else {\r
-                               $segments[] = $i+1;\r
-                               $values[$i] = $value;\r
-                               $VALUES[$i] = $VALUE;\r
-                               $escapedvalues[] = preg_quote($value, '/');\r
-                       }\r
-                       $i++;\r
-               }\r
-\r
-               // start the answers array\r
-               $a = 0;\r
-               $str = 'Answers['.($a++).'] = new Array('.implode(',', $segments).");\n";\r
-\r
-               // pattern to match the next part of an alternate answer\r
-               $pattern = '/^('.implode('|', $escapedvalues).')\\s*/i';\r
-\r
-               // XML tags to the start of an alternate answer\r
-               $tags = 'data,jumbled-order-exercise,alternate';\r
-\r
-               $i = 0;\r
-               while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {\r
-                       $segments = array();\r
-                       while (strlen($value) && preg_match($pattern, $value, $matches)) {\r
-                               $key = array_search($matches[1], $values);\r
-                               if (is_numeric($key)) {\r
-                                       $segments[] = $key+1;\r
-                                       $value = substr($value, strlen($matches[0]));\r
-                               } else {\r
-                                       // invalid alternate sequence\r
-                                       $segments = array();\r
-                                       break;\r
-                               }\r
-                       }\r
-                       if (count($segments)) {\r
-                               $str .= 'Answers['.($a++).'] = new Array('.implode(',', $segments).");\n";\r
-                       }\r
-                       $i++;\r
-               }\r
-               return $str;\r
-       }\r
-\r
-       // ===============================================================\r
-\r
-       // JMix (jmix6.js_)\r
-\r
-       function v6_expand_RemainingWords() {\r
-               return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',remaining-words');\r
-       }\r
-       function v6_expand_TimesUp() {\r
-               return $this->parent->xml_value('hotpot-config-file,global,times-up');\r
-       }\r
-\r
-       // nav bar\r
-\r
-       function v6_expand_NavBar($navbarid='') {\r
-               $this->navbarid = $navbarid;\r
-\r
-               $tag = 'navbar';\r
-               $this->read_template('hp6navbar.ht_', $tag);\r
-\r
-               unset($this->navbarid);\r
-\r
-               return $this->$tag;\r
-       }\r
-       function v6_expand_TopNavBar() {\r
-               return $this->v6_expand_NavBar('TopNavBar');\r
-       }\r
-       function v6_expand_BottomNavBar() {\r
-               return $this->v6_expand_NavBar('BottomNavBar');\r
-       }\r
-\r
-       // hp6navbar.ht_\r
-\r
-       function v6_expand_NavBarID() {\r
-               // $this->navbarid is set in "$this->v6_expand_NavBar"\r
-               return empty($this->navbarid) ? '' : $this->navbarid;\r
-       }\r
-       function v6_expand_ContentsURL() {\r
-               $url = $this->parent->xml_value('hotpot-config-file,global,contents-url');\r
-               if ($url) {\r
-                       $url = hotpot_convert_navbutton_url($this->parent->get_baseurl(), $this->parent->reference, $url, $this->parent->course);\r
-               }\r
-               return $url;\r
-       }\r
-       function v6_expand_NextExURL() {\r
-               $url = $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',next-ex-url');\r
-               if ($url) {\r
-                       $url = hotpot_convert_navbutton_url($this->parent->get_baseurl(), $this->parent->reference, $url, $this->parent->course);\r
-               }\r
-               return $url;\r
-       }\r
-\r
-       // conditional blocks\r
-\r
-       function v6_expand_ShowAnswer() {\r
-               return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-show-answer');\r
-       }\r
-       function v6_expand_Slide() {\r
-               return true; // whats's this (JMatch drag and drop)\r
-       }\r
-\r
-       // specials (JMatch)\r
-\r
-       function v6_expand_FixedArray() {\r
-               $l_items = array();\r
-               $r_items = array();\r
-               $this->get_jmatch_items($l_items, $r_items);\r
-\r
-               $str = '';\r
-               foreach ($l_items as $i=>$item) {\r
-                       $str .= "F[$i] = new Array();\n";\r
-                       $str .= "F[$i][0] = '".$this->js_safe($item['text'][0]['#'], true)."';\n";\r
-                       $str .= "F[$i][1] = ".($i+1).";\n";\r
-               }\r
-               return $str;\r
-       }\r
-       function v6_expand_DragArray() {\r
-               $l_items = array();\r
-               $r_items = array();\r
-               $this->get_jmatch_items($l_items, $r_items);\r
-\r
-               $str = '';\r
-               foreach ($r_items as $i=>$item) {\r
-                       $str .= "D[$i] = new Array();\n";\r
-                       $str .= "D[$i][0] = '".$this->js_safe($item['text'][0]['#'], true)."';\n";\r
-                       $str .= "D[$i][1] = ".($i+1).";\n";\r
-                       $str .= "D[$i][2] = 0;\n";\r
-               }\r
-               return $str;\r
-       }\r
-\r
-       function get_jmatch_items(&$l_items, &$r_items) {\r
-               $tags = 'data,matching-exercise,pair';\r
-               $i = 0;\r
-               while($item = $this->parent->xml_value($tags,"[$i]['#']['left-item'][0]['#']")) {\r
-                       if (!empty($item['text'][0]['#'])) {\r
-                               $l_items[] = $item;\r
-                       }\r
-                       $i++;\r
-               }\r
-               $i = 0;\r
-               while($item = $this->parent->xml_value($tags,"[$i]['#']['right-item'][0]['#']")) {\r
-                       if (!empty($item['text'][0]['#'])) {\r
-                               $r_items[] = $item;\r
-                       }\r
-                       $i++;\r
-               }\r
-       }\r
-       function shuffle_jmatch_items(&$items) {\r
-               // get moveable items\r
-               $moveable_keys = array();\r
-               for($i=0; $i<count($items); $i++) {\r
-                       if(empty($items[$i]['fixed'][0]['#'])) {\r
-                               $moveable_keys[] = $i;\r
-                       }\r
-               }\r
-               // shuffle moveable items\r
-               $this->seed_random_number_generator();\r
-               shuffle($moveable_keys);\r
-\r
-               $keys = array();\r
-               for($i=0, $ii=0; $i<count($items); $i++) {\r
-                       if(empty($items[$i]['fixed'][0]['#'])) {\r
-                               //      moveable items are inserted in a shuffled order\r
-                               $keys[] = $moveable_keys[$ii++];\r
-                       } else {\r
-                               //      fixed items stay where they are\r
-                               $keys[] = $i;\r
-                       }\r
-               }\r
-               return $keys;\r
-       }\r
-       function seed_random_number_generator() {\r
-               static $seeded_RNG = FALSE;\r
-               if (!$seeded_RNG) {\r
-                       srand((double) microtime() * 1000000);\r
-                       $seeded_RNG = TRUE;\r
-               }\r
-       }\r
-\r
-       // specials (JMix)\r
-\r
-\r
-       // specials (JCloze)\r
-\r
-       function v6_expand_ItemArray() {\r
-               $q = 0;\r
-               $str = '';\r
-               switch ($this->parent->quiztype) {\r
-                       case 'jcloze':\r
-                               $tags = 'data,gap-fill,question-record';\r
-                               while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
-                                       $a = 0;\r
-                                       $aa = 0;\r
-                                       while (($answer=$question."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {\r
-                                               $text = $this->js_value($tags,  $answer."['text'][0]['#']", true);\r
-                                               if (strlen($text)) {\r
-                                                       if ($aa==0) { // first time only\r
-                                                               $str .= "\n";\r
-                                                               $str .= "I[$q] = new Array();\n";\r
-                                                               $str .= "I[$q][1] = new Array();\n";\r
-                                                       }\r
-                                                       $str .= "I[$q][1][$aa] = new Array();\n";\r
-                                                       $str .= "I[$q][1][$aa][0] = '$text';\n";\r
-                                                       $aa++;\r
-                                               }\r
-                                               $a++;\r
-                                       }\r
-                                       // add clue, if any answers were found\r
-                                       if ($aa) {\r
-                                               $clue = $this->js_value($tags, $question."['clue'][0]['#']", true);\r
-                                               $str .= "I[$q][2] = '$clue';\n";\r
-                                       }\r
-                                       $q++;\r
-                               }\r
-                               break;\r
-                       case 'jquiz':\r
-                               $str .= "I=new Array();\n";\r
-                               $tags = 'data,questions,question-record';\r
-                               while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
-\r
-                                       $question_type = $this->int_value($tags, $question."['question-type'][0]['#']");\r
-                                       $weighting = $this->int_value($tags, $question."['weighting'][0]['#']");\r
-                                       $clue = $this->js_value($tags, $question."['clue'][0]['#']", true);\r
-\r
-                                       $answers = $question."['answers'][0]['#']";\r
-\r
-                                       $a = 0;\r
-                                       $aa = 0;\r
-                                       while (($answer = $answers."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {\r
-                                               $text =     $this->js_value($tags,  $answer."['text'][0]['#']", true);\r
-                                               $feedback = $this->js_value($tags,  $answer."['feedback'][0]['#']", true);\r
-                                               $correct =  $this->int_value($tags, $answer."['correct'][0]['#']");\r
-                                               $percent =  $this->int_value($tags, $answer."['percent-correct'][0]['#']");\r
-                                               $include =  $this->int_value($tags, $answer."['include-in-mc-options'][0]['#']");\r
-                                               if (strlen($text)) {\r
-                                                       if ($aa==0) { // first time only\r
-                                                               $str .= "\n";\r
-                                                               $str .= "I[$q] = new Array();\n";\r
-                                                               $str .= "I[$q][0] = $weighting;\n";\r
-                                                               $str .= "I[$q][1] = '$clue';\n";\r
-                                                               $str .= "I[$q][2] = '".($question_type-1)."';\n";\r
-                                                               $str .= "I[$q][3] = new Array();\n";\r
-                                                       }\r
-                                                       $str .= "I[$q][3][$aa] = new Array('$text','$feedback',$correct,$percent,$include);\n";\r
-                                                       $aa++;\r
-                                               }\r
-                                               $a++;\r
-                                       }\r
-                                       $q++;\r
-                               }\r
-                               break;\r
-               }\r
-               return $str;\r
-       }\r
-\r
-       function v6_expand_ClozeBody() {\r
-               $str = '';\r
-\r
-               // get drop down list of words, if required\r
-               $dropdownlist = '';\r
-               if ($this->v6_use_DropDownList()) {\r
-                       $this->v6_set_WordList();\r
-                       foreach ($this->wordlist as $word) {\r
-                               $dropdownlist .= '<option value="'.$word.'">'.$word.'</option>';\r
-                       }\r
-               }\r
-\r
-               // cache clues flag and caption\r
-               $includeclues = $this->v6_expand_Clues();\r
-               $cluecaption = $this->v6_expand_ClueCaption();\r
-\r
-               // detect if cloze starts with gap\r
-               $strpos = strpos($this->parent->source, '<gap-fill><question-record>');\r
-               if (is_numeric($strpos)) {\r
-                       $startwithgap = true;\r
-               } else {\r
-                       $startwithgap = false;\r
-               }\r
-\r
-               // initialize loop values\r
-               $q = 0;\r
-               $tags = 'data,gap-fill';\r
-               $question_record = "$tags,question-record";\r
-\r
-               // loop through text and gaps\r
-               do {\r
-                       $text = $this->parent->xml_value($tags, "[0]['#'][$q]");\r
-                       $gap = '';\r
-                       if (($question="[$q]['#']") && $this->parent->xml_value($question_record, $question)) {\r
-                               $gap .= '<span class="GapSpan" id="GapSpan'.$q.'">';\r
-                               if ($this->v6_use_DropDownList()) {\r
-                                       $gap .= '<select id="Gap'.$q.'"><option value=""></option>'.$dropdownlist.'</select>';\r
-                               } else {\r
-                                       // minimum gap size\r
-                                       $gapsize = 6;\r
-\r
-                                       // increase gap size to length of longest answer for this gap\r
-                                       $a = 0;\r
-                                       while (($answer=$question."['answer'][$a]['#']") && $this->parent->xml_value($question_record, $answer)) {\r
-                                               $answertext = $this->parent->xml_value($question_record,  $answer."['text'][0]['#']");\r
-                                               $answertext = preg_replace('|&[#a-zA-Z0-9]+;|', 'x', $answertext);\r
-                                               $gapsize = max($gapsize, strlen($answertext));\r
-                                               $a++;\r
-                                       }\r
-\r
-                                       $gap .= '<input type="text" id="Gap'.$q.'" onfocus="TrackFocus('.$q.')" onblur="LeaveGap()" class="GapBox" size="'.$gapsize.'"></input>';\r
-                               }\r
-                               if ($includeclues) {\r
-                                       $clue = $this->parent->xml_value($question_record, $question."['clue'][0]['#']");\r
-                                       if (strlen($clue)) {\r
-                                               $gap .= '<button style="line-height: 1.0" class="FuncButton" onfocus="FuncBtnOver(this)" onmouseover="FuncBtnOver(this)" onblur="FuncBtnOut(this)" onmouseout="FuncBtnOut(this)" onmousedown="FuncBtnDown(this)" onmouseup="FuncBtnOut(this)" onclick="ShowClue('.$q.')">'.$cluecaption.'</button>';\r
-                                       }\r
-                               }\r
-                               $gap .= '</span>';\r
-                       }\r
-                       if ($startwithgap) {\r
-                               $str .= "$gap$text";\r
-                       } else {\r
-                               $str .= "$text$gap";\r
-                       }\r
-                       $q++;\r
-               } while (strlen($text) || strlen($gap));\r
-\r
-               return $str;\r
-       }\r
-\r
-       // JCloze quiztype\r
-\r
-       function v6_expand_WordList() {\r
-               $str = '';\r
-               if ($this->v6_include_WordList()) {\r
-                       $this->v6_set_WordList();\r
-                       $str = implode(' &#160;&#160; ', $this->wordlist);\r
-               }\r
-               return $str;\r
-       }\r
-       function v6_include_WordList() {\r
-               return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-word-list');\r
-       }\r
-       function v6_use_DropDownList() {\r
-               return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',use-drop-down-list');\r
-       }\r
-       function v6_set_WordList() {\r
-\r
-               if (isset($this->wordlist)) {\r
-                       // do nothing\r
-               } else {\r
-                       $this->wordlist = array();\r
-\r
-                       // is the wordlist required\r
-                       if ($this->v6_include_WordList() || $this->v6_use_DropDownList()) {\r
-\r
-                               $q = 0;\r
-                               $tags = 'data,gap-fill,question-record';\r
-                               while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
-                                       $a = 0;\r
-                                       $aa = 0;\r
-                                       while (($answer=$question."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {\r
-                                               $text = $this->parent->xml_value($tags,  $answer."['text'][0]['#']");\r
-                                               $correct =  $this->int_value($tags, $answer."['correct'][0]['#']");\r
-                                               if ($text && $correct) { // $correct is always true\r
-                                                       $this->wordlist[] = $text;\r
-                                                       $aa++;\r
-                                               }\r
-                                               $a++;\r
-                                       }\r
-                                       $q++;\r
-                               }\r
-                               $this->wordlist = array_unique($this->wordlist);\r
-                               sort($this->wordlist);\r
-                       }\r
-               }\r
-       }\r
-       function v6_expand_Keypad() {\r
-               $str = '';\r
-               if ($this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-keypad')) {\r
-\r
-                       // these characters must always be in the keypad\r
-                       $chars = array();\r
-                       $this->add_keypad_chars($chars, $this->parent->xml_value('hotpot-config-file,global,keypad-characters'));\r
-\r
-                       // append other characters used in the answers\r
-                       $tags = '';\r
-                       switch ($this->parent->quiztype) {\r
-                               case 'jcloze':\r
-                                       $tags = 'data,gap-fill,question-record';\r
-                                       break;\r
-                               case 'jquiz':\r
-                                       $tags = 'data,questions,question-record';\r
-                                       break;\r
-                       }\r
-                       if ($tags) {\r
-                               $q = 0;\r
-                               while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
-\r
-                                       if ($this->parent->quiztype=='jquiz') {\r
-                                               $answers = $question."['answers'][0]['#']";\r
-                                       } else {\r
-                                               $answers = $question;\r
-                                       }\r
-\r
-                                       $a = 0;\r
-                                       while (($answer=$answers."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {\r
-                                               $this->add_keypad_chars($chars, $this->parent->xml_value($tags,  $answer."['text'][0]['#']"));\r
-                                               $a++;\r
-                                       }\r
-                                       $q++;\r
-                               }\r
-                       }\r
-\r
-                       // remove duplicate characters and sort\r
-                       $chars = array_unique($chars);\r
-                       usort($chars, "hotpot_sort_keypad_chars");\r
-\r
-                       // create keypad buttons for each character\r
-                       $str .= '<div class="Keypad">';\r
-                       foreach ($chars as $char) {\r
-                               $str .= "<button onclick=\"TypeChars('".$this->js_safe($char, true)."'); return false;\">$char</button>";\r
-                       }\r
-                       $str .= '</div>';\r
-               }\r
-               return $str;\r
-       }\r
-       function add_keypad_chars(&$chars, $text) {\r
-               if (preg_match_all('|&[^;]+;|i', $text, $more_chars)) {\r
-                       $chars = array_merge($chars, $more_chars[0]);\r
-               }\r
-       }\r
-       function v6_expand_Correct() {\r
-               return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guesses-correct');\r
-       }\r
-       function v6_expand_Incorrect() {\r
-               return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guesses-incorrect');\r
-       }\r
-       function v6_expand_GiveHint() {\r
-               return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',next-correct-letter');\r
-       }\r
-       function v6_expand_CaseSensitive() {\r
-               return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',case-sensitive');\r
-       }\r
-\r
-       // JCross quiztype\r
-\r
-       function v6_expand_CluesAcrossLabel() {\r
-               return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',clues-across');\r
-       }\r
-       function v6_expand_CluesDownLabel() {\r
-               return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',clues-down');\r
-       }\r
-       function v6_expand_EnterCaption() {\r
-               return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',enter-caption');\r
-       }\r
-       function v6_expand_ShowHideClueList() {\r
-               $value = $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-clue-list');\r
-               return empty($value) ? ' style="display: none;"' : '';\r
-       }\r
-\r
-       // JCross specials\r
-\r
-       function v6_expand_CluesDown() {\r
-               return $this->v6_expand_jcross_clues('D');\r
-       }\r
-       function v6_expand_CluesAcross() {\r
-               return $this->v6_expand_jcross_clues('A');\r
-       }\r
-       function v6_expand_jcross_clues($direction) {\r
-               // $direction: A(cross) or D(own)\r
-               $row = NULL;\r
-               $r_max = 0;\r
-               $c_max = 0;\r
-               $this->v6_get_jcross_grid($row, $r_max, $c_max);\r
-\r
-               $i = 0; // clue index;\r
-               $str = '';\r
-               for($r=0; $r<=$r_max; $r++) {\r
-                       for($c=0; $c<=$c_max; $c++) {\r
-                               $aword = $this->get_jcross_aword($row, $r, $r_max, $c, $c_max);\r
-                               $dword = $this->get_jcross_dword($row, $r, $r_max, $c, $c_max);\r
-                               if ($aword || $dword) {\r
-                                       $i++; // increment clue index\r
-\r
-                                       // get the definition for this word\r
-                                       $def = '';\r
-                                       $word = ($direction=='A') ? $aword : $dword;\r
-                                       $clues = $this->parent->xml_values('data,crossword,clues,item');\r
-                                       foreach ($clues as $clue) {\r
-                                               if ($clue['word'][0]['#']==$word) {\r
-                                                       $def = $clue['def'][0]['#'];\r
-                                                       $def = strtr($def, array('&#x003C;'=>'<', '&#x003E;'=>'>', "\n"=>'<br />'));\r
-                                                       break;\r
-                                               }\r
-                                       }\r
-\r
-                                       if (!empty($def)) {\r
-                                               $str .= '<tr><td class="ClueNum">'.$i.'. </td><td id="Clue_'.$direction.'_'.$i.'" class="Clue">'.$def.'</td></tr>';\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-               return $str;\r
-       }\r
-\r
-       // jcross6.js_\r
-\r
-       function v6_expand_LetterArray() {\r
-               $row = NULL;\r
-               $r_max = 0;\r
-               $c_max = 0;\r
-               $this->v6_get_jcross_grid($row, $r_max, $c_max);\r
-\r
-               $str = '';\r
-               for($r=0; $r<=$r_max; $r++) {\r
-                       $str .= "L[$r] = new Array(";\r
-                       for($c=0; $c<=$c_max; $c++) {\r
-                               $str .= ($c>0 ? ',' : '')."'".$this->js_safe($row[$r]['cell'][$c]['#'], true)."'";\r
-                       }\r
-                       $str .= ");\n";\r
-               }\r
-               return $str;\r
-       }\r
-       function v6_expand_GuessArray() {\r
-               $row = NULL;\r
-               $r_max = 0;\r
-               $c_max = 0;\r
-               $this->v6_get_jcross_grid($row, $r_max, $c_max);\r
-\r
-               $str = '';\r
-               for($r=0; $r<=$r_max; $r++) {\r
-                       $str .= "G[$r] = new Array('".str_repeat("','", $c_max)."');\n";\r
-               }\r
-               return $str;\r
-       }\r
-       function v6_expand_ClueNumArray() {\r
-               $row = NULL;\r
-               $r_max = 0;\r
-               $c_max = 0;\r
-               $this->v6_get_jcross_grid($row, $r_max, $c_max);\r
-\r
-               $i = 0; // clue index\r
-               $str = '';\r
-               for($r=0; $r<=$r_max; $r++) {\r
-                       $str .= "CL[$r] = new Array(";\r
-                       for($c=0; $c<=$c_max; $c++) {\r
-                               if ($c>0) {\r
-                                       $str .= ',';\r
-                               }\r
-                               $aword = $this->get_jcross_aword($row, $r, $r_max, $c, $c_max);\r
-                               $dword = $this->get_jcross_dword($row, $r, $r_max, $c, $c_max);\r
-                               if (empty($aword) && empty($dword)) {\r
-                                       $str .= 0;\r
-                               } else {\r
-                                       $i++; // increment the clue index\r
-                                       $str .= $i;\r
-                               }\r
-                       }\r
-                       $str .= ");\n";\r
-               }\r
-               return $str;\r
-       }\r
-       function v6_expand_GridBody() {\r
-               $row = NULL;\r
-               $r_max = 0;\r
-               $c_max = 0;\r
-               $this->v6_get_jcross_grid($row, $r_max, $c_max);\r
-\r
-               $i = 0; // clue index;\r
-               $str = '';\r
-               for($r=0; $r<=$r_max; $r++) {\r
-                       $str .= '<tr id="Row_'.$r.'">';\r
-                       for($c=0; $c<=$c_max; $c++) {\r
-                               if (empty($row[$r]['cell'][$c]['#'])) {\r
-                                       $str .= '<td class="BlankCell">&nbsp;</td>';\r
-                               } else {\r
-                                       $aword = $this->get_jcross_aword($row, $r, $r_max, $c, $c_max);\r
-                                       $dword = $this->get_jcross_dword($row, $r, $r_max, $c, $c_max);\r
-                                       if (empty($aword) && empty($dword)) {\r
-                                               $str .= '<td class="LetterOnlyCell"><span id="L_'.$r.'_'.$c.'">&nbsp;</span></td>';\r
-                                       } else {\r
-                                               $i++; // increment clue index\r
-                                               $str .= '<td class="NumLetterCell"><a href="javascript:void(0);" class="GridNum" onclick="ShowClue('.$i.','.$r.','.$c.')">'.$i.'</a><span class="NumLetterCellText" id="L_'.$r.'_'.$c.'" onclick="ShowClue('.$i.','.$r.','.$c.')">&nbsp;&nbsp;&nbsp;</span></td>';\r
-                                       }\r
-                               }\r
-                       }\r
-                       $str .= '</tr>';\r
-               }\r
-               return $str;\r
-       }\r
-       function v6_get_jcross_grid(&$row, &$r_max, &$c_max) {\r
-               $row = $this->parent->xml_values('data,crossword,grid,row');\r
-               $r_max = 0;\r
-               $c_max = 0;\r
-               if (isset($row) && is_array($row)) {\r
-                       for($r=0; $r<count($row); $r++) {\r
-                               if (isset($row[$r]['cell']) && is_array($row[$r]['cell'])) {\r
-                                       for($c=0; $c<count($row[$r]['cell']); $c++) {\r
-                                               if (!empty($row[$r]['cell'][$c]['#'])) {\r
-                                                       $r_max = max($r, $r_max);\r
-                                                       $c_max = max($c, $c_max);\r
-                                               }\r
-                                       } // end for $c\r
-                               }\r
-                       } // end for $r\r
-               }\r
-       }\r
-       function get_jcross_dword(&$row, $r, $r_max, $c, $c_max) {\r
-               $str = '';\r
-               if (($r==0 || empty($row[$r-1]['cell'][$c]['#'])) && $r<$r_max && !empty($row[$r+1]['cell'][$c]['#'])) {\r
-                       $str = $this->get_jcross_word($row, $r, $r_max, $c, $c_max, true);\r
-               }\r
-               return $str;\r
-       }\r
-       function get_jcross_aword(&$row, $r, $r_max, $c, $c_max) {\r
-               $str = '';\r
-               if (($c==0 || empty($row[$r]['cell'][$c-1]['#'])) && $c<$c_max && !empty($row[$r]['cell'][$c+1]['#'])) {\r
-                       $str = $this->get_jcross_word($row, $r, $r_max, $c, $c_max, false);\r
-               }\r
-               return $str;\r
-       }\r
-       function get_jcross_word(&$row, $r, $r_max, $c, $c_max, $go_down=false) {\r
-               $str = '';\r
-               while ($r<=$r_max && $c<=$c_max && !empty($row[$r]['cell'][$c]['#'])) {\r
-                       $str .= $row[$r]['cell'][$c]['#'];\r
-                       if ($go_down) {\r
-                               $r++;\r
-                       } else {\r
-                               $c++;\r
-                       }\r
-               }\r
-               return $str;\r
-       }\r
-\r
-       // specials (JQuiz)\r
-\r
-       function v6_expand_QuestionOutput() {\r
-               $str = '';\r
-               $str .= '<ol class="QuizQuestions" id="Questions">'."\n";\r
-\r
-               $q = 0;\r
-               $tags = 'data,questions,question-record';\r
-               while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
-\r
-                       // get question\r
-                       $question_text = $this->parent->xml_value($tags, $question."['question'][0]['#']");\r
-                       $question_type = $this->parent->xml_value($tags, $question."['question-type'][0]['#']");\r
-\r
-                       // check we have a question\r
-                       if ($question_text && $question_type) {\r
-\r
-                               $str .= '<li class="QuizQuestion" id="Q_'.$q.'" style="display: none;">';\r
-                               $str .= '<p class="QuestionText">'.$question_text.'</p>';\r
-\r
-                               if (\r
-                                       $question_type==HOTPOT_JQUIZ_SHORTANSWER || \r
-                                       $question_type==HOTPOT_JQUIZ_HYBRID\r
-                               ) {\r
-                                       $str .= '<div class="ShortAnswer" id="Q_'.$q.'_SA"><form method="post" action="" onsubmit="return false;"><div>';\r
-                                       $str .= '<input type="text" id="Q_'.$q.'_Guess" onfocus="TrackFocus('."'".'Q_'.$q.'_Guess'."'".')" onblur="LeaveGap()" class="ShortAnswerBox" size="9"></input><br /><br />';\r
-\r
-                                       $caption = $this->v6_expand_CheckCaption();\r
-                                       $str .= $this->v6_expand_jquiz_button($caption, "CheckShortAnswer($q)");\r
-\r
-                                       if ($this->v6_expand_Hint()) {\r
-                                               $caption = $this->v6_expand_HintCaption();\r
-                                               $str .= $this->v6_expand_jquiz_button($caption, "ShowHint($q)");\r
-                                       }\r
-\r
-                                       if ($this->v6_expand_ShowAnswer()) {\r
-                                               $caption = $this->v6_expand_ShowAnswerCaption();\r
-                                               $str .= $this->v6_expand_jquiz_button($caption, "ShowAnswers($q)");\r
-                                       }\r
-\r
-                                       $str .= '</div></form></div>';\r
-                               }\r
-\r
-                               if (\r
-                                       $question_type==HOTPOT_JQUIZ_MULTICHOICE || \r
-                                       $question_type==HOTPOT_JQUIZ_HYBRID ||\r
-                                       $question_type==HOTPOT_JQUIZ_MULTISELECT\r
-                               ) {\r
-\r
-                                       switch ($question_type) {\r
-                                               case HOTPOT_JQUIZ_MULTICHOICE: \r
-                                                       $str .= '<ol class="MCAnswers">'."\n";\r
-                                               break;\r
-                                               case HOTPOT_JQUIZ_HYBRID:\r
-                                                       $str .= '<ol class="MCAnswers" id="Q_'.$q.'_Hybrid_MC" style="display: none;">'."\n";\r
-                                               break;\r
-                                               case HOTPOT_JQUIZ_MULTISELECT:\r
-                                                       $str .= '<ol class="MSelAnswers">'."\n";\r
-                                               break;\r
-                                       }\r
-\r
-                                       $a = 0;\r
-                                       $aa = 0;\r
-                                       $answers = $question."['answers'][0]['#']";\r
-                                       while (($answer = $answers."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {\r
-                                               $text = $this->parent->xml_value($tags, $answer."['text'][0]['#']");\r
-                                               if ($text) {\r
-                                                       switch ($question_type) {\r
-                                                               case HOTPOT_JQUIZ_MULTICHOICE:\r
-                                                               case HOTPOT_JQUIZ_HYBRID:\r
-                                                                       $include = $this->int_value($tags, $answer."['include-in-mc-options'][0]['#']");\r
-                                                                       if ($include) {\r
-                                                                               $str .= '<li id="Q_'.$q.'_'.$aa.'"><button class="FuncButton" onfocus="FuncBtnOver(this)" onblur="FuncBtnOut(this)" onmouseover="FuncBtnOver(this)" onmouseout="FuncBtnOut(this)" onmousedown="FuncBtnDown(this)" onmouseup="FuncBtnOut(this)" id="Q_'.$q.'_'.$aa.'_Btn" onclick="CheckMCAnswer('.$q.','.$aa.',this)">&nbsp;&nbsp;?&nbsp;&nbsp;</button>&nbsp;&nbsp;'.$text.'</li>'."\n";\r
-                                                                       }\r
-                                                               break;\r
-                                                               case HOTPOT_JQUIZ_MULTISELECT:\r
-                                                                       $str .= '<li id="Q_'.$q.'_'.$aa.'"><form method="post" action="" onsubmit="return false;"><div><input type="checkbox" id="Q_'.$q.'_'.$aa.'_Chk" class="MSelCheckbox" />'.$text.'</div></form></li>'."\n";\r
-                                                               break;\r
-                                                       }\r
-                                                       $aa++;\r
-                                               }\r
-                                               $a++;\r
-                                       }\r
-\r
-                                       $str .= '</ol>';\r
-\r
-                                       if ($question_type==HOTPOT_JQUIZ_MULTISELECT) {\r
-                                               $caption = $this->v6_expand_CheckCaption();\r
-                                               $str .= $this->v6_expand_jquiz_button($caption, "CheckMultiSelAnswer($q)");\r
-                                       }\r
-                               }\r
-\r
-                               $str .= "</li>\n";\r
-                       }\r
-                       $q++;\r
-\r
-               } // end while $question\r
-\r
-               $str .= "</ol>\n";\r
-               return $str;\r
-       }\r
-\r
-       function v6_expand_jquiz_button($caption, $onclick) {\r
-               return '<button class="FuncButton" onfocus="FuncBtnOver(this)" onblur="FuncBtnOut(this)" onmouseover="FuncBtnOver(this)" onmouseout="FuncBtnOut(this)" onmousedown="FuncBtnDown(this)" onmouseup="FuncBtnOut(this)" onclick="'.$onclick.'">'.$caption.'</button>';\r
-       }\r
-\r
-       // jquiz.js_\r
-\r
-       function v6_expand_MultiChoice() {\r
-               return $this->v6_jquiz_question_type(HOTPOT_JQUIZ_MULTICHOICE);\r
-       }\r
-       function v6_expand_ShortAnswer() {\r
-               return $this->v6_jquiz_question_type(HOTPOT_JQUIZ_SHORTANSWER);\r
-       }\r
-       function v6_expand_MultiSelect() {\r
-               return $this->v6_jquiz_question_type(HOTPOT_JQUIZ_MULTISELECT);\r
-       }\r
-       function v6_jquiz_question_type($type) {\r
-               // does this quiz have any questions of the given $type?\r
-               $flag = false;\r
-\r
-               $q = 0;\r
-               $tags = 'data,questions,question-record';\r
-               while (($question = "[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
-                       $question_type = $this->parent->xml_value($tags, $question."['question-type'][0]['#']");\r
-                       if ($question_type==$type || ($question_type==HOTPOT_JQUIZ_HYBRID && ($type==HOTPOT_JQUIZ_MULTICHOICE || $type==HOTPOT_JQUIZ_SHORTANSWER))) {\r
-                               $flag = true;\r
-                               break;\r
-                       }\r
-                       $q++;\r
-               }\r
-               return $flag;\r
-       }\r
-       function v6_expand_CorrectFirstTime() {\r
-               return $this->js_value('hotpot-config-file,global,correct-first-time');\r
-       }\r
-       function v6_expand_ContinuousScoring() {\r
-               return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',continuous-scoring');\r
-       }\r
-       function v6_expand_ShowCorrectFirstTime() {\r
-               return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',show-correct-first-time');\r
-       }\r
-       function v6_expand_ShuffleAs() {\r
-               return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',shuffle-answers');\r
-       }\r
-\r
-       function v6_expand_DefaultRight() {\r
-               return $this->v6_expand_GuessCorrect();\r
-       }\r
-       function v6_expand_DefaultWrong() {\r
-               return $this->v6_expand_GuessIncorrect();\r
-       }\r
-       function v6_expand_ShowAllQuestionsCaptionJS() {\r
-               return $this->v6_expand_ShowAllQuestionsCaption();\r
-       }\r
-       function v6_expand_ShowOneByOneCaptionJS() {\r
-               return $this->v6_expand_ShowOneByOneCaption();\r
-       }\r
-\r
-       // hp6checkshortanswers.js_ (JQuiz)\r
-\r
-       function v6_expand_CorrectList() {\r
-               return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',correct-answers');\r
-       }\r
-       function v6_expand_HybridTries() {\r
-               return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',short-answer-tries-on-hybrid-q');\r
-       }\r
-       function v6_expand_PleaseEnter() {\r
-               return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',enter-a-guess');\r
-       }\r
-       function v6_expand_PartlyIncorrect() {\r
-               return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',partly-incorrect');\r
-       }\r
-       function v6_expand_ShowAnswerCaption() {\r
-               return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',show-answer-caption');\r
-       }\r
-       function v6_expand_ShowAlsoCorrect() {\r
-               return $this->bool_value('hotpot-config-file,global,show-also-correct');\r
-       }\r
+    // constructor function for this class\r
+    function hotpot_xml_quiz_template(&$parent) {\r
+\r
+        $this->parent = &$parent;\r
+        \r
+        $get_js = optional_param('js', false);\r
+        $get_css = optional_param('css', false);\r
+\r
+        if (!empty($get_css)) {\r
+            // set $this->css\r
+            $this->v6_expand_StyleSheet(); \r
+\r
+        } else if (!empty($get_js)) {\r
+            // set $this->js\r
+            $this->read_template($this->parent->draganddrop.$this->parent->quiztype.'6.js_', 'js');\r
+\r
+        } else {\r
+            // set $this->html\r
+            $this->read_template($this->parent->draganddrop.$this->parent->quiztype.'6.ht_', 'html');\r
+        }\r
+\r
+        // expand special strings, if any\r
+        $pattern = '';\r
+        switch ($this->parent->quiztype) {\r
+            case 'jcloze':\r
+                $pattern = '/\[(PreloadImageList)\]/';\r
+                break;\r
+            case 'jcross':\r
+                $pattern = '/\[(PreloadImageList|ShowHideClueList)\]/';\r
+                break;\r
+            case 'jmatch':\r
+                $pattern = '/\[(PreloadImageList|QsToShow|FixedArray|DragArray)\]/';\r
+                break;\r
+            case 'jmix':\r
+                $pattern = '/\[(PreloadImageList|SegmentArray|AnswerArray)\]/';\r
+                break;\r
+            case 'jquiz':\r
+                $pattern = '/\[(PreloadImageList|QsToShow)\]/';\r
+                break;\r
+        }\r
+        if (!empty($pattern)) {\r
+            $this->expand_strings('html', $pattern);\r
+        }\r
+    }\r
+\r
+    // captions and messages\r
+\r
+    function v6_expand_AlsoCorrect() {\r
+        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',also-correct');\r
+    }\r
+    function v6_expand_CapitalizeFirst() {\r
+        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',capitalize-first-letter');\r
+    }\r
+    function v6_expand_CheckCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,check-caption');\r
+    }\r
+    function v6_expand_CorrectIndicator() {\r
+        return $this->js_value('hotpot-config-file,global,correct-indicator');\r
+    }\r
+    function v6_expand_Back() {\r
+        return $this->int_value('hotpot-config-file,global,include-back');\r
+    }\r
+    function v6_expand_BackCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,back-caption');\r
+    }\r
+    function v6_expand_ClickToAdd() {\r
+        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',click-to-add');\r
+    }\r
+    function v6_expand_ClueCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,clue-caption');\r
+    }\r
+    function v6_expand_Clues() {\r
+        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-clues');\r
+    }\r
+    function v6_expand_Contents() {\r
+        return $this->int_value('hotpot-config-file,global,include-contents');\r
+    }\r
+    function v6_expand_ContentsCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,contents-caption');\r
+    }\r
+    function v6_expand_GuessCorrect() {\r
+        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guess-correct');\r
+    }\r
+    function v6_expand_GuessIncorrect() {\r
+        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guess-incorrect');\r
+    }\r
+    function v6_expand_Hint() {\r
+        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-hint');\r
+    }\r
+    function v6_expand_HintCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,hint-caption');\r
+    }\r
+    function v6_expand_IncorrectIndicator() {\r
+        return $this->js_value('hotpot-config-file,global,incorrect-indicator');\r
+    }\r
+    function v6_expand_LastQCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,last-q-caption');\r
+    }\r
+    function v6_expand_NextCorrect() {\r
+        $value = $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',next-correct-part');\r
+        if (empty($value)) { // jquiz\r
+            $value = $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',next-correct-letter');\r
+        }\r
+        return $value;\r
+    }\r
+    function v6_expand_NextEx() {\r
+        return $this->int_value('hotpot-config-file,global,include-next-ex');\r
+    }\r
+    function v6_expand_NextExCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,next-ex-caption');\r
+    }\r
+    function v6_expand_NextQCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,next-q-caption');\r
+    }\r
+    function v6_expand_OKCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,ok-caption');\r
+    }\r
+    function v6_expand_Restart() {\r
+        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-restart');\r
+    }\r
+    function v6_expand_RestartCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,restart-caption');\r
+    }\r
+    function v6_expand_ShowAllQuestionsCaption() {\r
+        return $this->js_value('hotpot-config-file,global,show-all-questions-caption');\r
+    }\r
+    function v6_expand_ShowOneByOneCaption() {\r
+        return $this->js_value('hotpot-config-file,global,show-one-by-one-caption');\r
+    }\r
+    function v6_expand_TheseAnswersToo() {\r
+        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',also-correct');\r
+    }\r
+    function v6_expand_ThisMuch() {\r
+        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',this-much-correct');\r
+    }\r
+    function v6_expand_Undo() {\r
+        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-undo');\r
+    }\r
+    function v6_expand_UndoCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,undo-caption');\r
+    }\r
+    function v6_expand_YourScoreIs() {\r
+        return $this->js_value('hotpot-config-file,global,your-score-is');\r
+    }\r
+\r
+    // reading\r
+\r
+    function v6_expand_Reading() {\r
+        return $this->int_value('data,reading,include-reading');\r
+    }\r
+    function v6_expand_ReadingText() {\r
+        $title = $this->v6_expand_ReadingTitle();\r
+        $value = $this->parent->xml_value('data,reading,reading-text');\r
+        $value = empty($value) ? '' : ('<div class="ReadingText">'.$value.'</div>');\r
+        return $title.$value;\r
+    }\r
+    function v6_expand_ReadingTitle() {\r
+        $value = $this->parent->xml_value('data,reading,reading-title');\r
+        return empty($value) ? '' : ('<h3 class="ExerciseSubtitle">'.$value.'</h3>');\r
+    }\r
+\r
+    // timer \r
+\r
+    function v6_expand_Timer() {\r
+        return $this->int_value('data,timer,include-timer');\r
+    }\r
+    function v6_expand_JSTimer() {\r
+        return $this->read_template('hp6timer.js_');\r
+    }\r
+    function v6_expand_Seconds() {\r
+        return $this->parent->xml_value('data,timer,seconds');\r
+    }\r
+\r
+    // send results \r
+\r
+    function v6_expand_SendResults() {\r
+        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',send-email');\r
+    }\r
+    function v6_expand_JSSendResults() {\r
+        return $this->read_template('hp6sendresults.js_');\r
+    }\r
+    function v6_expand_FormMailURL() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,formmail-url');\r
+    }\r
+    function v6_expand_EMail() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,email');\r
+    }\r
+    function v6_expand_NamePlease() {\r
+        return $this->js_value('hotpot-config-file,global,name-please');\r
+    }\r
+\r
+    // preload images\r
+\r
+    function v6_expand_PreloadImages() {\r
+        $value = $this->v6_expand_PreloadImageList();\r
+        return empty($value) ? false : true;\r
+    }\r
+    function v6_expand_PreloadImageList() {\r
+\r
+        // check it has not been set already\r
+        if (!isset($this->PreloadImageList)) {\r
+\r
+            // the list of image urls\r
+            $list = array();\r
+\r
+            // extract <img> tags\r
+            $img_tag = htmlspecialchars('|&#x003C;img.*?src="(.*?)".*?&#x003E;|is');\r
+            if (preg_match_all($img_tag, $this->parent->source, $matches)) {\r
+                $list = $matches[1];\r
+\r
+                // remove duplicates\r
+                $list = array_unique($list);\r
+            }\r
+\r
+            // convert to comma delimited string\r
+            $this->PreloadImageList = empty($list) ? '' : "'".implode(',', $list)."'";\r
+        }\r
+        return $this->PreloadImageList;\r
+    }\r
+\r
+    // html files (all quiz types)\r
+\r
+    function v6_expand_PlainTitle() {\r
+        return $this->parent->xml_value('data,title');\r
+    }\r
+    function v6_expand_ExerciseSubtitle() {\r
+        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',exercise-subtitle');\r
+    }\r
+    function v6_expand_Instructions() {\r
+        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',instructions');\r
+    }\r
+    function v6_expand_DublinCoreMetadata() {\r
+        $dc = '<link rel="schema.DC" href="'.$this->parent->xml_value('', "['rdf:RDF'][0]['@']['xmlns:dc']").'" />'."\n";\r
+        if (is_string($this->parent->xml_value('rdf:RDF,rdf:Description'))) {\r
+            // do nothing (there is no more dc info)\r
+        } else {\r
+            $dc .= '<meta name="DC:Creator" content="'.$this->parent->xml_value('rdf:RDF,rdf:Description,dc:creator').'" />'."\n";\r
+            $dc .= '<meta name="DC:Title" content="'.strip_tags($this->parent->xml_value('rdf:RDF,rdf:Description,dc:title')).'" />'."\n";\r
+        }\r
+        return $dc;\r
+    }\r
+    function v6_expand_FullVersionInfo() {\r
+        global $CFG;\r
+        require_once($CFG->hotpotroot.DIRECTORY_SEPARATOR.'version.php'); // set $module\r
+        return $this->parent->xml_value('version').'.x (Moodle '.$CFG->release.', hotpot-module '.$this->parent->obj_value($module, 'release').')';\r
+    }\r
+    function v6_expand_HeaderCode() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,header-code');\r
+    }\r
+    function v6_expand_StyleSheet() {\r
+        $this->read_template('hp6.cs_', 'css');\r
+        $this->css = hotpot_convert_stylesheets_urls($this->parent->get_baseurl(), $this->parent->reference, $this->css);\r
+        return $this->css;\r
+    }\r
+\r
+    // stylesheet (hp6.cs_)\r
+\r
+    function v6_expand_PageBGColor() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,page-bg-color');\r
+    }\r
+    function v6_expand_GraphicURL() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,graphic-url');\r
+    }\r
+    function v6_expand_ExBGColor() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,ex-bg-color');\r
+    }\r
+\r
+    function v6_expand_FontFace() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,font-face');\r
+    }\r
+    function v6_expand_FontSize() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,font-size');\r
+    }\r
+    function v6_expand_TextColor() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,text-color');\r
+    }\r
+    function v6_expand_TitleColor() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,title-color');\r
+    }\r
+    function v6_expand_LinkColor() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,link-color');\r
+    }\r
+    function v6_expand_VLinkColor() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,vlink-color');\r
+    }\r
+\r
+    function v6_expand_NavTextColor() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,page-bg-color');\r
+    }\r
+    function v6_expand_NavBarColor() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,nav-bar-color');\r
+    }\r
+    function v6_expand_NavLightColor() {\r
+        $color = $this->parent->xml_value('hotpot-config-file,global,nav-bar-color');\r
+        return $this->get_halfway_color($color, '#ffffff'); \r
+    }\r
+    function v6_expand_NavShadeColor() {\r
+        $color = $this->parent->xml_value('hotpot-config-file,global,nav-bar-color');\r
+        return $this->get_halfway_color($color, '#000000');\r
+    }\r
+\r
+    function v6_expand_FuncLightColor() { // top-left of buttons\r
+        $color = $this->parent->xml_value('hotpot-config-file,global,ex-bg-color');\r
+        return $this->get_halfway_color($color, '#ffffff');\r
+    }\r
+    function v6_expand_FuncShadeColor() { // bottom right of buttons\r
+        $color = $this->parent->xml_value('hotpot-config-file,global,ex-bg-color');\r
+        return $this->get_halfway_color($color, '#000000');\r
+    }\r
+\r
+    // navigation buttons\r
+\r
+    function v6_expand_NavButtons() {\r
+        $back = $this->v6_expand_Back();\r
+        $next_ex = $this->v6_expand_NextEx();\r
+        $contents = $this->v6_expand_Contents();\r
+        return (empty($back) && empty($next_ex) && empty($contents) ? false : true);\r
+    }\r
+    function v6_expand_NavBarJS() {\r
+        return $this->v6_expand_NavButtons();\r
+    }\r
+\r
+    // js files (all quiz types)\r
+\r
+    function v6_expand_JSBrowserCheck() {\r
+        return $this->read_template('hp6browsercheck.js_');\r
+    }\r
+    function v6_expand_JSButtons() {\r
+        return $this->read_template('hp6buttons.js_');\r
+    }\r
+    function v6_expand_JSCard() {\r
+        return $this->read_template('hp6card.js_');\r
+    }\r
+    function v6_expand_JSCheckShortAnswer() {\r
+        return $this->read_template('hp6checkshortanswer.js_');\r
+    }\r
+    function v6_expand_JSHotPotNet() {\r
+        return $this->read_template('hp6hotpotnet.js_');\r
+    }\r
+    function v6_expand_JSShowMessage() {\r
+        return $this->read_template('hp6showmessage.js_');\r
+    }\r
+    function v6_expand_JSUtilities() {\r
+        return $this->read_template('hp6utilities.js_');\r
+    }\r
+\r
+    // js files\r
+\r
+    function v6_expand_JSJCloze6() {\r
+        return $this->read_template('jcloze6.js_');\r
+    }\r
+    function v6_expand_JSJCross6() {\r
+        return $this->read_template('jcross6.js_');\r
+    }\r
+    function v6_expand_JSJMatch6() {\r
+        return $this->read_template('jmatch6.js_');\r
+    }\r
+    function v6_expand_JSJMix6() {\r
+        return $this->read_template('jmix6.js_');\r
+    }\r
+    function v6_expand_JSJQuiz6() {\r
+        return $this->read_template('jquiz6.js_');\r
+    }\r
+\r
+    // drag and drop\r
+\r
+    function v6_expand_JSDJMatch6() {\r
+        return $this->read_template('djmatch6.js_');\r
+    }\r
+    function v6_expand_JSDJMix6() {\r
+        return $this->read_template('djmix6.js_');\r
+    }\r
+\r
+    // what are these for?\r
+\r
+    function v6_expand_JSFJMatch6() {\r
+        return $this->read_template('fjmatch6.js_');\r
+    }\r
+    function v6_expand_JSFJMix6() {\r
+        return $this->read_template('fjmix6.js_');\r
+    }\r
+\r
+    // jmatch6.js_\r
+\r
+    function v6_expand_ShuffleQs() {\r
+        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',shuffle-questions');\r
+    }\r
+    function v6_expand_QsToShow() {\r
+        $i = $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',show-limited-questions');\r
+        if ($i) {\r
+            $i = $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',questions-to-show');\r
+        }\r
+        if (empty($i)) {\r
+            $i = 0;\r
+            switch ($this->parent->quiztype) {\r
+                case 'jmatch':\r
+                    $values = $this->parent->xml_values('data,matching-exercise,pair');\r
+                    $i = count($values);\r
+                    break;\r
+                case 'jquiz':\r
+                    while ($this->parent->xml_value('data,questions,question-record', "[$i]['#']['question'][0]['#']")) {\r
+                        $i++;\r
+                    }\r
+                    break;\r
+            } // end switch\r
+        }\r
+        return $i;\r
+    }\r
+    function v6_expand_MatchDivItems() {\r
+        $l_items = array();\r
+        $r_items = array();\r
+        $this->get_jmatch_items($l_items, $r_items);\r
+\r
+        $l_keys = $this->shuffle_jmatch_items($l_items);\r
+        $r_keys = $this->shuffle_jmatch_items($r_items);\r
+\r
+        $options = '<option value="x">'.$this->parent->xml_value('data,matching-exercise,default-right-item').'</option>';\r
+        foreach ($r_keys as $key) {\r
+            $options .= '<option value="'.$key.'">'.$r_items[$key]['text'][0]['#'].'</option>'."\n";\r
+        }\r
+\r
+        $str = '';\r
+        foreach ($l_keys as $key) {\r
+            $str .= '<tr><td class="LeftItem">'.$l_items[$key]['text'][0]['#'].'</td>';\r
+            $str .= '<td class="RightItem"><select id="s'.$key.'_'.$key.'">'.$options.'</select></td>';\r
+            $str .= '<td></td></tr>';\r
+        }\r
+        return $str;\r
+    }\r
+\r
+    // jmix6.js_\r
+\r
+    function v6_expand_Punctuation() {\r
+        $tags = 'data,jumbled-order-exercise';\r
+        $chars = array_merge(\r
+            $this->jmix_Punctuation("$tags,main-order,segment"),\r
+            $this->jmix_Punctuation("$tags,alternate")\r
+        );\r
+        $chars = array_unique($chars);\r
+        $chars = implode('', $chars);\r
+        $chars = $this->js_safe($chars, true);\r
+        return $chars;\r
+    }\r
+    function jmix_Punctuation($tags) {\r
+        $chars = array();\r
+\r
+        // all punctutation except '&#;' (because they are used in html entities)\r
+        $ENTITIES = $this->jmix_encode_punctuation('!"$%'."'".'()*+,-./:<=>?@[\]^_`{|}~');\r
+        $pattern = "/&#x([0-9A-F]+);/i";\r
+        $i = 0;\r
+\r
+        // get next segment (or alternate answer)\r
+        while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {\r
+\r
+            // convert low-ascii punctuation to entities\r
+            $value = strtr($value, $ENTITIES);\r
+\r
+            // extract all hex HTML entities\r
+            if (preg_match_all($pattern, $value, $matches)) {\r
+\r
+                // loop through hex entities\r
+                $m_max = count($matches[0]);\r
+                for ($m=0; $m<$m_max; $m++) {\r
+\r
+                    // convert to hex number\r
+                    eval('$hex=0x'.$matches[1][$m].';');\r
+\r
+                    // is this a punctuation character?\r
+                    if (\r
+                        ($hex>=0x0020 && $hex<=0x00BF) || // ascii punctuation\r
+                        ($hex>=0x2000 && $hex<=0x206F) || // general punctuation\r
+                        ($hex>=0x3000 && $hex<=0x303F) || // CJK punctuation\r
+                        ($hex>=0xFE30 && $hex<=0xFE4F) || // CJK compatability\r
+                        ($hex>=0xFE50 && $hex<=0xFE6F) || // small form variants\r
+                        ($hex>=0xFF00 && $hex<=0xFF40) || // halfwidth and fullwidth forms (1)\r
+                        ($hex>=0xFF5B && $hex<=0xFF65) || // halfwidth and fullwidth forms (2)\r
+                        ($hex>=0xFFE0 && $hex<=0xFFEE)    // halfwidth and fullwidth forms (3)\r
+                    ) {\r
+                        // add this character\r
+                        $chars[] = $matches[0][$m];\r
+                    }\r
+                }\r
+            }\r
+            $i++;\r
+        }\r
+\r
+        return $chars;\r
+    }\r
+    function v6_expand_OpenPunctuation() {\r
+        $tags = 'data,jumbled-order-exercise';\r
+        $chars = array_merge(\r
+            $this->jmix_OpenPunctuation("$tags,main-order,segment"),\r
+            $this->jmix_OpenPunctuation("$tags,alternate")\r
+        );\r
+        $chars = array_unique($chars);\r
+        $chars = implode('', $chars);\r
+        $chars = $this->js_safe($chars, true);\r
+        return $chars;\r
+    }\r
+    function jmix_OpenPunctuation($tags) {\r
+        $chars = array();\r
+\r
+        // unicode punctuation designations (pi="initial quote", ps="open")\r
+        //  http://www.sql-und-xml.de/unicode-database/pi.html\r
+        //  http://www.sql-und-xml.de/unicode-database/ps.html\r
+        $pi = '0022|0027|00AB|2018|201B|201C|201F|2039';\r
+        $ps = '0028|005B|007B|0F3A|0F3C|169B|201A|201E|2045|207D|208D|2329|23B4|2768|276A|276C|276E|2770|2772|2774|27E6|27E8|27EA|2983|2985|2987|2989|298B|298D|298F|2991|2993|2995|2997|29D8|29DA|29FC|3008|300A|300C|300E|3010|3014|3016|3018|301A|301D|FD3E|FE35|FE37|FE39|FE3B|FE3D|FE3F|FE41|FE43|FE47|FE59|FE5B|FE5D|FF08|FF3B|FF5B|FF5F|FF62';\r
+        $pattern = "/(&#x($pi|$ps);)/i";\r
+\r
+        $ENTITIES = $this->jmix_encode_punctuation('"'."'".'(<[{');\r
+\r
+        $i = 0;\r
+        while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {\r
+            $value = strtr($value, $ENTITIES);\r
+            if (preg_match_all($pattern, $value, $matches)) {\r
+                $chars = array_merge($chars, $matches[0]);\r
+            } \r
+            $i++;\r
+        }\r
+\r
+        return $chars;\r
+    }\r
+    function jmix_encode_punctuation($str) {\r
+        $ENTITIES = array();\r
+        $i_max = strlen($str);\r
+        for ($i=0; $i<$i_max; $i++) {\r
+            $ENTITIES[$str{$i}] = '&#x'.sprintf('%04X', ord($str{$i})).';';\r
+        }\r
+        return $ENTITIES;\r
+    }\r
+    function v6_expand_ExerciseTitle() {\r
+        return $this->parent->xml_value('data,title');\r
+    }\r
+\r
+    // Jmix specials\r
+\r
+    function v6_expand_SegmentArray() {\r
+\r
+        $segments = array();\r
+        $values = array();\r
+        $VALUES = array();\r
+\r
+        // XML tags to the start of a segment\r
+        $tags = 'data,jumbled-order-exercise,main-order,segment';\r
+\r
+        $i = 0;\r
+        while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {\r
+            $VALUE = strtoupper($value);\r
+            $key = array_search($VALUE, $VALUES);\r
+            if (is_numeric($key)) {\r
+                $segments[] = $key;\r
+            } else {\r
+                $segments[] = $i;\r
+                $values[$i] = $value;\r
+                $VALUES[$i] = $VALUE;\r
+            }\r
+            $i++;\r
+        }\r
+\r
+        $this->seed_random_number_generator();\r
+        $keys = array_keys($segments);\r
+        shuffle($keys);\r
+\r
+        $str = '';\r
+        for($i=0; $i<count($keys); $i++) {\r
+            $key = $segments[$keys[$i]];\r
+            $str .= "Segments[$i] = new Array();\n";\r
+            $str .= "Segments[$i][0] = '".$this->js_safe($values[$key], true)."';\n";\r
+            $str .= "Segments[$i][1] = ".($key+1).";\n";\r
+            $str .= "Segments[$i][2] = 0;\n";\r
+        }\r
+        return $str;\r
+    }\r
+    function v6_expand_AnswerArray() {\r
+\r
+        $segments = array();\r
+        $values = array();\r
+        $VALUES = array();\r
+        $escapedvalues = array();\r
+\r
+        // XML tags to the start of a segment\r
+        $tags = 'data,jumbled-order-exercise,main-order,segment';\r
+\r
+        $i = 0;\r
+        while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {\r
+            $VALUE = strtoupper($value);\r
+            $key = array_search($VALUE, $VALUES);\r
+            if (is_numeric($key)) {\r
+                $segments[] = $key+1;\r
+            } else {\r
+                $segments[] = $i+1;\r
+                $values[$i] = $value;\r
+                $VALUES[$i] = $VALUE;\r
+                $escapedvalues[] = preg_quote($value, '/');\r
+            }\r
+            $i++;\r
+        }\r
+\r
+        // start the answers array\r
+        $a = 0;\r
+        $str = 'Answers['.($a++).'] = new Array('.implode(',', $segments).");\n";\r
+\r
+        // pattern to match the next part of an alternate answer\r
+        $pattern = '/^('.implode('|', $escapedvalues).')\\s*/i';\r
+\r
+        // XML tags to the start of an alternate answer\r
+        $tags = 'data,jumbled-order-exercise,alternate';\r
+\r
+        $i = 0;\r
+        while ($value = $this->parent->xml_value($tags, "[$i]['#']")) {\r
+            $segments = array();\r
+            while (strlen($value) && preg_match($pattern, $value, $matches)) {\r
+                $key = array_search($matches[1], $values);\r
+                if (is_numeric($key)) {\r
+                    $segments[] = $key+1;\r
+                    $value = substr($value, strlen($matches[0]));\r
+                } else {\r
+                    // invalid alternate sequence\r
+                    $segments = array();\r
+                    break;\r
+                }\r
+            }\r
+            if (count($segments)) {\r
+                $str .= 'Answers['.($a++).'] = new Array('.implode(',', $segments).");\n";\r
+            }\r
+            $i++;\r
+        }\r
+        return $str;\r
+    }\r
+\r
+    // ===============================================================\r
+\r
+    // JMix (jmix6.js_)\r
+\r
+    function v6_expand_RemainingWords() {\r
+        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',remaining-words');\r
+    }\r
+    function v6_expand_TimesUp() {\r
+        return $this->parent->xml_value('hotpot-config-file,global,times-up');\r
+    }\r
+\r
+    // nav bar\r
+\r
+    function v6_expand_NavBar($navbarid='') {\r
+        $this->navbarid = $navbarid;\r
+\r
+        $tag = 'navbar';\r
+        $this->read_template('hp6navbar.ht_', $tag);\r
+\r
+        unset($this->navbarid);\r
+\r
+        return $this->$tag;\r
+    }\r
+    function v6_expand_TopNavBar() {\r
+        return $this->v6_expand_NavBar('TopNavBar');\r
+    }\r
+    function v6_expand_BottomNavBar() {\r
+        return $this->v6_expand_NavBar('BottomNavBar');\r
+    }\r
+\r
+    // hp6navbar.ht_\r
+\r
+    function v6_expand_NavBarID() {\r
+        // $this->navbarid is set in "$this->v6_expand_NavBar"\r
+        return empty($this->navbarid) ? '' : $this->navbarid;\r
+    }\r
+    function v6_expand_ContentsURL() {\r
+        $url = $this->parent->xml_value('hotpot-config-file,global,contents-url');\r
+        if ($url) {\r
+            $url = hotpot_convert_navbutton_url($this->parent->get_baseurl(), $this->parent->reference, $url, $this->parent->course);\r
+        }\r
+        return $url;\r
+    }\r
+    function v6_expand_NextExURL() {\r
+        $url = $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',next-ex-url');\r
+        if ($url) {\r
+            $url = hotpot_convert_navbutton_url($this->parent->get_baseurl(), $this->parent->reference, $url, $this->parent->course);\r
+        }\r
+        return $url;\r
+    }\r
+\r
+    // conditional blocks\r
+\r
+    function v6_expand_ShowAnswer() {\r
+        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-show-answer');\r
+    }\r
+    function v6_expand_Slide() {\r
+        return true; // whats's this (JMatch drag and drop)\r
+    }\r
+\r
+    // specials (JMatch)\r
+\r
+    function v6_expand_FixedArray() {\r
+        $l_items = array();\r
+        $r_items = array();\r
+        $this->get_jmatch_items($l_items, $r_items);\r
+\r
+        $str = '';\r
+        foreach ($l_items as $i=>$item) {\r
+            $str .= "F[$i] = new Array();\n";\r
+            $str .= "F[$i][0] = '".$this->js_safe($item['text'][0]['#'], true)."';\n";\r
+            $str .= "F[$i][1] = ".($i+1).";\n";\r
+        }\r
+        return $str;\r
+    }\r
+    function v6_expand_DragArray() {\r
+        $l_items = array();\r
+        $r_items = array();\r
+        $this->get_jmatch_items($l_items, $r_items);\r
+\r
+        $str = '';\r
+        foreach ($r_items as $i=>$item) {\r
+            $str .= "D[$i] = new Array();\n";\r
+            $str .= "D[$i][0] = '".$this->js_safe($item['text'][0]['#'], true)."';\n";\r
+            $str .= "D[$i][1] = ".($i+1).";\n";\r
+            $str .= "D[$i][2] = 0;\n";\r
+        }\r
+        return $str;\r
+    }\r
+\r
+    function get_jmatch_items(&$l_items, &$r_items) {\r
+        $tags = 'data,matching-exercise,pair';\r
+        $i = 0;\r
+        while($item = $this->parent->xml_value($tags,"[$i]['#']['left-item'][0]['#']")) {\r
+            if (!empty($item['text'][0]['#'])) {\r
+                $l_items[] = $item;\r
+            }\r
+            $i++;\r
+        }\r
+        $i = 0;\r
+        while($item = $this->parent->xml_value($tags,"[$i]['#']['right-item'][0]['#']")) {\r
+            if (!empty($item['text'][0]['#'])) {\r
+                $r_items[] = $item;\r
+            }\r
+            $i++;\r
+        }\r
+    }\r
+    function shuffle_jmatch_items(&$items) {\r
+        // get moveable items\r
+        $moveable_keys = array();\r
+        for($i=0; $i<count($items); $i++) {\r
+            if(empty($items[$i]['fixed'][0]['#'])) {\r
+                $moveable_keys[] = $i;\r
+            }\r
+        }\r
+        // shuffle moveable items\r
+        $this->seed_random_number_generator();\r
+        shuffle($moveable_keys);\r
+\r
+        $keys = array();\r
+        for($i=0, $ii=0; $i<count($items); $i++) {\r
+            if(empty($items[$i]['fixed'][0]['#'])) {\r
+                //  moveable items are inserted in a shuffled order\r
+                $keys[] = $moveable_keys[$ii++];\r
+            } else {\r
+                //  fixed items stay where they are\r
+                $keys[] = $i;\r
+            }\r
+        }\r
+        return $keys;\r
+    }\r
+    function seed_random_number_generator() {\r
+        static $seeded_RNG = FALSE;\r
+        if (!$seeded_RNG) {\r
+            srand((double) microtime() * 1000000);\r
+            $seeded_RNG = TRUE;\r
+        }\r
+    }\r
+\r
+    // specials (JMix)\r
+\r
+\r
+    // specials (JCloze)\r
+\r
+    function v6_expand_ItemArray() {\r
+        $q = 0;\r
+        $str = '';\r
+        switch ($this->parent->quiztype) {\r
+            case 'jcloze':\r
+                $tags = 'data,gap-fill,question-record';\r
+                while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
+                    $a = 0;\r
+                    $aa = 0;\r
+                    while (($answer=$question."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {\r
+                        $text = $this->js_value($tags,  $answer."['text'][0]['#']", true);\r
+                        if (strlen($text)) {\r
+                            if ($aa==0) { // first time only\r
+                                $str .= "\n";\r
+                                $str .= "I[$q] = new Array();\n";\r
+                                $str .= "I[$q][1] = new Array();\n";\r
+                            }\r
+                            $str .= "I[$q][1][$aa] = new Array();\n";\r
+                            $str .= "I[$q][1][$aa][0] = '$text';\n";\r
+                            $aa++;\r
+                        }\r
+                        $a++;\r
+                    }\r
+                    // add clue, if any answers were found\r
+                    if ($aa) {\r
+                        $clue = $this->js_value($tags, $question."['clue'][0]['#']", true);\r
+                        $str .= "I[$q][2] = '$clue';\n";\r
+                    }\r
+                    $q++;\r
+                }\r
+                break;\r
+            case 'jquiz':\r
+                $str .= "I=new Array();\n";\r
+                $tags = 'data,questions,question-record';\r
+                while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
+\r
+                    $question_type = $this->int_value($tags, $question."['question-type'][0]['#']");\r
+                    $weighting = $this->int_value($tags, $question."['weighting'][0]['#']");\r
+                    $clue = $this->js_value($tags, $question."['clue'][0]['#']", true);\r
+\r
+                    $answers = $question."['answers'][0]['#']";\r
+\r
+                    $a = 0;\r
+                    $aa = 0;\r
+                    while (($answer = $answers."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {\r
+                        $text =     $this->js_value($tags,  $answer."['text'][0]['#']", true);\r
+                        $feedback = $this->js_value($tags,  $answer."['feedback'][0]['#']", true);\r
+                        $correct =  $this->int_value($tags, $answer."['correct'][0]['#']");\r
+                        $percent =  $this->int_value($tags, $answer."['percent-correct'][0]['#']");\r
+                        $include =  $this->int_value($tags, $answer."['include-in-mc-options'][0]['#']");\r
+                        if (strlen($text)) {\r
+                            if ($aa==0) { // first time only\r
+                                $str .= "\n";\r
+                                $str .= "I[$q] = new Array();\n";\r
+                                $str .= "I[$q][0] = $weighting;\n";\r
+                                $str .= "I[$q][1] = '$clue';\n";\r
+                                $str .= "I[$q][2] = '".($question_type-1)."';\n";\r
+                                $str .= "I[$q][3] = new Array();\n";\r
+                            }\r
+                            $str .= "I[$q][3][$aa] = new Array('$text','$feedback',$correct,$percent,$include);\n";\r
+                            $aa++;\r
+                        }\r
+                        $a++;\r
+                    }\r
+                    $q++;\r
+                }\r
+                break;\r
+        }\r
+        return $str;\r
+    }\r
+\r
+    function v6_expand_ClozeBody() {\r
+        $str = '';\r
+\r
+        // get drop down list of words, if required\r
+        $dropdownlist = '';\r
+        if ($this->v6_use_DropDownList()) {\r
+            $this->v6_set_WordList();\r
+            foreach ($this->wordlist as $word) {\r
+                $dropdownlist .= '<option value="'.$word.'">'.$word.'</option>';\r
+            }\r
+        }\r
+\r
+        // cache clues flag and caption\r
+        $includeclues = $this->v6_expand_Clues();\r
+        $cluecaption = $this->v6_expand_ClueCaption();\r
+\r
+        // detect if cloze starts with gap\r
+        $strpos = strpos($this->parent->source, '<gap-fill><question-record>');\r
+        if (is_numeric($strpos)) {\r
+            $startwithgap = true;\r
+        } else {\r
+            $startwithgap = false;\r
+        }\r
+\r
+        // initialize loop values\r
+        $q = 0;\r
+        $tags = 'data,gap-fill';\r
+        $question_record = "$tags,question-record";\r
+\r
+        // loop through text and gaps\r
+        do {\r
+            $text = $this->parent->xml_value($tags, "[0]['#'][$q]");\r
+            $gap = '';\r
+            if (($question="[$q]['#']") && $this->parent->xml_value($question_record, $question)) {\r
+                $gap .= '<span class="GapSpan" id="GapSpan'.$q.'">';\r
+                if ($this->v6_use_DropDownList()) {\r
+                    $gap .= '<select id="Gap'.$q.'"><option value=""></option>'.$dropdownlist.'</select>';\r
+                } else {\r
+                    // minimum gap size\r
+                    $gapsize = 6;\r
+\r
+                    // increase gap size to length of longest answer for this gap\r
+                    $a = 0;\r
+                    while (($answer=$question."['answer'][$a]['#']") && $this->parent->xml_value($question_record, $answer)) {\r
+                        $answertext = $this->parent->xml_value($question_record,  $answer."['text'][0]['#']");\r
+                        $answertext = preg_replace('|&[#a-zA-Z0-9]+;|', 'x', $answertext);\r
+                        $gapsize = max($gapsize, strlen($answertext));\r
+                        $a++;\r
+                    }\r
+\r
+                    $gap .= '<input type="text" id="Gap'.$q.'" onfocus="TrackFocus('.$q.')" onblur="LeaveGap()" class="GapBox" size="'.$gapsize.'"></input>';\r
+                }\r
+                if ($includeclues) {\r
+                    $clue = $this->parent->xml_value($question_record, $question."['clue'][0]['#']");\r
+                    if (strlen($clue)) {\r
+                        $gap .= '<button style="line-height: 1.0" class="FuncButton" onfocus="FuncBtnOver(this)" onmouseover="FuncBtnOver(this)" onblur="FuncBtnOut(this)" onmouseout="FuncBtnOut(this)" onmousedown="FuncBtnDown(this)" onmouseup="FuncBtnOut(this)" onclick="ShowClue('.$q.')">'.$cluecaption.'</button>';\r
+                    }\r
+                }\r
+                $gap .= '</span>';\r
+            }\r
+            if ($startwithgap) {\r
+                $str .= "$gap$text";\r
+            } else {\r
+                $str .= "$text$gap";\r
+            }\r
+            $q++;\r
+        } while (strlen($text) || strlen($gap));\r
+\r
+        return $str;\r
+    }\r
+\r
+    // JCloze quiztype\r
+\r
+    function v6_expand_WordList() {\r
+        $str = '';\r
+        if ($this->v6_include_WordList()) {\r
+            $this->v6_set_WordList();\r
+            $str = implode(' &#160;&#160; ', $this->wordlist);\r
+        }\r
+        return $str;\r
+    }\r
+    function v6_include_WordList() {\r
+        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-word-list');\r
+    }\r
+    function v6_use_DropDownList() {\r
+        return $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',use-drop-down-list');\r
+    }\r
+    function v6_set_WordList() {\r
+\r
+        if (isset($this->wordlist)) {\r
+            // do nothing\r
+        } else {\r
+            $this->wordlist = array();\r
+\r
+            // is the wordlist required\r
+            if ($this->v6_include_WordList() || $this->v6_use_DropDownList()) {\r
+\r
+                $q = 0;\r
+                $tags = 'data,gap-fill,question-record';\r
+                while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
+                    $a = 0;\r
+                    $aa = 0;\r
+                    while (($answer=$question."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {\r
+                        $text = $this->parent->xml_value($tags,  $answer."['text'][0]['#']");\r
+                        $correct =  $this->int_value($tags, $answer."['correct'][0]['#']");\r
+                        if ($text && $correct) { // $correct is always true\r
+                            $this->wordlist[] = $text;\r
+                            $aa++;\r
+                        }\r
+                        $a++;\r
+                    }\r
+                    $q++;\r
+                }\r
+                $this->wordlist = array_unique($this->wordlist);\r
+                sort($this->wordlist);\r
+            }\r
+        }\r
+    }\r
+    function v6_expand_Keypad() {\r
+        $str = '';\r
+        if ($this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-keypad')) {\r
+\r
+            // these characters must always be in the keypad\r
+            $chars = array();\r
+            $this->add_keypad_chars($chars, $this->parent->xml_value('hotpot-config-file,global,keypad-characters'));\r
+\r
+            // append other characters used in the answers\r
+            $tags = '';\r
+            switch ($this->parent->quiztype) {\r
+                case 'jcloze':\r
+                    $tags = 'data,gap-fill,question-record';\r
+                    break;\r
+                case 'jquiz':\r
+                    $tags = 'data,questions,question-record';\r
+                    break;\r
+            }\r
+            if ($tags) {\r
+                $q = 0;\r
+                while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
+\r
+                    if ($this->parent->quiztype=='jquiz') {\r
+                        $answers = $question."['answers'][0]['#']";\r
+                    } else {\r
+                        $answers = $question;\r
+                    }\r
+\r
+                    $a = 0;\r
+                    while (($answer=$answers."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {\r
+                        $this->add_keypad_chars($chars, $this->parent->xml_value($tags,  $answer."['text'][0]['#']"));\r
+                        $a++;\r
+                    }\r
+                    $q++;\r
+                }\r
+            }\r
+\r
+            // remove duplicate characters and sort\r
+            $chars = array_unique($chars);\r
+            usort($chars, "hotpot_sort_keypad_chars");\r
+\r
+            // create keypad buttons for each character\r
+            $str .= '<div class="Keypad">';\r
+            foreach ($chars as $char) {\r
+                $str .= "<button onclick=\"TypeChars('".$this->js_safe($char, true)."'); return false;\">$char</button>";\r
+            }\r
+            $str .= '</div>';\r
+        }\r
+        return $str;\r
+    }\r
+    function add_keypad_chars(&$chars, $text) {\r
+        if (preg_match_all('|&[^;]+;|i', $text, $more_chars)) {\r
+            $chars = array_merge($chars, $more_chars[0]);\r
+        }\r
+    }\r
+    function v6_expand_Correct() {\r
+        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guesses-correct');\r
+    }\r
+    function v6_expand_Incorrect() {\r
+        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',guesses-incorrect');\r
+    }\r
+    function v6_expand_GiveHint() {\r
+        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',next-correct-letter');\r
+    }\r
+    function v6_expand_CaseSensitive() {\r
+        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',case-sensitive');\r
+    }\r
+\r
+    // JCross quiztype\r
+\r
+    function v6_expand_CluesAcrossLabel() {\r
+        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',clues-across');\r
+    }\r
+    function v6_expand_CluesDownLabel() {\r
+        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',clues-down');\r
+    }\r
+    function v6_expand_EnterCaption() {\r
+        return $this->js_value('hotpot-config-file,'.$this->parent->quiztype.',enter-caption');\r
+    }\r
+    function v6_expand_ShowHideClueList() {\r
+        $value = $this->int_value('hotpot-config-file,'.$this->parent->quiztype.',include-clue-list');\r
+        return empty($value) ? ' style="display: none;"' : '';\r
+    }\r
+\r
+    // JCross specials\r
+\r
+    function v6_expand_CluesDown() {\r
+        return $this->v6_expand_jcross_clues('D');\r
+    }\r
+    function v6_expand_CluesAcross() {\r
+        return $this->v6_expand_jcross_clues('A');\r
+    }\r
+    function v6_expand_jcross_clues($direction) {\r
+        // $direction: A(cross) or D(own)\r
+        $row = NULL;\r
+        $r_max = 0;\r
+        $c_max = 0;\r
+        $this->v6_get_jcross_grid($row, $r_max, $c_max);\r
+\r
+        $i = 0; // clue index;\r
+        $str = '';\r
+        for($r=0; $r<=$r_max; $r++) {\r
+            for($c=0; $c<=$c_max; $c++) {\r
+                $aword = $this->get_jcross_aword($row, $r, $r_max, $c, $c_max);\r
+                $dword = $this->get_jcross_dword($row, $r, $r_max, $c, $c_max);\r
+                if ($aword || $dword) {\r
+                    $i++; // increment clue index\r
+\r
+                    // get the definition for this word\r
+                    $def = '';\r
+                    $word = ($direction=='A') ? $aword : $dword;\r
+                    $clues = $this->parent->xml_values('data,crossword,clues,item');\r
+                    foreach ($clues as $clue) {\r
+                        if ($clue['word'][0]['#']==$word) {\r
+                            $def = $clue['def'][0]['#'];\r
+                            $def = strtr($def, array('&#x003C;'=>'<', '&#x003E;'=>'>', "\n"=>'<br />'));\r
+                            break;\r
+                        }\r
+                    }\r
+\r
+                    if (!empty($def)) {\r
+                        $str .= '<tr><td class="ClueNum">'.$i.'. </td><td id="Clue_'.$direction.'_'.$i.'" class="Clue">'.$def.'</td></tr>';\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        return $str;\r
+    }\r
+\r
+    // jcross6.js_\r
+\r
+    function v6_expand_LetterArray() {\r
+        $row = NULL;\r
+        $r_max = 0;\r
+        $c_max = 0;\r
+        $this->v6_get_jcross_grid($row, $r_max, $c_max);\r
+\r
+        $str = '';\r
+        for($r=0; $r<=$r_max; $r++) {\r
+            $str .= "L[$r] = new Array(";\r
+            for($c=0; $c<=$c_max; $c++) {\r
+                $str .= ($c>0 ? ',' : '')."'".$this->js_safe($row[$r]['cell'][$c]['#'], true)."'";\r
+            }\r
+            $str .= ");\n";\r
+        }\r
+        return $str;\r
+    }\r
+    function v6_expand_GuessArray() {\r
+        $row = NULL;\r
+        $r_max = 0;\r
+        $c_max = 0;\r
+        $this->v6_get_jcross_grid($row, $r_max, $c_max);\r
+\r
+        $str = '';\r
+        for($r=0; $r<=$r_max; $r++) {\r
+            $str .= "G[$r] = new Array('".str_repeat("','", $c_max)."');\n";\r
+        }\r
+        return $str;\r
+    }\r
+    function v6_expand_ClueNumArray() {\r
+        $row = NULL;\r
+        $r_max = 0;\r
+        $c_max = 0;\r
+        $this->v6_get_jcross_grid($row, $r_max, $c_max);\r
+\r
+        $i = 0; // clue index\r
+        $str = '';\r
+        for($r=0; $r<=$r_max; $r++) {\r
+            $str .= "CL[$r] = new Array(";\r
+            for($c=0; $c<=$c_max; $c++) {\r
+                if ($c>0) {\r
+                    $str .= ',';\r
+                }\r
+                $aword = $this->get_jcross_aword($row, $r, $r_max, $c, $c_max);\r
+                $dword = $this->get_jcross_dword($row, $r, $r_max, $c, $c_max);\r
+                if (empty($aword) && empty($dword)) {\r
+                    $str .= 0;\r
+                } else {\r
+                    $i++; // increment the clue index\r
+                    $str .= $i;\r
+                }\r
+            }\r
+            $str .= ");\n";\r
+        }\r
+        return $str;\r
+    }\r
+    function v6_expand_GridBody() {\r
+        $row = NULL;\r
+        $r_max = 0;\r
+        $c_max = 0;\r
+        $this->v6_get_jcross_grid($row, $r_max, $c_max);\r
+\r
+        $i = 0; // clue index;\r
+        $str = '';\r
+        for($r=0; $r<=$r_max; $r++) {\r
+            $str .= '<tr id="Row_'.$r.'">';\r
+            for($c=0; $c<=$c_max; $c++) {\r
+                if (empty($row[$r]['cell'][$c]['#'])) {\r
+                    $str .= '<td class="BlankCell">&nbsp;</td>';\r
+                } else {\r
+                    $aword = $this->get_jcross_aword($row, $r, $r_max, $c, $c_max);\r
+                    $dword = $this->get_jcross_dword($row, $r, $r_max, $c, $c_max);\r
+                    if (empty($aword) && empty($dword)) {\r
+                        $str .= '<td class="LetterOnlyCell"><span id="L_'.$r.'_'.$c.'">&nbsp;</span></td>';\r
+                    } else {\r
+                        $i++; // increment clue index\r
+                        $str .= '<td class="NumLetterCell"><a href="javascript:void(0);" class="GridNum" onclick="ShowClue('.$i.','.$r.','.$c.')">'.$i.'</a><span class="NumLetterCellText" id="L_'.$r.'_'.$c.'" onclick="ShowClue('.$i.','.$r.','.$c.')">&nbsp;&nbsp;&nbsp;</span></td>';\r
+                    }\r
+                }\r
+            }\r
+            $str .= '</tr>';\r
+        }\r
+        return $str;\r
+    }\r
+    function v6_get_jcross_grid(&$row, &$r_max, &$c_max) {\r
+        $row = $this->parent->xml_values('data,crossword,grid,row');\r
+        $r_max = 0;\r
+        $c_max = 0;\r
+        if (isset($row) && is_array($row)) {\r
+            for($r=0; $r<count($row); $r++) {\r
+                if (isset($row[$r]['cell']) && is_array($row[$r]['cell'])) {\r
+                    for($c=0; $c<count($row[$r]['cell']); $c++) {\r
+                        if (!empty($row[$r]['cell'][$c]['#'])) {\r
+                            $r_max = max($r, $r_max);\r
+                            $c_max = max($c, $c_max);\r
+                        }\r
+                    } // end for $c\r
+                }\r
+            } // end for $r\r
+        }\r
+    }\r
+    function get_jcross_dword(&$row, $r, $r_max, $c, $c_max) {\r
+        $str = '';\r
+        if (($r==0 || empty($row[$r-1]['cell'][$c]['#'])) && $r<$r_max && !empty($row[$r+1]['cell'][$c]['#'])) {\r
+            $str = $this->get_jcross_word($row, $r, $r_max, $c, $c_max, true);\r
+        }\r
+        return $str;\r
+    }\r
+    function get_jcross_aword(&$row, $r, $r_max, $c, $c_max) {\r
+        $str = '';\r
+        if (($c==0 || empty($row[$r]['cell'][$c-1]['#'])) && $c<$c_max && !empty($row[$r]['cell'][$c+1]['#'])) {\r
+            $str = $this->get_jcross_word($row, $r, $r_max, $c, $c_max, false);\r
+        }\r
+        return $str;\r
+    }\r
+    function get_jcross_word(&$row, $r, $r_max, $c, $c_max, $go_down=false) {\r
+        $str = '';\r
+        while ($r<=$r_max && $c<=$c_max && !empty($row[$r]['cell'][$c]['#'])) {\r
+            $str .= $row[$r]['cell'][$c]['#'];\r
+            if ($go_down) {\r
+                $r++;\r
+            } else {\r
+                $c++;\r
+            }\r
+        }\r
+        return $str;\r
+    }\r
+\r
+    // specials (JQuiz)\r
+\r
+    function v6_expand_QuestionOutput() {\r
+        $str = '';\r
+        $str .= '<ol class="QuizQuestions" id="Questions">'."\n";\r
+\r
+        $q = 0;\r
+        $tags = 'data,questions,question-record';\r
+        while (($question="[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
+\r
+            // get question\r
+            $question_text = $this->parent->xml_value($tags, $question."['question'][0]['#']");\r
+            $question_type = $this->parent->xml_value($tags, $question."['question-type'][0]['#']");\r
+\r
+            // check we have a question\r
+            if ($question_text && $question_type) {\r
+\r
+                $str .= '<li class="QuizQuestion" id="Q_'.$q.'" style="display: none;">';\r
+                $str .= '<p class="QuestionText">'.$question_text.'</p>';\r
+\r
+                if (\r
+                    $question_type==HOTPOT_JQUIZ_SHORTANSWER || \r
+                    $question_type==HOTPOT_JQUIZ_HYBRID\r
+                ) {\r
+                    $str .= '<div class="ShortAnswer" id="Q_'.$q.'_SA"><form method="post" action="" onsubmit="return false;"><div>';\r
+                    $str .= '<input type="text" id="Q_'.$q.'_Guess" onfocus="TrackFocus('."'".'Q_'.$q.'_Guess'."'".')" onblur="LeaveGap()" class="ShortAnswerBox" size="9"></input><br /><br />';\r
+\r
+                    $caption = $this->v6_expand_CheckCaption();\r
+                    $str .= $this->v6_expand_jquiz_button($caption, "CheckShortAnswer($q)");\r
+\r
+                    if ($this->v6_expand_Hint()) {\r
+                        $caption = $this->v6_expand_HintCaption();\r
+                        $str .= $this->v6_expand_jquiz_button($caption, "ShowHint($q)");\r
+                    }\r
+\r
+                    if ($this->v6_expand_ShowAnswer()) {\r
+                        $caption = $this->v6_expand_ShowAnswerCaption();\r
+                        $str .= $this->v6_expand_jquiz_button($caption, "ShowAnswers($q)");\r
+                    }\r
+\r
+                    $str .= '</div></form></div>';\r
+                }\r
+\r
+                if (\r
+                    $question_type==HOTPOT_JQUIZ_MULTICHOICE || \r
+                    $question_type==HOTPOT_JQUIZ_HYBRID ||\r
+                    $question_type==HOTPOT_JQUIZ_MULTISELECT\r
+                ) {\r
+\r
+                    switch ($question_type) {\r
+                        case HOTPOT_JQUIZ_MULTICHOICE: \r
+                            $str .= '<ol class="MCAnswers">'."\n";\r
+                        break;\r
+                        case HOTPOT_JQUIZ_HYBRID:\r
+                            $str .= '<ol class="MCAnswers" id="Q_'.$q.'_Hybrid_MC" style="display: none;">'."\n";\r
+                        break;\r
+                        case HOTPOT_JQUIZ_MULTISELECT:\r
+                            $str .= '<ol class="MSelAnswers">'."\n";\r
+                        break;\r
+                    }\r
+\r
+                    $a = 0;\r
+                    $aa = 0;\r
+                    $answers = $question."['answers'][0]['#']";\r
+                    while (($answer = $answers."['answer'][$a]['#']") && $this->parent->xml_value($tags, $answer)) {\r
+                        $text = $this->parent->xml_value($tags, $answer."['text'][0]['#']");\r
+                        if ($text) {\r
+                            switch ($question_type) {\r
+                                case HOTPOT_JQUIZ_MULTICHOICE:\r
+                                case HOTPOT_JQUIZ_HYBRID:\r
+                                    $include = $this->int_value($tags, $answer."['include-in-mc-options'][0]['#']");\r
+                                    if ($include) {\r
+                                        $str .= '<li id="Q_'.$q.'_'.$aa.'"><button class="FuncButton" onfocus="FuncBtnOver(this)" onblur="FuncBtnOut(this)" onmouseover="FuncBtnOver(this)" onmouseout="FuncBtnOut(this)" onmousedown="FuncBtnDown(this)" onmouseup="FuncBtnOut(this)" id="Q_'.$q.'_'.$aa.'_Btn" onclick="CheckMCAnswer('.$q.','.$aa.',this)">&nbsp;&nbsp;?&nbsp;&nbsp;</button>&nbsp;&nbsp;'.$text.'</li>'."\n";\r
+                                    }\r
+                                break;\r
+                                case HOTPOT_JQUIZ_MULTISELECT:\r
+                                    $str .= '<li id="Q_'.$q.'_'.$aa.'"><form method="post" action="" onsubmit="return false;"><div><input type="checkbox" id="Q_'.$q.'_'.$aa.'_Chk" class="MSelCheckbox" />'.$text.'</div></form></li>'."\n";\r
+                                break;\r
+                            }\r
+                            $aa++;\r
+                        }\r
+                        $a++;\r
+                    }\r
+\r
+                    $str .= '</ol>';\r
+\r
+                    if ($question_type==HOTPOT_JQUIZ_MULTISELECT) {\r
+                        $caption = $this->v6_expand_CheckCaption();\r
+                        $str .= $this->v6_expand_jquiz_button($caption, "CheckMultiSelAnswer($q)");\r
+                    }\r
+                }\r
+\r
+                $str .= "</li>\n";\r
+            }\r
+            $q++;\r
+\r
+        } // end while $question\r
+\r
+        $str .= "</ol>\n";\r
+        return $str;\r
+    }\r
+\r
+    function v6_expand_jquiz_button($caption, $onclick) {\r
+        return '<button class="FuncButton" onfocus="FuncBtnOver(this)" onblur="FuncBtnOut(this)" onmouseover="FuncBtnOver(this)" onmouseout="FuncBtnOut(this)" onmousedown="FuncBtnDown(this)" onmouseup="FuncBtnOut(this)" onclick="'.$onclick.'">'.$caption.'</button>';\r
+    }\r
+\r
+    // jquiz.js_\r
+\r
+    function v6_expand_MultiChoice() {\r
+        return $this->v6_jquiz_question_type(HOTPOT_JQUIZ_MULTICHOICE);\r
+    }\r
+    function v6_expand_ShortAnswer() {\r
+        return $this->v6_jquiz_question_type(HOTPOT_JQUIZ_SHORTANSWER);\r
+    }\r
+    function v6_expand_MultiSelect() {\r
+        return $this->v6_jquiz_question_type(HOTPOT_JQUIZ_MULTISELECT);\r
+    }\r
+    function v6_jquiz_question_type($type) {\r
+        // does this quiz have any questions of the given $type?\r
+        $flag = false;\r
+\r
+        $q = 0;\r
+        $tags = 'data,questions,question-record';\r
+        while (($question = "[$q]['#']") && $this->parent->xml_value($tags, $question)) {\r
+            $question_type = $this->parent->xml_value($tags, $question."['question-type'][0]['#']");\r
+            if ($question_type==$type || ($question_type==HOTPOT_JQUIZ_HYBRID && ($type==HOTPOT_JQUIZ_MULTICHOICE || $type==HOTPOT_JQUIZ_SHORTANSWER))) {\r
+                $flag = true;\r
+                break;\r
+            }\r
+            $q++;\r
+        }\r
+        return $flag;\r
+    }\r
+    function v6_expand_CorrectFirstTime() {\r
+        return $this->js_value('hotpot-config-file,global,correct-first-time');\r
+    }\r
+    function v6_expand_ContinuousScoring() {\r
+        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',continuous-scoring');\r
+    }\r
+    function v6_expand_ShowCorrectFirstTime() {\r
+        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',show-correct-first-time');\r
+    }\r
+    function v6_expand_ShuffleAs() {\r
+        return $this->bool_value('hotpot-config-file,'.$this->parent->quiztype.',shuffle-answers');\r
+    }\r
+\r
+    function v6_expand_DefaultRight() {\r
+        return $this->v6_expand_GuessCorrect();\r
+    }\r
+    function v6_expand_DefaultWrong() {\r
+        return $this->v6_expand_GuessIncorrect();\r
+    }\r
+    function v6_expand_ShowAllQuestionsCaptionJS() {\r
+        return $this->v6_expand_ShowAllQuestionsCaption();\r
+    }\r
+    function v6_expand_ShowOneByOneCaptionJS() {\r
+        return $this->v6_expand_ShowOneByOneCaption();\r
+    }\r
+\r
+    // hp6checkshortanswers.js_ (JQuiz)\r
+\r
+    function v6_expand_CorrectList() {\r
+        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',correct-answers');\r
+    }\r
+    function v6_expand_HybridTries() {\r
+        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',short-answer-tries-on-hybrid-q');\r
+    }\r
+    function v6_expand_PleaseEnter() {\r
+        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',enter-a-guess');\r
+    }\r
+    function v6_expand_PartlyIncorrect() {\r
+        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',partly-incorrect');\r
+    }\r
+    function v6_expand_ShowAnswerCaption() {\r
+        return $this->parent->xml_value('hotpot-config-file,'.$this->parent->quiztype.',show-answer-caption');\r
+    }\r
+    function v6_expand_ShowAlsoCorrect() {\r
+        return $this->bool_value('hotpot-config-file,global,show-also-correct');\r
+    }\r
 \r
 } // end class\r
 function hotpot_sort_keypad_chars($a, $b) {\r
-       $a =  hotpot_keypad_sort_value($a);\r
-       $b =  hotpot_keypad_sort_value($b);\r
-       return ($a<$b) ? -1 : ($a==$b ? 0 : 1);\r
+    $a =  hotpot_keypad_sort_value($a);\r
+    $b =  hotpot_keypad_sort_value($b);\r
+    return ($a<$b) ? -1 : ($a==$b ? 0 : 1);\r
 }\r
 function hotpot_keypad_sort_value($char) {\r
 \r
-       // hexadecimal\r
-       if (preg_match('|&#x([0-9A-F]+);|ie', $char, $matches)) {\r
-               $ord = hexdec($matches[1]);\r
+    // hexadecimal\r
+    if (preg_match('|&#x([0-9A-F]+);|ie', $char, $matches)) {\r
+        $ord = hexdec($matches[1]);\r
 \r
-       // decimal\r
-       } else if (preg_match('|&#(\d+);|i', $char, $matches)) {\r
-               $ord = intval($matches[1]);\r
+    // decimal\r
+    } else if (preg_match('|&#(\d+);|i', $char, $matches)) {\r
+        $ord = intval($matches[1]);\r
 \r
-       // other html entity\r
-       } else if (preg_match('|&[^;]+;|', $char, $matches)) {\r
-               $char = html_entity_decode($matches[0]);\r
-               $ord = empty($char) ? 0 : ord($char);\r
+    // other html entity\r
+    } else if (preg_match('|&[^;]+;|', $char, $matches)) {\r
+        $char = html_entity_decode($matches[0]);\r
+        $ord = empty($char) ? 0 : ord($char);\r
 \r
-       // not an html entity\r
-       } else {\r
-               $char = trim($char);\r
-               $ord = empty($char) ? 0 : ord($char);\r
-       }\r
+    // not an html entity\r
+    } else {\r
+        $char = trim($char);\r
+        $ord = empty($char) ? 0 : ord($char);\r
+    }\r
 \r
-       // lowercase letters (plain or accented)\r
-       if (($ord>=97 && $ord<=122) || ($ord>=224 && $ord<=255)) {\r
-               $sort_value = ($ord-31).'.'.sprintf('%04d', $ord);\r
+    // lowercase letters (plain or accented)\r
+    if (($ord>=97 && $ord<=122) || ($ord>=224 && $ord<=255)) {\r
+        $sort_value = ($ord-31).'.'.sprintf('%04d', $ord);\r
 \r
-       // all other characters\r
-       } else {\r
-               $sort_value = $ord;\r
-       }\r
+    // all other characters\r
+    } else {\r
+        $sort_value = $ord;\r
+    }\r
 \r
-       return $sort_value;\r
+    return $sort_value;\r
 } \r
 \r
 ?>\r
index ab9c01324dd9558e1c4dde97ab7a7751d6aec153..86b5d7332cc8d612d9578b371d2ea70c9df51da1 100644 (file)
 <?PHP // $Id$
-       /// This page prints a hotpot quiz
-       if (defined('HOTPOT_FIRST_ATTEMPT') && HOTPOT_FIRST_ATTEMPT==false) {
-               // this script is being included (by attempt.php)
-       } else {
-               // this script is being called directly from the browser
-               define('HOTPOT_FIRST_ATTEMPT', true);
-               require_once("../../config.php");
-               require_once("lib.php");
+    /// This page prints a hotpot quiz
+    if (defined('HOTPOT_FIRST_ATTEMPT') && HOTPOT_FIRST_ATTEMPT==false) {
+        // this script is being included (by attempt.php)
+    } else {
+        // this script is being called directly from the browser
+        define('HOTPOT_FIRST_ATTEMPT', true);
+        require_once("../../config.php");
+        require_once("lib.php");
 
-               $id = optional_param("id"); // Course Module ID, or
-               $hp = optional_param("hp"); // hotpot ID
+        $id = optional_param("id"); // Course Module ID, or
+        $hp = optional_param("hp"); // hotpot ID
 
-               if ($id) {
-                       if (! $cm = get_coursemodule_from_id('hotpot', $id)) {
-                               error("Course Module ID was incorrect");
-                       }
-                       if (! $course = get_record("course", "id", $cm->course)) {
-                               error("Course is misconfigured");
-                       }
-                       if (! $hotpot = get_record("hotpot", "id", $cm->instance)) {
-                               error("Course module is incorrect");
-                       }
+        if ($id) {
+            if (! $cm = get_coursemodule_from_id('hotpot', $id)) {
+                error("Course Module ID was incorrect");
+            }
+            if (! $course = get_record("course", "id", $cm->course)) {
+                error("Course is misconfigured");
+            }
+            if (! $hotpot = get_record("hotpot", "id", $cm->instance)) {
+                error("Course module is incorrect");
+            }
 
-               } else {
-                       if (! $hotpot = get_record("hotpot", "id", $hp)) {
-                               error("Course module is incorrect");
-                       }
-                       if (! $course = get_record("course", "id", $hotpot->course)) {
-                               error("Course is misconfigured");
-                       }
-                       if (! $cm = get_coursemodule_from_instance("hotpot", $hotpot->id, $course->id)) {
-                               error("Course Module ID was incorrect");
-                       }
-               }
-               require_login($course->id);
-       }
-       // set nextpage (for error messages)
-       $nextpage = "$CFG->wwwroot/course/view.php?id=$course->id";
-       // header strings
-       $title = strip_tags($course->shortname.': '.$hotpot->name);
-       $heading = "$course->fullname";
-       $target = empty($CFG->framename) ? '' : ' target="'.$CFG->framename.'"'; 
-       $navigation = '<a'.$target.' href="'.$CFG->wwwroot.'/mod/hotpot/index.php?id='.$course->id.'">'.get_string("modulenameplural", "hotpot")."</a> -> $hotpot->name";
-       if ($course->category) {
-               $navigation = '<a'.$target.' href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">'.$course->shortname.'</a> -> '.$navigation;
-       }
-       $button = update_module_button($cm->id, $course->id, get_string("modulename", "hotpot").'" style="font-size:0.75em;');
-       $loggedinas = '<span class="logininfo">'.user_login_string($course, $USER).'</span>';
-       $time = time();
-       $hppassword = optional_param('hppassword');
-       if (HOTPOT_FIRST_ATTEMPT && !isteacher($course->id)) {
-               // check this quiz is available to this student
-               // error message, if quiz is unavailable
-               $error = '';
-               // check quiz is visible
-               if (!hotpot_is_visible($cm)) {
-                       $error = get_string("activityiscurrentlyhidden");
-               // check network address
-               } else if ($hotpot->subnet && !address_in_subnet($_SERVER['REMOTE_ADDR'], $hotpot->subnet)) {
-                       $error = get_string("subneterror", "quiz");
-               // check number of attempts
-               } else if ($hotpot->attempts && $hotpot->attempts <= count_records('hotpot_attempts', 'hotpot', $hotpot->id, 'userid', $USER->id)) {
-                       $error = get_string("nomoreattempts", "quiz");
-               // get password
-               } else if ($hotpot->password && empty($hppassword)) {
-                       print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas, false);
-                       print_heading($hotpot->name);
-                       $boxalign = 'center';
-                       $boxwidth = 500;
-                       if (trim(strip_tags($hotpot->summary))) {
-                               print_simple_box_start($boxalign, $boxwidth);
-                               print '<div align="center">'.format_text($hotpot->summary)."</div>\n";
-                               print_simple_box_end();
-                               print "<br />\n";
-                       }
-                       print '<form name="passwordform" method="post" action="view.php?id='.$cm->id.'">'."\n";
-                       print_simple_box_start($boxalign, $boxwidth);
-                       print '<div align="center">';
-                       print get_string('requirepasswordmessage', 'quiz').'<br /><br />';
-                       print '<b>'.get_string('password').':</b> ';
-                       print '<input name="hppassword" type="password" value=""> ';
-                       print '<input type="submit" value="'.get_string("ok").'"> ';
-                       print "</div>\n";
-                       print_simple_box_end();
-                       print "</form>\n";
-                       print_footer();
-                       exit;
-               // check password
-               } else if ($hotpot->password && strcmp($hotpot->password, $hppassword)) {
-                       $error = get_string("passworderror", "quiz");
-                       $nextpage = "view.php?id=$cm->id";
-               // check quiz is open
-               } else if ($hotpot->timeopen && $hotpot->timeopen > $time) {
-                       $error = get_string("quiznotavailable", "quiz", userdate($hotpot->timeopen))."<br />\n";
-               // check quiz is not closed
-               } else if ($hotpot->timeclose && $hotpot->timeclose < $time) {
-                       $error = get_string("quizclosed", "quiz", userdate($hotpot->timeclose))."<br />\n";
-               }
-               if ($error) {
-                       print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas, false);
-                       notice($error, $nextpage);
-                       //
-                       // script stops here, if quiz is unavailable to student
-                       //
-               }
-       }
-       $available_msg = '';
-       if (!empty($hotpot->timeclose) && $hotpot->timeclose > $time) {
-               // quiz is available until 'timeclose'
-               $available_msg = get_string("quizavailable", "quiz", userdate($hotpot->timeclose))."<br />\n";
-       }
-       // open and parse the source file
-       if(!$hp = new hotpot_xml_quiz($hotpot)) {
-               error("Quiz is unavailable at the moment");
-       }
-       $get_js = optional_param('js');
-       $get_css = optional_param('css');
-       $framename = optional_param('framename');
-       // look for <frameset> (HP5 v5)
-       $frameset = '';
-       $frameset_tags = '';
-       if (preg_match_all('|<frameset([^>]*)>(.*?)</frameset>|is', $hp->html, $matches)) {
-               $last = count($matches[0])-1;
-               $frameset = $matches[2][$last];
-               $frameset_tags = $matches[1][$last];
-       }
-       // if HTML is being requested ...
-       if (empty($get_js) && empty($get_css)) {
-               if (empty($frameset)) { 
-                       // HP v6
-                       if ($hotpot->navigation==HOTPOT_NAVIGATION_FRAME || $hotpot->navigation==HOTPOT_NAVIGATION_IFRAME) {
-                               $get_html = ($framename=='main') ? true : false;
-                       } else {
-                               $get_html = true;
-                       }
-               } else { 
-                       // HP5 v5
-                       $get_html = empty($framename) ? true : false;
-               }
-               if ($get_html) {
-               
-                       if (HOTPOT_FIRST_ATTEMPT) {
-                               add_to_log($course->id, "hotpot", "view", "view.php?id=$cm->id", "$hotpot->id", "$cm->id");
+        } else {
+            if (! $hotpot = get_record("hotpot", "id", $hp)) {
+                error("Course module is incorrect");
+            }
+            if (! $course = get_record("course", "id", $hotpot->course)) {
+                error("Course is misconfigured");
+            }
+            if (! $cm = get_coursemodule_from_instance("hotpot", $hotpot->id, $course->id)) {
+                error("Course Module ID was incorrect");
+            }
+        }
+        require_login($course->id);
+    }
+    // set nextpage (for error messages)
+    $nextpage = "$CFG->wwwroot/course/view.php?id=$course->id";
+    // header strings
+    $title = strip_tags($course->shortname.': '.$hotpot->name);
+    $heading = "$course->fullname";
+    $target = empty($CFG->framename) ? '' : ' target="'.$CFG->framename.'"'; 
+    $navigation = '<a'.$target.' href="'.$CFG->wwwroot.'/mod/hotpot/index.php?id='.$course->id.'">'.get_string("modulenameplural", "hotpot")."</a> -> $hotpot->name";
+    if ($course->category) {
+        $navigation = '<a'.$target.' href="'.$CFG->wwwroot.'/course/view.php?id='.$course->id.'">'.$course->shortname.'</a> -> '.$navigation;
+    }
+    $button = update_module_button($cm->id, $course->id, get_string("modulename", "hotpot").'" style="font-size:0.75em;');
+    $loggedinas = '<span class="logininfo">'.user_login_string($course, $USER).'</span>';
+    $time = time();
+    $hppassword = optional_param('hppassword');
+    if (HOTPOT_FIRST_ATTEMPT && !isteacher($course->id)) {
+        // check this quiz is available to this student
+        // error message, if quiz is unavailable
+        $error = '';
+        // check quiz is visible
+        if (!hotpot_is_visible($cm)) {
+            $error = get_string("activityiscurrentlyhidden");
+        // check network address
+        } else if ($hotpot->subnet && !address_in_subnet($_SERVER['REMOTE_ADDR'], $hotpot->subnet)) {
+            $error = get_string("subneterror", "quiz");
+        // check number of attempts
+        } else if ($hotpot->attempts && $hotpot->attempts <= count_records('hotpot_attempts', 'hotpot', $hotpot->id, 'userid', $USER->id)) {
+            $error = get_string("nomoreattempts", "quiz");
+        // get password
+        } else if ($hotpot->password && empty($hppassword)) {
+            print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas, false);
+            print_heading($hotpot->name);
+            $boxalign = 'center';
+            $boxwidth = 500;
+            if (trim(strip_tags($hotpot->summary))) {
+                print_simple_box_start($boxalign, $boxwidth);
+                print '<div align="center">'.format_text($hotpot->summary)."</div>\n";
+                print_simple_box_end();
+                print "<br />\n";
+            }
+            print '<form name="passwordform" method="post" action="view.php?id='.$cm->id.'">'."\n";
+            print_simple_box_start($boxalign, $boxwidth);
+            print '<div align="center">';
+            print get_string('requirepasswordmessage', 'quiz').'<br /><br />';
+            print '<b>'.get_string('password').':</b> ';
+            print '<input name="hppassword" type="password" value=""> ';
+            print '<input type="submit" value="'.get_string("ok").'"> ';
+            print "</div>\n";
+            print_simple_box_end();
+            print "</form>\n";
+            print_footer();
+            exit;
+        // check password
+        } else if ($hotpot->password && strcmp($hotpot->password, $hppassword)) {
+            $error = get_string("passworderror", "quiz");
+            $nextpage = "view.php?id=$cm->id";
+        // check quiz is open
+        } else if ($hotpot->timeopen && $hotpot->timeopen > $time) {
+            $error = get_string("quiznotavailable", "quiz", userdate($hotpot->timeopen))."<br />\n";
+        // check quiz is not closed
+        } else if ($hotpot->timeclose && $hotpot->timeclose < $time) {
+            $error = get_string("quizclosed", "quiz", userdate($hotpot->timeclose))."<br />\n";
+        }
+        if ($error) {
+            print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas, false);
+            notice($error, $nextpage);
+            //
+            // script stops here, if quiz is unavailable to student
+            //
+        }
+    }
+    $available_msg = '';
+    if (!empty($hotpot->timeclose) && $hotpot->timeclose > $time) {
+        // quiz is available until 'timeclose'
+        $available_msg = get_string("quizavailable", "quiz", userdate($hotpot->timeclose))."<br />\n";
+    }
+    // open and parse the source file
+    if(!$hp = new hotpot_xml_quiz($hotpot)) {
+        error("Quiz is unavailable at the moment");
+    }
+    $get_js = optional_param('js');
+    $get_css = optional_param('css');
+    $framename = optional_param('framename');
+    // look for <frameset> (HP5 v5)
+    $frameset = '';
+    $frameset_tags = '';
+    if (preg_match_all('|<frameset([^>]*)>(.*?)</frameset>|is', $hp->html, $matches)) {
+        $last = count($matches[0])-1;
+        $frameset = $matches[2][$last];
+        $frameset_tags = $matches[1][$last];
+    }
+    // if HTML is being requested ...
+    if (empty($get_js) && empty($get_css)) {
+        if (empty($frameset)) { 
+            // HP v6
+            if ($hotpot->navigation==HOTPOT_NAVIGATION_FRAME || $hotpot->navigation==HOTPOT_NAVIGATION_IFRAME) {
+                $get_html = ($framename=='main') ? true : false;
+            } else {
+                $get_html = true;
+            }
+        } else { 
+            // HP5 v5
+            $get_html = empty($framename) ? true : false;
+        }
+        if ($get_html) {
+        
+            if (HOTPOT_FIRST_ATTEMPT) {
+                add_to_log($course->id, "hotpot", "view", "view.php?id=$cm->id", "$hotpot->id", "$cm->id");
 
-                               $attemptid = hotpot_add_attempt($hotpot->id);
-                               if (! is_numeric($attemptid)) {
-                                       error('Could not insert attempt record: '.$db->ErrorMsg);
-                               }
-                       }
-                       $hp->adjust_media_urls();
-                       if (empty($frameset)) {
-                               // HP6 v6
-                               switch ($hotpot->navigation) {
-                                       case HOTPOT_NAVIGATION_BUTTONS:
-                                               // do nothing (i.e. leave buttons as they are)
-                                               break;
-                                       case HOTPOT_NAVIGATION_GIVEUP:
-                                               $hp->insert_giveup_form($attemptid, '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->');
-                                               break;
-                                       default:
-                                               $hp->remove_nav_buttons();
-                               }
-                               if (isset($hp->real_outputformat) && $hp->real_outputformat==HOTPOT_OUTPUTFORMAT_MOBILE) {
-                                       $hp->insert_submission_form($attemptid, '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->', true);
-                               } else {
-                                       $hp->insert_submission_form($attemptid, '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->');
-                               }
-                       } else {
-                               // HP5 v5
-                               switch ($hotpot->navigation) {
-                                       case HOTPOT_NAVIGATION_BUTTONS:
-                                               // convert URLs in nav buttons
-                                               break;
-                                       case HOTPOT_NAVIGATION_GIVEUP:
-                                               //      $hp->insert_giveup_form($attemptid, '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->');
-                                               break;
-                                       default:
-                                               // remove navigation buttons
-                                               $hp->html = preg_replace('#NavBar\+=(.*);#', '', $hp->html);
-                               }
-                               $hp->insert_submission_form($attemptid, "var NavBar='", "';");
-                       }
-               }
-       }
-       //FEEDBACK = new Array();
-       //FEEDBACK[0] = ''; // url of feedback page/script
-       //FEEDBACK[1] = ''; // array of array('teachername', 'value');
-       //FEEDBACK[2] = ''; // 'student name' [formmail only]
-       //FEEDBACK[3] = ''; // 'student email' [formmail only]
-       //FEEDBACK[4] = ''; // window width
-       //FEEDBACK[5] = ''; // window height
-       //FEEDBACK[6] = ''; // 'Send a message to teacher' [prompt/button text]
-       //FEEDBACK[7] = ''; // 'Title'
-       //FEEDBACK[8] = ''; // 'Teacher'
-       //FEEDBACK[9] = ''; // 'Message'
-       //FEEDBACK[10] = ''; // 'Close this window'
-       $feedback = array();
-       switch ($hotpot->studentfeedback) {
-               case HOTPOT_FEEDBACK_NONE:
-                       // do nothing
-                       break;
-               case HOTPOT_FEEDBACK_WEBPAGE:
-                       if (empty($hotpot->studentfeedbackurl)) {
-                               $hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
-                       } else {
-                               $feedback[0] = "'$hotpot->studentfeedbackurl'";
-                       }
-                       break;
-               case HOTPOT_FEEDBACK_FORMMAIL:
-                       $teachers = hotpot_feedback_teachers($course, $hotpot);
-                       if (empty($teachers) || empty($hotpot->studentfeedbackurl)) {
-                               $hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
-                       } else {
-                               $feedback[0] = "'$hotpot->studentfeedbackurl'";
-                               $feedback[1] = $teachers;
-                               $feedback[2] = "'".fullname($USER)."'";
-                               $feedback[3] = "'".$USER->email."'";
-                               $feedback[4] = 500; // width
-                               $feedback[5] = 300; // height
-                       }
-                       break;
-               case HOTPOT_FEEDBACK_MOODLEFORUM:
-                       $module = get_record('modules', 'name', 'forum');
-                       $forums = get_records('forum', 'course', "$course->id");
-                       if (empty($module) || empty($module->visible) || empty($forums)) {
-                               $hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
-                       } else {
-                               $feedback[0] = "'$CFG->wwwroot/mod/forum/index.php?id=$course->id'";
-                       }
-                       break;
-               case HOTPOT_FEEDBACK_MOODLEMESSAGING:
-                       $teachers = hotpot_feedback_teachers($course, $hotpot);
-                       if (empty($CFG->messaging) || empty($teachers)) {
-                               $hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
-                       } else {
-                               $feedback[0] = "'$CFG->wwwroot/message/discussion.php?id='";
-                               $feedback[1] = $teachers;
-                               $feedback[4] = 400; // width
-                               $feedback[5] = 500; // height
-                       }
-                       break;
-               default:
-                       // do nothing
-       }
-       if ($hotpot->studentfeedback != HOTPOT_FEEDBACK_NONE) {
-               $feedback[6] = "'Send a message to teacher'";
-               $feedback[7] = "'Title'";
-               $feedback[8] = "'Teacher'";
-               $feedback[9] = "'Message'";
-               $feedback[10] = "'Close this window'";
-               $js = '';
-               foreach ($feedback as $i=>$str) {
-                       $js .= 'FEEDBACK['.$i."] = $str;\n";
-               }
-               $js = '<script type="text/javascript" language="javascript">'."<!--\n"."FEEDBACK = new Array();\n".$js."//--></script>\n";
-               $hp->html = preg_replace('|</head>|i', "$js</head>", $hp->html, 1);
-       }
-       // insert hot-potatoes.js
-       $hp->insert_script(HOTPOT_JS);
-       // extract first <head> tag
-       $head = '';
-       $pattern = '|<head([^>]*)>(.*?)</head>|is';
-       if (preg_match($pattern, $hp->html, $matches)) {
-               $head = $matches[2];
-               // remove <title>
-               $head = preg_replace('|<title[^>]*>(.*?)</title>|is', '', $head);
-       }
-       // extract <style> tags (and remove from $head)
-       $styles = '';
-       $pattern = '|<style([^>]*)>(.*?)</style>|is';
-       if (preg_match_all($pattern, $head, $matches)) {
-               $count = count($matches[0]);
-               for ($i=0; $i<$count; $i++) {
-                       $styles .= $matches[0][$i]."\n";
-                       $head = str_replace($matches[0][$i], '', $head);
-               }
-       }
-       // extract <script> tags (and remove from $head)
-       $scripts = '';
-       $pattern = '|<script([^>]*)>(.*?)</script>|is';
-       if (preg_match_all($pattern, $head, $matches)) {
-               $count = count($matches[0]);
-               for ($i=0; $i<$count; $i++) {
-                       $scripts .= $matches[0][$i]."\n";
-                       $head = str_replace($matches[0][$i], '', $head);
-               }
-       }
-       // extract <body> tags
-       $body = '';
-       $body_tags = '';
-       $footer = '</html>';
-       // HP6 and some HP5 (v6 and v4) 
-       if (preg_match('|<body'.'([^>]*'.'onLoad=(["\'])(.*?)(\\2)'.'[^>]*)'.'>(.*)</body>|is', $hp->html, $matches)) {
-               $body = $matches[5]; // contents of first <body onload="StartUp()">...</body> block
-               $body_tags = $matches[1];
-               // workaround to ensure javascript onload routine for quiz is always executed
-               //      $body_tags will only be inserted into the <body ...> tag
-               //      if it is included in the theme/$CFG->theme/header.html,
-               //      so some old or modified themes may not insert $body_tags
-               $body .= ""
-               .       '<script type="text/javascript">'."\n"
-               .       "<!--\n"
-               .       "       var s = (typeof(window.onload)=='function') ? onload.toString() : '';\n"
-               .       "       if (s.indexOf('".$matches[3]."')<0) {\n"
-               .       "               if (s=='') {\n" // no previous onload
-               .       "                       window.onload = new Function('".$matches[3]."');\n"
-               .       "               } else {\n"
-               .       "                       window.onload_hotpot = onload;\n"
-               .       "                       window.onload = new Function('window.onload_hotpot();'+'".$matches[3]."');\n"
-               .       "               }\n"
-               .       "        }\n"
-               .       "//-->\n"
-               .       "</script>\n"
-               ;
-               $footer = '</body>'.$footer;
-       } else if ($frameset) { // HP5 v5
-               switch ($framename) {
-                       case 'top':
-                               print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas);
-                               print $footer;
-                       break;
-                       default:
-                               // add a HotPot navigation frame at the top of the page
-                               //$rows = empty($CFG->resource_framesize) ? 85 : $CFG->resource_framesize;
-                               //$frameset = "\n\t".'<frame src="view.php?id='.$cm->id.'&framename=top" frameborder="0" name="top"></frame>'.$frameset;
-                               //$frameset_tags = preg_replace('|rows="(.*?)"|', 'rows="'.$rows.',\\1"', $frameset_tags);
-                               // put navigation into var NavBar='';
-                               // add form to TopFrame in "WriteFeedback" function
-                               // OR add form to BottomFrame in "DisplayExercise" function
-                               // submission form: '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->'
-                               // give up form: '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->'
-                               print "<html>\n";
-                               print "<head>\n<title>$title</title>\n$styles\n$scripts</head>\n";
-                               print "<frameset$frameset_tags>$frameset</frameset>\n";
-                               print "</html>\n";
-                       break;
-               } // end switch $framename
-               exit;
-       // other files (maybe not even a HotPots)
-       } else if (preg_match('|<body'.'([^>]*)'.'>(.*)</body>|is', $hp->html, $matches)) {
-               $body = $matches[2];
-               $body_tags = $matches[1];
-       }
-       // print the quiz to the browser
-       if ($get_js) {
-               print($scripts);
-               exit;
-       }
-       if ($get_css) {
-               print($styles);
-               exit;
-       }
-       switch ($hotpot->navigation) {
-               case HOTPOT_NAVIGATION_BAR:
-                       //update_module_button($cm->id, $course->id, $strmodulename.'" style="font-size:0.8em')
-                       print_header(
-                               $title, $heading, $navigation,
-                               "", $head.$styles.$scripts, true, $button, 
-                               $loggedinas, false, $body_tags
-                       );
-                       if (!empty($available_msg)) {
-                               notify($available_msg);
-                       }
-                       print $body.$footer;
-               break;
-               case HOTPOT_NAVIGATION_FRAME:
-                       switch ($framename) {
-                               case 'top':
-                                       print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas);
-                                       print $footer;
-                               break;
-                               case 'main':
-                                       if (!empty($available_msg)) {
-                                               $hp->insert_message('<!-- BeginTopNavButtons -->', $available_msg);
-                                       }
-                                       print $hp->html;
-                               break;
-                               default:
-                                       $rows = empty($CFG->resource_framesize) ? 85 : $CFG->resource_framesize;
-                                       print "<html>\n";
-                                       print "<head><title>$title</title></head>\n";
-                                       print "<frameset rows=$rows,*>\n";
-                                       print "<frame src=\"view.php?id=$cm->id&framename=top\">\n";
-                                       print "<frame src=\"view.php?id=$cm->id&framename=main\">\n";
-                                       print "</frameset>\n";
-                                       print "</html>\n";
-                               break;
-                       } // end switch $framename
-               break;
-               case HOTPOT_NAVIGATION_IFRAME:
-                       switch ($framename) {
-                               case 'main':
-                                       print $hp->html;
-                               break;
-                               default:
-                                       $iframe_id = 'hotpot_iframe';
-                                       $body_tags = " onload=\"set_iframe_height('$iframe_id')\"";
-                                       $iframe_js = '<script src="iframe.js" type="text/javascript" language="javascript"></script>'."\n";
-                                       print_header(
-                                               $title, $heading, $navigation, 
-                                               "", $head.$styles.$scripts.$iframe_js, true, $button, 
-                                               $loggedinas, false, $body_tags
-                                       );
-                                       if (!empty($available_msg)) {
-                                               notify($available_msg);
-                                       }
-                                       print "<iframe id=\"$iframe_id\" src=\"view.php?id=$cm->id&framename=main\" height=\"100%\" width=\"100%\">";
-                                       print "<ilayer name=\"$iframe_id\" src=\"view.php?id=$cm->id&framename=main\" height=\"100%\" width=\"100%\">";
-                                       print "</ilayer>\n";
-                                       print "</iframe>\n";
-                                       print $footer;
-                               break;
-                       } // end switch $framename
-               break;
-               default:
-                       // HOTPOT_NAVIGATION_BUTTONS
-                       // HOTPOT_NAVIGATION_GIVEUP
-                       // HOTPOT_NAVIGATION_NONE
-                       if (!empty($available_msg)) {
-                               $hp->insert_message('<!-- BeginTopNavButtons -->', $available_msg);
-                       }
-                       print($hp->html);
-       }
+                $attemptid = hotpot_add_attempt($hotpot->id);
+                if (! is_numeric($attemptid)) {
+                    error('Could not insert attempt record: '.$db->ErrorMsg);
+                }
+            }
+            $hp->adjust_media_urls();
+            if (empty($frameset)) {
+                // HP6 v6
+                switch ($hotpot->navigation) {
+                    case HOTPOT_NAVIGATION_BUTTONS:
+                        // do nothing (i.e. leave buttons as they are)
+                        break;
+                    case HOTPOT_NAVIGATION_GIVEUP:
+                        $hp->insert_giveup_form($attemptid, '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->');
+                        break;
+                    default:
+                        $hp->remove_nav_buttons();
+                }
+                if (isset($hp->real_outputformat) && $hp->real_outputformat==HOTPOT_OUTPUTFORMAT_MOBILE) {
+                    $hp->insert_submission_form($attemptid, '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->', true);
+                } else {
+                    $hp->insert_submission_form($attemptid, '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->');
+                }
+            } else {
+                // HP5 v5
+                switch ($hotpot->navigation) {
+                    case HOTPOT_NAVIGATION_BUTTONS:
+                        // convert URLs in nav buttons
+                        break;
+                    case HOTPOT_NAVIGATION_GIVEUP:
+                        //  $hp->insert_giveup_form($attemptid, '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->');
+                        break;
+                    default:
+                        // remove navigation buttons
+                        $hp->html = preg_replace('#NavBar\+=(.*);#', '', $hp->html);
+                }
+                $hp->insert_submission_form($attemptid, "var NavBar='", "';");
+            }
+        }
+    }
+    //FEEDBACK = new Array();
+    //FEEDBACK[0] = ''; // url of feedback page/script
+    //FEEDBACK[1] = ''; // array of array('teachername', 'value');
+    //FEEDBACK[2] = ''; // 'student name' [formmail only]
+    //FEEDBACK[3] = ''; // 'student email' [formmail only]
+    //FEEDBACK[4] = ''; // window width
+    //FEEDBACK[5] = ''; // window height
+    //FEEDBACK[6] = ''; // 'Send a message to teacher' [prompt/button text]
+    //FEEDBACK[7] = ''; // 'Title'
+    //FEEDBACK[8] = ''; // 'Teacher'
+    //FEEDBACK[9] = ''; // 'Message'
+    //FEEDBACK[10] = ''; // 'Close this window'
+    $feedback = array();
+    switch ($hotpot->studentfeedback) {
+        case HOTPOT_FEEDBACK_NONE:
+            // do nothing
+            break;
+        case HOTPOT_FEEDBACK_WEBPAGE:
+            if (empty($hotpot->studentfeedbackurl)) {
+                $hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
+            } else {
+                $feedback[0] = "'$hotpot->studentfeedbackurl'";
+            }
+            break;
+        case HOTPOT_FEEDBACK_FORMMAIL:
+            $teachers = hotpot_feedback_teachers($course, $hotpot);
+            if (empty($teachers) || empty($hotpot->studentfeedbackurl)) {
+                $hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
+            } else {
+                $feedback[0] = "'$hotpot->studentfeedbackurl'";
+                $feedback[1] = $teachers;
+                $feedback[2] = "'".fullname($USER)."'";
+                $feedback[3] = "'".$USER->email."'";
+                $feedback[4] = 500; // width
+                $feedback[5] = 300; // height
+            }
+            break;
+        case HOTPOT_FEEDBACK_MOODLEFORUM:
+            $module = get_record('modules', 'name', 'forum');
+            $forums = get_records('forum', 'course', "$course->id");
+            if (empty($module) || empty($module->visible) || empty($forums)) {
+                $hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
+            } else {
+                $feedback[0] = "'$CFG->wwwroot/mod/forum/index.php?id=$course->id'";
+            }
+            break;
+        case HOTPOT_FEEDBACK_MOODLEMESSAGING:
+            $teachers = hotpot_feedback_teachers($course, $hotpot);
+            if (empty($CFG->messaging) || empty($teachers)) {
+                $hotpot->studentfeedback = HOTPOT_FEEDBACK_NONE;
+            } else {
+                $feedback[0] = "'$CFG->wwwroot/message/discussion.php?id='";
+                $feedback[1] = $teachers;
+                $feedback[4] = 400; // width
+                $feedback[5] = 500; // height
+            }
+            break;
+        default:
+            // do nothing
+    }
+    if ($hotpot->studentfeedback != HOTPOT_FEEDBACK_NONE) {
+        $feedback[6] = "'Send a message to teacher'";
+        $feedback[7] = "'Title'";
+        $feedback[8] = "'Teacher'";
+        $feedback[9] = "'Message'";
+        $feedback[10] = "'Close this window'";
+        $js = '';
+        foreach ($feedback as $i=>$str) {
+            $js .= 'FEEDBACK['.$i."] = $str;\n";
+        }
+        $js = '<script type="text/javascript" language="javascript">'."<!--\n"."FEEDBACK = new Array();\n".$js."//--></script>\n";
+        $hp->html = preg_replace('|</head>|i', "$js</head>", $hp->html, 1);
+    }
+    // insert hot-potatoes.js
+    $hp->insert_script(HOTPOT_JS);
+    // extract first <head> tag
+    $head = '';
+    $pattern = '|<head([^>]*)>(.*?)</head>|is';
+    if (preg_match($pattern, $hp->html, $matches)) {
+        $head = $matches[2];
+        // remove <title>
+        $head = preg_replace('|<title[^>]*>(.*?)</title>|is', '', $head);
+    }
+    // extract <style> tags (and remove from $head)
+    $styles = '';
+    $pattern = '|<style([^>]*)>(.*?)</style>|is';
+    if (preg_match_all($pattern, $head, $matches)) {
+        $count = count($matches[0]);
+        for ($i=0; $i<$count; $i++) {
+            $styles .= $matches[0][$i]."\n";
+            $head = str_replace($matches[0][$i], '', $head);
+        }
+    }
+    // extract <script> tags (and remove from $head)
+    $scripts = '';
+    $pattern = '|<script([^>]*)>(.*?)</script>|is';
+    if (preg_match_all($pattern, $head, $matches)) {
+        $count = count($matches[0]);
+        for ($i=0; $i<$count; $i++) {
+            $scripts .= $matches[0][$i]."\n";
+            $head = str_replace($matches[0][$i], '', $head);
+        }
+    }
+    // extract <body> tags
+    $body = '';
+    $body_tags = '';
+    $footer = '</html>';
+    // HP6 and some HP5 (v6 and v4) 
+    if (preg_match('|<body'.'([^>]*'.'onLoad=(["\'])(.*?)(\\2)'.'[^>]*)'.'>(.*)</body>|is', $hp->html, $matches)) {
+        $body = $matches[5]; // contents of first <body onload="StartUp()">...</body> block
+        $body_tags = $matches[1];
+        // workaround to ensure javascript onload routine for quiz is always executed
+        //  $body_tags will only be inserted into the <body ...> tag
+        //  if it is included in the theme/$CFG->theme/header.html,
+        //  so some old or modified themes may not insert $body_tags
+        $body .= ""
+        .   '<script type="text/javascript">'."\n"
+        .   "<!--\n"
+        .   "   var s = (typeof(window.onload)=='function') ? onload.toString() : '';\n"
+        .   "   if (s.indexOf('".$matches[3]."')<0) {\n"
+        .   "       if (s=='') {\n" // no previous onload
+        .   "           window.onload = new Function('".$matches[3]."');\n"
+        .   "       } else {\n"
+        .   "           window.onload_hotpot = onload;\n"
+        .   "           window.onload = new Function('window.onload_hotpot();'+'".$matches[3]."');\n"
+        .   "       }\n"
+        .   "    }\n"
+        .   "//-->\n"
+        .   "</script>\n"
+        ;
+        $footer = '</body>'.$footer;
+    } else if ($frameset) { // HP5 v5
+        switch ($framename) {
+            case 'top':
+                print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas);
+                print $footer;
+            break;
+            default:
+                // add a HotPot navigation frame at the top of the page
+                //$rows = empty($CFG->resource_framesize) ? 85 : $CFG->resource_framesize;
+                //$frameset = "\n\t".'<frame src="view.php?id='.$cm->id.'&framename=top" frameborder="0" name="top"></frame>'.$frameset;
+                //$frameset_tags = preg_replace('|rows="(.*?)"|', 'rows="'.$rows.',\\1"', $frameset_tags);
+                // put navigation into var NavBar='';
+                // add form to TopFrame in "WriteFeedback" function
+                // OR add form to BottomFrame in "DisplayExercise" function
+                // submission form: '<!-- BeginSubmissionForm -->', '<!-- EndSubmissionForm -->'
+                // give up form: '<!-- BeginTopNavButtons -->', '<!-- EndTopNavButtons -->'
+                print "<html>\n";
+                print "<head>\n<title>$title</title>\n$styles\n$scripts</head>\n";
+                print "<frameset$frameset_tags>$frameset</frameset>\n";
+                print "</html>\n";
+            break;
+        } // end switch $framename
+        exit;
+    // other files (maybe not even a HotPots)
+    } else if (preg_match('|<body'.'([^>]*)'.'>(.*)</body>|is', $hp->html, $matches)) {
+        $body = $matches[2];
+        $body_tags = $matches[1];
+    }
+    // print the quiz to the browser
+    if ($get_js) {
+        print($scripts);
+        exit;
+    }
+    if ($get_css) {
+        print($styles);
+        exit;
+    }
+    switch ($hotpot->navigation) {
+        case HOTPOT_NAVIGATION_BAR:
+            //update_module_button($cm->id, $course->id, $strmodulename.'" style="font-size:0.8em')
+            print_header(
+                $title, $heading, $navigation,
+                "", $head.$styles.$scripts, true, $button, 
+                $loggedinas, false, $body_tags
+            );
+            if (!empty($available_msg)) {
+                notify($available_msg);
+            }
+            print $body.$footer;
+        break;
+        case HOTPOT_NAVIGATION_FRAME:
+            switch ($framename) {
+                case 'top':
+                    print_header($title, $heading, $navigation, "", "", true, $button, $loggedinas);
+                    print $footer;
+                break;
+                case 'main':
+                    if (!empty($available_msg)) {
+                        $hp->insert_message('<!-- BeginTopNavButtons -->', $available_msg);
+                    }
+                    print $hp->html;
+                break;
+                default:
+                    $rows = empty($CFG->resource_framesize) ? 85 : $CFG->resource_framesize;
+                    print "<html>\n";
+                    print "<head><title>$title</title></head>\n";
+                    print "<frameset rows=$rows,*>\n";
+                    print "<frame src=\"view.php?id=$cm->id&framename=top\">\n";
+                    print "<frame src=\"view.php?id=$cm->id&framename=main\">\n";
+                    print "</frameset>\n";
+                    print "</html>\n";
+                break;
+            } // end switch $framename
+        break;
+        case HOTPOT_NAVIGATION_IFRAME:
+            switch ($framename) {
+                case 'main':
+                    print $hp->html;
+                break;
+                default:
+                    $iframe_id = 'hotpot_iframe';
+                    $body_tags = " onload=\"set_iframe_height('$iframe_id')\"";
+                    $iframe_js = '<script src="iframe.js" type="text/javascript" language="javascript"></script>'."\n";
+                    print_header(
+                        $title, $heading, $navigation, 
+                        "", $head.$styles.$scripts.$iframe_js, true, $button, 
+                        $loggedinas, false, $body_tags
+                    );
+                    if (!empty($available_msg)) {
+                        notify($available_msg);
+                    }
+                    print "<iframe id=\"$iframe_id\" src=\"view.php?id=$cm->id&framename=main\" height=\"100%\" width=\"100%\">";
+                    print "<ilayer name=\"$iframe_id\" src=\"view.php?id=$cm->id&framename=main\" height=\"100%\" width=\"100%\">";
+                    print "</ilayer>\n";
+                    print "</iframe>\n";
+                    print $footer;
+                break;
+            } // end switch $framename
+        break;
+        default:
+            // HOTPOT_NAVIGATION_BUTTONS
+            // HOTPOT_NAVIGATION_GIVEUP
+            // HOTPOT_NAVIGATION_NONE
+            if (!empty($available_msg)) {
+                $hp->insert_message('<!-- BeginTopNavButtons -->', $available_msg);
+            }
+            print($hp->html);
+    }
 ///////////////////////////////////
-///    functions
+/// functions
 ///////////////////////////////////
 function hotpot_feedback_teachers(&$course, &$hotpot) {
-       global $CFG;
-       $teachers = get_records_sql("
-               SELECT 
-                       u.*
-               FROM 
-                       {$CFG->prefix}user AS u, 
-                       {$CFG->prefix}user_teachers AS t
-               WHERE 
-                       t.userid = u.id
-                       AND t.course = $course->id 
-       ");
-       $teacherdetails = '';
-       if (!empty($teachers)) {
-               $details = array();
-               foreach ($teachers as $teacher) {
-                       if ($hotpot->studentfeedback==HOTPOT_FEEDBACK_MOODLEMESSAGING) {
-                               $detail = $teacher->id;
-                       } else {
-                               $detail =$teacher->email;
-                       }
-                       $details[] = "new Array('".fullname($teacher)."', '$detail')";
-               }
-               $teacherdetails = 'new Array('.implode(',', $details).");\n";
-       }
-       return $teacherdetails;
+    global $CFG;
+    $teachers = get_records_sql("
+        SELECT 
+            u.*
+        FROM 
+            {$CFG->prefix}user AS u, 
+            {$CFG->prefix}user_teachers AS t
+        WHERE 
+            t.userid = u.id
+            AND t.course = $course->id 
+    ");
+    $teacherdetails = '';
+    if (!empty($teachers)) {
+        $details = array();
+        foreach ($teachers as $teacher) {
+            if ($hotpot->studentfeedback==HOTPOT_FEEDBACK_MOODLEMESSAGING) {
+                $detail = $teacher->id;
+            } else {
+                $detail =$teacher->email;
+            }
+            $details[] = "new Array('".fullname($teacher)."', '$detail')";
+        }
+        $teacherdetails = 'new Array('.implode(',', $details).");\n";
+    }
+    return $teacherdetails;
 }
 ?>
index a7bcbf28d42214171f2c8df2bc98bbfb4f09378c..4d5dec9971bedb4b1f9f46fbb91b0ccdadadfa50 100644 (file)
         error('Flash is not supported yet');
     
     } else if ($mimetype == "audio/x-pn-realaudio") {   // It's a realmedia file
-       
-               echo '<object id="rvocx" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="600" height="50">';
+        
+        echo '<object id="rvocx" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="600" height="50">';
         echo "<param name=\"src\" value=\"$fullurl\">";
         echo '<param name="console" value="video">';  // not sure what the console param should equal
         echo '<param name="controls" value="ControlPanel">';
index 0e4a061b3e1212767693426b637a3eff31ce1734..d778c3f025e002e4e49bd8e34db3848a26a6256f 100644 (file)
@@ -461,9 +461,9 @@ if ($form->mode == "add") {
             $select = "course = $course->id AND id != $form->instance";
         }
         if ($lessons = get_records_select('lesson', $select, 'name ASC')) {
-               foreach($lessons as $lesson) {
-                       $options[$lesson->id] = $lesson->name;
-               }
+            foreach($lessons as $lesson) {
+                $options[$lesson->id] = $lesson->name;
+            }
         }
         
         choose_from_menu($options, "dependency", $form->dependency, "");
index 23ece40c210f1b9a2a4e7911458ce781e32c5780..f9387937b653b3f6675177dc067c0444f2c81d8d 100644 (file)
             var ourForm = document.forms['responseform']; 
             ourForm.page.value=page;
             if (ourForm.onsubmit) {
-                   ourForm.onsubmit();
-               }
+                ourForm.onsubmit();
+            }
             ourForm.submit();
         }
         </script>
index 662066c4fb11b1e7335d9fa429b6a2c24fdbc7d8..7c805511d59ec57ceb06aa2d24293ee14fe6c392 100644 (file)
@@ -552,22 +552,22 @@ function quiz_upgrade($oldversion) {
 
     if ($oldversion < 2005051400) {
         modify_database('', 'ALTER TABLE prefix_quiz_rqp_type RENAME prefix_quiz_rqp_types;');
-       modify_database('', "CREATE TABLE `prefix_quiz_rqp_servers` (
-                             id int(10) unsigned NOT NULL auto_increment,
-                             typeid int(10) unsigned NOT NULL default '0',
-                             url varchar(255) NOT NULL default '',
-                             can_render tinyint(2) unsigned NOT NULL default '0',
-                             can_author tinyint(2) unsigned NOT NULL default '0',
-                             PRIMARY KEY  (id)
-                           ) TYPE=MyISAM COMMENT='Information about RQP servers';");
-       if ($types = get_records('quiz_rqp_types')) {
-           foreach($types as $type) {
-                       $server->typeid = $type->id;
-                       $server->url = $type->rendering_server;
-                       $server->can_render = 1;
-                       insert_record('quiz_rqp_servers', $server);
-           }
-       }
+        modify_database('', "CREATE TABLE `prefix_quiz_rqp_servers` (
+                      id int(10) unsigned NOT NULL auto_increment,
+                      typeid int(10) unsigned NOT NULL default '0',
+                      url varchar(255) NOT NULL default '',
+                      can_render tinyint(2) unsigned NOT NULL default '0',
+                      can_author tinyint(2) unsigned NOT NULL default '0',
+                      PRIMARY KEY  (id)
+                    ) TYPE=MyISAM COMMENT='Information about RQP servers';");
+        if ($types = get_records('quiz_rqp_types')) {
+            foreach($types as $type) {
+                $server->typeid = $type->id;
+                $server->url = $type->rendering_server;
+                $server->can_render = 1;
+                insert_record('quiz_rqp_servers', $server);
+            }
+        }
         modify_database('', 'ALTER TABLE prefix_quiz_rqp_types DROP rendering_server');
         modify_database('', 'ALTER TABLE prefix_quiz_rqp_types DROP cloning_server');
         modify_database('', 'ALTER TABLE prefix_quiz_rqp_types DROP flags');
index b4140b83df54edbb536cdcfc4f53e629dad41c99..d2793f8df0e7f65694e9fff702353d9813b8acd8 100644 (file)
@@ -1143,7 +1143,7 @@ function quiz_upgrade($oldversion) {
     }
 
     if ($oldversion < 2006032100) {
-       // change from the old questiontype numbers to using the questiontype names
+        // change from the old questiontype numbers to using the questiontype names
         table_column('question', 'qtype', 'qtype',  'varchar', 20, '', '', 'not null');
         set_field('question', 'qtype', 'shortanswer', 'qtype', 1);
         set_field('question', 'qtype', 'truefalse', 'qtype', 2);
@@ -1362,11 +1362,11 @@ function quiz_upgrade($oldversion) {
         modify_database('', 'ALTER TABLE prefix_question_multichoice DROP CONSTRAINT prefix_quiz_multichoice_pkey');
         modify_database('', 'ALTER TABLE prefix_question_multichoice ADD CONSTRAINT prefix_question_multichoice_pkey PRIMARY KEY (id)');
 
-        modify_database('', 'ALTER TABLE prefix_question_rqp_states    DROP CONSTRAINT prefix_quiz_rqp_states_pkey');
-        modify_database('', 'ALTER TABLE prefix_question_rqp_states    ADD CONSTRAINT prefix_question_rqp_states_pkey PRIMARY KEY (id)');
+        modify_database('', 'ALTER TABLE prefix_question_rqp_states DROP CONSTRAINT prefix_quiz_rqp_states_pkey');
+        modify_database('', 'ALTER TABLE prefix_question_rqp_states ADD CONSTRAINT prefix_question_rqp_states_pkey PRIMARY KEY (id)');
 
-        modify_database('', 'ALTER TABLE prefix_question_categories    DROP CONSTRAINT prefix_quiz_categories_pkey');
-        modify_database('', 'ALTER TABLE prefix_question_categories    ADD CONSTRAINT prefix_question_categories_pkey PRIMARY KEY (id)');
+        modify_database('', 'ALTER TABLE prefix_question_categories DROP CONSTRAINT prefix_quiz_categories_pkey');
+        modify_database('', 'ALTER TABLE prefix_question_categories ADD CONSTRAINT prefix_question_categories_pkey PRIMARY KEY (id)');
 
         modify_database('', 'ALTER TABLE prefix_question_shortanswer DROP CONSTRAINT prefix_quiz_shortanswer_pkey');
         modify_database('', 'ALTER TABLE prefix_question_shortanswer ADD CONSTRAINT prefix_question_shortanswer_pkey PRIMARY KEY (id)');
@@ -1377,8 +1377,8 @@ function quiz_upgrade($oldversion) {
         modify_database('', 'ALTER TABLE prefix_question_sessions DROP CONSTRAINT prefix_quiz_newest_states_pkey');
         modify_database('', 'ALTER TABLE prefix_question_sessions ADD CONSTRAINT prefix_question_sessions_pkey PRIMARY KEY (id)');
 
-        modify_database('', 'ALTER TABLE prefix_question_calculated    DROP CONSTRAINT prefix_quiz_calculated_pkey');
-        modify_database('', 'ALTER TABLE prefix_question_calculated    ADD CONSTRAINT prefix_question_calculated_pkey PRIMARY KEY (id)');
+        modify_database('', 'ALTER TABLE prefix_question_calculated DROP CONSTRAINT prefix_quiz_calculated_pkey');
+        modify_database('', 'ALTER TABLE prefix_question_calculated ADD CONSTRAINT prefix_question_calculated_pkey PRIMARY KEY (id)');
 
         modify_database('', 'ALTER TABLE prefix_question_answers DROP CONSTRAINT prefix_quiz_answers_pkey');
         modify_database('', 'ALTER TABLE prefix_question_answers ADD CONSTRAINT prefix_question_answers_pkey PRIMARY KEY (id)');
index 8927155e4e9edbbba4112924d9391f62f3bd233b..cc865d20654d0474ccdc7d70ec764fbbd2a2cebb 100644 (file)
@@ -36,7 +36,7 @@
        'quiz_fix_timelimit' => 0,
        'quiz_fix_adaptive' => 0,
        'quiz_fix_penaltyscheme' => 0,
-          'quiz_fix_delay1' => 0,
+       'quiz_fix_delay1' => 0,
        'quiz_fix_delay2' => 0,
 
     );
index abe58e098d2a621f1242e9c1c3b803d82956658a..861647d56583d3b7b9be41b558ae8c4541a48951 100644 (file)
@@ -85,7 +85,7 @@ body#mod-quiz-grading table#grading td
 }
 
 #mod-quiz-attempt #page {
-       text-align: center;
+    text-align: center;
 }
 
 #mod-quiz-attempt #timer .generalbox {
index 7bad6ae47dac3c16b5c740d9352fd2bc0ed1b29d..3b15f4b45929a21d356bcc32fc560c5de13ce04f 100644 (file)
@@ -2,7 +2,7 @@
 \r
     require_once("../../config.php");\r
     require_once('locallib.php');\r
-       \r
+    \r
     $id = optional_param('id', '', PARAM_INT);       // Course Module ID, or\r
     $a = optional_param('a', '', PARAM_INT);         // scorm ID\r
     $scoid = required_param('scoid', PARAM_INT);  // sco ID\r
index 18224556fe3b6557d72b432d8f57b3c2b31b9292..2930e78ea98aff350dc350d4f0b1249eeab95f7f 100755 (executable)
@@ -2,7 +2,7 @@
 \r
     require_once("../../config.php");\r
     require_once('locallib.php');\r
-       \r
+    \r
     $id = optional_param('id', '', PARAM_INT);    // Course Module ID, or\r
     $a = optional_param('a', '', PARAM_INT);     // SCORM ID\r
     $b = optional_param('b', '', PARAM_INT);     // SCO ID\r
@@ -58,8 +58,8 @@
         $strscorm  = get_string("modulename", "scorm");\r
         $strreport  = get_string("report", "scorm");\r
         $strname  = get_string('name');\r
-               $strcoefficient = get_string('coefficient',"scorm");\r
-               $strcoefficient = "Thiet lap he so";\r
+        $strcoefficient = get_string('coefficient',"scorm");\r
+        $strcoefficient = "Thiet lap he so";\r
         if (empty($b)) {\r
             print_header("$course->shortname: ".format_string($scorm->name), "$course->fullname",\r
                      "$navigation <a href=\"index.php?id=$course->id\">$strscorms</a>\r
 \r
     $scormpixdir = $CFG->modpixpath.'/scorm/pix';\r
 \r
-       //Phan trinh bay chinh\r
+    //Phan trinh bay chinh\r
 ?>\r
 \r
   <?php\r
-       $examScoes = get_records_select('scorm_scoes', 'scorm ='.($scorm->id).' and minnormalizedmeasure > -1');\r
-       foreach ($examScoes as $examSco){\r
-               $newcoefficient = optional_param($examSco->id,'',PARAM_INT);\r
-               $sco = get_record('scorm_scoes','scorm',$scorm->id,'id',$examSco->id,'','');\r
-               $sco->score_coefficient = $newcoefficient;\r
-               $ketqua = update_record('scorm_scoes',$sco);\r
-               //echo "Cap nhat $examSco->id voi he so diem ".$newcoefficient."<br>";\r
-       }\r
+    $examScoes = get_records_select('scorm_scoes', 'scorm ='.($scorm->id).' and minnormalizedmeasure > -1');\r
+    foreach ($examScoes as $examSco){\r
+        $newcoefficient = optional_param($examSco->id,'',PARAM_INT);\r
+        $sco = get_record('scorm_scoes','scorm',$scorm->id,'id',$examSco->id,'','');\r
+        $sco->score_coefficient = $newcoefficient;\r
+        $ketqua = update_record('scorm_scoes',$sco);\r
+        //echo "Cap nhat $examSco->id voi he so diem ".$newcoefficient."<br>";\r
+    }\r
 \r
-       if ($ketqua)\r
-       {\r
-               echo "".get_string('updatesuccess','scorm');\r
-       }\r
-       else\r
-       {\r
-               echo "".get_string('updatefail','scorm');\r
-       }\r
+    if ($ketqua)\r
+    {\r
+        echo "".get_string('updatesuccess','scorm');\r
+    }\r
+    else\r
+    {\r
+        echo "".get_string('updatefail','scorm');\r
+    }\r
 \r
-       echo "<br><br><a href=coefficientsetting.php?id=$id>".get_string('back','scorm')."</a>"\r
+    echo "<br><br><a href=coefficientsetting.php?id=$id>".get_string('back','scorm')."</a>"\r
 ?>\r
 <?php\r
-       //ket thuc phan trinh bay chinh\r
+    //ket thuc phan trinh bay chinh\r
 \r
     if (empty($noheader)) {\r
         print_footer($course);\r
index cec2b70553504cd27b359c7fedb07c745300b025..788420be8addc21e910abcc15dc6bc54fd833665 100755 (executable)
@@ -2,7 +2,7 @@
 \r
     require_once("../../config.php");\r
     require_once('locallib.php');\r
-       \r
+    \r
     $id = optional_param('id', '', PARAM_INT);    // Course Module ID, or\r
     $a = optional_param('a', '', PARAM_INT);     // SCORM ID\r
     $b = optional_param('b', '', PARAM_INT);     // SCO ID\r
@@ -58,7 +58,7 @@
         $strscorm  = get_string("modulename", "scorm");\r
         $strreport  = get_string("report", "scorm");\r
         $strname  = get_string('name');\r
-               $strcoefficient = get_string('coefficient','scorm');\r
+        $strcoefficient = get_string('coefficient','scorm');\r
         if (empty($b)) {\r
             print_header("$course->shortname: ".format_string($scorm->name), "$course->fullname",\r
                      "$navigation <a href=\"index.php?id=$course->id\">$strscorms</a>\r
 \r
     $scormpixdir = $CFG->modpixpath.'/scorm/pix';\r
 \r
-       //Phan trinh bay chinh\r
+    //Phan trinh bay chinh\r
 ?>\r
 <script type="text/javascript">\r
 function validate_form()\r
 {\r
-       return true;\r
+    return true;\r
 }\r
 </script>\r
 <form name="form" method="post" action="coefficientconfirm.php" onsubmit="return validate_form();" >\r
@@ -92,15 +92,15 @@ function validate_form()
     </tr>\r
  \r
   <?php\r
-       $examScoes = get_records_select('scorm_scoes', 'scorm ='.($scorm->id).' and minnormalizedmeasure > -1');\r
-       if(!empty($examScoes))\r
-       {\r
-       \r
-               foreach ($examScoes as $examSco){\r
-               echo "<tr><td>";        \r
-               echo "$examSco->identifier.</td><td><input type='text' name='$examSco->id' class='scormtextbox' value=$examSco->score_coefficient /></td></tr><br>";\r
-               }\r
-       }\r
+    $examScoes = get_records_select('scorm_scoes', 'scorm ='.($scorm->id).' and minnormalizedmeasure > -1');\r
+    if(!empty($examScoes))\r
+    {\r
+    \r
+        foreach ($examScoes as $examSco){\r
+        echo "<tr><td>";    \r
+        echo "$examSco->identifier.</td><td><input type='text' name='$examSco->id' class='scormtextbox' value=$examSco->score_coefficient /></td></tr><br>";\r
+        }\r
+    }\r
 \r
 ?>\r
  </table>\r
@@ -109,7 +109,7 @@ function validate_form()
 <input type="submit" value="<?php print_string('savechanges') ?>" />\r
 </form>\r
 <?php\r
-       //ket thuc phan trinh bay chinh\r
+    //ket thuc phan trinh bay chinh\r
 \r
     if (empty($noheader)) {\r
         print_footer($course);\r
index c3227c47d2de866d33f61f9ffa3f732cf50f1a87..309c505bb0f924a1e193448408c0b7d83b97e8f9 100644 (file)
@@ -91,7 +91,7 @@ function SCORMapi1_3() {
         'cmi.learner_preference.language':{'defaultvalue':'', 'format':CMIString250, 'mod':'rw'},
         'cmi.learner_preference.delivery_speed':{'defaultvalue':'0', 'format':CMIDecimal, 'range':speed_range, 'mod':'rw'},
         'cmi.learner_preference.audio_caption':{'defaultvalue':'0', 'format':CMISInteger, 'range':text_range, 'mod':'rw'},
-               'cmi.location':{'defaultvalue':<?php echo isset($userdata->{'cmi.location'})?'\''.$userdata->{'cmi.location'}.'\'':'null' ?>, 'format':CMIString1000, 'mod':'rw'},
+        'cmi.location':{'defaultvalue':<?php echo isset($userdata->{'cmi.location'})?'\''.$userdata->{'cmi.location'}.'\'':'null' ?>, 'format':CMIString1000, 'mod':'rw'},
         'cmi.max_time_allowed':{'defaultvalue':<?php echo isset($userdata->maxtimeallowed)?'\''.$userdata->maxtimeallowed.'\'':'null' ?>, 'mod':'r'},
         'cmi.mode':{'defaultvalue':'<?php echo $userdata->mode ?>', 'mod':'r'},
         'cmi.objectives._children':{'defaultvalue':objectives_children, 'mod':'r'},
index 841cabb511cf93e89245c36c618d2aebd3430aa1..e5e9c5ff7520f07db8a2c4dd1bf28893f2c766c7 100755 (executable)
@@ -189,7 +189,7 @@ function scorm_upgrade($oldversion) {
             foreach($scorms as $scorm) {
                 if ($scorm->browsemode = 1) {
                     $scorm->hidebrowse = 0;
-               } else {
+                } else {
                     $scorm->hidebrowse = 1;
                 }
                 update_record('scorm',$scorm);
index 23f18ab85b12367f4a813e13371bf2e5fdfdb648..f95defe6403429f7d62046d584400989db849ec8 100755 (executable)
@@ -205,7 +205,7 @@ function scorm_upgrade($oldversion) {
             foreach($scorms as $scorm) {
                 if ($scorm->browsemode = 1) {
                     $scorm->hidebrowse = 0;
-               } else {
+                } else {
                     $scorm->hidebrowse = 1;
                 }
                 update_record('scorm',$scorm);
index 2c67f540297237de160d9f6b6ab514caffc54be9..adb7fad9f268203cafba278b1a890fc69ca5e4ab 100755 (executable)
@@ -71,8 +71,8 @@
         } else if (isstudent($course->id)) {\r
            require_once('locallib.php');\r
            $report = scorm_grade_user_new(get_records('scorm_scoes','scorm',$scorm->id), $USER->id, $scorm->grademethod);\r
-                  $sco_count = scorm_get_user_sco_count($scorm->id,$USER->id);\r
-                       $reportshow = get_string('implement','scorm').$sco_count.get_string('lesson','scorm') ."<br><table width=".($report*100)."% bgcolor=#800000><tr><td height=15></td></tr></table>".get_string('scoreRate','scorm').": ".($report*100)."%";        }\r
+           $sco_count = scorm_get_user_sco_count($scorm->id,$USER->id);\r
+            $reportshow = get_string('implement','scorm').$sco_count.get_string('lesson','scorm') ."<br><table width=".($report*100)."% bgcolor=#800000><tr><td height=15></td></tr></table>".get_string('scoreRate','scorm').": ".($report*100)."%";        }\r
         if (!$scorm->visible) {\r
            //Show dimmed if the mod is hidden\r
            $table->data[] = array ($tt, "<a class=\"dimmed\" href=\"view.php?id=$scorm->coursemodule\">".format_string($scorm->name,true)."</a>",\r
index 514e58e96c530e2370a2727945f0a7d3e6d888cc..2701282c09e7d8eeea8858948bc4bc3e22033a8c 100755 (executable)
@@ -112,10 +112,10 @@ function scorm_update_instance($scorm) {
 
     // Check if scorm manifest needs to be reparsed
     if ($scorm->launch == 0) {
-               //$f = "D:\\test.txt";
-               //@$ft = fopen($f,"a");
-               //fwrite($ft,"\n Xu ly trong update trong lib.php \n");
-               //fwrite($ft,"\n Lauch co gia tri \n".($scorm->launch));
+        //$f = "D:\\test.txt";
+        //@$ft = fopen($f,"a");
+        //fwrite($ft,"\n Xu ly trong update trong lib.php \n");
+        //fwrite($ft,"\n Lauch co gia tri \n".($scorm->launch));
 
         // Delete old related records
         delete_records('scorm_scoes','scorm',$scorm->id);
@@ -124,9 +124,9 @@ function scorm_update_instance($scorm) {
         delete_records('scorm_sequencing_rolluprules','scormid',$scorm->id);
         delete_records('scorm_sequencing_rolluprule','scormid',$scorm->id);
         delete_records('scorm_sequencing_rollupruleconditions','scormid',$scorm->id);
-        delete_records('scorm_sequencing_rolluprulecondition','scormid',$scorm->id);                           
+        delete_records('scorm_sequencing_rolluprulecondition','scormid',$scorm->id);                
         delete_records('scorm_sequencing_ruleconditions','scormid',$scorm->id);
-        delete_records('scorm_sequencing_rulecondition','scormid',$scorm->id);                         
+        delete_records('scorm_sequencing_rulecondition','scormid',$scorm->id);              
 
         
         $scorm->dir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm';
@@ -193,7 +193,7 @@ function scorm_delete_instance($id) {
     }
     if (! delete_records('scorm_sequencing_ruleconditions', 'scormid', $scorm->id)) {
         $result = false;
-    }          
+    }       
     return $result;
 }
 
@@ -220,8 +220,8 @@ function scorm_user_outline($course, $user, $mod, $scorm) {
         require_once('locallib.php');
         foreach ($scoes as $sco) {
             if ($sco->launch!='') {
-               $scores->count++;
-               if ($userdata = scorm_get_tracks($sco->id, $user->id)) {
+        $scores->count++;
+        if ($userdata = scorm_get_tracks($sco->id, $user->id)) {
                     if (!isset($scores->{$userdata->status})) {
                         $scores->{$userdata->status} = 1;
                     } else {    
@@ -240,7 +240,7 @@ function scorm_user_outline($course, $user, $mod, $scorm) {
         }
         switch ($scorm->grademethod) {
             case GRADEHIGHEST:
-               if ($scores->values > 0) {
+        if ($scores->values > 0) {
                     $return->info = get_string('score','scorm').':&nbsp;'.$scores->max;
                     $return->time = $scores->lastmodify;
                 }
@@ -261,30 +261,30 @@ function scorm_user_outline($course, $user, $mod, $scorm) {
                 $return->info = '';
                 $scores->notattempted = $scores->count;
                 if (isset($scores->completed)) {
-                   $return->info .= get_string('completed','scorm').':&nbsp;'.$scores->completed.'<br />';
+            $return->info .= get_string('completed','scorm').':&nbsp;'.$scores->completed.'<br />';
                     $scores->notattempted -= $scores->completed;
                 }
                 if (isset($scores->passed)) {
-                   $return->info .= get_string('passed','scorm').':&nbsp;'.$scores->passed.'<br />';
+            $return->info .= get_string('passed','scorm').':&nbsp;'.$scores->passed.'<br />';
                     $scores->notattempted -= $scores->passed;
                 }
                 if (isset($scores->failed)) {
-                   $return->info .= get_string('failed','scorm').':&nbsp;'.$scores->failed.'<br />';
+            $return->info .= get_string('failed','scorm').':&nbsp;'.$scores->failed.'<br />';
                     $scores->notattempted -= $scores->failed;
                 }
                 if (isset($scores->incomplete)) {
-                   $return->info .= get_string('incomplete','scorm').':&nbsp;'.$scores->incomplete.'<br />';
+            $return->info .= get_string('incomplete','scorm').':&nbsp;'.$scores->incomplete.'<br />';
                     $scores->notattempted -= $scores->incomplete;
                 }
                 if (isset($scores->browsed)) {
-                   $return->info .= get_string('browsed','scorm').':&nbsp;'.$scores->browsed.'<br />';
+            $return->info .= get_string('browsed','scorm').':&nbsp;'.$scores->browsed.'<br />';
                     $scores->notattempted -= $scores->browsed;
                 }
                 $return->time = $scores->lastmodify;
                 if ($return->info == '') {
                     $return = NULL;
                 } else {
-                   $return->info .= get_string('notattempted','scorm').':&nbsp;'.$scores->notattempted.'<br />';
+            $return->info .= get_string('notattempted','scorm').':&nbsp;'.$scores->notattempted.'<br />';
                 }
             break;
         }
@@ -422,7 +422,7 @@ function scorm_user_complete($course, $user, $mod, $scorm) {
         echo get_string('report','scorm').":<br />\n";
         echo $report;
     } else {
-       print_string('noactivity','scorm');
+        print_string('noactivity','scorm');
     }
 
     return true;
index ea33994c99e9aab10e0a462ac3e051b47b245945..ee77d8a3e9f315113ffa660fa272a7375752d591 100755 (executable)
@@ -1,7 +1,7 @@
 <?php\r
     require_once("../../config.php");\r
     require_once('locallib.php');\r
-       \r
+    \r
     $id = optional_param('id', '', PARAM_INT);       // Course Module ID, or\r
     $a = optional_param('a', '', PARAM_INT);         // scorm ID\r
     $scoid = required_param('scoid', PARAM_INT); // sco ID\r
index 8c5b7724491b9485a4be76f12e9b0f80951d1bee..8d707b83b07ff29eb3537d0ca83dbfb8b694612d 100755 (executable)
                result.concat('<?php print_string('errorlogs','scorm') ?>:\n'+errorlogs);\r
             }\r
             alert(result);\r
-                       alert("Khong tuan chuan Scorm");\r
-                       document.form.name.focus();\r
+            alert("Khong tuan chuan Scorm");\r
+            document.form.name.focus();\r
 \r
             return false;\r
         }\r
index 1935a3bba926dff5b422cd47f3299313e75b910e..c2df9bb7c58080cb1c0a2cef14d0e54f890b05db 100755 (executable)
@@ -4,7 +4,7 @@
 
     require_once("../../config.php");
     require_once('locallib.php');
-       
+    
     $id = optional_param('id', '', PARAM_INT);    // Course Module ID, or
     $a = optional_param('a', '', PARAM_INT);     // SCORM ID
     $b = optional_param('b', '', PARAM_INT);     // SCO ID
             error('Missing script parameter');
         }
     }
-       
+    
     print_heading(format_string(get_string('timestatistic','scorm')));
-       $scousers=get_records_select("scorm_scoes_track", "scormid='$scorm->id' GROUP BY userid,scormid", "", "userid,scormid");        
-    $attempt = scorm_get_last_attempt($scorm->id,$USER->id);   
-       
-       foreach($scousers as $scouser){
-               $str = 'scormid ='.($scorm->id).' and userid = '.$scouser->userid.' and attempt = '.$attempt.' ORDER BY timemodified asc';
-               $endtrack       = get_record_select("scorm_scoes_track", $str,'max(timemodified) as maxtimemodified');
+    $scousers=get_records_select("scorm_scoes_track", "scormid='$scorm->id' GROUP BY userid,scormid", "", "userid,scormid");    
+    $attempt = scorm_get_last_attempt($scorm->id,$USER->id);    
+    
+    foreach($scousers as $scouser){
+        $str = 'scormid ='.($scorm->id).' and userid = '.$scouser->userid.' and attempt = '.$attempt.' ORDER BY timemodified asc';
+        $endtrack   = get_record_select("scorm_scoes_track", $str,'max(timemodified) as maxtimemodified');
 
-       }
+    }
 
 //Phan trinh bay thong ke theo thoi gian
-               $table = new stdClass();
-               $table->head = array('&nbsp;', get_string('name','scorm'));
-               $table->align = array('center', 'left');
-               $table->wrap = array('nowrap', 'nowrap');
-               $table->width = '100%';
-               $table->size = array(10, '*');
+        $table = new stdClass();
+        $table->head = array('&nbsp;', get_string('name','scorm'));
+        $table->align = array('center', 'left');
+        $table->wrap = array('nowrap', 'nowrap');
+        $table->width = '100%';
+        $table->size = array(10, '*');
 
-               $table->head[]=scorm_string_wrap(get_string('beginTime','scorm'));
-               $table->align[] = 'center';
-               $table->wrap[] = 'nowrap';
-               $table->size[] = '*';
+        $table->head[]=scorm_string_wrap(get_string('beginTime','scorm'));
+        $table->align[] = 'center';
+        $table->wrap[] = 'nowrap';
+        $table->size[] = '*';
 
-               $table->head[]=scorm_string_wrap(get_string('endTime','scorm'));
-               $table->align[] = 'center';
-               $table->wrap[] = 'nowrap';
-               $table->size[] = '*';
+        $table->head[]=scorm_string_wrap(get_string('endTime','scorm'));
+        $table->align[] = 'center';
+        $table->wrap[] = 'nowrap';
+        $table->size[] = '*';
 
-               $row = array();
-               $row[] = "";
-               $row[] = "(".get_string('coefficient','scorm').")";
-       foreach($scousers as $scouser){
-               $userdata = scorm_get_user_data($scouser->userid);
-               $row = array();
-               $row[] = print_user_picture($scouser->userid, $course->id, $userdata->picture, false, true);
-               $row[] = "<a href=\"$CFG->wwwroot/user/view.php?id=$scouser->userid&course=$course->id\">".
-                                                "$userdata->firstname $userdata->lastname</a>";        
-               $str = 'scormid ='.($scorm->id).' and userid = '.$scouser->userid.' and attempt = '.$attempt.' ORDER BY timemodified asc';
-               $begintrack     = get_record_select("scorm_scoes_track", $str,'min(timemodified) as mintimemodified');          
-               $row[] = strftime( "%H h -%M ' - %S s - %d -%m-%Y", $begintrack->mintimemodified);              
-               $endtrack       = get_record_select("scorm_scoes_track", $str,'max(timemodified) as maxtimemodified');
-               $row[] = strftime( "%H h -%M ' - %S s - %d -%m-%Y", $endtrack->maxtimemodified);
-        $table->data[] = $row;
-               }
-               print_table($table);
-       
-       echo "<br><a href='viewScore.php?a=$scorm->id'>".format_string(get_string('viewscore','scorm'))."</a>";
+        $row = array();
+        $row[] = "";
+        $row[] = "(".get_string('coefficient','scorm').")";
+    foreach($scousers as $scouser){
+        $userdata = scorm_get_user_data($scouser->userid);
+        $row = array();
+        $row[] = print_user_picture($scouser->userid, $course->id, $userdata->picture, false, true);
+        $row[] = "<a href=\"$CFG->wwwroot/user/view.php?id=$scouser->userid&course=$course->id\">".
+                         "$userdata->firstname $userdata->lastname</a>";    
+        $str = 'scormid ='.($scorm->id).' and userid = '.$scouser->userid.' and attempt = '.$attempt.' ORDER BY timemodified asc';
+        $begintrack = get_record_select("scorm_scoes_track", $str,'min(timemodified) as mintimemodified');      
+        $row[] = strftime( "%H h -%M ' - %S s - %d -%m-%Y", $begintrack->mintimemodified);      
+        $endtrack   = get_record_select("scorm_scoes_track", $str,'max(timemodified) as maxtimemodified');
+        $row[] = strftime( "%H h -%M ' - %S s - %d -%m-%Y", $endtrack->maxtimemodified);
+         $table->data[] = $row;
+        }
+        print_table($table);
+    
+    echo "<br><a href='viewScore.php?a=$scorm->id'>".format_string(get_string('viewscore','scorm'))."</a>";
     if (empty($noheader)) {
         print_footer($course);
     }
index 920dd746ff6ad837fbda45afcc8c76b3d36e5061..2534af515b43855995c038ad004598e30a641b71 100644 (file)
 
         #-- I'm sorry for that, but all the @ annoy me
         error_reporting(0x0000377 & error_reporting());
-#      error_reporting(E_ALL^E_NOTICE);
+#   error_reporting(E_ALL^E_NOTICE);
 
-       #-- the position of your ewiki-wrapper script
-       define("EWIKI_SCRIPT", "?id=");         # relative/absolute to docroot
-#      define("EWIKI_SCRIPT_URL", "http://...?id=");           # absolute URL
+    #-- the position of your ewiki-wrapper script
+    define("EWIKI_SCRIPT", "?id=");     # relative/absolute to docroot
+#   define("EWIKI_SCRIPT_URL", "http://...?id=");       # absolute URL
 
         #-- change to your needs (site lang)
-       define("EWIKI_NAME", "ErfurtWiki");
-       define("EWIKI_PAGE_INDEX", "ErfurtWiki");
-       define("EWIKI_PAGE_NEWEST", "NewestPages");
-       define("EWIKI_PAGE_SEARCH", "SearchPages");
-       define("EWIKI_PAGE_HITS", "MostVisitedPages");
-       define("EWIKI_PAGE_VERSIONS", "MostOftenChangedPages");
-       define("EWIKI_PAGE_UPDATES", "UpdatedPages");
-
-       #-- default settings are good settings - most often ;)
+    define("EWIKI_NAME", "ErfurtWiki");
+    define("EWIKI_PAGE_INDEX", "ErfurtWiki");
+    define("EWIKI_PAGE_NEWEST", "NewestPages");
+    define("EWIKI_PAGE_SEARCH", "SearchPages");
+    define("EWIKI_PAGE_HITS", "MostVisitedPages");
+    define("EWIKI_PAGE_VERSIONS", "MostOftenChangedPages");
+    define("EWIKI_PAGE_UPDATES", "UpdatedPages");
+
+    #-- default settings are good settings - most often ;)
         #- look & feel
-       define("EWIKI_PRINT_TITLE", 1);         # <h2>WikiPageName</h2> on top
-       define("EWIKI_SPLIT_TITLE", 0);         # <h2>Wiki Page Name</h2>
-       define("EWIKI_CONTROL_LINE", 1);        # EditThisPage-link at bottom
-       define("EWIKI_LIST_LIMIT", 20);         # listing limit
+    define("EWIKI_PRINT_TITLE", 1);     # <h2>WikiPageName</h2> on top
+    define("EWIKI_SPLIT_TITLE", 0);     # <h2>Wiki Page Name</h2>
+    define("EWIKI_CONTROL_LINE", 1);    # EditThisPage-link at bottom
+    define("EWIKI_LIST_LIMIT", 20);     # listing limit
         #- behaviour
-       define("EWIKI_AUTO_EDIT", 1);           # edit box for non-existent pages
-       define("EWIKI_EDIT_REDIRECT", 1);       # redirect after edit save
-       define("EWIKI_DEFAULT_ACTION", "view"); # (keep!)
-       define("EWIKI_CASE_INSENSITIVE", 1);    # wikilink case sensitivity
-       define("EWIKI_HIT_COUNTING", 1);
-       define("UNIX_MILLENNIUM", 1000000000);
+    define("EWIKI_AUTO_EDIT", 1);       # edit box for non-existent pages
+    define("EWIKI_EDIT_REDIRECT", 1);   # redirect after edit save
+    define("EWIKI_DEFAULT_ACTION", "view"); # (keep!)
+    define("EWIKI_CASE_INSENSITIVE", 1);    # wikilink case sensitivity
+    define("EWIKI_HIT_COUNTING", 1);
+    define("UNIX_MILLENNIUM", 1000000000);
         #- rendering
-       define("EWIKI_ALLOW_HTML", 0);          # often a very bad idea
-       define("EWIKI_HTML_CHARS", 1);          # allows for &#200;
-       define("EWIKI_ESCAPE_AT", 1);           # "@" -> "&#x40;"
+    define("EWIKI_ALLOW_HTML", 0);      # often a very bad idea
+    define("EWIKI_HTML_CHARS", 1);      # allows for &#200;
+    define("EWIKI_ESCAPE_AT", 1);       # "@" -> "&#x40;"
         #- http/urls
-       define("EWIKI_HTTP_HEADERS", 1);        # most often a good thing
-       define("EWIKI_NO_CACHE", 1);            # browser+proxy shall not cache
-       define("EWIKI_URLENCODE", 1);           # disable when _USE_PATH_INFO
-       define("EWIKI_URLDECODE", 1);
-       define("EWIKI_USE_PATH_INFO", 1  &&!strstr($_SERVER["SERVER_SOFTWARE"],"Apache"));
-       define("EWIKI_USE_ACTION_PARAM", 1);
-       define("EWIKI_ACTION_SEP_CHAR", "/");
-       define("EWIKI_UP_PAGENUM", "n");        # _UP_ means "url parameter"
-       define("EWIKI_UP_PAGEEND", "e");
-       define("EWIKI_UP_BINARY", "binary");
-       define("EWIKI_UP_UPLOAD", "upload");
+    define("EWIKI_HTTP_HEADERS", 1);    # most often a good thing
+    define("EWIKI_NO_CACHE", 1);        # browser+proxy shall not cache
+    define("EWIKI_URLENCODE", 1);       # disable when _USE_PATH_INFO
+    define("EWIKI_URLDECODE", 1);
+    define("EWIKI_USE_PATH_INFO", 1  &&!strstr($_SERVER["SERVER_SOFTWARE"],"Apache"));
+    define("EWIKI_USE_ACTION_PARAM", 1);
+    define("EWIKI_ACTION_SEP_CHAR", "/");
+    define("EWIKI_UP_PAGENUM", "n");    # _UP_ means "url parameter"
+    define("EWIKI_UP_PAGEEND", "e");
+    define("EWIKI_UP_BINARY", "binary");
+    define("EWIKI_UP_UPLOAD", "upload");
         #- other stuff
         define("EWIKI_DEFAULT_LANG", "en");
         define("EWIKI_CHARSET", current_charset());
-       #- user permissions
-       define("EWIKI_PROTECTED_MODE", 0);      # disable funcs + require auth
-       define("EWIKI_PROTECTED_MODE_HIDING", 0);  # hides disallowed actions
-       define("EWIKI_AUTH_DEFAULT_RING", 3);   # 0=root 1=priv 2=user 3=view
-       define("EWIKI_AUTO_LOGIN", 1);          # [auth_query] on startup
+    #- user permissions
+    define("EWIKI_PROTECTED_MODE", 0);  # disable funcs + require auth
+    define("EWIKI_PROTECTED_MODE_HIDING", 0);  # hides disallowed actions
+    define("EWIKI_AUTH_DEFAULT_RING", 3);   # 0=root 1=priv 2=user 3=view
+    define("EWIKI_AUTO_LOGIN", 1);      # [auth_query] on startup
 
-       #-- allowed WikiPageNameCharacters
+    #-- allowed WikiPageNameCharacters
 
 #### BEGIN MOODLE CHANGES - to remove auto-camelcase linking.   
     global $moodle_disable_camel_case;   
     else {
 #### END MOODLE CHANGES
 
-       define("EWIKI_CHARS_L", "a-z_µ¤$\337-\377");
+    define("EWIKI_CHARS_L", "a-z_µ¤$\337-\377");
     define("EWIKI_CHARS_U", "A-Z0-9\300-\336");
 
 #### BEGIN MOODLE CHANGES   
     }
 #### END MOODLE CHANGES
    
-       define("EWIKI_CHARS", EWIKI_CHARS_L.EWIKI_CHARS_U);
+    define("EWIKI_CHARS", EWIKI_CHARS_L.EWIKI_CHARS_U);
 
         #-- database
-       define("EWIKI_DB_TABLE_NAME", "ewiki");      # MySQL / ADOdb
-       define("EWIKI_DBFILES_DIRECTORY", "/tmp");   # see "db_flat_files.php"
-       define("EWIKI_DBA", "/tmp/ewiki.dba");       # see "db_dba.php"
-       define("EWIKI_DBQUERY_BUFFER", 512*1024);    # 512K
-       define("EWIKI_INIT_PAGES", "./init-pages");  # for initialization
-
-       define("EWIKI_DB_F_TEXT", 1<<0);
-       define("EWIKI_DB_F_BINARY", 1<<1);
-       define("EWIKI_DB_F_DISABLED", 1<<2);
-       define("EWIKI_DB_F_HTML", 1<<3);
-       define("EWIKI_DB_F_READONLY", 1<<4);
-       define("EWIKI_DB_F_WRITEABLE", 1<<5);
-       define("EWIKI_DB_F_APPENDONLY", 1<<6);  #nyi
-       define("EWIKI_DB_F_SYSTEM", 1<<7);
-       define("EWIKI_DB_F_PART", 1<<8);
-       define("EWIKI_DB_F_TYPE", EWIKI_DB_F_TEXT | EWIKI_DB_F_BINARY | EWIKI_DB_F_DISABLED | EWIKI_DB_F_SYSTEM | EWIKI_DB_F_PART);
-       define("EWIKI_DB_F_ACCESS", EWIKI_DB_F_READONLY | EWIKI_DB_F_WRITEABLE | EWIKI_DB_F_APPENDONLY);
-       define("EWIKI_DB_F_COPYMASK", EWIKI_DB_F_TYPE | EWIKI_DB_F_ACCESS);
-
-       define("EWIKI_DBFILES_NLR", '\\n');
-       define("EWIKI_DBFILES_ENCODE", 0 || (DIRECTORY_SEPARATOR != "/"));
-       define("EWIKI_DBFILES_GZLEVEL", "2");
-
-       #-- internal
-       define("EWIKI_ADDPARAMDELIM", (strstr(EWIKI_SCRIPT,"?") ? "&" : "?"));
-
-       #-- binary content (images)
-       define("EWIKI_SCRIPT_BINARY", /*"/binary.php?binary="*/  ltrim(strtok(" ".EWIKI_SCRIPT,"?"))."?".EWIKI_UP_BINARY."="  );
-       define("EWIKI_CACHE_IMAGES", 1  &&!headers_sent());
-       define("EWIKI_IMAGE_MAXSIZE", 64 *1024);
-       define("EWIKI_IMAGE_MAXWIDTH", 3072);
-       define("EWIKI_IMAGE_MAXHEIGHT", 2048);
-       define("EWIKI_IMAGE_MAXALLOC", 1<<19);
-       define("EWIKI_IMAGE_RESIZE", 1);
-       define("EWIKI_IMAGE_ACCEPT", "image/jpeg,image/png,image/gif,application/x-shockwave-flash");
-       define("EWIKI_IDF_INTERNAL", "internal://");
-       define("EWIKI_ACCEPT_BINARY", 0);   # for arbitrary binary data files
-
-       #-- misc
+    define("EWIKI_DB_TABLE_NAME", "ewiki");      # MySQL / ADOdb
+    define("EWIKI_DBFILES_DIRECTORY", "/tmp");   # see "db_flat_files.php"
+    define("EWIKI_DBA", "/tmp/ewiki.dba");       # see "db_dba.php"
+    define("EWIKI_DBQUERY_BUFFER", 512*1024);    # 512K
+    define("EWIKI_INIT_PAGES", "./init-pages");  # for initialization
+
+    define("EWIKI_DB_F_TEXT", 1<<0);
+    define("EWIKI_DB_F_BINARY", 1<<1);
+    define("EWIKI_DB_F_DISABLED", 1<<2);
+    define("EWIKI_DB_F_HTML", 1<<3);
+    define("EWIKI_DB_F_READONLY", 1<<4);
+    define("EWIKI_DB_F_WRITEABLE", 1<<5);
+    define("EWIKI_DB_F_APPENDONLY", 1<<6);  #nyi
+    define("EWIKI_DB_F_SYSTEM", 1<<7);
+    define("EWIKI_DB_F_PART", 1<<8);
+    define("EWIKI_DB_F_TYPE", EWIKI_DB_F_TEXT | EWIKI_DB_F_BINARY | EWIKI_DB_F_DISABLED | EWIKI_DB_F_SYSTEM | EWIKI_DB_F_PART);
+    define("EWIKI_DB_F_ACCESS", EWIKI_DB_F_READONLY | EWIKI_DB_F_WRITEABLE | EWIKI_DB_F_APPENDONLY);
+    define("EWIKI_DB_F_COPYMASK", EWIKI_DB_F_TYPE | EWIKI_DB_F_ACCESS);
+
+    define("EWIKI_DBFILES_NLR", '\\n');
+    define("EWIKI_DBFILES_ENCODE", 0 || (DIRECTORY_SEPARATOR != "/"));
+    define("EWIKI_DBFILES_GZLEVEL", "2");
+
+    #-- internal
+    define("EWIKI_ADDPARAMDELIM", (strstr(EWIKI_SCRIPT,"?") ? "&" : "?"));
+
+    #-- binary content (images)
+    define("EWIKI_SCRIPT_BINARY", /*"/binary.php?binary="*/  ltrim(strtok(" ".EWIKI_SCRIPT,"?"))."?".EWIKI_UP_BINARY."="  );
+    define("EWIKI_CACHE_IMAGES", 1  &&!headers_sent());
+    define("EWIKI_IMAGE_MAXSIZE", 64 *1024);
+    define("EWIKI_IMAGE_MAXWIDTH", 3072);
+    define("EWIKI_IMAGE_MAXHEIGHT", 2048);
+    define("EWIKI_IMAGE_MAXALLOC", 1<<19);
+    define("EWIKI_IMAGE_RESIZE", 1);
+    define("EWIKI_IMAGE_ACCEPT", "image/jpeg,image/png,image/gif,application/x-shockwave-flash");
+    define("EWIKI_IDF_INTERNAL", "internal://");
+    define("EWIKI_ACCEPT_BINARY", 0);   # for arbitrary binary data files
+
+    #-- misc
         define("EWIKI_TMP", $_SERVER["TEMP"] ? $_SERVER["TEMP"] : "/tmp");
-       define("EWIKI_LOGLEVEL", -1);           # 0=error 1=warn 2=info 3=debug
-       define("EWIKI_LOGFILE", "/tmp/ewiki.log");
-
-       #-- plugins (tasks mapped to function names)
-       $ewiki_plugins["database"][] = "ewiki_database_mysql";
-       $ewiki_plugins["edit_preview"][] = "ewiki_page_edit_preview";
-       $ewiki_plugins["render"][] = "ewiki_format";
-       $ewiki_plugins["init"][-5] = "ewiki_localization";
-       $ewiki_plugins["init"][-1] = "ewiki_binary";
+    define("EWIKI_LOGLEVEL", -1);       # 0=error 1=warn 2=info 3=debug
+    define("EWIKI_LOGFILE", "/tmp/ewiki.log");
+
+    #-- plugins (tasks mapped to function names)
+    $ewiki_plugins["database"][] = "ewiki_database_mysql";
+    $ewiki_plugins["edit_preview"][] = "ewiki_page_edit_preview";
+    $ewiki_plugins["render"][] = "ewiki_format";
+    $ewiki_plugins["init"][-5] = "ewiki_localization";
+    $ewiki_plugins["init"][-1] = "ewiki_binary";
         $ewiki_plugins["handler"][-105] = "ewiki_eventually_initialize";
         $ewiki_plugins["handler"][] = "ewiki_intermap_walking";
-       $ewiki_plugins["view_append"][-1] = "ewiki_control_links";
+    $ewiki_plugins["view_append"][-1] = "ewiki_control_links";
         $ewiki_plugins["view_final"][-1] = "ewiki_add_title";
         $ewiki_plugins["page_final"][] = "ewiki_http_headers";
         $ewiki_plugins["page_final"][99115115] = "ewiki_page_css_container";
-       $ewiki_plugins["edit_form_final"][] = "ewiki_page_edit_form_final_imgupload";
+    $ewiki_plugins["edit_form_final"][] = "ewiki_page_edit_form_final_imgupload";
         $ewiki_plugins["format_block"]["pre"][] = "ewiki_format_pre";
         $ewiki_plugins["format_block"]["code"][] = "ewiki_format_pre";
         $ewiki_plugins["format_block"]["htm"][] = "ewiki_format_html";
         $ewiki_plugins["format_block"]["comment"][] = "ewiki_format_comment";
 
 
-       #-- internal pages
-       $ewiki_plugins["page"][EWIKI_PAGE_NEWEST] = "ewiki_page_newest";
-       $ewiki_plugins["page"][EWIKI_PAGE_SEARCH] = "ewiki_page_search";
-       if (EWIKI_HIT_COUNTING) $ewiki_plugins["page"][EWIKI_PAGE_HITS] = "ewiki_page_hits";
-       $ewiki_plugins["page"][EWIKI_PAGE_VERSIONS] = "ewiki_page_versions";
-       $ewiki_plugins["page"][EWIKI_PAGE_UPDATES] = "ewiki_page_updates";
-
-       #-- page actions
-       $ewiki_plugins["action"]["edit"] = "ewiki_page_edit";
-       $ewiki_plugins["action_always"]["links"] = "ewiki_page_links";
-       $ewiki_plugins["action"]["info"] = "ewiki_page_info";
-       $ewiki_plugins["action"]["view"] = "ewiki_page_view";
-
-       #-- helper vars ---------------------------------------------------
-       $ewiki_config["idf"]["url"] = array("http://", "mailto:", "internal://", "ftp://", "https://", "irc://", "telnet://", "news://", "chrome://", "file://", "gopher://", "httpz://");
-       $ewiki_config["idf"]["img"] = array(".jpeg", ".png", ".jpg", ".gif", ".j2k");
-       $ewiki_config["idf"]["obj"] = array(".swf", ".svg");
-
-       #-- entitle actions
-       $ewiki_config["action_links"]["view"] = @array_merge(array(
-               "edit" => "EDITTHISPAGE",       # ewiki_t() is called on these
-               "links" => "BACKLINKS",
-               "info" => "PAGEHISTORY",
-               "like" => "LIKEPAGES",
-       ), @$ewiki_config["action_links"]["view"]
+    #-- internal pages
+    $ewiki_plugins["page"][EWIKI_PAGE_NEWEST] = "ewiki_page_newest";
+    $ewiki_plugins["page"][EWIKI_PAGE_SEARCH] = "ewiki_page_search";
+    if (EWIKI_HIT_COUNTING) $ewiki_plugins["page"][EWIKI_PAGE_HITS] = "ewiki_page_hits";
+    $ewiki_plugins["page"][EWIKI_PAGE_VERSIONS] = "ewiki_page_versions";
+    $ewiki_plugins["page"][EWIKI_PAGE_UPDATES] = "ewiki_page_updates";
+
+    #-- page actions
+    $ewiki_plugins["action"]["edit"] = "ewiki_page_edit";
+    $ewiki_plugins["action_always"]["links"] = "ewiki_page_links";
+    $ewiki_plugins["action"]["info"] = "ewiki_page_info";
+    $ewiki_plugins["action"]["view"] = "ewiki_page_view";
+
+    #-- helper vars ---------------------------------------------------
+    $ewiki_config["idf"]["url"] = array("http://", "mailto:", "internal://", "ftp://", "https://", "irc://", "telnet://", "news://", "chrome://", "file://", "gopher://", "httpz://");
+    $ewiki_config["idf"]["img"] = array(".jpeg", ".png", ".jpg", ".gif", ".j2k");
+    $ewiki_config["idf"]["obj"] = array(".swf", ".svg");
+
+    #-- entitle actions
+    $ewiki_config["action_links"]["view"] = @array_merge(array(
+        "edit" => "EDITTHISPAGE",   # ewiki_t() is called on these
+        "links" => "BACKLINKS",
+        "info" => "PAGEHISTORY",
+        "like" => "LIKEPAGES",
+    ), @$ewiki_config["action_links"]["view"]
         );
-       $ewiki_config["action_links"]["info"] = @array_merge(array(
-               "view" => "browse",
-               "edit" => "fetchback",
-       ), @$ewiki_config["action_links"]["info"]
+    $ewiki_config["action_links"]["info"] = @array_merge(array(
+        "view" => "browse",
+        "edit" => "fetchback",
+    ), @$ewiki_config["action_links"]["info"]
         );
 
         #-- variable configuration settings (go into '$ewiki_config')
            "script" => EWIKI_SCRIPT,
            "script_url" => (defined("EWIKI_SCRIPT_URL")?EWIKI_SCRIPT_URL:NULL),
            "script_binary" => EWIKI_SCRIPT_BINARY,
-       #-- heart of the wiki -- don't try to read this! ;)
+    #-- heart of the wiki -- don't try to read this! ;)
 
-           "wiki_pre_scan_regex" =>    '/
-               (?<![~!])
-               ((?:(?:\w+:)*['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+){2,}[\w\d]*)
-               |\^([-'.EWIKI_CHARS_L.EWIKI_CHARS_U.']{3,})
-               |\[ (?:"[^\]\"]+" | \s+ | [^:\]#]+\|)*  ([^\|\"\[\]\#]+)  (?:\s+ | "[^\]\"]+")* [\]\#] 
-               |(\w{3,9}:\/\/[^?#\s\[\]\'\"\)\,<]+)    /x',
+           "wiki_pre_scan_regex" => '/
+        (?<![~!])
+        ((?:(?:\w+:)*['.EWIKI_CHARS_U.']+['.EWIKI_CHARS_L.']+){2,}[\w\d]*)
+        |\^([-'.EWIKI_CHARS_L.EWIKI_CHARS_U.']{3,})
+        |\[ (?:"[^\]\"]+" | \s+ | [^:\]#]+\|)*  ([^\|\"\[\]\#]+)  (?:\s+ | "[^\]\"]+")* [\]\#] 
+        |(\w{3,9}:\/\/[^?#\s\[\]\'\"\)\,<]+)    /x',
 
            "wiki_link_regex" => "\007 [!~]?(
-               \#?\[[^<>\[\]\n]+\] |
-               \^[-".EWIKI_CHARS_U.EWIKI_CHARS_L."]{3,} |
-               \b([\w]{3,}:)*([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,}\#?[\w\d]* |
-               ([a-z]{2,9}://|mailto:)[^\s\[\]\'\"\)\,<]+ |
-               \w[-_.+\w]+@(\w[-_\w]+[.])+\w{2,}       ) \007x",
+        \#?\[[^<>\[\]\n]+\] |
+        \^[-".EWIKI_CHARS_U.EWIKI_CHARS_L."]{3,} |
+        \b([\w]{3,}:)*([".EWIKI_CHARS_U."]+[".EWIKI_CHARS_L."]+){2,}\#?[\w\d]* |
+        ([a-z]{2,9}://|mailto:)[^\s\[\]\'\"\)\,<]+ |
+        \w[-_.+\w]+@(\w[-_\w]+[.])+\w{2,}   ) \007x",
 
-       #-- rendering ruleset
+    #-- rendering ruleset
            "wm_indent" => '<div style="margin-left:15px;" class="indent">',
            "wm_table_defaults" => 'cellpadding="2" border="1" cellspacing="0"',
            "wm_whole_line" => array(),
            "htmlentities" => array(
-               "&" => "&amp;",
-               ">" => "&gt;",
-               "<" => "&lt;",
+        "&" => "&amp;",
+        ">" => "&gt;",
+        "<" => "&lt;",
            ),
            "wm_source" => array(
-               "%%%" => "<br />",
-               "\t" => "        ",
-               "\n;:" => "\n      ",   # workaround, replaces the old ;:
+        "%%%" => "<br />",
+        "\t" => "        ",
+        "\n;:" => "\n      ",   # workaround, replaces the old ;:
            ),
            "wm_list" => array(
-               "-" => array('ul type="square"', "", "li"),
-               "*" => array('ul type="circle"', "", "li"),
-               "#" => array("ol", "", "li"),
-               ":" => array("dl", "dt", "dd"),
-       #<out># ";" => array("dl", "dt", "dd"),
+        "-" => array('ul type="square"', "", "li"),
+        "*" => array('ul type="circle"', "", "li"),
+        "#" => array("ol", "", "li"),
+        ":" => array("dl", "dt", "dd"),
+    #<out># ";" => array("dl", "dt", "dd"),
            ),
            "wm_style" => array(
-               "'''''" => array("<b><i>", "</i></b>"),
-               "'''" => array("<b>", "</b>"),
-               "___" => array("<i><b>", "</b></i>"),
-               "''" => array("<em>", "</em>"),
-               "__" => array("<strong>", "</strong>"),
-               "^^" => array("<sup>", "</sup>"),
-               "==" => array("<tt>", "</tt>"),
-       #<off># "***" => array("<b><i>", "</i></b>"),
-       #<off># "###" => array("<big><b>", "</b></big>"),
-               "**" => array("<b>", "</b>"),
-               "##" => array("<big>", "</big>"),
-               "µµ" => array("<small>", "</small>"),
+        "'''''" => array("<b><i>", "</i></b>"),
+        "'''" => array("<b>", "</b>"),
+        "___" => array("<i><b>", "</b></i>"),
+        "''" => array("<em>", "</em>"),
+        "__" => array("<strong>", "</strong>"),
+        "^^" => array("<sup>", "</sup>"),
+        "==" => array("<tt>", "</tt>"),
+    #<off># "***" => array("<b><i>", "</i></b>"),
+    #<off># "###" => array("<big><b>", "</b></big>"),
+        "**" => array("<b>", "</b>"),
+        "##" => array("<big>", "</big>"),
+        "µµ" => array("<small>", "</small>"),
            ),
            "wm_start_end" => array(
            ),
-       #-- rendering plugins
+    #-- rendering plugins
            "format_block" => array(
-               "html" => array("&lt;html&gt;", "&lt;/html&gt;", "html", 0x0000),
-               "htm" => array("&lt;htm&gt;", "&lt;/htm&gt;", "html", 0x0003),
-               "code" => array("&lt;code&gt;", "&lt;/code&gt;", false, 0x0000),
-               "pre" => array("&lt;pre&gt;", "&lt;/pre&gt;", false, 0x003F),
-               "comment" => array("\n&lt;!--", "--&gt;", false, 0x0030),
-               #  "verbatim" => array("&lt;verbatim&gt;", "&lt;/verbatim&gt;", false, 0x0000),
+        "html" => array("&lt;html&gt;", "&lt;/html&gt;", "html", 0x0000),
+        "htm" => array("&lt;htm&gt;", "&lt;/htm&gt;", "html", 0x0003),
+        "code" => array("&lt;code&gt;", "&lt;/code&gt;", false, 0x0000),
+        "pre" => array("&lt;pre&gt;", "&lt;/pre&gt;", false, 0x003F),
+        "comment" => array("\n&lt;!--", "--&gt;", false, 0x0030),
+        #  "verbatim" => array("&lt;verbatim&gt;", "&lt;/verbatim&gt;", false, 0x0000),
            ),
            "format_params" => array(
-               "scan_links" => 1,
-               "html" => EWIKI_ALLOW_HTML,
-               "mpi" => 1,
+        "scan_links" => 1,
+        "html" => EWIKI_ALLOW_HTML,
+        "mpi" => 1,
            ),
         );
         foreach ($ewiki_config_DEFAULTSTMP as $set => $val) {
         }
         $ewiki_config_DEFAULTSTMP = $valv = $vali = $val = NULL;
 
-       #-- init stuff, autostarted parts
-       ksort($ewiki_plugins["init"]);
-       if ($pf_a = $ewiki_plugins["init"]) foreach ($pf_a as $pf) {
+    #-- init stuff, autostarted parts
+    ksort($ewiki_plugins["init"]);
+    if ($pf_a = $ewiki_plugins["init"]) foreach ($pf_a as $pf) {
            // Binary Handling starts here
            #### MOODLE CHANGE TO BE COMPATIBLE WITH PHP 4.1
            #if(headers_sent($file,$line)) {
            }
            $pf($GLOBALS);
         }
-       unset($ewiki_plugins["init"]);
+    unset($ewiki_plugins["init"]);
 
-       #-- text  (never remove the "C" or "en" sections!)
+    #-- text  (never remove the "C" or "en" sections!)
         #
-       $ewiki_t["C"] = @array_merge(@$ewiki_t["C"], array(
+    $ewiki_t["C"] = @array_merge(@$ewiki_t["C"], array(
            "DATE" => "%a, %d %b %G %T %Z",
-          "EDIT_TEXTAREA_RESIZE_JS" => '<a href="javascript:ewiki_enlarge()" style="text-decoration:none">+</a><script type="text/javascript"><!--'."\n".'function ewiki_enlarge() {var ta=document.getElementById("ewiki_content");ta.style.width=((ta.cols*=1.1)*10).toString()+"px";ta.style.height=((ta.rows*=1.1)*30).toString()+"px";}'."\n".'//--></script>',
+       "EDIT_TEXTAREA_RESIZE_JS" => '<a href="javascript:ewiki_enlarge()" style="text-decoration:none">+</a><script type="text/javascript"><!--'."\n".'function ewiki_enlarge() {var ta=document.getElementById("ewiki_content");ta.style.width=((ta.cols*=1.1)*10).toString()+"px";ta.style.height=((ta.rows*=1.1)*30).toString()+"px";}'."\n".'//--></script>',
         ));
         #
-       $ewiki_t["en"] = @array_merge(@$ewiki_t["en"], array(
-          "EDITTHISPAGE" => "EditThisPage",
+    $ewiki_t["en"] = @array_merge(@$ewiki_t["en"], array(
+       "EDITTHISPAGE" => "EditThisPage",
            "APPENDTOPAGE" => "Add to",
-          "BACKLINKS" => "BackLinks",
-          "PAGESLINKINGTO" => "Pages linking to \$title",
-          "PAGEHISTORY" => "PageInfo",
-          "INFOABOUTPAGE" => "Information about page",
-          "LIKEPAGES" => "Pages like this",
-          "NEWESTPAGES" => "Newest Pages",
-          "LASTCHANGED" => "last changed on %c",
-          "DOESNOTEXIST" => "This page does not yet exist, please click on EditThisPage if you'd like to create it.",
-          "DISABLEDPAGE" => "This page is currently not available.",
-          "ERRVERSIONSAVE" => "Sorry, while you edited this page someone else
-               did already save a changed version. Please go back to the
-               previous screen and copy your changes to your computers
-               clipboard to insert it again after you reload the edit
-               screen.",
-          "ERRORSAVING" => "An error occoured while saving your changes. Please try again.",
-          "THANKSFORCONTRIBUTION" => "Thank you for your contribution!",
-          "CANNOTCHANGEPAGE" => "This page cannot be changed.",
-          "OLDVERCOMEBACK" => "Make this old version come back to replace the current one",
-          "PREVIEW" => "Preview",
-          "SAVE" => "Save",
-          "CANCEL_EDIT" => "CancelEditing",
-          "UPLOAD_PICTURE_BUTTON" => "upload picture &gt;&gt;&gt;",
-          "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."GoodStyle\">GoodStyle</a> is to
-               write what comes to your mind. Don't care about how it
-               looks too much now. You can add <a href=\"".EWIKI_SCRIPT."WikiMarkup\">WikiMarkup</a>
-               also later if you think it is necessary.<br />",
-          "EDIT_FORM_2" => "<br />Please do not write things, which may make other
-               people angry. And please keep in mind that you are not all that
-               anonymous in the internet (find out more about your computers
-               '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' at Google).",
-          "BIN_IMGTOOLARGE" => "Image file is too large!",
-          "BIN_NOIMG" => "This is no image file (inacceptable file format)!",
-          "FORBIDDEN" => "You are not authorized to access this page.",
-       ));
+       "BACKLINKS" => "BackLinks",
+       "PAGESLINKINGTO" => "Pages linking to \$title",
+       "PAGEHISTORY" => "PageInfo",
+       "INFOABOUTPAGE" => "Information about page",
+       "LIKEPAGES" => "Pages like this",
+       "NEWESTPAGES" => "Newest Pages",
+       "LASTCHANGED" => "last changed on %c",
+       "DOESNOTEXIST" => "This page does not yet exist, please click on EditThisPage if you'd like to create it.",
+       "DISABLEDPAGE" => "This page is currently not available.",
+       "ERRVERSIONSAVE" => "Sorry, while you edited this page someone else
+        did already save a changed version. Please go back to the
+        previous screen and copy your changes to your computers
+        clipboard to insert it again after you reload the edit
+        screen.",
+       "ERRORSAVING" => "An error occoured while saving your changes. Please try again.",
+       "THANKSFORCONTRIBUTION" => "Thank you for your contribution!",
+       "CANNOTCHANGEPAGE" => "This page cannot be changed.",
+       "OLDVERCOMEBACK" => "Make this old version come back to replace the current one",
+       "PREVIEW" => "Preview",
+       "SAVE" => "Save",
+       "CANCEL_EDIT" => "CancelEditing",
+       "UPLOAD_PICTURE_BUTTON" => "upload picture &gt;&gt;&gt;",
+       "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."GoodStyle\">GoodStyle</a> is to
+        write what comes to your mind. Don't care about how it
+        looks too much now. You can add <a href=\"".EWIKI_SCRIPT."WikiMarkup\">WikiMarkup</a>
+        also later if you think it is necessary.<br />",
+       "EDIT_FORM_2" => "<br />Please do not write things, which may make other
+        people angry. And please keep in mind that you are not all that
+        anonymous in the internet (find out more about your computers
+        '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' at Google).",
+       "BIN_IMGTOOLARGE" => "Image file is too large!",
+       "BIN_NOIMG" => "This is no image file (inacceptable file format)!",
+       "FORBIDDEN" => "You are not authorized to access this page.",
+    ));
         #
         $ewiki_t["es"] = @array_merge(@$ewiki_t["es"], array(
            "EDITTHISPAGE" => "EditarEstaPágina",
            "DOESNOTEXIST" => "Esta página aún no existe, por favor eliga EditarEstaPágina si desea crearla.",
            "DISABLEDPAGE" => "Esta página no está disponible en este momento.",
            "ERRVERSIONSAVE" => "Disculpe, mientras editaba esta página alguién más
-               salvó una versión modificada. Por favor regrese a
-               a la pantalla anterior y copie sus cambios a su computador
-               para insertalos nuevamente después de que cargue
-               la pantalla de edición.",
+        salvó una versión modificada. Por favor regrese a
+        a la pantalla anterior y copie sus cambios a su computador
+        para insertalos nuevamente después de que cargue
+        la pantalla de edición.",
            "ERRORSAVING" => "Ocurrió un error mientras se salvavan sus cambios. Por favor intente de nuevo.",
            "THANKSFORCONTRIBUTION" => "Gracias por su contribución!",
            "CANNOTCHANGEPAGE" => "Esta página no puede ser modificada.",
            "CANCEL_EDIT" => "CancelarEdición",
            "UPLOAD_PICTURE_BUTTON" => "subir gráfica &gt;&gt;&gt;",
            "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."BuenEstilo\">BuenEstilo</a> es
-               escribir lo que viene a su mente. No se preocupe mucho
-               por la apariencia. También puede agregar <a href=\"".EWIKI_SCRIPT."ReglasDeMarcadoWiki\">ReglasDeMarcadoWiki</a>
-               más adelante si piensa que es necesario.<br />",
+        escribir lo que viene a su mente. No se preocupe mucho
+        por la apariencia. También puede agregar <a href=\"".EWIKI_SCRIPT."ReglasDeMarcadoWiki\">ReglasDeMarcadoWiki</a>
+        más adelante si piensa que es necesario.<br />",
            "EDIT_FORM_2" => "<br />Por favor no escriba cosas, que puedan
-               enfadar a otras personas. Y por favor tenga en mente que
-               usted no es del todo anónimo en Internet 
-               (encuentre más sobre 
-               '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' de su computador con Google).",
+        enfadar a otras personas. Y por favor tenga en mente que
+        usted no es del todo anónimo en Internet 
+        (encuentre más sobre 
+        '<a href=\"http://google.com/search?q=my+computers+IP+address\">IP address</a>' de su computador con Google).",
            "BIN_IMGTOOLARGE" => "¡La gráfica es demasiado grande!",
            "BIN_NOIMG" => "¡No es un archivo con una gráfica (formato de archivo inaceptable)!",
            "FORBIDDEN" => "No está autorizado para acceder a esta página.",
         ));
         #
-       $ewiki_t["de"] = @array_merge(@$ewiki_t["de"], array(
-          "EDITTHISPAGE" => "DieseSeiteÄndern",
+    $ewiki_t["de"] = @array_merge(@$ewiki_t["de"], array(
+       "EDITTHISPAGE" => "DieseSeiteÄndern",
            "APPENDTOPAGE" => "Ergänze",
-          "BACKLINKS" => "ZurückLinks",
-          "PAGESLINKINGTO" => "Verweise zur Seite \$title",
-          "PAGEHISTORY" => "SeitenInfo",
-          "INFOABOUTPAGE" => "Informationen über Seite",
-          "LIKEPAGES" => "Ähnliche Seiten",
-          "NEWESTPAGES" => "Neueste Seiten",
-          "LASTCHANGED" => "zuletzt geändert am %d.%m.%Y um %H:%M",
-          "DISABLEDPAGE" => "Diese Seite kann momentan nicht angezeigt werden.",
-          "ERRVERSIONSAVE" => "Entschuldige, aber während Du an der Seite
-               gearbeitet hast, hat bereits jemand anders eine geänderte
-               Fassung gespeichert. Damit nichts verloren geht, browse bitte
-               zurück und speichere Deine Änderungen in der Zwischenablage
-               (Bearbeiten->Kopieren) um sie dann wieder an der richtigen
-               Stelle einzufügen, nachdem du die EditBoxSeite nocheinmal
-               geladen hast.<br />
-               Vielen Dank für Deine Mühe.",
-          "ERRORSAVING" => "Beim Abspeichern ist ein Fehler aufgetreten. Bitte versuche es erneut.",
-          "THANKSFORCONTRIBUTION" => "Vielen Dank für Deinen Beitrag!",
-          "CANNOTCHANGEPAGE" => "Diese Seite kann nicht geändert werden.",
-          "OLDVERCOMEBACK" => "Diese alte Version der Seite wieder zur Aktuellen machen",
-          "PREVIEW" => "Vorschau",
-          "SAVE" => "Speichern",
-          "CANCEL_EDIT" => "ÄnderungenVerwerfen",
-          "UPLOAD_PICTURE_BUTTON" => "Bild hochladen &gt;&gt;&gt;",
-          "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."GuterStil\">GuterStil</a> ist es,
-               ganz einfach das zu schreiben, was einem gerade in den
-               Sinn kommt. Du solltest dich jetzt noch nicht so sehr
-               darum kümmern, wie die Seite aussieht. Du kannst später
-               immernoch zurückkommen und den Text mit <a href=\"".EWIKI_SCRIPT."FormatierungsRegeln\">WikiTextFormatierungsRegeln</a>
-               aufputschen.<br />",
-          "EDIT_FORM_2" => "<br />Bitte schreib keine Dinge, die andere Leute
-               verärgern könnten. Und bedenke auch, daß es schnell auf
-               dich zurückfallen kann wenn du verschiedene andere Dinge sagst (mehr Informationen zur
-               '<a href=\"http://google.de/search?q=computer+IP+adresse\">IP Adresse</a>'
-               deines Computers findest du bei Google).",
-       ));
-
-       #-- InterWiki:Links
-       $ewiki_config["interwiki"] = @array_merge(
-       @$ewiki_config["interwiki"],
-       array(
+       "BACKLINKS" => "ZurückLinks",
+       "PAGESLINKINGTO" => "Verweise zur Seite \$title",
+       "PAGEHISTORY" => "SeitenInfo",
+       "INFOABOUTPAGE" => "Informationen über Seite",
+       "LIKEPAGES" => "Ähnliche Seiten",
+       "NEWESTPAGES" => "Neueste Seiten",
+       "LASTCHANGED" => "zuletzt geändert am %d.%m.%Y um %H:%M",
+       "DISABLEDPAGE" => "Diese Seite kann momentan nicht angezeigt werden.",
+       "ERRVERSIONSAVE" => "Entschuldige, aber während Du an der Seite
+        gearbeitet hast, hat bereits jemand anders eine geänderte
+        Fassung gespeichert. Damit nichts verloren geht, browse bitte
+        zurück und speichere Deine Änderungen in der Zwischenablage
+        (Bearbeiten->Kopieren) um sie dann wieder an der richtigen
+        Stelle einzufügen, nachdem du die EditBoxSeite nocheinmal
+        geladen hast.<br />
+        Vielen Dank für Deine Mühe.",
+       "ERRORSAVING" => "Beim Abspeichern ist ein Fehler aufgetreten. Bitte versuche es erneut.",
+       "THANKSFORCONTRIBUTION" => "Vielen Dank für Deinen Beitrag!",
+       "CANNOTCHANGEPAGE" => "Diese Seite kann nicht geändert werden.",
+       "OLDVERCOMEBACK" => "Diese alte Version der Seite wieder zur Aktuellen machen",
+       "PREVIEW" => "Vorschau",
+       "SAVE" => "Speichern",
+       "CANCEL_EDIT" => "ÄnderungenVerwerfen",
+       "UPLOAD_PICTURE_BUTTON" => "Bild hochladen &gt;&gt;&gt;",
+       "EDIT_FORM_1" => "<a href=\"".EWIKI_SCRIPT."GuterStil\">GuterStil</a> ist es,
+        ganz einfach das zu schreiben, was einem gerade in den
+        Sinn kommt. Du solltest dich jetzt noch nicht so sehr
+        darum kümmern, wie die Seite aussieht. Du kannst später
+        immernoch zurückkommen und den Text mit <a href=\"".EWIKI_SCRIPT."FormatierungsRegeln\">WikiTextFormatierungsRegeln</a>
+        aufputschen.<br />",
+       "EDIT_FORM_2" => "<br />Bitte schreib keine Dinge, die andere Leute
+        verärgern könnten. Und bedenke auch, daß es schnell auf
+        dich zurückfallen kann wenn du verschiedene andere Dinge sagst (mehr Informationen zur
+        '<a href=\"http://google.de/search?q=computer+IP+adresse\">IP Adresse</a>'
+        deines Computers findest du bei Google).",
+    ));
+
+    #-- InterWiki:Links
+    $ewiki_config["interwiki"] = @array_merge(
+    @$ewiki_config["interwiki"],
+    array(
            "javascript" => "",  # this actually protects from javascript: links
            "url" => "",
 #          "self" => "this",
            "this" => EWIKI_SCRIPT,  # better was absolute _URL to ewiki wrapper
            "jump" => "",
-          "ErfurtWiki" => "http://erfurtwiki.sourceforge.net/?id=",
-          "InterWiki" => "InterWikiSearch",
-          "InterWikiSearch" => "http://sunir.org/apps/meta.pl?",
-          "Wiki" => "WardsWiki",
-          "WardsWiki" => "http://www.c2.com/cgi/wiki?",
-          "WikiFind" => "http://c2.com/cgi/wiki?FindPage&amp;value=",
-          "WikiPedia" => "http://www.wikipedia.com/wiki.cgi?",
-          "MeatBall" => "MeatballWiki",
-          "MeatballWiki" => "http://www.usemod.com/cgi-bin/mb.pl?",
-          "UseMod"       => "http://www.usemod.com/cgi-bin/wiki.pl?",
-          "PhpWiki" => "http://phpwiki.sourceforge.net/phpwiki/index.php3?",
-          "LinuxWiki" => "http://linuxwiki.de/",
-          "OpenWiki" => "http://openwiki.com/?",
-          "Tavi" => "http://andstuff.org/tavi/",
-          "TWiki" => "http://twiki.sourceforge.net/cgi-bin/view/",
-          "MoinMoin" => "http://www.purl.net/wiki/moin/",
-          "Google" => "http://google.com/search?q=",
-          "ISBN" => "http://www.amazon.com/exec/obidos/ISBN=",
-          "icq" => "http://www.icq.com/",
-       ));
+       "ErfurtWiki" => "http://erfurtwiki.sourceforge.net/?id=",
+       "InterWiki" => "InterWikiSearch",
+       "InterWikiSearch" => "http://sunir.org/apps/meta.pl?",
+       "Wiki" => "WardsWiki",
+       "WardsWiki" => "http://www.c2.com/cgi/wiki?",
+       "WikiFind" => "http://c2.com/cgi/wiki?FindPage&amp;value=",
+       "WikiPedia" => "http://www.wikipedia.com/wiki.cgi?",
+       "MeatBall" => "MeatballWiki",
+       "MeatballWiki" => "http://www.usemod.com/cgi-bin/mb.pl?",
+       "UseMod"       => "http://www.usemod.com/cgi-bin/wiki.pl?",
+       "PhpWiki" => "http://phpwiki.sourceforge.net/phpwiki/index.php3?",
+       "LinuxWiki" => "http://linuxwiki.de/",
+       "OpenWiki" => "http://openwiki.com/?",
+       "Tavi" => "http://andstuff.org/tavi/",
+       "TWiki" => "http://twiki.sourceforge.net/cgi-bin/view/",
+       "MoinMoin" => "http://www.purl.net/wiki/moin/",
+       "Google" => "http://google.com/search?q=",
+       "ISBN" => "http://www.amazon.com/exec/obidos/ISBN=",
+       "icq" => "http://www.icq.com/",
+    ));
 
 
 
@@ -2091,7 +2091,7 @@ function ewiki_format (
         global $ewiki_use_editor, $ewiki_editor_content;
         if(!($ewiki_use_editor && $ewiki_editor_content)) {
       ##### END MOODLE ADDITION #####
-             ewiki_render_wiki_links($ooo[$in][0]);
+          ewiki_render_wiki_links($ooo[$in][0]);
       ##### BEGIN MOODLE ADDITION #####
          }
       ##### END MOODLE ADDITION #####
@@ -2422,7 +2422,7 @@ function ewiki_link_regex_callback($uu, $force_noimg=0) {
          $str = ($obj ? '<embed width="70%"' : '<img') . ' src="' . $href . '"' .
                 ' alt="' . ($title) . '"' .
                 (@$states["titled"] ? ' title="' . ($title) . '"' : '').
-               ($x && $y ? " width=\"$x\" height=\"$y\"" : "") .
+        ($x && $y ? " width=\"$x\" height=\"$y\"" : "") .
                 $align . " />" . ($obj ? "</embed>" : "");
                                             # htmlentities($title)
       }
@@ -2977,8 +2977,8 @@ function ewiki_array($array, $key=false, $am=1, $ci=EWIKI_CASE_INSENSITIVE) {
             $r[$i] = $v;
          }
          else {
-            $r[$i] .= $v;      //RET: doubling for images`meta won't happen
-         }                     // but should be "+" here for integers
+            $r[$i] .= $v;   //RET: doubling for images`meta won't happen
+         }          // but should be "+" here for integers
       }
       $array = &$r;
    }
@@ -3008,7 +3008,7 @@ function ewiki_author($defstr="") {
 
    (empty($author)) && (
       ($author = $defstr) ||
-      ($author = $_SERVER["HTTP_FROM"]) ||     // RFC2068 sect 14.22
+      ($author = $_SERVER["HTTP_FROM"]) ||  // RFC2068 sect 14.22
       ($author = $_SERVER["PHP_AUTH_USER"])
    );
 
@@ -3418,7 +3418,7 @@ function ewiki_database_mysql($action, &$args, $sw1, $sw2) {
           existing entries (using WRITE); returns 0 on failure and 1 if
           saved correctly.
       */
-      case "OVERWRITE":                // fall-through
+      case "OVERWRITE":     // fall-through
          $COMMAND = "REPLACE";
 
       case "WRITE":
index 2c91799df167e46b5b8aad30fc1d7319cafbc075..57deae4aefc070c74fc48b5053eb2f1935cfa75d 100644 (file)
     /// Insert a link to force page refresh if new content isn't showing.
     
     // build new URL + query string
-    $queries = preg_split('/[?&]/', me());     
+    $queries = preg_split('/[?&]/', me());  
     $nqueries = count($queries);
     $me = $queries[0] . '?';
     for($i=1; $i < $nqueries; $i++)
     {
         if( !strstr($queries[$i], 'allowcache') )
-               $me .= $queries[$i] . '&'; 
+            $me .= $queries[$i] . '&'; 
     }
     $me .= 'allowcache=0';