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