function scorm_format_toc_for_treeview($user, $scorm, $scoes, $usertracks, $cmid, $toclink = TOCJSLINK, $currentorg = '', $attempt = '', $play = false, $organizationsco = null, $children = false) { global $CFG; $result = new stdClass(); $result->prerequisites = true; $result->incomplete = true; $result->toc = ''; if (!$children) { $attemptsmade = scorm_get_attempt_count($user->id, $scorm); $result->attemptleft = $scorm->maxattempt == 0 ? 1 : $scorm->maxattempt - $attemptsmade; } if (!$children) { $result->toc = "<ul>\n"; if (!$play && !empty($organizationsco)) { $result->toc .= "\t<li>" . $organizationsco->title . "</li>\n"; } } $prevsco = ''; if (!empty($scoes)) { foreach ($scoes as $sco) { $result->toc .= "\t<li>\n"; $scoid = $sco->id; $sco->isvisible = true; if ($sco->isvisible) { $score = ''; if (isset($usertracks[$sco->identifier])) { $viewscore = has_capability('mod/scorm:viewscores', context_module::instance($cmid)); if (isset($usertracks[$sco->identifier]->score_raw) && $viewscore) { if ($usertracks[$sco->identifier]->score_raw != '') { $score = '(' . get_string('score', 'scorm') . ': ' . $usertracks[$sco->identifier]->score_raw . ')'; } } } if (!empty($sco->prereq)) { if ($sco->id == $scoid) { $result->prerequisites = true; } if (!empty($prevsco) && scorm_version_check($scorm->version, SCORM_13) && !empty($prevsco->hidecontinue)) { if ($sco->scormtype == 'sco') { $result->toc .= '<span>' . $sco->statusicon . ' ' . format_string($sco->title) . '</span>'; } else { $result->toc .= '<span> ' . format_string($sco->title) . '</span>'; } } else { if ($toclink == TOCFULLURL) { $url = $CFG->wwwroot . '/mod/scorm/player.php?' . $sco->url; if (!empty($sco->launch)) { if ($sco->scormtype == 'sco') { $result->toc .= $sco->statusicon . ' <a href="' . $url . '">' . format_string($sco->title) . '</a>' . $score . "\n"; } else { $result->toc .= ' <a data-scoid="' . $sco->id . '" href="' . $url . '">' . format_string($sco->title) . '</a>' . $score . "\n"; } } else { if ($sco->scormtype == 'sco') { $result->toc .= $sco->statusicon . ' ' . format_string($sco->title) . $score . "\n"; } else { $result->toc .= ' ' . format_string($sco->title) . $score . "\n"; } } } else { if (!empty($sco->launch)) { if ($sco->scormtype == 'sco') { $result->toc .= '<a data-scoid="' . $sco->id . '" title="' . $sco->url . '">' . $sco->statusicon . ' ' . format_string($sco->title) . ' ' . $score . '</a>'; } else { $result->toc .= '<a data-scoid="' . $sco->id . '" title="' . $sco->url . '"> ' . format_string($sco->title) . ' ' . $score . '</a>'; } } else { if ($sco->scormtype == 'sco') { $result->toc .= '<span>' . $sco->statusicon . ' ' . format_string($sco->title) . '</span>'; } else { $result->toc .= '<span> ' . format_string($sco->title) . '</span>'; } } } } } else { if ($play) { if ($sco->scormtype == 'sco') { $result->toc .= '<span>' . $sco->statusicon . ' ' . format_string($sco->title) . '</span>'; } else { $result->toc .= ' ' . format_string($sco->title) . '</span>'; } } else { if ($sco->scormtype == 'sco') { $result->toc .= $sco->statusicon . ' ' . format_string($sco->title) . "\n"; } else { $result->toc .= ' ' . format_string($sco->title) . "\n"; } } } } else { $result->toc .= "\t\t " . format_string($sco->title) . "\n"; } if (!empty($sco->children)) { $result->toc .= "\n\t\t<ul>\n"; $childresult = scorm_format_toc_for_treeview($user, $scorm, $sco->children, $usertracks, $cmid, $toclink, $currentorg, $attempt, $play, $organizationsco, true); $result->toc .= $childresult->toc; $result->toc .= "\t\t</ul>\n"; $result->toc .= "\t</li>\n"; } else { $result->toc .= "\t</li>\n"; } $prevsco = $sco; } $result->incomplete = $sco->incomplete; } if (!$children) { $result->toc .= "</ul>\n"; } return $result; }
function scorm_get_toc($user,$scorm,$cmid,$toclink=TOCJSLINK,$currentorg='',$scoid='',$mode='normal',$attempt='',$play=false, $tocheader=false) { global $CFG, $DB, $PAGE, $OUTPUT; $modestr = ''; if ($mode == 'browse') { $modestr = '&mode='.$mode; } $result = new stdClass(); if ($tocheader) { $result->toc = '<div id="scorm_layout">'; $result->toc .= '<div id="scorm_toc">'; $result->toc .= '<div id="scorm_tree">'; } $result->toc .= '<ul>'; $tocmenus = array(); $result->prerequisites = true; $incomplete = false; // // Get the current organization infos // if (!empty($currentorg)) { if (($organizationtitle = $DB->get_field('scorm_scoes','title', array('scorm'=>$scorm->id,'identifier'=>$currentorg))) != '') { if ($play) { $result->toctitle = "$organizationtitle"; } else { $result->toc .= "\t<li>$organizationtitle</li>\n"; } $tocmenus[] = $organizationtitle; } } // // If not specified retrieve the last attempt number // if (empty($attempt)) { $attempt = scorm_get_attempt_count($user->id, $scorm); } $result->attemptleft = $scorm->maxattempt == 0 ? 1 : $scorm->maxattempt - $attempt; if ($scoes = scorm_get_scoes($scorm->id, $currentorg)){ // // Retrieve user tracking data for each learning object // $usertracks = array(); foreach ($scoes as $sco) { if (!empty($sco->launch)) { if ($usertrack = scorm_get_tracks($sco->id,$user->id,$attempt)) { if ($usertrack->status == '') { $usertrack->status = 'notattempted'; } $usertracks[$sco->identifier] = $usertrack; } } } $level=0; $sublist=1; $previd = 0; $nextid = 0; $findnext = false; $parents[$level]='/'; $prevsco = ''; foreach ($scoes as $pos => $sco) { $isvisible = false; $sco->title = $sco->title; if (!isset($sco->isvisible) || (isset($sco->isvisible) && ($sco->isvisible == 'true'))) { $isvisible = true; } if ($parents[$level] != $sco->parent) { if ($newlevel = array_search($sco->parent,$parents)) { for ($i=0; $i<($level-$newlevel); $i++) { $result->toc .= "\t\t</li></ul></li>\n"; } $level = $newlevel; } else { $i = $level; $closelist = ''; while (($i > 0) && ($parents[$level] != $sco->parent)) { if ($i === 1 && $level > 1) { $closelist .= "\t\t</ul></li>\n"; } else { $closelist .= "\t</li></ul></li>\n"; } $i--; } if (($i == 0) && ($sco->parent != $currentorg)) { $result->toc .= "\n\t<ul>\n"; $level++; } else { $result->toc .= $closelist; $level = $i; } $parents[$level] = $sco->parent; } } if ($isvisible) { $result->toc .= "<li>"; } if (isset($scoes[$pos+1])) { $nextsco = $scoes[$pos+1]; } else { $nextsco = false; } $nextisvisible = false; if (($nextsco !== false) && (!isset($nextsco->isvisible) || (isset($nextsco->isvisible) && ($nextsco->isvisible == 'true')))) { $nextisvisible = true; } if ($nextisvisible && ($nextsco !== false) && ($sco->parent != $nextsco->parent) && (($level==0) || (($level>0) && ($nextsco->parent == $sco->identifier)))) { $sublist++; } if (empty($sco->title)) { $sco->title = $sco->identifier; } if ($isvisible) { if (!empty($sco->launch)) { $score = ''; if (empty($scoid) && ($mode != 'normal')) { $scoid = $sco->id; } if (isset($usertracks[$sco->identifier])) { $usertrack = $usertracks[$sco->identifier]; $strstatus = get_string($usertrack->status,'scorm'); if ($sco->scormtype == 'sco') { $statusicon = '<img src="'.$OUTPUT->pix_url($usertrack->status, 'scorm').'" alt="'.$strstatus.'" title="'.$strstatus.'" />'; } else { $statusicon = '<img src="'.$OUTPUT->pix_url('assetc', 'scorm').'" alt="'.get_string('assetlaunched','scorm').'" title="'.get_string('assetlaunched','scorm').'" />'; } if (($usertrack->status == 'notattempted') || ($usertrack->status == 'incomplete') || ($usertrack->status == 'browsed')) { $incomplete = true; if ($play && empty($scoid)) { $scoid = $sco->id; } } if ($usertrack->score_raw != '' && has_capability('mod/scorm:viewscores', get_context_instance(CONTEXT_MODULE,$cmid))) { $score = '('.get_string('score','scorm').': '.$usertrack->score_raw.')'; } $strsuspended = get_string('suspended','scorm'); $exitvar = 'cmi.core.exit'; if (scorm_version_check($scorm->version, SCORM_13)) { $exitvar = 'cmi.exit'; } if ($incomplete && isset($usertrack->{$exitvar}) && ($usertrack->{$exitvar} == 'suspend')) { $statusicon = '<img src="'.$OUTPUT->pix_url('suspend', 'scorm').'" alt="'.$strstatus.' - '.$strsuspended.'" title="'.$strstatus.' - '.$strsuspended.'" />'; } } else { if ($play && empty($scoid)) { $scoid = $sco->id; } $incomplete = true; if ($sco->scormtype == 'sco') { $statusicon = '<img src="'.$OUTPUT->pix_url('notattempted', 'scorm').'" alt="'.get_string('notattempted','scorm').'" title="'.get_string('notattempted','scorm').'" />'; } else { $statusicon = '<img src="'.$OUTPUT->pix_url('asset', 'scorm').'" alt="'.get_string('asset','scorm').'" title="'.get_string('asset','scorm').'" />'; } } if ($sco->id == $scoid) { $findnext = true; } if (($nextid == 0) && (scorm_count_launchable($scorm->id,$currentorg) > 1) && ($nextsco!==false) && (!$findnext)) { if (!empty($sco->launch)) { $previd = $sco->id; } } if (scorm_version_check($scorm->version, SCORM_13)) { require_once($CFG->dirroot.'/mod/scorm/datamodels/sequencinglib.php'); $prereq = scorm_seq_evaluate($sco->id,$usertracks); } else { //TODO: split check for sco->prerequisites only for AICC as I think that's the only case it's set. $prereq = empty($sco->prerequisites) || scorm_eval_prerequisites($sco->prerequisites,$usertracks); } if ($prereq) { if ($sco->id == $scoid) { $result->prerequisites = true; } if (!empty($prevsco) && scorm_version_check($scorm->version, SCORM_13) && !empty($prevsco->hidecontinue)) { $result->toc .= '<span>'.$statusicon.' '.format_string($sco->title).'</span>'; } else if ($toclink == TOCFULLURL) { //display toc with urls for structure page $url = $CFG->wwwroot.'/mod/scorm/player.php?a='.$scorm->id.'&currentorg='.$currentorg.$modestr.'&scoid='.$sco->id; $result->toc .= $statusicon.' <a href="'.$url.'">'.format_string($sco->title).'</a>'.$score."\n"; } else { //display toc for inside scorm player if ($sco->launch) { $link = 'a='.$scorm->id.'&scoid='.$sco->id.'¤torg='.$currentorg.$modestr.'&attempt='.$attempt; $result->toc .= '<a title="'.$link.'">'.$statusicon.' '.format_string($sco->title).' '.$score.'</a>'; } else { $result->toc .= '<span>'.$statusicon.' '.format_string($sco->title).'</span>'; } } $tocmenus[$sco->id] = scorm_repeater('−',$level) . '>' . format_string($sco->title); } else { if ($sco->id == $scoid) { $result->prerequisites = false; } if ($play) { // should be disabled $result->toc .= '<span>'.$statusicon.' '.format_string($sco->title).'</span>'; } else { $result->toc .= $statusicon.' '.format_string($sco->title)."\n"; } } } else { $result->toc .= ' '.format_string($sco->title); } if (($nextsco === false) || $nextsco->parent == $sco->parent) { $result->toc .= "</li>\n"; } } if (($nextsco !== false) && ($nextid == 0) && ($findnext)) { if (!empty($nextsco->launch)) { $nextid = $nextsco->id; } } $prevsco = $sco; } for ($i=0;$i<$level;$i++) { $result->toc .= "\t\t</ul></li>\n"; } if ($play) { // it is possible that $scoid is still not set, in this case we don't want an empty object if ($scoid) { $sco = scorm_get_sco($scoid); } $sco->previd = $previd; $sco->nextid = $nextid; $result->sco = $sco; $result->incomplete = $incomplete; } else { $result->incomplete = $incomplete; } } $result->toc .= '</ul>'; // NEW IMS TOC if ($tocheader) { $result->toc .= '</div></div></div>'; $result->toc .= '<div id="scorm_navpanel"></div>'; } $url = new moodle_url('/mod/scorm/player.php?a='.$scorm->id.'¤torg='.$currentorg.$modestr); $result->tocmenu = $OUTPUT->single_select($url, 'scoid', $tocmenus, $sco->id, null, "tocmenu"); return $result; }
if ($userdata->mode == 'normal') { $userdata->credit = 'credit'; } else { $userdata->credit = 'no-credit'; } if ($scodatas = scorm_get_sco($scoid, SCO_DATA)) { foreach ($scodatas as $key => $value) { $userdata->$key = addslashes_js($value); } } else { print_error('cannotfindsco', 'scorm'); } if (!$sco = scorm_get_sco($scoid)) { print_error('cannotfindsco', 'scorm'); } if (scorm_version_check($scorm->version, SCORM_13)) { $objectives = $DB->get_records('scorm_seq_objective', array('scoid' => $scoid)); $index = 0; foreach ($objectives as $objective) { if (!empty($objective->minnormalizedmeasure)) { $userdata->{'cmi.scaled_passing_score'} = $objective->minnormalizedmeasure; } if (!empty($objective->objectiveid)) { $userdata->{'cmi.objectives.N'.$index.'.id'} = $objective->objectiveid; $index++; } } } header('Content-Type: text/javascript; charset=UTF-8');
+ ' name="getDiagnosticButton">' + ' <input type="button"' + ' value="<?php echo $LMS_prefix; ?> Commit() "' + ' onclick="tryLMSCommit();"' + ' id="commitButton"' + ' name="commitButton">' + ' <input type="button"' + ' value="<?php echo scorm_version_check($scorm->version, SCORM_12) ? 'LMSFinish' : 'Terminate'; ?> () "' + ' onclick="try<?php echo scorm_version_check($scorm->version, SCORM_12) ? 'LMSFinish' : 'LMSTerminate'; ?> ();"' + ' id="finishButton"' + ' name="finishButton">' + ' </td>' + ' </tr>' + ' <tr>' + ' <td>' + ' <label>Result: </label><br />' + ' <textarea name="msgtxt" id="msgtxt" rows="2" cols="150" wrap="VIRTUAL" readonly>None</textarea>' + ' </td>' + ' </tr>' + ' </table>' + '</form>' + '<h3 id="mod-scorm-marker">SCORM API Activity Log<\/h3>';
$userdata->{'cmi.scaled_passing_score'} = $objective->minnormalizedmeasure; } if (!empty($objective->objectiveid)) { $userdata->{'cmi.objectives.N'.$index.'.id'} = $objective->objectiveid; $index++; } } } header('Content-Type: text/javascript; charset=UTF-8'); $scorm->version = strtolower(clean_param($scorm->version, PARAM_SAFEDIR)); // Just to be safe. /* * TCAPI - Bypass loading of API since we don't need it when is TCAPI. */ if (scorm_version_check($scorm->version, SCORM_TCAPI)) { // Do nothing and bypass API loading } else if (file_exists($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'.js.php')) { include_once($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'.js.php'); } else { include_once($CFG->dirroot.'/mod/scorm/datamodels/scorm_12.js.php'); } // Set the start time of this SCO. scorm_insert_track($USER->id, $scorm->id, $scoid, $attempt, 'x.start.time', time()); ?> var errorCode = "0"; function underscore(str) { str = String(str).replace(/.N/g,"."); return str.replace(/\./g,"__");
} add_to_log($course->id, 'scorm', 'launch', 'view.php?id='.$cm->id, $result, $cm->id); header('Content-Type: text/html; charset=UTF-8'); if ($sco->scormtype == 'asset') { // HTTP 302 Found => Moved Temporarily. header('Location: ' . $result); // Provide a short feedback in case of slow network connection. echo '<html><body><p>' . get_string('activitypleasewait', 'scorm'). '</p></body></html>'; exit; } // We expect a SCO: select which API are we looking for. $LMS_api = (scorm_version_check($scorm->version, SCORM_12) || empty($scorm->version)) ? 'API' : 'API_1484_11'; ?> <html> <head> <title>LoadSCO</title> <script type="text/javascript"> //<![CDATA[ var myApiHandle = null; var myFindAPITries = 0; function myGetAPIHandle() { myFindAPITries = 0; if (myApiHandle == null) { myApiHandle = myGetAPI(); }
/** * displays the full report * @param \stdClass $scorm full SCORM object * @param \stdClass $cm - full course_module object * @param \stdClass $course - full course object * @param string $download - type of download being requested */ public function display($scorm, $cm, $course, $download) { global $CFG, $DB, $OUTPUT, $PAGE; $contextmodule = \context_module::instance($cm->id); $action = optional_param('action', '', PARAM_ALPHA); $attemptids = optional_param_array('attemptid', array(), PARAM_RAW); $attemptsmode = optional_param('attemptsmode', SCORM_REPORT_ATTEMPTS_ALL_STUDENTS, PARAM_INT); $PAGE->set_url(new \moodle_url($PAGE->url, array('attemptsmode' => $attemptsmode))); if ($action == 'delete' && has_capability('mod/scorm:deleteresponses', $contextmodule) && confirm_sesskey()) { if (scorm_delete_responses($attemptids, $scorm)) { // Delete responses. echo $OUTPUT->notification(get_string('scormresponsedeleted', 'scorm'), 'notifysuccess'); } } // Find out current groups mode. $currentgroup = groups_get_activity_group($cm, true); // Detailed report. $mform = new \mod_scorm_report_objectives_settings($PAGE->url, compact('currentgroup')); if ($fromform = $mform->get_data()) { $pagesize = $fromform->pagesize; $showobjectivescore = $fromform->objectivescore; set_user_preference('scorm_report_pagesize', $pagesize); set_user_preference('scorm_report_objectives_score', $showobjectivescore); } else { $pagesize = get_user_preferences('scorm_report_pagesize', 0); $showobjectivescore = get_user_preferences('scorm_report_objectives_score', 0); } if ($pagesize < 1) { $pagesize = SCORM_REPORT_DEFAULT_PAGE_SIZE; } // Select group menu. $displayoptions = array(); $displayoptions['attemptsmode'] = $attemptsmode; $displayoptions['objectivescore'] = $showobjectivescore; $mform->set_data($displayoptions + array('pagesize' => $pagesize)); if ($groupmode = groups_get_activity_groupmode($cm)) { // Groups are being used. if (!$download) { groups_print_activity_menu($cm, new \moodle_url($PAGE->url, $displayoptions)); } } $formattextoptions = array('context' => \context_course::instance($course->id)); // We only want to show the checkbox to delete attempts // if the user has permissions and if the report mode is showing attempts. $candelete = has_capability('mod/scorm:deleteresponses', $contextmodule) && $attemptsmode != SCORM_REPORT_ATTEMPTS_STUDENTS_WITH_NO; // Select the students. $nostudents = false; if (empty($currentgroup)) { // All users who can attempt scoes. if (!($students = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', 'u.id', '', '', '', '', '', false))) { echo $OUTPUT->notification(get_string('nostudentsyet')); $nostudents = true; $allowedlist = ''; } else { $allowedlist = array_keys($students); } unset($students); } else { // All users who can attempt scoes and who are in the currently selected group. $groupstudents = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', 'u.id', '', '', '', $currentgroup, '', false); if (!$groupstudents) { echo $OUTPUT->notification(get_string('nostudentsingroup')); $nostudents = true; $groupstudents = array(); } $allowedlist = array_keys($groupstudents); unset($groupstudents); } if (!$nostudents) { // Now check if asked download of data. $coursecontext = \context_course::instance($course->id); if ($download) { $filename = clean_filename("{$course->shortname} " . format_string($scorm->name, true, $formattextoptions)); } // Define table columns. $columns = array(); $headers = array(); if (!$download && $candelete) { $columns[] = 'checkbox'; $headers[] = null; } if (!$download && $CFG->grade_report_showuserimage) { $columns[] = 'picture'; $headers[] = ''; } $columns[] = 'fullname'; $headers[] = get_string('name'); $extrafields = get_extra_user_fields($coursecontext); foreach ($extrafields as $field) { $columns[] = $field; $headers[] = get_user_field_name($field); } $columns[] = 'attempt'; $headers[] = get_string('attempt', 'scorm'); $columns[] = 'start'; $headers[] = get_string('started', 'scorm'); $columns[] = 'finish'; $headers[] = get_string('last', 'scorm'); $columns[] = 'score'; $headers[] = get_string('score', 'scorm'); $scoes = $DB->get_records('scorm_scoes', array("scorm" => $scorm->id), 'sortorder, id'); foreach ($scoes as $sco) { if ($sco->launch != '') { $columns[] = 'scograde' . $sco->id; $headers[] = format_string($sco->title, '', $formattextoptions); } } $params = array(); list($usql, $params) = $DB->get_in_or_equal($allowedlist, SQL_PARAMS_NAMED); // Construct the SQL. $select = 'SELECT DISTINCT ' . $DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)') . ' AS uniqueid, '; $select .= 'st.scormid AS scormid, st.attempt AS attempt, ' . \user_picture::fields('u', array('idnumber'), 'userid') . get_extra_user_fields_sql($coursecontext, 'u', '', array('email', 'idnumber')) . ' '; // This part is the same for all cases - join users and scorm_scoes_track tables. $from = 'FROM {user} u '; $from .= 'LEFT JOIN {scorm_scoes_track} st ON st.userid = u.id AND st.scormid = ' . $scorm->id; switch ($attemptsmode) { case SCORM_REPORT_ATTEMPTS_STUDENTS_WITH: // Show only students with attempts. $where = ' WHERE u.id ' . $usql . ' AND st.userid IS NOT NULL'; break; case SCORM_REPORT_ATTEMPTS_STUDENTS_WITH_NO: // Show only students without attempts. $where = ' WHERE u.id ' . $usql . ' AND st.userid IS NULL'; break; case SCORM_REPORT_ATTEMPTS_ALL_STUDENTS: // Show all students with or without attempts. $where = ' WHERE u.id ' . $usql . ' AND (st.userid IS NOT NULL OR st.userid IS NULL)'; break; } $countsql = 'SELECT COUNT(DISTINCT(' . $DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)') . ')) AS nbresults, '; $countsql .= 'COUNT(DISTINCT(' . $DB->sql_concat('u.id', '\'#\'', 'st.attempt') . ')) AS nbattempts, '; $countsql .= 'COUNT(DISTINCT(u.id)) AS nbusers '; $countsql .= $from . $where; $nbmaincolumns = count($columns); // Get number of main columns used. $objectives = get_scorm_objectives($scorm->id); $nosort = array(); foreach ($objectives as $scoid => $sco) { foreach ($sco as $id => $objectivename) { $colid = $scoid . 'objectivestatus' . $id; $columns[] = $colid; $nosort[] = $colid; if (!$displayoptions['objectivescore']) { // Display the objective name only. $headers[] = $objectivename; } else { // Display the objective status header with a "status" suffix to avoid confusion. $headers[] = $objectivename . ' ' . get_string('status', 'scormreport_objectives'); // Now print objective score headers. $colid = $scoid . 'objectivescore' . $id; $columns[] = $colid; $nosort[] = $colid; $headers[] = $objectivename . ' ' . get_string('score', 'scormreport_objectives'); } } } $emptycell = ''; // Used when an empty cell is being printed - in html we add a space. if (!$download) { $emptycell = ' '; $table = new \flexible_table('mod-scorm-report'); $table->define_columns($columns); $table->define_headers($headers); $table->define_baseurl($PAGE->url); $table->sortable(true); $table->collapsible(true); // This is done to prevent redundant data, when a user has multiple attempts. $table->column_suppress('picture'); $table->column_suppress('fullname'); foreach ($extrafields as $field) { $table->column_suppress($field); } foreach ($nosort as $field) { $table->no_sorting($field); } $table->no_sorting('start'); $table->no_sorting('finish'); $table->no_sorting('score'); $table->no_sorting('checkbox'); $table->no_sorting('picture'); foreach ($scoes as $sco) { if ($sco->launch != '') { $table->no_sorting('scograde' . $sco->id); } } $table->column_class('picture', 'picture'); $table->column_class('fullname', 'bold'); $table->column_class('score', 'bold'); $table->set_attribute('cellspacing', '0'); $table->set_attribute('id', 'attempts'); $table->set_attribute('class', 'generaltable generalbox'); // Start working -- this is necessary as soon as the niceties are over. $table->setup(); } else { if ($download == 'ODS') { require_once "{$CFG->libdir}/odslib.class.php"; $filename .= ".ods"; // Creating a workbook. $workbook = new \MoodleODSWorkbook("-"); // Sending HTTP headers. $workbook->send($filename); // Creating the first worksheet. $sheettitle = get_string('report', 'scorm'); $myxls = $workbook->add_worksheet($sheettitle); // Format types. $format = $workbook->add_format(); $format->set_bold(0); $formatbc = $workbook->add_format(); $formatbc->set_bold(1); $formatbc->set_align('center'); $formatb = $workbook->add_format(); $formatb->set_bold(1); $formaty = $workbook->add_format(); $formaty->set_bg_color('yellow'); $formatc = $workbook->add_format(); $formatc->set_align('center'); $formatr = $workbook->add_format(); $formatr->set_bold(1); $formatr->set_color('red'); $formatr->set_align('center'); $formatg = $workbook->add_format(); $formatg->set_bold(1); $formatg->set_color('green'); $formatg->set_align('center'); // Here starts workshhet headers. $colnum = 0; foreach ($headers as $item) { $myxls->write(0, $colnum, $item, $formatbc); $colnum++; } $rownum = 1; } else { if ($download == 'Excel') { require_once "{$CFG->libdir}/excellib.class.php"; $filename .= ".xls"; // Creating a workbook. $workbook = new \MoodleExcelWorkbook("-"); // Sending HTTP headers. $workbook->send($filename); // Creating the first worksheet. $sheettitle = get_string('report', 'scorm'); $myxls = $workbook->add_worksheet($sheettitle); // Format types. $format = $workbook->add_format(); $format->set_bold(0); $formatbc = $workbook->add_format(); $formatbc->set_bold(1); $formatbc->set_align('center'); $formatb = $workbook->add_format(); $formatb->set_bold(1); $formaty = $workbook->add_format(); $formaty->set_bg_color('yellow'); $formatc = $workbook->add_format(); $formatc->set_align('center'); $formatr = $workbook->add_format(); $formatr->set_bold(1); $formatr->set_color('red'); $formatr->set_align('center'); $formatg = $workbook->add_format(); $formatg->set_bold(1); $formatg->set_color('green'); $formatg->set_align('center'); $colnum = 0; foreach ($headers as $item) { $myxls->write(0, $colnum, $item, $formatbc); $colnum++; } $rownum = 1; } else { if ($download == 'CSV') { $csvexport = new \csv_export_writer("tab"); $csvexport->set_filename($filename, ".txt"); $csvexport->add_data($headers); } } } } if (!$download) { $sort = $table->get_sql_sort(); } else { $sort = ''; } // Fix some wired sorting. if (empty($sort)) { $sort = ' ORDER BY uniqueid'; } else { $sort = ' ORDER BY ' . $sort; } if (!$download) { // Add extra limits due to initials bar. list($twhere, $tparams) = $table->get_sql_where(); if ($twhere) { $where .= ' AND ' . $twhere; // Initial bar. $params = array_merge($params, $tparams); } if (!empty($countsql)) { $count = $DB->get_record_sql($countsql, $params); $totalinitials = $count->nbresults; if ($twhere) { $countsql .= ' AND ' . $twhere; } $count = $DB->get_record_sql($countsql, $params); $total = $count->nbresults; } $table->pagesize($pagesize, $total); echo \html_writer::start_div('scormattemptcounts'); if ($count->nbresults == $count->nbattempts) { echo get_string('reportcountattempts', 'scorm', $count); } else { if ($count->nbattempts > 0) { echo get_string('reportcountallattempts', 'scorm', $count); } else { echo $count->nbusers . ' ' . get_string('users'); } } echo \html_writer::end_div(); } // Fetch the attempts. if (!$download) { $attempts = $DB->get_records_sql($select . $from . $where . $sort, $params, $table->get_page_start(), $table->get_page_size()); echo \html_writer::start_div('', array('id' => 'scormtablecontainer')); if ($candelete) { // Start form. $strreallydel = addslashes_js(get_string('deleteattemptcheck', 'scorm')); echo \html_writer::start_tag('form', array('id' => 'attemptsform', 'method' => 'post', 'action' => $PAGE->url->out(false), 'onsubmit' => 'return confirm("' . $strreallydel . '");')); echo \html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'action', 'value' => 'delete')); echo \html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())); echo \html_writer::start_div('', array('style' => 'display: none;')); echo \html_writer::input_hidden_params($PAGE->url); echo \html_writer::end_div(); echo \html_writer::start_div(); } $table->initialbars($totalinitials > 20); // Build table rows. } else { $attempts = $DB->get_records_sql($select . $from . $where . $sort, $params); } if ($attempts) { foreach ($attempts as $scouser) { $row = array(); if (!empty($scouser->attempt)) { $timetracks = scorm_get_sco_runtime($scorm->id, false, $scouser->userid, $scouser->attempt); } else { $timetracks = ''; } if (in_array('checkbox', $columns)) { if ($candelete && !empty($timetracks->start)) { $row[] = \html_writer::checkbox('attemptid[]', $scouser->userid . ':' . $scouser->attempt, false); } else { if ($candelete) { $row[] = ''; } } } if (in_array('picture', $columns)) { $user = new \stdClass(); $additionalfields = explode(',', \user_picture::fields()); $user = username_load_fields_from_object($user, $scouser, null, $additionalfields); $user->id = $scouser->userid; $row[] = $OUTPUT->user_picture($user, array('courseid' => $course->id)); } if (!$download) { $url = new \moodle_url('/user/view.php', array('id' => $scouser->userid, 'course' => $course->id)); $row[] = \html_writer::link($url, fullname($scouser)); } else { $row[] = fullname($scouser); } foreach ($extrafields as $field) { $row[] = s($scouser->{$field}); } if (empty($timetracks->start)) { $row[] = '-'; $row[] = '-'; $row[] = '-'; $row[] = '-'; } else { if (!$download) { $url = new \moodle_url('/mod/scorm/report/userreport.php', array('id' => $cm->id, 'user' => $scouser->userid, 'attempt' => $scouser->attempt)); $row[] = \html_writer::link($url, $scouser->attempt); } else { $row[] = $scouser->attempt; } if ($download == 'ODS' || $download == 'Excel') { $row[] = userdate($timetracks->start, get_string("strftimedatetime", "langconfig")); } else { $row[] = userdate($timetracks->start); } if ($download == 'ODS' || $download == 'Excel') { $row[] = userdate($timetracks->finish, get_string('strftimedatetime', 'langconfig')); } else { $row[] = userdate($timetracks->finish); } $row[] = scorm_grade_user_attempt($scorm, $scouser->userid, $scouser->attempt); } // Print out all scores of attempt. foreach ($scoes as $sco) { if ($sco->launch != '') { if ($trackdata = scorm_get_tracks($sco->id, $scouser->userid, $scouser->attempt)) { if ($trackdata->status == '') { $trackdata->status = 'notattempted'; } $strstatus = get_string($trackdata->status, 'scorm'); if ($trackdata->score_raw != '') { // If raw score exists, print it. $score = $trackdata->score_raw; // Add max score if it exists. if (isset($trackdata->score_max)) { $score .= '/' . $trackdata->score_max; } } else { // ...else print out status. $score = $strstatus; } if (!$download) { $url = new \moodle_url('/mod/scorm/report/userreporttracks.php', array('id' => $cm->id, 'scoid' => $sco->id, 'user' => $scouser->userid, 'attempt' => $scouser->attempt)); $row[] = \html_writer::img($OUTPUT->pix_url($trackdata->status, 'scorm'), $strstatus, array('title' => $strstatus)) . \html_writer::empty_tag('br') . \html_writer::link($url, $score, array('title' => get_string('details', 'scorm'))); } else { $row[] = $score; } // Iterate over tracks and match objective id against values. $scorm2004 = false; if (scorm_version_check($scorm->version, SCORM_13)) { $scorm2004 = true; $objectiveprefix = "cmi.objectives."; } else { $objectiveprefix = "cmi.objectives_"; } $keywords = array(".id", $objectiveprefix); $objectivestatus = array(); $objectivescore = array(); foreach ($trackdata as $name => $value) { if (strpos($name, $objectiveprefix) === 0 && strrpos($name, '.id') !== false) { $num = trim(str_ireplace($keywords, '', $name)); if (is_numeric($num)) { if ($scorm2004) { $element = $objectiveprefix . $num . '.completion_status'; } else { $element = $objectiveprefix . $num . '.status'; } if (isset($trackdata->{$element})) { $objectivestatus[$value] = $trackdata->{$element}; } else { $objectivestatus[$value] = ''; } if ($displayoptions['objectivescore']) { $element = $objectiveprefix . $num . '.score.raw'; if (isset($trackdata->{$element})) { $objectivescore[$value] = $trackdata->{$element}; } else { $objectivescore[$value] = ''; } } } } } // Interaction data. if (!empty($objectives[$trackdata->scoid])) { foreach ($objectives[$trackdata->scoid] as $name) { if (isset($objectivestatus[$name])) { $row[] = s($objectivestatus[$name]); } else { $row[] = $emptycell; } if ($displayoptions['objectivescore']) { if (isset($objectivescore[$name])) { $row[] = s($objectivescore[$name]); } else { $row[] = $emptycell; } } } } // End of interaction data. } else { // If we don't have track data, we haven't attempted yet. $strstatus = get_string('notattempted', 'scorm'); if (!$download) { $row[] = \html_writer::img($OUTPUT->pix_url('notattempted', 'scorm'), $strstatus, array('title' => $strstatus)) . \html_writer::empty_tag('br') . $strstatus; } else { $row[] = $strstatus; } // Complete the empty cells. for ($i = 0; $i < count($columns) - $nbmaincolumns; $i++) { $row[] = $emptycell; } } } } if (!$download) { $table->add_data($row); } else { if ($download == 'Excel' or $download == 'ODS') { $colnum = 0; foreach ($row as $item) { $myxls->write($rownum, $colnum, $item, $format); $colnum++; } $rownum++; } else { if ($download == 'CSV') { $csvexport->add_data($row); } } } } if (!$download) { $table->finish_output(); if ($candelete) { echo \html_writer::start_tag('table', array('id' => 'commands')); echo \html_writer::start_tag('tr') . \html_writer::start_tag('td'); echo \html_writer::link('javascript:select_all_in(\'DIV\', null, \'scormtablecontainer\');', get_string('selectall', 'scorm')) . ' / '; echo \html_writer::link('javascript:deselect_all_in(\'DIV\', null, \'scormtablecontainer\');', get_string('selectnone', 'scorm')); echo ' '; echo \html_writer::empty_tag('input', array('type' => 'submit', 'value' => get_string('deleteselected', 'scorm'), 'class' => 'btn btn-secondary')); echo \html_writer::end_tag('td') . \html_writer::end_tag('tr') . \html_writer::end_tag('table'); // Close form. echo \html_writer::end_tag('div'); echo \html_writer::end_tag('form'); } echo \html_writer::end_div(); if (!empty($attempts)) { echo \html_writer::start_tag('table', array('class' => 'boxaligncenter')) . \html_writer::start_tag('tr'); echo \html_writer::start_tag('td'); echo $OUTPUT->single_button(new \moodle_url($PAGE->url, array('download' => 'ODS') + $displayoptions), get_string('downloadods'), 'post', ['class' => 'm-t-1']); echo \html_writer::end_tag('td'); echo \html_writer::start_tag('td'); echo $OUTPUT->single_button(new \moodle_url($PAGE->url, array('download' => 'Excel') + $displayoptions), get_string('downloadexcel'), 'post', ['class' => 'm-t-1']); echo \html_writer::end_tag('td'); echo \html_writer::start_tag('td'); echo $OUTPUT->single_button(new \moodle_url($PAGE->url, array('download' => 'CSV') + $displayoptions), get_string('downloadtext'), 'post', ['class' => 'm-t-1']); echo \html_writer::end_tag('td'); echo \html_writer::start_tag('td'); echo \html_writer::end_tag('td'); echo \html_writer::end_tag('tr') . \html_writer::end_tag('table'); } } } else { if ($candelete && !$download) { echo \html_writer::end_div(); echo \html_writer::end_tag('form'); $table->finish_output(); } echo \html_writer::end_div(); } // Show preferences form irrespective of attempts are there to report or not. if (!$download) { $mform->set_data(compact('detailedrep', 'pagesize', 'attemptsmode')); $mform->display(); } if ($download == 'Excel' or $download == 'ODS') { $workbook->close(); exit; } else { if ($download == 'CSV') { $csvexport->download_file(); exit; } } } else { echo $OUTPUT->notification(get_string('noactivity', 'scorm')); } }
$event->add_record_snapshot('course_modules', $cm); $event->add_record_snapshot('scorm', $scorm); $event->add_record_snapshot('scorm_scoes', $sco); $event->trigger(); header('Content-Type: text/html; charset=UTF-8'); if ($sco->scormtype == 'asset') { // HTTP 302 Found => Moved Temporarily. header('Location: ' . $result); // Provide a short feedback in case of slow network connection. echo html_writer::start_tag('html'); echo html_writer::tag('body', html_writer::tag('p', get_string('activitypleasewait', 'scorm'))); echo html_writer::end_tag('html'); exit; } // We expect a SCO: select which API are we looking for. $lmsapi = scorm_version_check($scorm->version, SCORM_12) || empty($scorm->version) ? 'API' : 'API_1484_11'; echo html_writer::start_tag('html'); echo html_writer::start_tag('head'); echo html_writer::tag('title', 'LoadSCO'); ?> <script type="text/javascript"> //<![CDATA[ var myApiHandle = null; var myFindAPITries = 0; function myGetAPIHandle() { myFindAPITries = 0; if (myApiHandle == null) { myApiHandle = myGetAPI(); } return myApiHandle;
print_error('invalidcoursemodule'); } } else { print_error('missingparameter'); } $url = new moodle_url('/mod/scorm/loaddatamodel.php', array('scoid'=>$scoid, 'id'=>$cm->id, 'attempt'=>$attempt)); if ($mode !== '') { $url->param('mode', $mode); } $PAGE->set_url($url); require_login($course, false, $cm); if ($usertrack = scorm_get_tracks($scoid, $USER->id, $attempt)) { if ((isset($usertrack->{'cmi.exit'}) && ($usertrack->{'cmi.exit'} != 'time-out')) || (!scorm_version_check($scorm->version, SCORM_13))) { foreach ($usertrack as $key => $value) { $userdata->$key = addslashes_js($value); } } else { $userdata->status = ''; $userdata->score_raw = ''; } } else { $userdata->status = ''; $userdata->score_raw = ''; } $userdata->student_id = addslashes_js($USER->username); $userdata->student_name = addslashes_js($USER->lastname .', '. $USER->firstname); $userdata->mode = 'normal'; if (isset($mode)) {
/** * displays the full report * @param stdClass $scorm full SCORM object * @param stdClass $cm - full course_module object * @param stdClass $course - full course object * @param string $download - type of download being requested */ function display($scorm, $cm, $course, $download) { global $CFG, $DB, $OUTPUT, $PAGE; $contextmodule = context_module::instance($cm->id); $action = optional_param('action', '', PARAM_ALPHA); $attemptids = optional_param_array('attemptid', array(), PARAM_RAW); $attemptsmode = optional_param('attemptsmode', SCORM_REPORT_ATTEMPTS_ALL_STUDENTS, PARAM_INT); $PAGE->set_url(new moodle_url($PAGE->url, array('attemptsmode' => $attemptsmode))); if ($action == 'delete' && has_capability('mod/scorm:deleteresponses', $contextmodule) && confirm_sesskey()) { if (scorm_delete_responses($attemptids, $scorm)) { //delete responses. add_to_log($course->id, 'scorm', 'delete attempts', 'report.php?id=' . $cm->id, implode(",", $attemptids), $cm->id); echo $OUTPUT->notification(get_string('scormresponsedeleted', 'scorm'), 'notifysuccess'); } } // find out current groups mode $currentgroup = groups_get_activity_group($cm, true); // detailed report $mform = new mod_scorm_report_settings($PAGE->url, compact('currentgroup')); if ($fromform = $mform->get_data()) { $detailedrep = $fromform->detailedrep; $pagesize = $fromform->pagesize; set_user_preference('scorm_report_detailed', $detailedrep); set_user_preference('scorm_report_pagesize', $pagesize); } else { $detailedrep = get_user_preferences('scorm_report_detailed', false); $pagesize = get_user_preferences('scorm_report_pagesize', 0); } if ($pagesize < 1) { $pagesize = SCORM_REPORT_DEFAULT_PAGE_SIZE; } // select group menu $displayoptions = array(); $displayoptions['attemptsmode'] = $attemptsmode; if ($groupmode = groups_get_activity_groupmode($cm)) { // Groups are being used if (!$download) { groups_print_activity_menu($cm, new moodle_url($PAGE->url, $displayoptions)); } } // We only want to show the checkbox to delete attempts // if the user has permissions and if the report mode is showing attempts. $candelete = has_capability('mod/scorm:deleteresponses', $contextmodule) && $attemptsmode != SCORM_REPORT_ATTEMPTS_STUDENTS_WITH_NO; // select the students $nostudents = false; if (empty($currentgroup)) { // all users who can attempt scoes if (!($students = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', 'u.id', '', '', '', '', '', false))) { echo $OUTPUT->notification(get_string('nostudentsyet')); $nostudents = true; $allowedlist = ''; } else { $allowedlist = array_keys($students); } unset($students); } else { // all users who can attempt scoes and who are in the currently selected group if (!($groupstudents = get_users_by_capability($contextmodule, 'mod/scorm:savetrack', 'u.id', '', '', '', $currentgroup, '', false))) { echo $OUTPUT->notification(get_string('nostudentsingroup')); $nostudents = true; $groupstudents = array(); } $allowedlist = array_keys($groupstudents); unset($groupstudents); } if (!$nostudents) { // Now check if asked download of data $coursecontext = context_course::instance($course->id); if ($download) { $shortname = format_string($course->shortname, true, array('context' => $coursecontext)); $filename = clean_filename("{$shortname} " . format_string($scorm->name, true)); } // Define table columns $columns = array(); $headers = array(); if (!$download && $candelete) { $columns[] = 'checkbox'; $headers[] = null; } if (!$download && $CFG->grade_report_showuserimage) { $columns[] = 'picture'; $headers[] = ''; } $columns[] = 'fullname'; $headers[] = get_string('name'); $extrafields = get_extra_user_fields($coursecontext); foreach ($extrafields as $field) { $columns[] = $field; $headers[] = get_user_field_name($field); } $columns[] = 'attempt'; $headers[] = get_string('attempt', 'scorm'); $columns[] = 'start'; $headers[] = get_string('started', 'scorm'); $columns[] = 'finish'; $headers[] = get_string('last', 'scorm'); $columns[] = 'score'; $headers[] = get_string('score', 'scorm'); if ($detailedrep && ($scoes = $DB->get_records('scorm_scoes', array("scorm" => $scorm->id), 'sortorder, id'))) { foreach ($scoes as $sco) { if ($sco->launch != '') { $columns[] = 'scograde' . $sco->id; $headers[] = format_string($sco->title); } } } else { $scoes = null; } if (!$download) { $table = new flexible_table('mod-scorm-report'); $table->define_columns($columns); $table->define_headers($headers); $table->define_baseurl($PAGE->url); $table->sortable(true); $table->collapsible(true); // This is done to prevent redundant data, when a user has multiple attempts $table->column_suppress('picture'); $table->column_suppress('fullname'); foreach ($extrafields as $field) { $table->column_suppress($field); } $table->no_sorting('start'); $table->no_sorting('finish'); $table->no_sorting('score'); if ($scoes) { foreach ($scoes as $sco) { if ($sco->launch != '') { $table->no_sorting('scograde' . $sco->id); } } } $table->column_class('picture', 'picture'); $table->column_class('fullname', 'bold'); $table->column_class('score', 'bold'); $table->set_attribute('cellspacing', '0'); $table->set_attribute('id', 'attempts'); $table->set_attribute('class', 'generaltable generalbox'); // Start working -- this is necessary as soon as the niceties are over $table->setup(); } else { if ($download == 'ODS') { require_once "{$CFG->libdir}/odslib.class.php"; $filename .= ".ods"; // Creating a workbook $workbook = new MoodleODSWorkbook("-"); // Sending HTTP headers $workbook->send($filename); // Creating the first worksheet $sheettitle = get_string('report', 'scorm'); $myxls = $workbook->add_worksheet($sheettitle); // format types $format = $workbook->add_format(); $format->set_bold(0); $formatbc = $workbook->add_format(); $formatbc->set_bold(1); $formatbc->set_align('center'); $formatb = $workbook->add_format(); $formatb->set_bold(1); $formaty = $workbook->add_format(); $formaty->set_bg_color('yellow'); $formatc = $workbook->add_format(); $formatc->set_align('center'); $formatr = $workbook->add_format(); $formatr->set_bold(1); $formatr->set_color('red'); $formatr->set_align('center'); $formatg = $workbook->add_format(); $formatg->set_bold(1); $formatg->set_color('green'); $formatg->set_align('center'); // Here starts workshhet headers $colnum = 0; foreach ($headers as $item) { $myxls->write(0, $colnum, $item, $formatbc); $colnum++; } $rownum = 1; } else { if ($download == 'Excel') { require_once "{$CFG->libdir}/excellib.class.php"; $filename .= ".xls"; // Creating a workbook $workbook = new MoodleExcelWorkbook("-"); // Sending HTTP headers $workbook->send($filename); // Creating the first worksheet $sheettitle = get_string('report', 'scorm'); $myxls = $workbook->add_worksheet($sheettitle); // format types $format = $workbook->add_format(); $format->set_bold(0); $formatbc = $workbook->add_format(); $formatbc->set_bold(1); $formatbc->set_align('center'); $formatb = $workbook->add_format(); $formatb->set_bold(1); $formaty = $workbook->add_format(); $formaty->set_bg_color('yellow'); $formatc = $workbook->add_format(); $formatc->set_align('center'); $formatr = $workbook->add_format(); $formatr->set_bold(1); $formatr->set_color('red'); $formatr->set_align('center'); $formatg = $workbook->add_format(); $formatg->set_bold(1); $formatg->set_color('green'); $formatg->set_align('center'); $colnum = 0; foreach ($headers as $item) { $myxls->write(0, $colnum, $item, $formatbc); $colnum++; } $rownum = 1; } else { if ($download == 'CSV') { $csvexport = new csv_export_writer("tab"); $csvexport->set_filename($filename, ".txt"); $csvexport->add_data($headers); } } } } $params = array(); list($usql, $params) = $DB->get_in_or_equal($allowedlist, SQL_PARAMS_NAMED); // Construct the SQL $select = 'SELECT DISTINCT ' . $DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)') . ' AS uniqueid, '; $select .= 'st.scormid AS scormid, st.attempt AS attempt, ' . user_picture::fields('u', array('idnumber'), 'userid') . get_extra_user_fields_sql($coursecontext, 'u', '', array('email', 'idnumber')) . ' '; // This part is the same for all cases - join users and scorm_scoes_track tables $from = 'FROM {user} u '; $from .= 'LEFT JOIN {scorm_scoes_track} st ON st.userid = u.id AND st.scormid = ' . $scorm->id; switch ($attemptsmode) { case SCORM_REPORT_ATTEMPTS_STUDENTS_WITH: // Show only students with attempts $where = ' WHERE u.id ' . $usql . ' AND st.userid IS NOT NULL'; break; case SCORM_REPORT_ATTEMPTS_STUDENTS_WITH_NO: // Show only students without attempts $where = ' WHERE u.id ' . $usql . ' AND st.userid IS NULL'; break; case SCORM_REPORT_ATTEMPTS_ALL_STUDENTS: // Show all students with or without attempts $where = ' WHERE u.id ' . $usql . ' AND (st.userid IS NOT NULL OR st.userid IS NULL)'; break; } $countsql = 'SELECT COUNT(DISTINCT(' . $DB->sql_concat('u.id', '\'#\'', 'COALESCE(st.attempt, 0)') . ')) AS nbresults, '; $countsql .= 'COUNT(DISTINCT(' . $DB->sql_concat('u.id', '\'#\'', 'st.attempt') . ')) AS nbattempts, '; $countsql .= 'COUNT(DISTINCT(u.id)) AS nbusers '; $countsql .= $from . $where; if (!$download) { $sort = $table->get_sql_sort(); } else { $sort = ''; } // Fix some wired sorting if (empty($sort)) { $sort = ' ORDER BY uniqueid'; } else { $sort = ' ORDER BY ' . $sort; } if (!$download) { // Add extra limits due to initials bar list($twhere, $tparams) = $table->get_sql_where(); if ($twhere) { $where .= ' AND ' . $twhere; //initial bar $params = array_merge($params, $tparams); } if (!empty($countsql)) { $count = $DB->get_record_sql($countsql, $params); $totalinitials = $count->nbresults; if ($twhere) { $countsql .= ' AND ' . $twhere; } $count = $DB->get_record_sql($countsql, $params); $total = $count->nbresults; } $table->pagesize($pagesize, $total); echo '<div class="quizattemptcounts">'; if ($count->nbresults == $count->nbattempts) { echo get_string('reportcountattempts', 'scorm', $count); } else { if ($count->nbattempts > 0) { echo get_string('reportcountallattempts', 'scorm', $count); } else { echo $count->nbusers . ' ' . get_string('users'); } } echo '</div>'; } // Fetch the attempts if (!$download) { $attempts = $DB->get_records_sql($select . $from . $where . $sort, $params, $table->get_page_start(), $table->get_page_size()); echo '<div id="scormtablecontainer">'; if ($candelete) { // Start form $strreallydel = addslashes_js(get_string('deleteattemptcheck', 'scorm')); echo '<form id="attemptsform" method="post" action="' . $PAGE->url->out(false) . '" onsubmit="return confirm(\'' . $strreallydel . '\');">'; echo '<input type="hidden" name="action" value="delete"/>'; echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />'; echo '<div style="display: none;">'; echo html_writer::input_hidden_params($PAGE->url); echo '</div>'; echo '<div>'; } $table->initialbars($totalinitials > 20); // Build table rows } else { $attempts = $DB->get_records_sql($select . $from . $where . $sort, $params); } if ($attempts) { foreach ($attempts as $scouser) { $row = array(); if (!empty($scouser->attempt)) { $timetracks = scorm_get_sco_runtime($scorm->id, false, $scouser->userid, $scouser->attempt); } else { $timetracks = ''; } if (in_array('checkbox', $columns)) { if ($candelete && !empty($timetracks->start)) { $row[] = '<input type="checkbox" name="attemptid[]" value="' . $scouser->userid . ':' . $scouser->attempt . '" />'; } else { if ($candelete) { $row[] = ''; } } } if (in_array('picture', $columns)) { $user = (object) array('id' => $scouser->userid, 'picture' => $scouser->picture, 'imagealt' => $scouser->imagealt, 'email' => $scouser->email); foreach (get_all_user_name_fields() as $addname) { $user->{$addname} = $scouser->{$addname}; } $row[] = $OUTPUT->user_picture($user, array('courseid' => $course->id)); } if (!$download) { $row[] = '<a href="' . $CFG->wwwroot . '/user/view.php?id=' . $scouser->userid . '&course=' . $course->id . '">' . fullname($scouser) . '</a>'; } else { $row[] = fullname($scouser); } foreach ($extrafields as $field) { $row[] = s($scouser->{$field}); } if (empty($timetracks->start)) { $row[] = '-'; $row[] = '-'; $row[] = '-'; $row[] = '-'; } else { if (!$download) { $row[] = '<a href="' . $CFG->wwwroot . '/mod/scorm/report/userreport.php?id=' . $cm->id . '&user='******'&attempt=' . $scouser->attempt . '">' . $scouser->attempt . '</a>'; } else { $row[] = $scouser->attempt; } if ($download == 'ODS' || $download == 'Excel') { $row[] = userdate($timetracks->start, get_string("strftimedatetime", "langconfig")); } else { $row[] = userdate($timetracks->start); } if ($download == 'ODS' || $download == 'Excel') { $row[] = userdate($timetracks->finish, get_string('strftimedatetime', 'langconfig')); } else { $row[] = userdate($timetracks->finish); } $row[] = scorm_grade_user_attempt($scorm, $scouser->userid, $scouser->attempt); } // print out all scores of attempt if ($scoes) { foreach ($scoes as $sco) { if ($sco->launch != '') { if ($trackdata = scorm_get_tracks($sco->id, $scouser->userid, $scouser->attempt)) { if ($trackdata->status == '') { $trackdata->status = 'notattempted'; } $strstatus = get_string($trackdata->status, 'scorm'); // if raw score exists, print it if ($trackdata->score_raw != '') { $score = $trackdata->score_raw; // add max score if it exists if (scorm_version_check($scorm->version, SCORM_13)) { $maxkey = 'cmi.score.max'; } else { $maxkey = 'cmi.core.score.max'; } if (isset($trackdata->{$maxkey})) { $score .= '/' . $trackdata->{$maxkey}; } // else print out status } else { $score = $strstatus; } if (!$download) { $row[] = '<img src="' . $OUTPUT->pix_url($trackdata->status, 'scorm') . '" alt="' . $strstatus . '" title="' . $strstatus . '" /><br/> <a href="' . $CFG->wwwroot . '/mod/scorm/report/userreporttracks.php?id=' . $cm->id . '&scoid=' . $sco->id . '&user='******'&attempt=' . $scouser->attempt . '" title="' . get_string('details', 'scorm') . '">' . $score . '</a>'; } else { $row[] = $score; } } else { // if we don't have track data, we haven't attempted yet $strstatus = get_string('notattempted', 'scorm'); if (!$download) { $row[] = '<img src="' . $OUTPUT->pix_url('notattempted', 'scorm') . '" alt="' . $strstatus . '" title="' . $strstatus . '" /><br/>' . $strstatus; } else { $row[] = $strstatus; } } } } } if (!$download) { $table->add_data($row); } else { if ($download == 'Excel' or $download == 'ODS') { $colnum = 0; foreach ($row as $item) { $myxls->write($rownum, $colnum, $item, $format); $colnum++; } $rownum++; } else { if ($download == 'CSV') { $csvexport->add_data($row); } } } } if (!$download) { $table->finish_output(); if ($candelete) { echo '<table id="commands">'; echo '<tr><td>'; echo '<a href="javascript:select_all_in(\'DIV\', null, \'scormtablecontainer\');">' . get_string('selectall', 'scorm') . '</a> / '; echo '<a href="javascript:deselect_all_in(\'DIV\', null, \'scormtablecontainer\');">' . get_string('selectnone', 'scorm') . '</a> '; echo ' '; echo '<input type="submit" value="' . get_string('deleteselected', 'quiz_overview') . '"/>'; echo '</td></tr></table>'; // Close form echo '</div>'; echo '</form>'; } echo '</div>'; if (!empty($attempts)) { echo '<table class="boxaligncenter"><tr>'; echo '<td>'; echo $OUTPUT->single_button(new moodle_url($PAGE->url, array('download' => 'ODS') + $displayoptions), get_string('downloadods')); echo "</td>\n"; echo '<td>'; echo $OUTPUT->single_button(new moodle_url($PAGE->url, array('download' => 'Excel') + $displayoptions), get_string('downloadexcel')); echo "</td>\n"; echo '<td>'; echo $OUTPUT->single_button(new moodle_url($PAGE->url, array('download' => 'CSV') + $displayoptions), get_string('downloadtext')); echo "</td>\n"; echo "<td>"; echo "</td>\n"; echo '</tr></table>'; } } } else { if ($candelete && !$download) { echo '</div>'; echo '</form>'; $table->finish_output(); } echo '</div>'; } // Show preferences form irrespective of attempts are there to report or not if (!$download) { $mform->set_data(compact('detailedrep', 'pagesize', 'attemptsmode')); $mform->display(); } if ($download == 'Excel' or $download == 'ODS') { $workbook->close(); exit; } else { if ($download == 'CSV') { $csvexport->download_file(); exit; } } } else { echo $OUTPUT->notification(get_string('noactivity', 'scorm')); } }
+ ' onclick="tryLMSGetErrorString();"' + ' id="getErrorStringButton"' + ' name="getErrorStringButton">' + ' <input type="button"' + ' value="<?php echo $LMS_prefix; ?>GetDiagnostic() "' + ' onclick="tryLMSGetDiagnostic();"' + ' id="getDiagnosticButton"' + ' name="getDiagnosticButton">' + ' <input type="button"' + ' value="<?php echo $LMS_prefix; ?>Commit() "' + ' onclick="tryLMSCommit();"' + ' id="commitButton"' + ' name="commitButton">' + ' <input type="button"' + ' value="<?php echo scorm_version_check($scorm->version, SCORM_12) ? 'LMSFinish' : 'Terminate'; ?>() "' + ' onclick="try<?php echo scorm_version_check($scorm->version, SCORM_12) ? 'LMSFinish' : 'LMSTerminate'; ?>();"' + ' id="finishButton"' + ' name="finishButton">' + ' </td>' + ' </tr>' + ' <tr>' + ' <td>' + ' <label>Result: </label><br />' + ' <textarea name="msgtxt" id="msgtxt" rows="2" cols="150" wrap="VIRTUAL" readonly>None</textarea>' + ' </td>' + ' </tr>' + ' </table>' + '</form>' + '<h3 id="mod-scorm-marker">SCORM API Activity Log<\/h3>'; // Is logging active?
function scorm_format_toc_for_treeview($user, $scorm, $scoes, $usertracks, $cmid, $toclink=TOCJSLINK, $currentorg='', $attempt='', $play=false, $organizationsco=null, $children=false) { global $CFG; $result = new stdClass(); $result->prerequisites = true; $result->incomplete = true; $result->toc = ''; if (!$children) { $attemptsmade = scorm_get_attempt_count($user->id, $scorm); $result->attemptleft = $scorm->maxattempt == 0 ? 1 : $scorm->maxattempt - $attemptsmade; } if (!$children) { $result->toc = html_writer::start_tag('ul'); if (!$play && !empty($organizationsco)) { $result->toc .= html_writer::start_tag('li').$organizationsco->title.html_writer::end_tag('li'); } } $prevsco = ''; if (!empty($scoes)) { foreach ($scoes as $sco) { $result->toc .= html_writer::start_tag('li'); $scoid = $sco->id; $sco->isvisible = true; if ($sco->isvisible) { $score = ''; if (isset($usertracks[$sco->identifier])) { $viewscore = has_capability('mod/scorm:viewscores', context_module::instance($cmid)); if (isset($usertracks[$sco->identifier]->score_raw) && $viewscore) { if ($usertracks[$sco->identifier]->score_raw != '') { $score = '('.get_string('score', 'scorm').': '.$usertracks[$sco->identifier]->score_raw.')'; } } } if (!empty($sco->prereq)) { if ($sco->id == $scoid) { $result->prerequisites = true; } if (!empty($prevsco) && scorm_version_check($scorm->version, SCORM_13) && !empty($prevsco->hidecontinue)) { if ($sco->scormtype == 'sco') { $result->toc .= html_writer::span($sco->statusicon.' '.format_string($sco->title)); } else { $result->toc .= html_writer::span(' '.format_string($sco->title)); } } else if ($toclink == TOCFULLURL) { $url = $CFG->wwwroot.'/mod/scorm/player.php?'.$sco->url; if (!empty($sco->launch)) { if ($sco->scormtype == 'sco') { $result->toc .= $sco->statusicon.' '; $result->toc .= html_writer::link($url, format_string($sco->title)).$score; } else { $result->toc .= ' '.html_writer::link($url, format_string($sco->title), array('data-scoid' => $sco->id)).$score; } } else { if ($sco->scormtype == 'sco') { $result->toc .= $sco->statusicon.' '.format_string($sco->title).$score; } else { $result->toc .= ' '.format_string($sco->title).$score; } } } else { if (!empty($sco->launch)) { if ($sco->scormtype == 'sco') { $result->toc .= html_writer::tag('a', $sco->statusicon.' '. format_string($sco->title).' '.$score, array('data-scoid' => $sco->id, 'title' => $sco->url)); } else { $result->toc .= html_writer::tag('a', ' '.format_string($sco->title).' '.$score, array('data-scoid' => $sco->id, 'title' => $sco->url)); } } else { if ($sco->scormtype == 'sco') { $result->toc .= html_writer::span($sco->statusicon.' '.format_string($sco->title)); } else { $result->toc .= html_writer::span(' '.format_string($sco->title)); } } } } else { if ($play) { if ($sco->scormtype == 'sco') { $result->toc .= html_writer::span($sco->statusicon.' '.format_string($sco->title)); } else { $result->toc .= ' '.format_string($sco->title).html_writer::end_span(); } } else { if ($sco->scormtype == 'sco') { $result->toc .= $sco->statusicon.' '.format_string($sco->title); } else { $result->toc .= ' '.format_string($sco->title); } } } } else { $result->toc .= " ".format_string($sco->title); } if (!empty($sco->children)) { $result->toc .= html_writer::start_tag('ul'); $childresult = scorm_format_toc_for_treeview($user, $scorm, $sco->children, $usertracks, $cmid, $toclink, $currentorg, $attempt, $play, $organizationsco, true); $result->toc .= $childresult->toc; $result->toc .= html_writer::end_tag('ul'); $result->toc .= html_writer::end_tag('li'); } else { $result->toc .= html_writer::end_tag('li'); } $prevsco = $sco; } $result->incomplete = $sco->incomplete; } if (!$children) { $result->toc .= html_writer::end_tag('ul'); } return $result; }