|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00024 define('SCORM_TYPE_LOCAL', 'local'); 00026 define('SCORM_TYPE_LOCALSYNC', 'localsync'); 00028 define('SCORM_TYPE_EXTERNAL', 'external'); 00030 define('SCORM_TYPE_IMSREPOSITORY', 'imsrepository'); 00032 define('SCORM_TYPE_AICCURL', 'aiccurl'); 00033 00034 define('SCORM_TOC_SIDE', 0); 00035 define('SCORM_TOC_HIDDEN', 1); 00036 define('SCORM_TOC_POPUP', 2); 00037 define('SCORM_TOC_DISABLED', 3); 00038 00039 //used to check what SCORM version is being used. 00040 define('SCORM_12', 1); 00041 define('SCORM_13', 2); 00042 define('SCORM_AICC', 3); 00043 00061 function scorm_add_instance($scorm, $mform=null) { 00062 global $CFG, $DB; 00063 00064 require_once($CFG->dirroot.'/mod/scorm/locallib.php'); 00065 00066 if (empty($scorm->timeopen)) { 00067 $scorm->timeopen = 0; 00068 } 00069 if (empty($scorm->timeclose)) { 00070 $scorm->timeclose = 0; 00071 } 00072 $cmid = $scorm->coursemodule; 00073 $cmidnumber = $scorm->cmidnumber; 00074 $courseid = $scorm->course; 00075 00076 $context = get_context_instance(CONTEXT_MODULE, $cmid); 00077 00078 $scorm = scorm_option2text($scorm); 00079 $scorm->width = (int)str_replace('%', '', $scorm->width); 00080 $scorm->height = (int)str_replace('%', '', $scorm->height); 00081 00082 if (!isset($scorm->whatgrade)) { 00083 $scorm->whatgrade = 0; 00084 } 00085 00086 $id = $DB->insert_record('scorm', $scorm); 00087 00089 $DB->set_field('course_modules', 'instance', $id, array('id'=>$cmid)); 00090 00092 $record = $DB->get_record('scorm', array('id'=>$id)); 00093 00095 if ($record->scormtype === SCORM_TYPE_LOCAL) { 00096 if ($mform) { 00097 $filename = $mform->get_new_filename('packagefile'); 00098 if ($filename !== false) { 00099 $fs = get_file_storage(); 00100 $fs->delete_area_files($context->id, 'mod_scorm', 'package'); 00101 $mform->save_stored_file('packagefile', $context->id, 'mod_scorm', 'package', 0, '/', $filename); 00102 $record->reference = $filename; 00103 } 00104 } 00105 00106 } else if ($record->scormtype === SCORM_TYPE_LOCALSYNC) { 00107 $record->reference = $scorm->packageurl; 00108 } else if ($record->scormtype === SCORM_TYPE_EXTERNAL) { 00109 $record->reference = $scorm->packageurl; 00110 } else if ($record->scormtype === SCORM_TYPE_IMSREPOSITORY) { 00111 $record->reference = $scorm->packageurl; 00112 } else if ($record->scormtype === SCORM_TYPE_AICCURL) { 00113 $record->reference = $scorm->packageurl; 00114 } else { 00115 return false; 00116 } 00117 00118 // save reference 00119 $DB->update_record('scorm', $record); 00120 00122 $record->course = $courseid; 00123 $record->cmidnumber = $cmidnumber; 00124 $record->cmid = $cmid; 00125 00126 scorm_parse($record, true); 00127 00128 scorm_grade_item_update($record); 00129 00130 return $record->id; 00131 } 00132 00149 function scorm_update_instance($scorm, $mform=null) { 00150 global $CFG, $DB; 00151 00152 require_once($CFG->dirroot.'/mod/scorm/locallib.php'); 00153 00154 if (empty($scorm->timeopen)) { 00155 $scorm->timeopen = 0; 00156 } 00157 if (empty($scorm->timeclose)) { 00158 $scorm->timeclose = 0; 00159 } 00160 00161 $cmid = $scorm->coursemodule; 00162 $cmidnumber = $scorm->cmidnumber; 00163 $courseid = $scorm->course; 00164 00165 $scorm->id = $scorm->instance; 00166 00167 $context = get_context_instance(CONTEXT_MODULE, $cmid); 00168 00169 if ($scorm->scormtype === SCORM_TYPE_LOCAL) { 00170 if ($mform) { 00171 $filename = $mform->get_new_filename('packagefile'); 00172 if ($filename !== false) { 00173 $scorm->reference = $filename; 00174 $fs = get_file_storage(); 00175 $fs->delete_area_files($context->id, 'mod_scorm', 'package'); 00176 $mform->save_stored_file('packagefile', $context->id, 'mod_scorm', 'package', 0, '/', $filename); 00177 } 00178 } 00179 00180 } else if ($scorm->scormtype === SCORM_TYPE_LOCALSYNC) { 00181 $scorm->reference = $scorm->packageurl; 00182 00183 } else if ($scorm->scormtype === SCORM_TYPE_EXTERNAL) { 00184 $scorm->reference = $scorm->packageurl; 00185 00186 } else if ($scorm->scormtype === SCORM_TYPE_IMSREPOSITORY) { 00187 $scorm->reference = $scorm->packageurl; 00188 } else if ($scorm->scormtype === SCORM_TYPE_AICCURL) { 00189 $scorm->reference = $scorm->packageurl; 00190 } else { 00191 return false; 00192 } 00193 00194 $scorm = scorm_option2text($scorm); 00195 $scorm->width = (int)str_replace('%', '', $scorm->width); 00196 $scorm->height = (int)str_replace('%', '', $scorm->height); 00197 $scorm->timemodified = time(); 00198 00199 if (!isset($scorm->whatgrade)) { 00200 $scorm->whatgrade = 0; 00201 } 00202 00203 $DB->update_record('scorm', $scorm); 00204 00205 $scorm = $DB->get_record('scorm', array('id'=>$scorm->id)); 00206 00208 $scorm->course = $courseid; 00209 $scorm->idnumber = $cmidnumber; 00210 $scorm->cmid = $cmid; 00211 00212 scorm_parse($scorm, (bool)$scorm->updatefreq); 00213 00214 scorm_grade_item_update($scorm); 00215 scorm_update_grades($scorm); 00216 00217 return true; 00218 } 00219 00230 function scorm_delete_instance($id) { 00231 global $CFG, $DB; 00232 00233 if (! $scorm = $DB->get_record('scorm', array('id'=>$id))) { 00234 return false; 00235 } 00236 00237 $result = true; 00238 00239 // Delete any dependent records 00240 if (! $DB->delete_records('scorm_scoes_track', array('scormid'=>$scorm->id))) { 00241 $result = false; 00242 } 00243 if ($scoes = $DB->get_records('scorm_scoes', array('scorm'=>$scorm->id))) { 00244 foreach ($scoes as $sco) { 00245 if (! $DB->delete_records('scorm_scoes_data', array('scoid'=>$sco->id))) { 00246 $result = false; 00247 } 00248 } 00249 $DB->delete_records('scorm_scoes', array('scorm'=>$scorm->id)); 00250 } else { 00251 $result = false; 00252 } 00253 if (! $DB->delete_records('scorm', array('id'=>$scorm->id))) { 00254 $result = false; 00255 } 00256 00257 /*if (! $DB->delete_records('scorm_sequencing_controlmode', array('scormid'=>$scorm->id))) { 00258 $result = false; 00259 } 00260 if (! $DB->delete_records('scorm_sequencing_rolluprules', array('scormid'=>$scorm->id))) { 00261 $result = false; 00262 } 00263 if (! $DB->delete_records('scorm_sequencing_rolluprule', array('scormid'=>$scorm->id))) { 00264 $result = false; 00265 } 00266 if (! $DB->delete_records('scorm_sequencing_rollupruleconditions', array('scormid'=>$scorm->id))) { 00267 $result = false; 00268 } 00269 if (! $DB->delete_records('scorm_sequencing_rolluprulecondition', array('scormid'=>$scorm->id))) { 00270 $result = false; 00271 } 00272 if (! $DB->delete_records('scorm_sequencing_rulecondition', array('scormid'=>$scorm->id))) { 00273 $result = false; 00274 } 00275 if (! $DB->delete_records('scorm_sequencing_ruleconditions', array('scormid'=>$scorm->id))) { 00276 $result = false; 00277 }*/ 00278 00279 scorm_grade_item_delete($scorm); 00280 00281 return $result; 00282 } 00283 00296 function scorm_user_outline($course, $user, $mod, $scorm) { 00297 global $CFG; 00298 require_once($CFG->dirroot.'/mod/scorm/locallib.php'); 00299 00300 require_once("$CFG->libdir/gradelib.php"); 00301 $grades = grade_get_grades($course->id, 'mod', 'scorm', $scorm->id, $user->id); 00302 if (!empty($grades->items[0]->grades)) { 00303 $grade = reset($grades->items[0]->grades); 00304 $result = new stdClass(); 00305 $result->info = get_string('grade') . ': '. $grade->str_long_grade; 00306 00307 //datesubmitted == time created. dategraded == time modified or time overridden 00308 //if grade was last modified by the user themselves use date graded. Otherwise use date submitted 00309 //TODO: move this copied & pasted code somewhere in the grades API. See MDL-26704 00310 if ($grade->usermodified == $user->id || empty($grade->datesubmitted)) { 00311 $result->time = $grade->dategraded; 00312 } else { 00313 $result->time = $grade->datesubmitted; 00314 } 00315 00316 return $result; 00317 } 00318 return null; 00319 } 00320 00333 function scorm_user_complete($course, $user, $mod, $scorm) { 00334 global $CFG, $DB, $OUTPUT; 00335 require_once("$CFG->libdir/gradelib.php"); 00336 00337 $liststyle = 'structlist'; 00338 $now = time(); 00339 $firstmodify = $now; 00340 $lastmodify = 0; 00341 $sometoreport = false; 00342 $report = ''; 00343 00344 // First Access and Last Access dates for SCOs 00345 require_once($CFG->dirroot.'/mod/scorm/locallib.php'); 00346 $timetracks = scorm_get_sco_runtime($scorm->id, false, $user->id); 00347 $firstmodify = $timetracks->start; 00348 $lastmodify = $timetracks->finish; 00349 00350 $grades = grade_get_grades($course->id, 'mod', 'scorm', $scorm->id, $user->id); 00351 if (!empty($grades->items[0]->grades)) { 00352 $grade = reset($grades->items[0]->grades); 00353 echo $OUTPUT->container(get_string('grade').': '.$grade->str_long_grade); 00354 if ($grade->str_feedback) { 00355 echo $OUTPUT->container(get_string('feedback').': '.$grade->str_feedback); 00356 } 00357 } 00358 00359 if ($orgs = $DB->get_records_select('scorm_scoes', 'scorm = ? AND '. 00360 $DB->sql_isempty('scorm_scoes', 'launch', false, true).' AND '. 00361 $DB->sql_isempty('scorm_scoes', 'organization', false, false), 00362 array($scorm->id), 'id', 'id,identifier,title')) { 00363 if (count($orgs) <= 1) { 00364 unset($orgs); 00365 $orgs[]->identifier = ''; 00366 } 00367 $report .= '<div class="mod-scorm">'."\n"; 00368 foreach ($orgs as $org) { 00369 $conditions = array(); 00370 $currentorg = ''; 00371 if (!empty($org->identifier)) { 00372 $report .= '<div class="orgtitle">'.$org->title.'</div>'; 00373 $currentorg = $org->identifier; 00374 $conditions['organization'] = $currentorg; 00375 } 00376 $report .= "<ul id='0' class='$liststyle'>"; 00377 $conditions['scorm'] = $scorm->id; 00378 if ($scoes = $DB->get_records('scorm_scoes', $conditions, "id ASC")) { 00379 // drop keys so that we can access array sequentially 00380 $scoes = array_values($scoes); 00381 $level=0; 00382 $sublist=1; 00383 $parents[$level]='/'; 00384 foreach ($scoes as $pos => $sco) { 00385 if ($parents[$level]!=$sco->parent) { 00386 if ($level>0 && $parents[$level-1]==$sco->parent) { 00387 $report .= "\t\t</ul></li>\n"; 00388 $level--; 00389 } else { 00390 $i = $level; 00391 $closelist = ''; 00392 while (($i > 0) && ($parents[$level] != $sco->parent)) { 00393 $closelist .= "\t\t</ul></li>\n"; 00394 $i--; 00395 } 00396 if (($i == 0) && ($sco->parent != $currentorg)) { 00397 $report .= "\t\t<li><ul id='$sublist' class='$liststyle'>\n"; 00398 $level++; 00399 } else { 00400 $report .= $closelist; 00401 $level = $i; 00402 } 00403 $parents[$level]=$sco->parent; 00404 } 00405 } 00406 $report .= "\t\t<li>"; 00407 if (isset($scoes[$pos+1])) { 00408 $nextsco = $scoes[$pos+1]; 00409 } else { 00410 $nextsco = false; 00411 } 00412 if (($nextsco !== false) && ($sco->parent != $nextsco->parent) && (($level==0) || (($level>0) && ($nextsco->parent == $sco->identifier)))) { 00413 $sublist++; 00414 } else { 00415 $report .= '<img src="'.$OUTPUT->pix_url('spacer', 'scorm').'" alt="" />'; 00416 } 00417 00418 if ($sco->launch) { 00419 $score = ''; 00420 $totaltime = ''; 00421 if ($usertrack=scorm_get_tracks($sco->id, $user->id)) { 00422 if ($usertrack->status == '') { 00423 $usertrack->status = 'notattempted'; 00424 } 00425 $strstatus = get_string($usertrack->status, 'scorm'); 00426 $report .= "<img src='".$OUTPUT->pix_url($usertrack->status, 'scorm')."' alt='$strstatus' title='$strstatus' />"; 00427 } else { 00428 if ($sco->scormtype == 'sco') { 00429 $report .= '<img src="'.$OUTPUT->pix_url('notattempted', 'scorm').'" alt="'.get_string('notattempted', 'scorm').'" title="'.get_string('notattempted', 'scorm').'" />'; 00430 } else { 00431 $report .= '<img src="'.$OUTPUT->pix_url('asset', 'scorm').'" alt="'.get_string('asset', 'scorm').'" title="'.get_string('asset', 'scorm').'" />'; 00432 } 00433 } 00434 $report .= " $sco->title $score$totaltime</li>\n"; 00435 if ($usertrack !== false) { 00436 $sometoreport = true; 00437 $report .= "\t\t\t<li><ul class='$liststyle'>\n"; 00438 foreach ($usertrack as $element => $value) { 00439 if (substr($element, 0, 3) == 'cmi') { 00440 $report .= '<li>'.$element.' => '.s($value).'</li>'; 00441 } 00442 } 00443 $report .= "\t\t\t</ul></li>\n"; 00444 } 00445 } else { 00446 $report .= " $sco->title</li>\n"; 00447 } 00448 } 00449 for ($i=0; $i<$level; $i++) { 00450 $report .= "\t\t</ul></li>\n"; 00451 } 00452 } 00453 $report .= "\t</ul><br />\n"; 00454 } 00455 $report .= "</div>\n"; 00456 } 00457 if ($sometoreport) { 00458 if ($firstmodify < $now) { 00459 $timeago = format_time($now - $firstmodify); 00460 echo get_string('firstaccess', 'scorm').': '.userdate($firstmodify).' ('.$timeago.")<br />\n"; 00461 } 00462 if ($lastmodify > 0) { 00463 $timeago = format_time($now - $lastmodify); 00464 echo get_string('lastaccess', 'scorm').': '.userdate($lastmodify).' ('.$timeago.")<br />\n"; 00465 } 00466 echo get_string('report', 'scorm').":<br />\n"; 00467 echo $report; 00468 } else { 00469 print_string('noactivity', 'scorm'); 00470 } 00471 00472 return true; 00473 } 00474 00484 function scorm_cron () { 00485 global $CFG, $DB; 00486 00487 require_once($CFG->dirroot.'/mod/scorm/locallib.php'); 00488 00489 $sitetimezone = $CFG->timezone; 00491 00492 if (!isset($CFG->scorm_updatetimelast)) { // To catch the first time 00493 set_config('scorm_updatetimelast', 0); 00494 } 00495 00496 $timenow = time(); 00497 $updatetime = usergetmidnight($timenow, $sitetimezone); 00498 00499 if ($CFG->scorm_updatetimelast < $updatetime and $timenow > $updatetime) { 00500 00501 set_config('scorm_updatetimelast', $timenow); 00502 00503 mtrace('Updating scorm packages which require daily update');//We are updating 00504 00505 $scormsupdate = $DB->get_records_select('scorm', 'updatefreq = ? AND scormtype <> ?', array(SCORM_UPDATE_EVERYDAY, SCORM_TYPE_LOCAL)); 00506 foreach ($scormsupdate as $scormupdate) { 00507 scorm_parse($scormupdate, true); 00508 } 00509 00510 //now clear out AICC session table with old session data 00511 $cfg_scorm = get_config('scorm'); 00512 if (!empty($cfg_scorm->allowaicchacp)) { 00513 $expiretime = time() - ($cfg_scorm->aicchacpkeepsessiondata*24*60*60); 00514 $DB->delete_records_select('scorm_aicc_session', 'timemodified < ?', array($expiretime)); 00515 } 00516 } 00517 00518 return true; 00519 } 00520 00530 function scorm_get_user_grades($scorm, $userid=0) { 00531 global $CFG, $DB; 00532 require_once($CFG->dirroot.'/mod/scorm/locallib.php'); 00533 00534 $grades = array(); 00535 if (empty($userid)) { 00536 if ($scousers = $DB->get_records_select('scorm_scoes_track', "scormid=? GROUP BY userid", array($scorm->id), "", "userid,null")) { 00537 foreach ($scousers as $scouser) { 00538 $grades[$scouser->userid] = new stdClass(); 00539 $grades[$scouser->userid]->id = $scouser->userid; 00540 $grades[$scouser->userid]->userid = $scouser->userid; 00541 $grades[$scouser->userid]->rawgrade = scorm_grade_user($scorm, $scouser->userid); 00542 } 00543 } else { 00544 return false; 00545 } 00546 00547 } else { 00548 if (!$DB->get_records_select('scorm_scoes_track', "scormid=? AND userid=? GROUP BY userid", array($scorm->id, $userid), "", "userid,null")) { 00549 return false; //no attempt yet 00550 } 00551 $grades[$userid] = new stdClass(); 00552 $grades[$userid]->id = $userid; 00553 $grades[$userid]->userid = $userid; 00554 $grades[$userid]->rawgrade = scorm_grade_user($scorm, $userid); 00555 } 00556 00557 return $grades; 00558 } 00559 00569 function scorm_update_grades($scorm, $userid=0, $nullifnone=true) { 00570 global $CFG, $DB; 00571 require_once($CFG->libdir.'/gradelib.php'); 00572 00573 if ($grades = scorm_get_user_grades($scorm, $userid)) { 00574 scorm_grade_item_update($scorm, $grades); 00575 00576 } else if ($userid and $nullifnone) { 00577 $grade = new stdClass(); 00578 $grade->userid = $userid; 00579 $grade->rawgrade = null; 00580 scorm_grade_item_update($scorm, $grade); 00581 00582 } else { 00583 scorm_grade_item_update($scorm); 00584 } 00585 } 00586 00592 function scorm_upgrade_grades() { 00593 global $DB; 00594 00595 $sql = "SELECT COUNT('x') 00596 FROM {scorm} s, {course_modules} cm, {modules} m 00597 WHERE m.name='scorm' AND m.id=cm.module AND cm.instance=s.id"; 00598 $count = $DB->count_records_sql($sql); 00599 00600 $sql = "SELECT s.*, cm.idnumber AS cmidnumber, s.course AS courseid 00601 FROM {scorm} s, {course_modules} cm, {modules} m 00602 WHERE m.name='scorm' AND m.id=cm.module AND cm.instance=s.id"; 00603 $rs = $DB->get_recordset_sql($sql); 00604 if ($rs->valid()) { 00605 $pbar = new progress_bar('scormupgradegrades', 500, true); 00606 $i=0; 00607 foreach ($rs as $scorm) { 00608 $i++; 00609 upgrade_set_timeout(60*5); // set up timeout, may also abort execution 00610 scorm_update_grades($scorm, 0, false); 00611 $pbar->update($i, $count, "Updating Scorm grades ($i/$count)."); 00612 } 00613 } 00614 $rs->close(); 00615 } 00616 00628 function scorm_grade_item_update($scorm, $grades=null) { 00629 global $CFG, $DB; 00630 require_once($CFG->dirroot.'/mod/scorm/locallib.php'); 00631 if (!function_exists('grade_update')) { //workaround for buggy PHP versions 00632 require_once($CFG->libdir.'/gradelib.php'); 00633 } 00634 00635 $params = array('itemname'=>$scorm->name); 00636 if (isset($scorm->cmidnumber)) { 00637 $params['idnumber'] = $scorm->cmidnumber; 00638 } 00639 00640 if ($scorm->grademethod == GRADESCOES) { 00641 if ($maxgrade = $DB->count_records_select('scorm_scoes', 'scorm = ? AND '.$DB->sql_isnotempty('scorm_scoes', 'launch', false, true), array($scorm->id))) { 00642 $params['gradetype'] = GRADE_TYPE_VALUE; 00643 $params['grademax'] = $maxgrade; 00644 $params['grademin'] = 0; 00645 } else { 00646 $params['gradetype'] = GRADE_TYPE_NONE; 00647 } 00648 } else { 00649 $params['gradetype'] = GRADE_TYPE_VALUE; 00650 $params['grademax'] = $scorm->maxgrade; 00651 $params['grademin'] = 0; 00652 } 00653 00654 if ($grades === 'reset') { 00655 $params['reset'] = true; 00656 $grades = null; 00657 } 00658 00659 return grade_update('mod/scorm', $scorm->course, 'mod', 'scorm', $scorm->id, 0, $grades, $params); 00660 } 00661 00669 function scorm_grade_item_delete($scorm) { 00670 global $CFG; 00671 require_once($CFG->libdir.'/gradelib.php'); 00672 00673 return grade_update('mod/scorm', $scorm->course, 'mod', 'scorm', $scorm->id, 0, null, array('deleted'=>1)); 00674 } 00675 00679 function scorm_get_view_actions() { 00680 return array('pre-view', 'view', 'view all', 'report'); 00681 } 00682 00686 function scorm_get_post_actions() { 00687 return array(); 00688 } 00689 00694 function scorm_option2text($scorm) { 00695 $scorm_popoup_options = scorm_get_popup_options_array(); 00696 00697 if (isset($scorm->popup)) { 00698 if ($scorm->popup == 1) { 00699 $optionlist = array(); 00700 foreach ($scorm_popoup_options as $name => $option) { 00701 if (isset($scorm->$name)) { 00702 $optionlist[] = $name.'='.$scorm->$name; 00703 } else { 00704 $optionlist[] = $name.'=0'; 00705 } 00706 } 00707 $scorm->options = implode(',', $optionlist); 00708 } else { 00709 $scorm->options = ''; 00710 } 00711 } else { 00712 $scorm->popup = 0; 00713 $scorm->options = ''; 00714 } 00715 return $scorm; 00716 } 00717 00724 function scorm_reset_course_form_definition(&$mform) { 00725 $mform->addElement('header', 'scormheader', get_string('modulenameplural', 'scorm')); 00726 $mform->addElement('advcheckbox', 'reset_scorm', get_string('deleteallattempts', 'scorm')); 00727 } 00728 00734 function scorm_reset_course_form_defaults($course) { 00735 return array('reset_scorm'=>1); 00736 } 00737 00746 function scorm_reset_gradebook($courseid, $type='') { 00747 global $CFG, $DB; 00748 00749 $sql = "SELECT s.*, cm.idnumber as cmidnumber, s.course as courseid 00750 FROM {scorm} s, {course_modules} cm, {modules} m 00751 WHERE m.name='scorm' AND m.id=cm.module AND cm.instance=s.id AND s.course=?"; 00752 00753 if ($scorms = $DB->get_records_sql($sql, array($courseid))) { 00754 foreach ($scorms as $scorm) { 00755 scorm_grade_item_update($scorm, 'reset'); 00756 } 00757 } 00758 } 00759 00769 function scorm_reset_userdata($data) { 00770 global $CFG, $DB; 00771 00772 $componentstr = get_string('modulenameplural', 'scorm'); 00773 $status = array(); 00774 00775 if (!empty($data->reset_scorm)) { 00776 $scormssql = "SELECT s.id 00777 FROM {scorm} s 00778 WHERE s.course=?"; 00779 00780 $DB->delete_records_select('scorm_scoes_track', "scormid IN ($scormssql)", array($data->courseid)); 00781 00782 // remove all grades from gradebook 00783 if (empty($data->reset_gradebook_grades)) { 00784 scorm_reset_gradebook($data->courseid); 00785 } 00786 00787 $status[] = array('component'=>$componentstr, 'item'=>get_string('deleteallattempts', 'scorm'), 'error'=>false); 00788 } 00789 00790 // no dates to shift here 00791 00792 return $status; 00793 } 00794 00800 function scorm_get_extra_capabilities() { 00801 return array('moodle/site:accessallgroups'); 00802 } 00803 00812 function scorm_get_file_areas($course, $cm, $context) { 00813 $areas = array(); 00814 $areas['content'] = get_string('areacontent', 'scorm'); 00815 $areas['package'] = get_string('areapackage', 'scorm'); 00816 return $areas; 00817 } 00818 00833 function scorm_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) { 00834 global $CFG; 00835 00836 if (!has_capability('moodle/course:managefiles', $context)) { 00837 return null; 00838 } 00839 00840 // no writing for now! 00841 00842 $fs = get_file_storage(); 00843 00844 if ($filearea === 'content') { 00845 00846 $filepath = is_null($filepath) ? '/' : $filepath; 00847 $filename = is_null($filename) ? '.' : $filename; 00848 00849 $urlbase = $CFG->wwwroot.'/pluginfile.php'; 00850 if (!$storedfile = $fs->get_file($context->id, 'mod_scorm', 'content', 0, $filepath, $filename)) { 00851 if ($filepath === '/' and $filename === '.') { 00852 $storedfile = new virtual_root_file($context->id, 'mod_scorm', 'content', 0); 00853 } else { 00854 // not found 00855 return null; 00856 } 00857 } 00858 require_once("$CFG->dirroot/mod/scorm/locallib.php"); 00859 return new scorm_package_file_info($browser, $context, $storedfile, $urlbase, $areas[$filearea], true, true, false, false); 00860 00861 } else if ($filearea === 'package') { 00862 $filepath = is_null($filepath) ? '/' : $filepath; 00863 $filename = is_null($filename) ? '.' : $filename; 00864 00865 $urlbase = $CFG->wwwroot.'/pluginfile.php'; 00866 if (!$storedfile = $fs->get_file($context->id, 'mod_scorm', 'package', 0, $filepath, $filename)) { 00867 if ($filepath === '/' and $filename === '.') { 00868 $storedfile = new virtual_root_file($context->id, 'mod_scorm', 'package', 0); 00869 } else { 00870 // not found 00871 return null; 00872 } 00873 } 00874 return new file_info_stored($browser, $context, $storedfile, $urlbase, $areas[$filearea], false, true, false, false); 00875 } 00876 00877 // scorm_intro handled in file_browser 00878 00879 return false; 00880 } 00881 00893 function scorm_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload) { 00894 global $CFG; 00895 00896 if ($context->contextlevel != CONTEXT_MODULE) { 00897 return false; 00898 } 00899 00900 require_login($course, true, $cm); 00901 00902 $lifetime = isset($CFG->filelifetime) ? $CFG->filelifetime : 86400; 00903 00904 if ($filearea === 'content') { 00905 $revision = (int)array_shift($args); // prevents caching problems - ignored here 00906 $relativepath = implode('/', $args); 00907 $fullpath = "/$context->id/mod_scorm/content/0/$relativepath"; 00908 // TODO: add any other access restrictions here if needed! 00909 00910 } else if ($filearea === 'package') { 00911 if (!has_capability('moodle/course:manageactivities', $context)) { 00912 return false; 00913 } 00914 $relativepath = implode('/', $args); 00915 $fullpath = "/$context->id/mod_scorm/package/0/$relativepath"; 00916 $lifetime = 0; // no caching here 00917 00918 } else { 00919 return false; 00920 } 00921 00922 $fs = get_file_storage(); 00923 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) { 00924 return false; 00925 } 00926 00927 // finally send the file 00928 send_stored_file($file, $lifetime, 0, false); 00929 } 00930 00942 function scorm_supports($feature) { 00943 switch($feature) { 00944 case FEATURE_GROUPS: return false; 00945 case FEATURE_GROUPINGS: return false; 00946 case FEATURE_GROUPMEMBERSONLY: return true; 00947 case FEATURE_MOD_INTRO: return true; 00948 case FEATURE_COMPLETION_TRACKS_VIEWS: return true; 00949 case FEATURE_GRADE_HAS_GRADE: return true; 00950 case FEATURE_GRADE_OUTCOMES: return true; 00951 case FEATURE_BACKUP_MOODLE2: return true; 00952 case FEATURE_SHOW_DESCRIPTION: return true; 00953 00954 default: return null; 00955 } 00956 } 00957 00969 function scorm_extend_navigation($navigation, $course, $module, $cm) { 00975 $navigation->nodetype = navigation_node::NODETYPE_LEAF; 00976 } 00977 00985 function scorm_debug_log_filename($type, $scoid) { 00986 global $CFG, $USER; 00987 00988 $logpath = $CFG->tempdir.'/scormlogs'; 00989 $logfile = $logpath.'/'.$type.'debug_'.$USER->id.'_'.$scoid.'.log'; 00990 return $logfile; 00991 } 00992 01000 function scorm_debug_log_write($type, $text, $scoid) { 01001 01002 $debugenablelog = get_config('scorm', 'allowapidebug'); 01003 if (!$debugenablelog || empty($text)) { 01004 return; 01005 } 01006 if (make_temp_directory('scormlogs/')) { 01007 $logfile = scorm_debug_log_filename($type, $scoid); 01008 @file_put_contents($logfile, date('Y/m/d H:i:s O')." DEBUG $text\r\n", FILE_APPEND); 01009 } 01010 } 01011 01019 function scorm_debug_log_remove($type, $scoid) { 01020 01021 $debugenablelog = get_config('scorm', 'allowapidebug'); 01022 $logfile = scorm_debug_log_filename($type, $scoid); 01023 if (!$debugenablelog || !file_exists($logfile)) { 01024 return false; 01025 } 01026 01027 return @unlink($logfile); 01028 } 01029 01037 function scorm_print_overview($courses, &$htmlarray) { 01038 global $USER, $CFG, $DB; 01039 01040 if (empty($courses) || !is_array($courses) || count($courses) == 0) { 01041 return array(); 01042 } 01043 01044 if (!$scorms = get_all_instances_in_courses('scorm', $courses)) { 01045 return; 01046 } 01047 01048 $scormids = array(); 01049 01050 // Do scorm::isopen() here without loading the whole thing for speed 01051 foreach ($scorms as $key => $scorm) { 01052 $time = time(); 01053 if ($scorm->timeopen) { 01054 $isopen = ($scorm->timeopen <= $time && $time <= $scorm->timeclose); 01055 } 01056 if (empty($scorm->displayattemptstatus) && (empty($isopen) || empty($scorm->timeclose))) { 01057 unset($scorms[$key]); 01058 } else { 01059 $scormids[] = $scorm->id; 01060 } 01061 } 01062 01063 if (empty($scormids)) { 01064 // no scorms to look at - we're done 01065 return true; 01066 } 01067 $strscorm = get_string('modulename', 'scorm'); 01068 $strduedate = get_string('duedate', 'scorm'); 01069 01070 foreach ($scorms as $scorm) { 01071 $str = '<div class="scorm overview"><div class="name">'.$strscorm. ': '. 01072 '<a '.($scorm->visible ? '':' class="dimmed"'). 01073 'title="'.$strscorm.'" href="'.$CFG->wwwroot. 01074 '/mod/scorm/view.php?id='.$scorm->coursemodule.'">'. 01075 $scorm->name.'</a></div>'; 01076 if ($scorm->timeclose) { 01077 $str .= '<div class="info">'.$strduedate.': '.userdate($scorm->timeclose).'</div>'; 01078 } 01079 if ($scorm->displayattemptstatus == 1) { 01080 require_once($CFG->dirroot.'/mod/scorm/locallib.php'); 01081 $str .= '<div class="details">'.scorm_get_attempt_status($USER, $scorm).'</div>'; 01082 } 01083 $str .= '</div>'; 01084 if (empty($htmlarray[$scorm->course]['scorm'])) { 01085 $htmlarray[$scorm->course]['scorm'] = $str; 01086 } else { 01087 $htmlarray[$scorm->course]['scorm'] .= $str; 01088 } 01089 } 01090 } 01091 01098 function scorm_page_type_list($pagetype, $parentcontext, $currentcontext) { 01099 $module_pagetype = array('mod-scorm-*'=>get_string('page-mod-scorm-x', 'scorm')); 01100 return $module_pagetype; 01101 } 01102 01109 function scorm_version_check($scormversion, $version='') { 01110 $scormversion = trim(strtolower($scormversion)); 01111 if (empty($version) || $version==SCORM_12) { 01112 if ($scormversion == 'scorm_12' || $scormversion == 'scorm_1.2') { 01113 return SCORM_12; 01114 } 01115 if (!empty($version)) { 01116 return false; 01117 } 01118 } 01119 if (empty($version) || $version == SCORM_13) { 01120 if ($scormversion == 'scorm_13' || $scormversion == 'scorm_1.3') { 01121 return SCORM_13; 01122 } 01123 if (!empty($version)) { 01124 return false; 01125 } 01126 } 01127 if (empty($version) || $version == SCORM_AICC) { 01128 if (strpos($scormversion, 'aicc')) { 01129 return SCORM_AICC; 01130 } 01131 if (!empty($version)) { 01132 return false; 01133 } 01134 } 01135 return false; 01136 }