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