e4aa175a |
1 | <?php // $Id$ |
2 | |
e4aa175a |
3 | /** |
4 | * Given an object containing all the necessary data, |
5 | * (defined by the form in mod.html) this function |
6 | * will create a new instance and return the id number |
7 | * of the new instance. |
8 | * |
9 | * @param mixed $scorm Form data |
10 | * @return int |
11 | */ |
bfe8c2f0 |
12 | require_once('locallib.php'); |
e4aa175a |
13 | function scorm_add_instance($scorm) { |
76ea4fb4 |
14 | $validate = scorm_validate($scorm); |
15 | |
16 | $errors = array(); |
17 | if (($validate->result != "regular") && ($validate->result != "found")) { |
18 | $errors[] = $validate->result; |
19 | if (isset($validate->errors) && (count($validate->errors[0]) > 0)) { |
20 | foreach ($validate->errors as $error) { |
21 | $errors[] = $error; |
22 | } |
23 | } |
24 | } else { |
25 | $scorm->pkgtype = $validate->pkgtype; |
26 | $scorm->datadir = $validate->datadir; |
27 | $scorm->launch = $validate->launch; |
28 | $scorm->parse = 1; |
29 | } |
30 | |
e4aa175a |
31 | if(empty($scorm->datadir)) { //check to make sure scorm object is valid BEFORE entering it in the database. |
76ea4fb4 |
32 | $errorstr = ''; |
33 | if (!empty($errors)) { |
34 | foreach ($errors as $error) { |
35 | $errorstr .= get_string($error,'scorm').'<br />'; |
36 | } |
37 | error($errorstr); |
38 | } else { |
39 | error(get_string('badpackage', 'scorm')); |
40 | } |
e4aa175a |
41 | } else { |
42 | global $CFG; |
43 | $scorm->timemodified = time(); |
456f5e6e |
44 | if(substr($scorm->reference,0,7)== 'http://'){ |
45 | $scorm->md5_result=md5_file($scorm->reference); |
46 | } |
e4aa175a |
47 | $scorm = scorm_option2text($scorm); |
48 | $scorm->width = str_replace('%','',$scorm->width); |
49 | $scorm->height = str_replace('%','',$scorm->height); |
50 | |
51 | //sanitize submitted values a bit |
52 | $scorm->width = clean_param($scorm->width, PARAM_INT); |
53 | $scorm->height = clean_param($scorm->height, PARAM_INT); |
b3659259 |
54 | |
55 | if (!isset($scorm->whatgrade)) { |
56 | $scorm->whatgrade = 0; |
57 | } |
a30b6819 |
58 | $scorm->grademethod = ($scorm->whatgrade * 10) + $scorm->grademethod; |
e4aa175a |
59 | |
60 | $id = insert_record('scorm', $scorm); |
61 | |
5c1ac70c |
62 | if ((basename($scorm->reference) != 'imsmanifest.xml') && ($scorm->reference[0] != '#')) { |
e4aa175a |
63 | // Rename temp scorm dir to scorm id |
64 | $scorm->dir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm'; |
65 | rename($scorm->dir.$scorm->datadir,$scorm->dir.'/'.$id); |
66 | } |
67 | |
68 | // Parse scorm manifest |
5c1ac70c |
69 | if ($scorm->parse == 1) { |
e4aa175a |
70 | require_once('locallib.php'); |
71 | $scorm->id = $id; |
72 | $scorm->launch = scorm_parse($scorm); |
73 | set_field('scorm','launch',$scorm->launch,'id',$scorm->id); |
74 | } |
75 | |
76 | return $id; |
77 | } |
78 | } |
79 | |
80 | /** |
81 | * Given an object containing all the necessary data, |
82 | * (defined by the form in mod.html) this function |
83 | * will update an existing instance with new data. |
84 | * |
85 | * @param mixed $scorm Form data |
86 | * @return int |
87 | */ |
88 | function scorm_update_instance($scorm) { |
e4aa175a |
89 | global $CFG; |
90 | |
76ea4fb4 |
91 | $validate = scorm_validate($scorm); |
92 | |
93 | $errors = array(); |
94 | if (($validate->result != "regular") && ($validate->result != "found")) { |
95 | $errorstr = get_string($validate->result,'scorm'); |
96 | if (isset($validate->errors) && (count($validate->errors[0]) > 0)) { |
97 | foreach ($validate->errors as $error) { |
98 | $errorstr .= '<br />'.get_string($error,'scorm'); |
99 | } |
100 | } |
101 | error($errorstr); |
102 | exit(); |
103 | } else { |
104 | $scorm->pkgtype = $validate->pkgtype; |
105 | if ($validate->launch == 0) { |
106 | $scorm->launch = $validate->launch; |
107 | $scorm->datadir = $validate->datadir; |
108 | $scorm->parse = 1; |
109 | } else { |
110 | $scorm->parse = 0; |
111 | } |
112 | } |
113 | |
e4aa175a |
114 | $scorm->timemodified = time(); |
115 | $scorm->id = $scorm->instance; |
456f5e6e |
116 | if(substr($scorm->reference,0,7)== 'http://'){ |
117 | $scorm->md5_result=md5_file($scorm->reference); |
bfe8c2f0 |
118 | mtrace($scorm->md5_result); |
119 | |
456f5e6e |
120 | } |
e4aa175a |
121 | $scorm = scorm_option2text($scorm); |
122 | $scorm->width = str_replace('%','',$scorm->width); |
123 | $scorm->height = str_replace('%','',$scorm->height); |
124 | |
b3659259 |
125 | if (!isset($scorm->whatgrade)) { |
126 | $scorm->whatgrade = 0; |
127 | } |
a30b6819 |
128 | $scorm->grademethod = ($scorm->whatgrade * 10) + $scorm->grademethod; |
129 | |
e4aa175a |
130 | // Check if scorm manifest needs to be reparsed |
5c1ac70c |
131 | if ($scorm->parse == 1) { |
132 | require_once('locallib.php'); |
e4aa175a |
133 | $scorm->dir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm'; |
5c1ac70c |
134 | if (is_dir($scorm->dir.'/'.$scorm->id)) { |
e4aa175a |
135 | scorm_delete_files($scorm->dir.'/'.$scorm->id); |
5c1ac70c |
136 | } |
137 | if (isset($scorm->datadir) && ($scorm->datadir != $scorm->id) && |
138 | (basename($scorm->reference) != 'imsmanifest.xml') && ($scorm->reference[0] != '#')) { |
e4aa175a |
139 | rename($scorm->dir.$scorm->datadir,$scorm->dir.'/'.$scorm->id); |
140 | } |
a30b6819 |
141 | |
e4aa175a |
142 | $scorm->launch = scorm_parse($scorm); |
a9d22c84 |
143 | } else { |
144 | $oldscorm = get_record('scorm','id',$scorm->id); |
145 | $scorm->reference = $oldscorm->reference; // This fix a problem with Firefox when the teacher choose Cancel on overwrite question |
e4aa175a |
146 | } |
a9d22c84 |
147 | |
e4aa175a |
148 | return update_record('scorm', $scorm); |
149 | } |
150 | |
151 | /** |
152 | * Given an ID of an instance of this module, |
153 | * this function will permanently delete the instance |
154 | * and any data that depends on it. |
155 | * |
156 | * @param int $id Scorm instance id |
157 | * @return boolean |
158 | */ |
159 | function scorm_delete_instance($id) { |
160 | |
161 | global $CFG; |
162 | |
163 | if (! $scorm = get_record('scorm', 'id', $id)) { |
164 | return false; |
165 | } |
166 | |
167 | $result = true; |
168 | |
2b3447c3 |
169 | $scorm->dir = $CFG->dataroot.'/'.$scorm->course.'/moddata/scorm'; |
170 | if (is_dir($scorm->dir.'/'.$scorm->id)) { |
171 | // Delete any dependent files |
172 | require_once('locallib.php'); |
173 | scorm_delete_files($scorm->dir.'/'.$scorm->id); |
174 | } |
e4aa175a |
175 | |
176 | // Delete any dependent records |
177 | if (! delete_records('scorm_scoes_track', 'scormid', $scorm->id)) { |
178 | $result = false; |
179 | } |
b3659259 |
180 | if ($scoes = get_records('scorm_scoes','scorm',$scorm->id)) { |
181 | foreach ($scoes as $sco) { |
182 | if (! delete_records('scorm_scoes_data', 'scoid', $sco->id)) { |
183 | $result = false; |
184 | } |
185 | } |
186 | delete_records('scorm_scoes', 'scorm', $scorm->id); |
187 | } else { |
e4aa175a |
188 | $result = false; |
189 | } |
190 | if (! delete_records('scorm', 'id', $scorm->id)) { |
191 | $result = false; |
192 | } |
a30b6819 |
193 | |
2b3447c3 |
194 | /*if (! delete_records('scorm_sequencing_controlmode', 'scormid', $scorm->id)) { |
e4aa175a |
195 | $result = false; |
196 | } |
197 | if (! delete_records('scorm_sequencing_rolluprules', 'scormid', $scorm->id)) { |
198 | $result = false; |
199 | } |
200 | if (! delete_records('scorm_sequencing_rolluprule', 'scormid', $scorm->id)) { |
201 | $result = false; |
202 | } |
203 | if (! delete_records('scorm_sequencing_rollupruleconditions', 'scormid', $scorm->id)) { |
204 | $result = false; |
205 | } |
206 | if (! delete_records('scorm_sequencing_rolluprulecondition', 'scormid', $scorm->id)) { |
207 | $result = false; |
208 | } |
209 | if (! delete_records('scorm_sequencing_rulecondition', 'scormid', $scorm->id)) { |
210 | $result = false; |
211 | } |
212 | if (! delete_records('scorm_sequencing_ruleconditions', 'scormid', $scorm->id)) { |
213 | $result = false; |
2b3447c3 |
214 | }*/ |
e4aa175a |
215 | return $result; |
216 | } |
217 | |
218 | /** |
219 | * Return a small object with summary information about what a |
220 | * user has done with a given particular instance of this module |
221 | * Used for user activity reports. |
222 | * |
223 | * @param int $course Course id |
224 | * @param int $user User id |
225 | * @param int $mod |
226 | * @param int $scorm The scorm id |
227 | * @return mixed |
228 | */ |
229 | function scorm_user_outline($course, $user, $mod, $scorm) { |
230 | |
231 | $return = NULL; |
a30b6819 |
232 | |
233 | require_once('locallib.php'); |
234 | |
235 | $return = scorm_grade_user($scorm, $user->id, true); |
236 | |
e4aa175a |
237 | return $return; |
238 | } |
239 | |
240 | /** |
241 | * Print a detailed representation of what a user has done with |
242 | * a given particular instance of this module, for user activity reports. |
243 | * |
244 | * @param int $course Course id |
245 | * @param int $user User id |
246 | * @param int $mod |
247 | * @param int $scorm The scorm id |
248 | * @return boolean |
249 | */ |
250 | function scorm_user_complete($course, $user, $mod, $scorm) { |
251 | global $CFG; |
252 | |
253 | $liststyle = 'structlist'; |
254 | $scormpixdir = $CFG->modpixpath.'/scorm/pix'; |
255 | $now = time(); |
256 | $firstmodify = $now; |
257 | $lastmodify = 0; |
258 | $sometoreport = false; |
259 | $report = ''; |
260 | |
261 | if ($orgs = get_records_select('scorm_scoes',"scorm='$scorm->id' AND organization='' AND launch=''",'id','id,identifier,title')) { |
262 | if (count($orgs) <= 1) { |
263 | unset($orgs); |
264 | $orgs[]->identifier = ''; |
265 | } |
266 | $report .= '<div class="mod-scorm">'."\n"; |
267 | foreach ($orgs as $org) { |
268 | $organizationsql = ''; |
269 | $currentorg = ''; |
270 | if (!empty($org->identifier)) { |
271 | $report .= '<div class="orgtitle">'.$org->title.'</div>'; |
272 | $currentorg = $org->identifier; |
273 | $organizationsql = "AND organization='$currentorg'"; |
274 | } |
275 | $report .= "<ul id='0' class='$liststyle'>"; |
276 | if ($scoes = get_records_select('scorm_scoes',"scorm='$scorm->id' $organizationsql order by id ASC")){ |
277 | $level=0; |
278 | $sublist=1; |
279 | $parents[$level]='/'; |
280 | foreach ($scoes as $sco) { |
281 | if ($parents[$level]!=$sco->parent) { |
282 | if ($level>0 && $parents[$level-1]==$sco->parent) { |
283 | $report .= "\t\t</ul></li>\n"; |
284 | $level--; |
285 | } else { |
286 | $i = $level; |
287 | $closelist = ''; |
288 | while (($i > 0) && ($parents[$level] != $sco->parent)) { |
289 | $closelist .= "\t\t</ul></li>\n"; |
290 | $i--; |
291 | } |
292 | if (($i == 0) && ($sco->parent != $currentorg)) { |
293 | $report .= "\t\t<li><ul id='$sublist' class='$liststyle'>\n"; |
294 | $level++; |
295 | } else { |
296 | $report .= $closelist; |
297 | $level = $i; |
298 | } |
299 | $parents[$level]=$sco->parent; |
300 | } |
301 | } |
302 | $report .= "\t\t<li>"; |
303 | $nextsco = next($scoes); |
304 | if (($nextsco !== false) && ($sco->parent != $nextsco->parent) && (($level==0) || (($level>0) && ($nextsco->parent == $sco->identifier)))) { |
305 | $sublist++; |
306 | } else { |
7150b8ae |
307 | $report .= '<img src="'.$scormpixdir.'/spacer.gif" alt="" />'; |
e4aa175a |
308 | } |
309 | |
310 | if ($sco->launch) { |
311 | require_once('locallib.php'); |
312 | $score = ''; |
313 | $totaltime = ''; |
314 | if ($usertrack=scorm_get_tracks($sco->id,$user->id)) { |
315 | if ($usertrack->status == '') { |
316 | $usertrack->status = 'notattempted'; |
317 | } |
318 | $strstatus = get_string($usertrack->status,'scorm'); |
319 | $report .= "<img src='".$scormpixdir.'/'.$usertrack->status.".gif' alt='$strstatus' title='$strstatus' />"; |
320 | if ($usertrack->timemodified != 0) { |
321 | if ($usertrack->timemodified > $lastmodify) { |
322 | $lastmodify = $usertrack->timemodified; |
323 | } |
324 | if ($usertrack->timemodified < $firstmodify) { |
325 | $firstmodify = $usertrack->timemodified; |
326 | } |
327 | } |
328 | } else { |
329 | if ($sco->scormtype == 'sco') { |
330 | $report .= '<img src="'.$scormpixdir.'/'.'notattempted.gif" alt="'.get_string('notattempted','scorm').'" title="'.get_string('notattempted','scorm').'" />'; |
331 | } else { |
332 | $report .= '<img src="'.$scormpixdir.'/'.'asset.gif" alt="'.get_string('asset','scorm').'" title="'.get_string('asset','scorm').'" />'; |
333 | } |
334 | } |
335 | $report .= " $sco->title $score$totaltime</li>\n"; |
336 | if ($usertrack !== false) { |
337 | $sometoreport = true; |
338 | $report .= "\t\t\t<li><ul class='$liststyle'>\n"; |
339 | foreach($usertrack as $element => $value) { |
340 | if (substr($element,0,3) == 'cmi') { |
341 | $report .= '<li>'.$element.' => '.$value.'</li>'; |
342 | } |
343 | } |
344 | $report .= "\t\t\t</ul></li>\n"; |
345 | } |
346 | } else { |
347 | $report .= " $sco->title</li>\n"; |
348 | } |
349 | } |
350 | for ($i=0;$i<$level;$i++) { |
351 | $report .= "\t\t</ul></li>\n"; |
352 | } |
353 | } |
354 | $report .= "\t</ul><br />\n"; |
355 | } |
356 | $report .= "</div>\n"; |
357 | } |
358 | if ($sometoreport) { |
359 | if ($firstmodify < $now) { |
360 | $timeago = format_time($now - $firstmodify); |
361 | echo get_string('firstaccess','scorm').': '.userdate($firstmodify).' ('.$timeago.")<br />\n"; |
362 | } |
363 | if ($lastmodify > 0) { |
364 | $timeago = format_time($now - $lastmodify); |
365 | echo get_string('lastaccess','scorm').': '.userdate($lastmodify).' ('.$timeago.")<br />\n"; |
366 | } |
367 | echo get_string('report','scorm').":<br />\n"; |
368 | echo $report; |
369 | } else { |
dabfd0ed |
370 | print_string('noactivity','scorm'); |
e4aa175a |
371 | } |
372 | |
373 | return true; |
374 | } |
375 | |
376 | /** |
377 | * Given a list of logs, assumed to be those since the last login |
378 | * this function prints a short list of changes related to this module |
379 | * If isteacher is true then perhaps additional information is printed. |
380 | * This function is called from course/lib.php: print_recent_activity() |
381 | * |
382 | * @param reference $logs Logs reference |
383 | * @param boolean $isteacher |
384 | * @return boolean |
385 | */ |
386 | function scorm_print_recent_activity(&$logs, $isteacher=false) { |
387 | return false; // True if anything was printed, otherwise false |
388 | } |
389 | |
390 | /** |
391 | * Function to be run periodically according to the moodle cron |
392 | * This function searches for things that need to be done, such |
393 | * as sending out mail, toggling flags etc ... |
394 | * |
395 | * @return boolean |
396 | */ |
397 | function scorm_cron () { |
398 | |
399 | global $CFG; |
bfe8c2f0 |
400 | $sitetimezone = $CFG->timezone; |
401 | /// Now see if there are any digest mails waiting to be sent, and if we should send them |
402 | if (!isset($CFG->scorm_updatetimelast)) { // To catch the first time |
403 | set_config('scorm_updatetimelast', 0); |
404 | } |
405 | |
406 | $timenow = time(); |
407 | $updatetime = usergetmidnight($timenow, $sitetimezone) + ($CFG->scorm_updatetime * 3600); |
408 | if ($CFG->scorm_updatetimelast < $updatetime and $timenow > $updatetime) { |
409 | |
410 | set_config('scorm_updatetimelast', $timenow); |
e4aa175a |
411 | |
bfe8c2f0 |
412 | mtrace('Updating scorm packages which require daily update');//"estamos actualizando" |
413 | |
414 | $scormsupdate = get_records_select("scorm","external=1"); |
415 | if(!empty($scormsupdate)) { |
416 | foreach($scormsupdate as $scormupdate) { |
417 | $scormupdate->instance = $scormupdate->id; |
418 | $scormupinst = scorm_update_instance($scormupdate); |
419 | } |
420 | } |
421 | } |
e4aa175a |
422 | return true; |
423 | } |
424 | |
425 | /** |
426 | * Given a scorm id return all the grades of that activity |
427 | * |
428 | * @param int $scormid Scorm instance id |
429 | * @return mixed |
430 | */ |
431 | function scorm_grades($scormid) { |
432 | |
433 | global $CFG; |
434 | |
435 | if (!$scorm = get_record('scorm', 'id', $scormid)) { |
436 | return NULL; |
437 | } |
e4aa175a |
438 | |
a30b6819 |
439 | if (($scorm->grademethod % 10) == 0) { // GRADESCOES |
e4aa175a |
440 | if (!$return->maxgrade = count_records_select('scorm_scoes',"scorm='$scormid' AND launch<>''")) { |
441 | return NULL; |
442 | } |
443 | } else { |
444 | $return->maxgrade = $scorm->maxgrade; |
445 | } |
446 | |
447 | $return->grades = NULL; |
448 | if ($scousers=get_records_select('scorm_scoes_track', "scormid='$scormid' GROUP BY userid", "", "userid,null")) { |
449 | require_once('locallib.php'); |
450 | foreach ($scousers as $scouser) { |
a30b6819 |
451 | $return->grades[$scouser->userid] = scorm_grade_user($scorm, $scouser->userid); |
e4aa175a |
452 | } |
453 | } |
454 | return $return; |
455 | } |
456 | |
457 | function scorm_get_view_actions() { |
458 | return array('pre-view','view','view all','report'); |
459 | } |
460 | |
461 | function scorm_get_post_actions() { |
462 | return array(); |
463 | } |
464 | |
e4aa175a |
465 | function scorm_option2text($scorm) { |
466 | global $SCORM_POPUP_OPTIONS; |
e4aa175a |
467 | if (isset($scorm->popup)) { |
76ea4fb4 |
468 | if ($scorm->popup == 1) { |
e4aa175a |
469 | $optionlist = array(); |
470 | foreach ($SCORM_POPUP_OPTIONS as $name => $option) { |
471 | if (isset($scorm->$name)) { |
472 | $optionlist[] = $name.'='.$scorm->$name; |
473 | } else { |
474 | $optionlist[] = $name.'=0'; |
475 | } |
476 | } |
477 | $scorm->options = implode(',', $optionlist); |
478 | } else { |
479 | $scorm->options = ''; |
480 | } |
481 | } else { |
482 | $scorm->popup = 0; |
483 | $scorm->options = ''; |
484 | } |
485 | return $scorm; |
486 | } |
487 | |
5c1ac70c |
488 | ?> |