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