53406995625e547ea3d87f035f58fbaceb00bdae
[moodle.git] / mod / scorm / lib.php
1 <?PHP  // $Id$
3 /// Library of functions and constants for module scorm
4 /// (replace scorm with the name of your module and delete this line)
6 $SCORM_WINDOW_OPTIONS = array("resizable", "scrollbars", "status", "height", "width");
8 if (!isset($CFG->scorm_popup)) {
9     set_config("scorm_popup", "");
10 }  
12 foreach ($SCORM_WINDOW_OPTIONS as $popupoption) {
13     $popupoption = "scorm_popup$popupoption";
14     if (!isset($CFG->$popupoption)) {
15         if ($popupoption == "scorm_popupheight") {
16             set_config($popupoption, 450);
17         } else if ($popupoption == "scorm_popupwidth") {
18             set_config($popupoption, 620);
19         } else {
20             set_config($popupoption, "checked");
21         }
22     }  
23 }
25 if (!isset($CFG->scorm_framesize)) {
26     set_config("scorm_framesize", 140);
27 }
29 function scorm_add_instance($scorm) {
30 /// Given an object containing all the necessary data, 
31 /// (defined by the form in mod.html) this function 
32 /// will create a new instance and return the id number 
33 /// of the new instance.
35     $scorm->timemodified = time();
37     # May have to add extra stuff in here #
38     global $SCORM_WINDOW_OPTIONS;
39     
40     if (isset($scorm->setnewwindow)) {
41         $optionlist = array();
42         foreach ($SCORM_WINDOW_OPTIONS as $option) {
43             if (isset($scorm->$option)) {
44                 $optionlist[] = $option."=".$scorm->$option;
45             }
46         }
47         $scorm->popup = implode(',', $optionlist);
48         $scorm->popup .= ',location=0,menubar=0,toolbar=0';
49         $scorm->auto = '0';
50     }
51     
52     return insert_record("scorm", $scorm);
53 }
56 function scorm_update_instance($scorm) {
57 /// Given an object containing all the necessary data, 
58 /// (defined by the form in mod.html) this function 
59 /// will update an existing instance with new data.
60     
61     $scorm->timemodified = time();
62     $scorm->id = $scorm->instance;
64     # May have to add extra stuff in here #
65     global $SCORM_WINDOW_OPTIONS;
66     
67     if (isset($scorm->setnewwindow)) {
68         $optionlist = array();
69         foreach ($SCORM_WINDOW_OPTIONS as $option) {
70             if (isset($scorm->$option)) {
71                 $optionlist[] = $option."=".$scorm->$option;
72             }
73         }
74         $scorm->popup = implode(',', $optionlist);
75         $scorm->popup .= ',location=0,menubar=0,toolbar=0';
76         $scorm->auto = '0';
77     }
79     return update_record("scorm", $scorm);
80 }
83 function scorm_delete_instance($id) {
84 /// Given an ID of an instance of this module, 
85 /// this function will permanently delete the instance 
86 /// and any data that depends on it.  
87     
88     require('../config.php');
90     if (! $scorm = get_record("scorm", "id", "$id")) {
91         return false;
92     }
94     $result = true;
96     # Delete any dependent files #
97     scorm_delete_files($CFG->dataroot."/".$scorm->course."/moddata/scorm".$scorm->datadir);
99     # Delete any dependent records here #
100     if (! delete_records("scorm_sco_users", "scormid", "$scorm->id")) {
101         $result = false;
102     }
103     if (! delete_records("scorm_scoes", "scorm", "$scorm->id")) {
104         $result = false;
105     }
106     if (! delete_records("scorm", "id", "$scorm->id")) {
107         $result = false;
108     }
109     
111     return $result;
114 function scorm_user_outline($course, $user, $mod, $scorm) {
115 /// Return a small object with summary information about what a 
116 /// user has done with a given particular instance of this module
117 /// Used for user activity reports.
118 /// $return->time = the time they did it
119 /// $return->info = a short text description
121     return $return;
124 function scorm_user_complete($course, $user, $mod, $scorm) {
125 /// Print a detailed representation of what a  user has done with 
126 /// a given particular instance of this module, for user activity reports.
128     return true;
131 function scorm_print_recent_activity(&$logs, $isteacher=false) {
132 /// Given a list of logs, assumed to be those since the last login 
133 /// this function prints a short list of changes related to this module
134 /// If isteacher is true then perhaps additional information is printed.
135 /// This function is called from course/lib.php: print_recent_activity()
137     global $CFG, $COURSE_TEACHER_COLOR;
139     $content = NULL;
141     return $content;  // True if anything was printed, otherwise false
144 function scorm_cron () {
145 /// Function to be run periodically according to the moodle cron
146 /// This function searches for things that need to be done, such 
147 /// as sending out mail, toggling flags etc ... 
149     global $CFG;
151     return true;
154 function scorm_grades($scormid) {
155 /// Must return an array of grades for a given instance of this module, 
156 /// indexed by user.  It also returns a maximum allowed grade.
158     global $CFG;
159     
160     if (!$return->maxgrade = count_records_select("scorm_scoes","scorm='$scormid' AND launch<>''")) {
161         return NULL;
162     }
163     
164     $return->grades = NULL;
165     if ($sco_users=get_records_select("scorm_sco_users", "scormid='$scormid' GROUP BY userid")) {
166         foreach ($sco_users as $sco_user) {
167             $user_data=get_records_select("scorm_sco_users","scormid='$scormid' AND userid='$sco_user->userid'");
168             $scores->completed=0;
169             $scores->browsed=0;
170             $scores->incomplete=0;
171             $scores->failed=0;
172             $scores->notattempted=0;
173             $result="";
174             $data = current($user_data);
175             foreach ($user_data as $data) {
176                 if ($data->cmi_core_lesson_status=="passed")
177                     $scores->completed++;
178                 else
179                     $scores->{scorm_remove_spaces($data->cmi_core_lesson_status)}++;
180                 
181             }
182             if ($scores->completed)
183                 $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/completed.gif\" alt=\"".get_string("completed","scorm")."\" title=\"".get_string("completed","scorm")."\"> $scores->completed ";
184             if ($scores->incomplete)
185                 $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/incomplete.gif\" alt=\"".get_string("incomplete","scorm")."\" title=\"".get_string("incomplete","scorm")."\"> $scores->incomplete ";
186             if ($scores->failed)
187                 $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/failed.gif\" alt=\"".get_string("failed","scorm")."\" title=\"".get_string("failed","scorm")."\"> $scores->failed ";
188             if ($scores->browsed)
189                 $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/browsed.gif\" alt=\"".get_string("browsed","scorm")."\" title=\"".get_string("browsed","scorm")."\"> $scores->browsed ";
190             if ($scores->notattempted)
191                 $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/notattempted.gif\" alt=\"".get_string("notattempted","scorm")."\" title=\"".get_string("notattempted","scorm")."\"> $scores->notattempted ";
192             
193             $return->grades[$sco_user->userid]=$result;
194         }
195         
196     }
198     return $return;
202 //////////////////////////////////////////////////////////////////////////////////////
203 /// Any other scorm functions go here.  Each of them must have a name that 
204 /// starts with scorm_
207 function scorm_randstring($len = "8")
209         $rstring = NULL;
210         for($i=0; $i<$len; $i++) {
211                 $char = chr(rand(48,122));
212                 while (!ereg("[a-zA-Z0-9]", $char)){
213                         if($char == $lchar) continue;
214                         $char = chr(rand(48,90));
215                 }
216                 $rstring .= $char;
217                 $lchar = $char;
218         }
219         return $rstring;
222  
223 function scorm_datadir($strPath, $existingdir="", $prefix = "SCORM")
225     global $CFG;
227     if (($existingdir!="") && (is_dir($strPath.$existingdir)))
228         return $strPath.$existingdir;
229         
230     if (is_dir($strPath)) {
231         do {
232             $datadir="/".$prefix.scorm_randstring();
233         } while (file_exists($strPath.$datadir));
234         mkdir($strPath.$datadir, $CFG->directorypermissions);
235         @chmod($strPath.$datadir, $CFG->directorypermissions);  // Just in case mkdir didn't do it
236         return $strPath.$datadir;
237     } else {
238         return false;
239     }
240
242 function scorm_validate($manifest)
244     if (is_file ($manifest)) {
245     if (file_exists($manifest))
246     {
247         return "regular";
248     }
249     } else {
250         return "nomanifest";
251     }
254 function scorm_delete_files($directory)
256     if (is_dir($directory))
257     {
258         $handle=opendir($directory);
259         while (($file = readdir($handle)) != '')
260         {
261             if ($file != "." && $file != "..")
262         {
263             if (!is_dir($directory."/".$file))
264                     unlink($directory."/".$file);
265             else
266             scorm_delete_files($directory."/".$file);
267         }
268         }
269         rmdir($directory);
270     }
273 function scorm_startElement($parser, $name, $attrs) {
274     global $manifest,$i,$resources,$parent,$level;
275     if ($name == "ITEM") {
276         $i++;
277         $manifest[$i]["identifier"] = $attrs["IDENTIFIER"];
278         if (empty($attrs["IDENTIFIERREF"]))
279             $attrs["IDENTIFIERREF"] = "";
280         $manifest[$i]["identifierref"] = $attrs["IDENTIFIERREF"];
281         if (empty($attrs["ISVISIBLE"]))
282             $attrs["ISVISIBLE"] = "";
283         $manifest[$i]["isvisible"] = $attrs["ISVISIBLE"];
284         $manifest[$i]["parent"] = $parent[$level];
285         $level++;
286         $parent[$level] = $attrs["IDENTIFIER"];
287     }
288     if ($name == "RESOURCE") {
289         $resources[$attrs["IDENTIFIER"]]["href"]=$attrs["HREF"];
290         $resources[$attrs["IDENTIFIER"]]["type"]=$attrs["ADLCP:SCORMTYPE"];
291     }
294 function scorm_endElement($parser, $name) {
295     global $manifest,$i,$level,$datacontent,$navigation;
296     if ($name == "ITEM") {
297         $level--;
298     }
299     if ($name == "TITLE" && $level>0)
300     $manifest[$i]["title"] = $datacontent;
301     if ($name == "ADLCP:HIDERTSUI")
302     $manifest[$i][$datacontent] = 1;
305 function scorm_characterData($parser, $data) {
306     global $datacontent;
307     $datacontent = $data;
310 function scorm_parse($basedir,$file,$scorm_id) {
311     global $manifest,$i,$resources,$parent,$level;
312     $datacontent = "";
313     $manifest[][] = "";
314     $resources[] = "";
315     $i = 0;
316     $level = 0;
317     $parent[$level] = "/";
319     $xml_parser = xml_parser_create();
320     // use case-folding so we are sure to find the tag in $map_array
321     xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
322     xml_set_element_handler($xml_parser, "scorm_startElement", "scorm_endElement");
323     xml_set_character_data_handler($xml_parser, "scorm_characterData");
324     if (!($fp = fopen($basedir.$file, "r"))) {
325        die("could not open XML input");
326     }
328     while ($data = fread($fp, 4096)) {
329         if (!xml_parse($xml_parser, $data, feof($fp))) {
330             die(sprintf("XML error: %s at line %d",
331                     xml_error_string(xml_get_error_code($xml_parser)),
332                     xml_get_current_line_number($xml_parser)));
333         }
334     }
335     xml_parser_free($xml_parser);
336     $launch = 0;
338     $sco->scorm = $scorm_id;
339     delete_records("scorm_scoes","scorm",$scorm_id);
340     delete_records("scorm_sco_users","scormid",$scorm_id);
341     for ($j=1; $j<=$i; $j++) {
342         $sco->identifier = $manifest[$j]["identifier"];
343         $sco->parent = $manifest[$j]["parent"];
344         $sco->title = $manifest[$j]["title"];
345         if (empty($resources[($manifest[$j]["identifierref"])]["href"]))
346             $resources[($manifest[$j]["identifierref"])]["href"] = "";
347         $sco->launch = $resources[($manifest[$j]["identifierref"])]["href"];
348         if (empty($resources[($manifest[$j]["identifierref"])]["type"]))
349             $resources[($manifest[$j]["identifierref"])]["type"] = "";
350     $sco->type = $resources[($manifest[$j]["identifierref"])]["type"];
351     if (empty($manifest[$j]["previous"]))
352         $manifest[$j]["previous"] = 0;
353     $sco->previous = $manifest[$j]["previous"];
354     if (empty($manifest[$j]["continue"]))
355         $manifest[$j]["continue"] = 0;
356     $sco->next = $manifest[$j]["continue"];
357     if (scorm_remove_spaces($manifest[$j]["isvisible"]) != "false")
358         $id = insert_record("scorm_scoes",$sco);
359     if ($launch==0 && $sco->launch)
360         $launch = $id;  
361     }
362     return $launch;
365 function scorm_get_scoes_records($sco_user) {
366 /// Gets all info required to display the table of scorm results
367 /// for report.php
368     global $CFG;
370     return get_records_sql("SELECT su.*, u.firstname, u.lastname, u.picture 
371                             FROM {$CFG->prefix}scorm_sco_users su, 
372                                  {$CFG->prefix}user u
373                             WHERE su.scormid = '$sco_user->scormid'
374                               AND su.userid = u.id
375                               AND su.userid = $sco_user->userid
376                               ORDER BY scoid");
379 function scorm_remove_spaces($sourcestr) {
380 // Remove blank space from a string
381     $newstr="";
382     for( $i=0; $i<strlen($sourcestr); $i++) {
383         if ($sourcestr[$i]!=' ')
384             $newstr .=$sourcestr[$i];
385     }
386     return $newstr;
389 function scorm_string_round($stringa) {
390 // Crop a string to $len character and set an anchor title to the full string
391     $len=11;
392     if ( strlen($stringa)>$len ) {
393     return "<A name=\"\" title=\"$stringa\">".substr($stringa,0,$len-4)."...".substr($stringa,strlen($stringa)-1,1)."</A>";
394     } else
395     return $stringa;
398 function scorm_external_link($link) {
399 // check if a link is external
400     $result = false;
401     $link = strtolower($link);
402     if (substr($link,0,7) == "http://")
403         $result = true;
404     else if (substr($link,0,8) == "https://")
405         $result = true;
406     else if (substr($link,0,4) == "www.")
407         $result = true;
408     /*else if (substr($link,0,7) == "rstp://")
409         $result = true;
410     else if (substr($link,0,6) == "rtp://")
411         $result = true;
412     else if (substr($link,0,6) == "ftp://")
413         $result = true;
414     else if (substr($link,0,9) == "gopher://")
415         $result = true; */
416     return $result;
417 }    
418 ?>