First step to SCORM2004, new communication subsystem
[moodle.git] / mod / scorm / lib.php
CommitLineData
d1290cec 1<?php // $Id$
98ca59f6 2
3/// Library of functions and constants for module scorm
4/// (replace scorm with the name of your module and delete this line)
5
1a12b1f1 6define('VALUESCOES', '0');
7define('VALUEHIGHEST', '1');
8define('VALUEAVERAGE', '2');
9define('VALUESUM', '3');
10$SCORM_GRADE_METHOD = array (VALUESCOES => get_string("gradescoes", "scorm"),
11 VALUEHIGHEST => get_string("gradehighest", "scorm"),
12 VALUEAVERAGE => get_string("gradeaverage", "scorm"),
13 VALUESUM => get_string("gradesum", "scorm"));
14
15$SCORM_WINDOW_OPTIONS = array('resizable', 'scrollbars', 'status', 'height', 'width');
98ca59f6 16
76d35423 17if (!isset($CFG->scorm_popup)) {
1a12b1f1 18 set_config('scorm_popup', '');
19}
20if (!isset($CFG->scorm_validate)) {
21 $scorm_validate = 'none';
b7237c1e 22 //I've commented this out for Moodle 1.4, as I've seen errors in
23 //SCORM packages even though the actual package worked fine. -- Martin Dougiamas
ced8b969 24 if (extension_loaded('domxml') && version_compare(phpversion(),'5.0.0','<')) {
25 $scorm_validate = 'domxml';
26 }
27 if (version_compare(phpversion(),'5.0.0','>=')) {
28 $scorm_validate = 'php5';
29 }
1a12b1f1 30 set_config('scorm_validate', $scorm_validate);
31}
76d35423 32
33foreach ($SCORM_WINDOW_OPTIONS as $popupoption) {
34 $popupoption = "scorm_popup$popupoption";
35 if (!isset($CFG->$popupoption)) {
1a12b1f1 36 if ($popupoption == 'scorm_popupheight') {
76d35423 37 set_config($popupoption, 450);
1a12b1f1 38 } else if ($popupoption == 'scorm_popupwidth') {
76d35423 39 set_config($popupoption, 620);
40 } else {
1a12b1f1 41 set_config($popupoption, 'checked');
76d35423 42 }
43 }
44}
45
46if (!isset($CFG->scorm_framesize)) {
1a12b1f1 47 set_config('scorm_framesize', 140);
76d35423 48}
98ca59f6 49
50function scorm_add_instance($scorm) {
51/// Given an object containing all the necessary data,
52/// (defined by the form in mod.html) this function
53/// will create a new instance and return the id number
54/// of the new instance.
55
56 $scorm->timemodified = time();
57
58 # May have to add extra stuff in here #
2a0407b7 59 global $CFG,$SCORM_WINDOW_OPTIONS;
76d35423 60
1a12b1f1 61 $scorm->popup = '';
2a0407b7 62
b98eebbf 63 $optionlist = array();
64 foreach ($SCORM_WINDOW_OPTIONS as $option) {
65 if (isset($scorm->$option)) {
1a12b1f1 66 $optionlist[] = $option.'='.$scorm->$option;
76d35423 67 }
76d35423 68 }
b98eebbf 69 $scorm->popup = implode(',', $optionlist);
de8595db 70
b98eebbf 71
1a12b1f1 72 if ($scorm->popup != '') {
b98eebbf 73 $scorm->popup .= ',location=0,menubar=0,toolbar=0';
de8595db 74 $scorm->auto = '0';
75 }
2a0407b7 76 $id = insert_record('scorm', $scorm);
98ca59f6 77
2a0407b7 78 //
79 // Parse scorm manifest
80 //
81 if ($scorm->launch == 0) {
82 $basedir = $CFG->dataroot."/".$scorm->course;
83 $scormdir = "/moddata/scorm";
84 $scorm->launch = scorm_parse($basedir,$scormdir.$scorm->datadir."/imsmanifest.xml",$id);
85 set_field("scorm","launch",$scorm->launch,"id",$id);
86 }
87
88 return $id;
98ca59f6 89}
90
91
92function scorm_update_instance($scorm) {
93/// Given an object containing all the necessary data,
94/// (defined by the form in mod.html) this function
95/// will update an existing instance with new data.
76d35423 96
98ca59f6 97 $scorm->timemodified = time();
98 $scorm->id = $scorm->instance;
99
100 # May have to add extra stuff in here #
2a0407b7 101 global $CFG,$SCORM_WINDOW_OPTIONS;
76d35423 102
1a12b1f1 103 $scorm->popup = '';
b98eebbf 104
105 $optionlist = array();
106 foreach ($SCORM_WINDOW_OPTIONS as $option) {
107 if (isset($scorm->$option)) {
1a12b1f1 108 $optionlist[] = $option.'='.$scorm->$option;
76d35423 109 }
76d35423 110 }
b98eebbf 111 $scorm->popup = implode(',', $optionlist);
b98eebbf 112
1a12b1f1 113 if ($scorm->popup != '') {
b98eebbf 114 $scorm->popup .= ',location=0,menubar=0,toolbar=0';
de8595db 115 $scorm->auto = '0';
116 }
2a0407b7 117
2a0407b7 118 //
119 // Check if scorm manifest needs to be reparsed
120 //
121 if ($scorm->launch == 0) {
122 $basedir = $CFG->dataroot."/".$scorm->course;
123 $scormdir = "/moddata/scorm";
92a489eb 124 $scorm->launch = scorm_parse($basedir,$scormdir.$scorm->datadir."/imsmanifest.xml",$scorm->id);
2a0407b7 125 }
126
92a489eb 127 return update_record('scorm', $scorm);
98ca59f6 128}
129
130
131function scorm_delete_instance($id) {
132/// Given an ID of an instance of this module,
133/// this function will permanently delete the instance
134/// and any data that depends on it.
4a9df373 135
2a0407b7 136 require('../config.php');
98ca59f6 137
1a12b1f1 138 if (! $scorm = get_record('scorm', 'id', $id)) {
98ca59f6 139 return false;
140 }
141
142 $result = true;
143
144 # Delete any dependent files #
1a12b1f1 145 scorm_delete_files($CFG->dataroot.'/'.$scorm->course.'/moddata/scorm'.$scorm->datadir);
98ca59f6 146
147 # Delete any dependent records here #
1a12b1f1 148 if (! delete_records('scorm_sco_users', 'scormid', $scorm->id)) {
98ca59f6 149 $result = false;
150 }
1a12b1f1 151 if (! delete_records('scorm_scoes', 'scorm', $scorm->id)) {
98ca59f6 152 $result = false;
153 }
1a12b1f1 154 if (! delete_records('scorm', 'id', $scorm->id)) {
98ca59f6 155 $result = false;
156 }
157
158
159 return $result;
160}
161
162function scorm_user_outline($course, $user, $mod, $scorm) {
163/// Return a small object with summary information about what a
164/// user has done with a given particular instance of this module
165/// Used for user activity reports.
166/// $return->time = the time they did it
167/// $return->info = a short text description
168
169 return $return;
170}
171
172function scorm_user_complete($course, $user, $mod, $scorm) {
173/// Print a detailed representation of what a user has done with
174/// a given particular instance of this module, for user activity reports.
175
176 return true;
177}
178
179function scorm_print_recent_activity(&$logs, $isteacher=false) {
180/// Given a list of logs, assumed to be those since the last login
181/// this function prints a short list of changes related to this module
182/// If isteacher is true then perhaps additional information is printed.
183/// This function is called from course/lib.php: print_recent_activity()
184
185 global $CFG, $COURSE_TEACHER_COLOR;
186
e1e108d4 187 $content = NULL;
188
98ca59f6 189 return $content; // True if anything was printed, otherwise false
190}
191
192function scorm_cron () {
193/// Function to be run periodically according to the moodle cron
194/// This function searches for things that need to be done, such
195/// as sending out mail, toggling flags etc ...
196
197 global $CFG;
198
199 return true;
200}
201
202function scorm_grades($scormid) {
203/// Must return an array of grades for a given instance of this module,
204/// indexed by user. It also returns a maximum allowed grade.
205
4a9df373 206 global $CFG;
207
1a12b1f1 208 if (!$scorm = get_record("scorm", "id", $scormid)) {
4a9df373 209 return NULL;
210 }
211
1a12b1f1 212 if ($scorm->grademethod == VALUESCOES) {
213 if (!$return->maxgrade = count_records_select('scorm_scoes',"scorm='$scormid' AND launch<>''")) {
214 return NULL;
215 }
216
217 $return->grades = NULL;
218 if ($sco_users=get_records_select('scorm_sco_users', "scormid='$scormid' GROUP BY userid")) {
219 foreach ($sco_users as $sco_user) {
220 $user_data=get_records_select('scorm_sco_users',"scormid='$scormid' AND userid='$sco_user->userid'");
221 $scores->completed=0;
222 $scores->browsed=0;
223 $scores->incomplete=0;
224 $scores->failed=0;
225 $scores->notattempted=0;
226 $result='';
227 $data = current($user_data);
228 foreach ($user_data as $data) {
229 if ($data->cmi_core_lesson_status=='passed')
230 $scores->completed++;
231 else
232 $scores->{scorm_remove_spaces($data->cmi_core_lesson_status)}++;
233 }
234 if ($scores->completed)
e0b7b090 235 $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/completed.gif\" alt=\"".get_string('completed','scorm')."\" title=\"".get_string('completed','scorm')."\" /> $scores->completed ";
1a12b1f1 236 if ($scores->incomplete)
e0b7b090 237 $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/incomplete.gif\" alt=\"".get_string('incomplete','scorm')."\" title=\"".get_string('incomplete','scorm')."\" /> $scores->incomplete ";
1a12b1f1 238 if ($scores->failed)
e0b7b090 239 $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/failed.gif\" alt=\"".get_string('failed','scorm')."\" title=\"".get_string('failed','scorm')."\" /> $scores->failed ";
1a12b1f1 240 if ($scores->browsed)
e0b7b090 241 $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/browsed.gif\" alt=\"".get_string('browsed','scorm')."\" title=\"".get_string('browsed','scorm')."\" /> $scores->browsed ";
1a12b1f1 242 if ($scores->notattempted)
e0b7b090 243 $result.="<img src=\"$CFG->wwwroot/mod/scorm/pix/notattempted.gif\" alt=\"".get_string('notattempted','scorm')."\" title=\"".get_string('notattempted','scorm')."\" /> $scores->notattempted ";
4a9df373 244
1a12b1f1 245 $return->grades[$sco_user->userid]=$result;
246 }
98ca59f6 247
1a12b1f1 248 }
249 } else {
250 $grades = get_records_select("scorm_sco_users", "scormid=$scormid AND cmi_core_score_raw>0","","id,userid,cmi_core_score_raw");
251 //$grades = get_records_menu("scorm_sco_users", "scormid",$scormid,"","userid,cmi_core_score_raw");
252 $valutations = array();
253 foreach ($grades as $grade) {
254 if (!isset($valutations[$grade->userid])) {
255 if ($scorm->grademethod == VALUEAVERAGE) {
256 $values = array();
257 $values[$grade->userid]->grade = 0;
258 $values[$grade->userid]->values = 0;
259 }
260 $valutations[$grade->userid] = 0;
261 }
262 switch ($scorm->grademethod) {
263 case VALUEHIGHEST:
264 if ($grade->cmi_core_score_raw > $valutations[$grade->userid]) {
265 $valutations[$grade->userid] = $grade->cmi_core_score_raw;
266 }
267 break;
268 case VALUEAVERAGE:
269 $values[$grade->userid]->grade += $grade->cmi_core_score_raw;
270 $values[$grade->userid]->values++;
271 break;
272 case VALUESUM:
273 $valutations[$grade->userid] += $grade->cmi_core_score_raw;
274 break;
275 }
276 }
277 if ($scorm->grademethod == VALUEAVERAGE) {
278 foreach($values as $userid => $value) {
279 $valutations[$userid] = $value->grade/$value->values;
280 }
281 }
282 //print_r($grades);
283 $return->grades = $valutations;
284 $return->maxgrade = $scorm->maxgrade;
98ca59f6 285 }
98ca59f6 286 return $return;
287}
288
289
290//////////////////////////////////////////////////////////////////////////////////////
291/// Any other scorm functions go here. Each of them must have a name that
292/// starts with scorm_
293
294
1a12b1f1 295function scorm_randstring($len = '8')
98ca59f6 296{
297 $rstring = NULL;
1a12b1f1 298 $lchar = '';
98ca59f6 299 for($i=0; $i<$len; $i++) {
300 $char = chr(rand(48,122));
1a12b1f1 301 while (!ereg('[a-zA-Z0-9]', $char)){
98ca59f6 302 if($char == $lchar) continue;
303 $char = chr(rand(48,90));
304 }
305 $rstring .= $char;
306 $lchar = $char;
307 }
308 return $rstring;
309}
310
98ca59f6 311
1a12b1f1 312function scorm_datadir($strPath, $existingdir='', $prefix = 'SCORM')
98ca59f6 313{
e23ef951 314 global $CFG;
315
1a12b1f1 316 if (($existingdir!='') && (is_dir($strPath.$existingdir)))
4a9df373 317 return $strPath.$existingdir;
318
319 if (is_dir($strPath)) {
320 do {
1a12b1f1 321 $datadir='/'.$prefix.scorm_randstring();
4a9df373 322 } while (file_exists($strPath.$datadir));
323 mkdir($strPath.$datadir, $CFG->directorypermissions);
e23ef951 324 @chmod($strPath.$datadir, $CFG->directorypermissions); // Just in case mkdir didn't do it
4a9df373 325 return $strPath.$datadir;
326 } else {
327 return false;
328 }
98ca59f6 329}
330
1a12b1f1 331if ($CFG->scorm_validate == 'domxml') {
332 require_once('validatordomxml.php');
333}
334
98ca59f6 335function scorm_validate($manifest)
336{
1a12b1f1 337 global $CFG;
338
339 global $item_idref_array;
340 global $idres_array;
341 global $def_org_array;
342 global $id_org_array;
343
98ca59f6 344 if (is_file ($manifest)) {
1a12b1f1 345 if (file_exists($manifest)) {
346 if ($CFG->scorm_validate == 'domxml') {
347 $manifest_string = file_get_contents($manifest);
348
349 /* Elimino i caratteri speciali di spaziatura e ritorno a capo dal file xml */
350
351 $spec = array('\n', '\r', '\t', '\0', '\x0B');
352 $content = str_replace($spec, '', $manifest_string);
353
354 if ($xmldoc = domxml_open_mem($content)) {
355 $root = $xmldoc->document_element();
356 if (!testRoot($root)) {
357 return 'syntax';
358 }
359 if (testNode($root)) {
360 // Nel corpo di questo if si controllano le corrispondenze fra gli attributi
361 // Nello Standard SCORM ad ogni attributo idRef di <item> deve corrispondere
362 // un attributo ID di <resource>
363 // Gli array degli attributi sono stati dichiarati globali in validator.php
364 // pertanto possono essere utilizzati direttamente all'interno di main.php
365
366 foreach($item_idref_array as $elem_it) {
367 if (array_search($elem_it, $idres_array) === false) {
368 return 'mismatch';
369 }
370 }
371
372 foreach($def_org_array as $elem_def) {
373 if (array_search($elem_it, $id_org_array) === false) {
374 return 'mismatch';
375 }
376 }
377
378 } else {
379 return 'badmanifest';
380 }
381 }
382 return 'regular';
383 } else {
384 return 'found';
385 }
386 }
98ca59f6 387 } else {
1a12b1f1 388 return 'nomanifest';
98ca59f6 389 }
390}
391
b7237c1e 392function scorm_delete_files($directory) {
393 if (is_dir($directory)) {
394 $files=scorm_scandir($directory);
395 //print_r($files);
396 foreach($files as $file) {
397 if (($file != '.') && ($file != '..')) {
1a12b1f1 398 if (!is_dir($directory.'/'.$file)) {
399 //chmod($directory.'/'.$file,0777);
400 unlink($directory.'/'.$file);
401 } else {
402 scorm_delete_files($directory.'/'.$file);
403 }
404 }
98ca59f6 405 }
406 rmdir($directory);
407 }
408}
409
b7237c1e 410function scorm_scandir($directory) {
411 if (version_compare(phpversion(),'5.0.0','>=')) {
412 return scandir($directory);
413 } else {
414 $files = null;
415 if ($dh = opendir($directory)) {
416 while (($file = readdir($dh)) !== false) {
417 $files[] = $file;
418 }
419 closedir($dh);
420 }
421 return $files;
422 }
423}
424
98ca59f6 425function scorm_startElement($parser, $name, $attrs) {
2c508ab9 426
1a12b1f1 427 global $scoes,$i,$resources,$parent,$level,$organization,$manifest,$defaultorg;
2c508ab9 428
1a12b1f1 429 if ($name == 'ITEM') {
4a9df373 430 $i++;
1a12b1f1 431 $scoes[$i]['manifest'] = $manifest;
432 $scoes[$i]['organization'] = $organization;
433 $scoes[$i]['identifier'] = $attrs['IDENTIFIER'];
434 if (empty($attrs['IDENTIFIERREF']))
435 $attrs['IDENTIFIERREF'] = '';
436 $scoes[$i]['identifierref'] = $attrs['IDENTIFIERREF'];
437 if (empty($attrs['ISVISIBLE']))
438 $attrs['ISVISIBLE'] = '';
439 $scoes[$i]['isvisible'] = $attrs['ISVISIBLE'];
440 $scoes[$i]['parent'] = $parent[$level];
4a9df373 441 $level++;
1a12b1f1 442 $parent[$level] = $attrs['IDENTIFIER'];
443 }
444 if ($name == 'RESOURCE') {
445 if (!isset($attrs['HREF'])) {
446 $attrs['HREF'] = '';
447 }
448 $resources[$attrs['IDENTIFIER']]['href']=$attrs['HREF'];
2c508ab9 449 if (!isset($attrs['ADLCP:SCORMTYPE'])) {
450 $attrs['ADLCP:SCORMTYPE'] = '';
451 }
1a12b1f1 452 $resources[$attrs['IDENTIFIER']]['type']=$attrs['ADLCP:SCORMTYPE'];
453 }
454 if ($name == 'ORGANIZATION') {
2c508ab9 455 $i++;
456 $scoes[$i]['manifest'] = $manifest;
457 $scoes[$i]['organization'] = '';
458 $scoes[$i]['identifier'] = $attrs['IDENTIFIER'];
459 $scoes[$i]['identifierref'] = '';
460 $scoes[$i]['isvisible'] = '';
461 $scoes[$i]['parent'] = $parent[$level];
462 $level++;
463 $parent[$level] = $attrs['IDENTIFIER'];
1a12b1f1 464 $organization = $attrs['IDENTIFIER'];
465 }
466 if ($name == 'MANIFEST') {
467 $manifest = $attrs['IDENTIFIER'];
98ca59f6 468 }
1a12b1f1 469 if ($name == 'ORGANIZATIONS') {
2c508ab9 470 if (!isset($attrs['DEFAULT'])) {
471 $attrs['DEFAULT'] = '';
472 }
1a12b1f1 473 $defaultorg = $attrs['DEFAULT'];
98ca59f6 474 }
475}
476
477function scorm_endElement($parser, $name) {
1a12b1f1 478 global $scoes,$i,$level,$datacontent,$navigation;
479 if ($name == 'ITEM') {
98ca59f6 480 $level--;
481 }
2c508ab9 482 //if ($name == 'TITLE' && $level>0) {
483 if ($name == 'TITLE') {
1a12b1f1 484 $scoes[$i]['title'] = $datacontent;
2c508ab9 485 }
486 if ($name == 'ADLCP:HIDERTSUI') {
1a12b1f1 487 $scoes[$i][$datacontent] = 1;
2c508ab9 488 }
489 if ($name == 'ADLCP:DATAFROMLMS') {
1a12b1f1 490 $scoes[$i]['datafromlms'] = $datacontent;
2c508ab9 491 }
492 if ($name == 'ORGANIZATION') {
493 $organization = '';
494 $level--;
495 }
496 if ($name == 'MANIFEST') {
497 $manifest = '';
498 }
98ca59f6 499}
500
501function scorm_characterData($parser, $data) {
502 global $datacontent;
b7237c1e 503 $datacontent = utf8_decode($data);
98ca59f6 504}
505
506function scorm_parse($basedir,$file,$scorm_id) {
1a12b1f1 507 global $scoes,$i,$resources,$parent,$level,$defaultorg;
508 $datacontent = '';
509 $scoes[][] = '';
510 $resources[] = '';
511 $organization = '';
512 $defaultorg = '';
98ca59f6 513 $i = 0;
514 $level = 0;
1a12b1f1 515 $parent[$level] = '/';
98ca59f6 516
b7976058 517 $xml_parser = xml_parser_create('UTF-8');
98ca59f6 518 // use case-folding so we are sure to find the tag in $map_array
519 xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true);
1a12b1f1 520 xml_set_element_handler($xml_parser, 'scorm_startElement', 'scorm_endElement');
521 xml_set_character_data_handler($xml_parser, 'scorm_characterData');
522 if (!($fp = fopen($basedir.$file, 'r'))) {
523 die('could not open XML input');
98ca59f6 524 }
525
526 while ($data = fread($fp, 4096)) {
4a9df373 527 if (!xml_parse($xml_parser, $data, feof($fp))) {
1a12b1f1 528 die(sprintf('XML error: %s at line %d',
98ca59f6 529 xml_error_string(xml_get_error_code($xml_parser)),
530 xml_get_current_line_number($xml_parser)));
531 }
532 }
533 xml_parser_free($xml_parser);
534 $launch = 0;
535
536 $sco->scorm = $scorm_id;
1a12b1f1 537 delete_records('scorm_scoes','scorm',$scorm_id);
538 delete_records('scorm_sco_users','scormid',$scorm_id);
434983ca 539
1a12b1f1 540 if (isset($scoes[1])) {
541 for ($j=1; $j<=$i; $j++) {
542 $sco->identifier = $scoes[$j]['identifier'];
543 $sco->parent = $scoes[$j]['parent'];
544 $sco->title = $scoes[$j]['title'];
545 $sco->organization = $scoes[$j]['organization'];
546 if (!isset($scoes[$j]['datafromlms'])) {
547 $scoes[$j]['datafromlms'] = '';
548 }
549 $sco->datafromlms = $scoes[$j]['datafromlms'];
434983ca 550
1a12b1f1 551 if (!isset($resources[($scoes[$j]['identifierref'])]['href'])) {
552 $resources[($scoes[$j]['identifierref'])]['href'] = '';
553 }
554 $sco->launch = $resources[($scoes[$j]['identifierref'])]['href'];
434983ca 555
1a12b1f1 556 if (!isset($resources[($scoes[$j]['identifierref'])]['type'])) {
557 $resources[($scoes[$j]['identifierref'])]['type'] = '';
558 }
559 $sco->type = $resources[($scoes[$j]['identifierref'])]['type'];
434983ca 560
1a12b1f1 561 if (!isset($scoes[$j]['previous'])) {
562 $scoes[$j]['previous'] = 0;
563 }
564 $sco->previous = $scoes[$j]['previous'];
434983ca 565
1a12b1f1 566 if (!isset($scoes[$j]['continue'])) {
567 $scoes[$j]['continue'] = 0;
568 }
569 $sco->next = $scoes[$j]['continue'];
434983ca 570
1a12b1f1 571 if (scorm_remove_spaces($scoes[$j]['isvisible']) != 'false') {
572 $id = insert_record('scorm_scoes',$sco);
573 }
2c508ab9 574 //if (($launch==0) && (isset($sco->launch)) && ($defaultorg==$sco->organization)) {
575 if (($launch==0) && ($defaultorg==$sco->identifier)) {
1a12b1f1 576 $launch = $id;
577 }
578 }
579 } else {
580 foreach ($resources as $label => $resource) {
d64bc8ae 581 if (!empty($resource['href'])) {
1a12b1f1 582 $sco->identifier = $label;
583 $sco->title = $label;
584 $sco->parent = '/';
585 $sco->launch = $resource['href'];
586 $sco->type = $resource['type'];
587 $id = insert_record('scorm_scoes',$sco);
588
589 if ($launch == 0) {
590 $launch = $id;
591 }
592 }
593 }
98ca59f6 594 }
595 return $launch;
596}
597
598function scorm_get_scoes_records($sco_user) {
599/// Gets all info required to display the table of scorm results
600/// for report.php
601 global $CFG;
602
603 return get_records_sql("SELECT su.*, u.firstname, u.lastname, u.picture
604 FROM {$CFG->prefix}scorm_sco_users su,
605 {$CFG->prefix}user u
606 WHERE su.scormid = '$sco_user->scormid'
607 AND su.userid = u.id
3f8eeff2 608 AND su.userid = '$sco_user->userid'
98ca59f6 609 ORDER BY scoid");
610}
611
612function scorm_remove_spaces($sourcestr) {
613// Remove blank space from a string
1a12b1f1 614 $newstr='';
4a9df373 615 for( $i=0; $i<strlen($sourcestr); $i++) {
616 if ($sourcestr[$i]!=' ')
617 $newstr .=$sourcestr[$i];
618 }
619 return $newstr;
98ca59f6 620}
621
622function scorm_string_round($stringa) {
623// Crop a string to $len character and set an anchor title to the full string
624 $len=11;
625 if ( strlen($stringa)>$len ) {
59c71f4b 626 return "<a name=\"none\" title=\"$stringa\">".substr($stringa,0,$len-4).'...'.substr($stringa,strlen($stringa)-1,1).'</a>';
98ca59f6 627 } else
4a9df373 628 return $stringa;
98ca59f6 629}
630
631function scorm_external_link($link) {
632// check if a link is external
633 $result = false;
634 $link = strtolower($link);
1a12b1f1 635 if (substr($link,0,7) == 'http://')
4a9df373 636 $result = true;
1a12b1f1 637 else if (substr($link,0,8) == 'https://')
4a9df373 638 $result = true;
1a12b1f1 639 else if (substr($link,0,4) == 'www.')
4a9df373 640 $result = true;
1a12b1f1 641 /*else if (substr($link,0,7) == 'rstp://')
4a9df373 642 $result = true;
1a12b1f1 643 else if (substr($link,0,6) == 'rtp://')
4a9df373 644 $result = true;
1a12b1f1 645 else if (substr($link,0,6) == 'ftp://')
4a9df373 646 $result = true;
1a12b1f1 647 else if (substr($link,0,9) == 'gopher://')
4a9df373 648 $result = true; */
98ca59f6 649 return $result;
650}
651?>