From: piers Date: Sat, 29 Nov 2008 17:51:47 +0000 (+0000) Subject: MDL-16651 - add in delete attempt capability - thanks Dan/Tim. X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=7554f67190345190e1bb879056970026585bceef;p=moodle.git MDL-16651 - add in delete attempt capability - thanks Dan/Tim. --- diff --git a/lang/en_utf8/scorm.php b/lang/en_utf8/scorm.php index 4b01d1e458..721aaba99d 100644 --- a/lang/en_utf8/scorm.php +++ b/lang/en_utf8/scorm.php @@ -1,4 +1,4 @@ - \ No newline at end of file diff --git a/mod/scorm/db/access.php b/mod/scorm/db/access.php index 3f4a7dfbfe..173bf64f2c 100644 --- a/mod/scorm/db/access.php +++ b/mod/scorm/db/access.php @@ -75,8 +75,17 @@ $mod_scorm_capabilities = array( 'editingteacher' => CAP_ALLOW, 'admin' => CAP_ALLOW ) - ) + ), + 'mod/scorm:deleteresponses' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + 'admin' => CAP_ALLOW + ) + ) ); -?> +?> \ No newline at end of file diff --git a/mod/scorm/locallib.php b/mod/scorm/locallib.php index 56e3ff9fdd..bd80ca6ff4 100755 --- a/mod/scorm/locallib.php +++ b/mod/scorm/locallib.php @@ -26,37 +26,37 @@ define('LASTATTEMPT', '3'); /** * Returns an array of the popup options for SCORM and each options default value - * + * * @return array an array of popup options as the key and their defaults as the value */ function scorm_get_popup_options_array(){ global $CFG; $cfg_scorm = get_config('scorm'); - - return array('resizable'=> isset($cfg_scorm->resizable) ? $cfg_scorm->resizable : 0, - 'scrollbars'=> isset($cfg_scorm->scrollbars) ? $cfg_scorm->scrollbars : 0, - 'directories'=> isset($cfg_scorm->directories) ? $cfg_scorm->directories : 0, + + return array('resizable'=> isset($cfg_scorm->resizable) ? $cfg_scorm->resizable : 0, + 'scrollbars'=> isset($cfg_scorm->scrollbars) ? $cfg_scorm->scrollbars : 0, + 'directories'=> isset($cfg_scorm->directories) ? $cfg_scorm->directories : 0, 'location'=> isset($cfg_scorm->location) ? $cfg_scorm->location : 0, - 'menubar'=> isset($cfg_scorm->menubar) ? $cfg_scorm->menubar : 0, - 'toolbar'=> isset($cfg_scorm->toolbar) ? $cfg_scorm->toolbar : 0, - 'status'=> isset($cfg_scorm->status) ? $cfg_scorm->status : 0); + 'menubar'=> isset($cfg_scorm->menubar) ? $cfg_scorm->menubar : 0, + 'toolbar'=> isset($cfg_scorm->toolbar) ? $cfg_scorm->toolbar : 0, + 'status'=> isset($cfg_scorm->status) ? $cfg_scorm->status : 0); } /** * Returns an array of the array of what grade options - * + * * @return array an array of what grade options */ function scorm_get_grade_method_array(){ return array (GRADESCOES => get_string('gradescoes', 'scorm'), GRADEHIGHEST => get_string('gradehighest', 'scorm'), GRADEAVERAGE => get_string('gradeaverage', 'scorm'), - GRADESUM => get_string('gradesum', 'scorm')); + GRADESUM => get_string('gradesum', 'scorm')); } /** * Returns an array of the array of what grade options - * + * * @return array an array of what grade options */ function scorm_get_what_grade_array(){ @@ -68,7 +68,7 @@ function scorm_get_what_grade_array(){ /** * Returns an array of the array of skip view options - * + * * @return array an array of skip view options */ function scorm_get_skip_view_array(){ @@ -79,7 +79,7 @@ function scorm_get_skip_view_array(){ /** * Returns an array of the array of hide table of contents options - * + * * @return array an array of hide table of contents options */ function scorm_get_hidetoc_array(){ @@ -90,7 +90,7 @@ function scorm_get_hidetoc_array(){ /** * Returns an array of the array of update frequency options - * + * * @return array an array of update frequency options */ function scorm_get_updatefreq_array(){ @@ -102,7 +102,7 @@ function scorm_get_updatefreq_array(){ /** * Returns an array of the array of popup display options - * + * * @return array an array of popup display options */ function scorm_get_popup_display_array(){ @@ -112,17 +112,17 @@ function scorm_get_popup_display_array(){ /** * Returns an array of the array of attempt options - * + * * @return array an array of attempt options */ function scorm_get_attempts_array(){ $attempts = array(0 => get_string('nolimit','scorm'), 1 => get_string('attempt1','scorm')); - + for ($i=2; $i<=6; $i++) { $attempts[$i] = get_string('attemptsx','scorm', $i); } - + return $attempts; } /** @@ -732,10 +732,10 @@ function scorm_view_display ($user, $scorm, $action, $cm, $boxwidth='') { echo $result->toc; print_simple_box_end(); } - + // is this the first attempt ? $attemptcount = scorm_get_attempt_count($user, $scorm); - + // do not give the player launch FORM if the SCORM object is locked after the final attempt if ($scorm->lastattemptlock == 0 || $result->attemptleft > 0) { ?> @@ -845,7 +845,7 @@ function scorm_get_count_users($scormid, $groupingid=null) { * @param string $element_name Name of array element to get values for * @param array $children list of sub elements of this array element that also need instantiating * @return None -*/ +*/ function scorm_reconstitute_array_element($sversion, $userdata, $element_name, $children) { // reconstitute comments_from_learner and comments_from_lms $current = ''; @@ -853,7 +853,7 @@ function scorm_reconstitute_array_element($sversion, $userdata, $element_name, $ $current_sub = ''; $count = 0; $count_sub = 0; - + // filter out the ones we want $element_list = array(); foreach($userdata as $element => $value){ @@ -861,10 +861,10 @@ function scorm_reconstitute_array_element($sversion, $userdata, $element_name, $ $element_list[$element] = $value; } } - + // sort elements in .n array order uksort($element_list, "scorm_element_cmp"); - + // generate JavaScript foreach($element_list as $element => $value){ if ($sversion == 'scorm_13') { @@ -878,7 +878,7 @@ function scorm_reconstitute_array_element($sversion, $userdata, $element_name, $ if ($count_sub > 0) { echo ' '.$element_name.'_'.$current.'.'.$current_subelement.'._count = '.$count_sub.";\n"; } - $current = $matches[1]; + $current = $matches[1]; $count++; $current_subelement = ''; $current_sub = ''; @@ -892,7 +892,7 @@ function scorm_reconstitute_array_element($sversion, $userdata, $element_name, $ echo ' '.$subelement.".".$child."._children = ".$child."_children;\n"; } } - + // now - flesh out the second level elements if there are any if ($sversion == 'scorm_13') { $element = preg_replace('/(.*?\.N\d+\..*?)\.(\d+)\./', "\$1.N\$2.", $element); @@ -901,7 +901,7 @@ function scorm_reconstitute_array_element($sversion, $userdata, $element_name, $ $element = preg_replace('/(.*?\_\d+\..*?)\.(\d+)\./', "\$1_\$2.", $element); preg_match('/.*?\_\d+\.(.*?)\_(\d+)\./', $element, $matches); } - + // check the sub element type if (count($matches) > 0 && $current_subelement != $matches[1]) { if ($count_sub > 0) { @@ -914,16 +914,16 @@ function scorm_reconstitute_array_element($sversion, $userdata, $element_name, $ $subelement = substr($element,0,$end); echo ' '.$subelement." = new Object();\n"; } - + // now check the subelement subscript if (count($matches) > 0 && $current_sub != $matches[2]) { - $current_sub = $matches[2]; + $current_sub = $matches[2]; $count_sub++; $end = strrpos($element,$matches[2])+strlen($matches[2]); $subelement = substr($element,0,$end); echo ' '.$subelement." = new Object();\n"; } - + echo ' '.$element.' = \''.$value."';\n"; } if ($count_sub > 0) { @@ -940,7 +940,7 @@ function scorm_reconstitute_array_element($sversion, $userdata, $element_name, $ * @param string $a left array element * @param string $b right array element * @return comparator - 0,1,-1 -*/ +*/ function scorm_element_cmp($a, $b) { preg_match('/.*?(\d+)\./', $a, $matches); $left = intval($matches[1]); @@ -982,17 +982,17 @@ function scorm_element_cmp($a, $b) { * @param object $user Current context user * @param object $scorm a moodle scrom object - mdl_scorm * @return string - Attempt status string -*/ +*/ function scorm_get_attempt_status($user, $scorm) { global $DB; - + $attempts = $DB->get_records_select('scorm_scoes_track',"element='cmi.core.score.raw' AND userid=? AND scormid=?", array($user->id, $scorm->id),'attempt','attempt AS attemptnumber, value AS grade'); if(empty($attempts)) { $attemptcount = 0; } else { $attemptcount = count($attempts); } - + $result = '

'.get_string('noattemptsallowed', 'scorm').': '; if ($scorm->maxattempt > 0) { $result .= $scorm->maxattempt . '
'; @@ -1017,7 +1017,7 @@ function scorm_get_attempt_status($user, $scorm) { $grademethod = get_string('gradescoes', 'scorm'); break; } - + if(!empty($attempts)) { foreach($attempts as $attempt) { $gradereported = scorm_grade_user_attempt($scorm, $user->id, $attempt->attemptnumber); @@ -1044,7 +1044,7 @@ function scorm_get_attempt_status($user, $scorm) { * @param object $user Current context user * @param object $scorm a moodle scrom object - mdl_scorm * @return int - no. of attempts so far -*/ +*/ function scorm_get_attempt_count($user, $scorm) { global $DB; $attemptcount = 0; @@ -1064,11 +1064,11 @@ function scorm_get_attempt_count($user, $scorm) { * * @param object $scorm a moodle scrom object - mdl_scorm * @return boolean - debugging true/false -*/ +*/ function scorm_debugging($scorm) { global $CFG, $USER; $cfg_scorm = get_config('scorm'); - + if (!$cfg_scorm->allowapidebug) { return false; } @@ -1082,4 +1082,54 @@ function scorm_debugging($scorm) { eval('$res = preg_match(\'/^'.$test.'/\', $identifier) ? true : false;'); return $res; } + +/** +* Delete Scorm tracks for selected users +* +* @param array $attemptids list of attempts that need to be deleted +* @param int $scormid ID of Scorm +* +* return bool true deleted all responses, false failed deleting an attempt - stopped here +*/ +function scorm_delete_responses($attemptids, $scormid) { + if(!is_array($attemptids) || empty($attemptids)) { + return false; + } + + foreach($attemptids as $num => $attemptid) { + if(empty($attemptid)) { + unset($attemptids[$num]); + } + } + + foreach($attemptids as $attempt) { + $keys = explode(':', $attempt); + if (count($keys) == 2) { + $userid = clean_param($keys[0], PARAM_INT); + $attemptid = clean_param($keys[1], PARAM_INT); + if (!$userid || !$attemptid || !scorm_delete_attempt($userid, $scormid, $attemptid)) { + return false; + } + } else { + return false; + } + } + return true; +} + +/** +* Delete Scorm tracks for selected users +* +* @param int $userid ID of User +* @param int $scormid ID of Scorm +* @param int $attemptid user attempt that need to be deleted +* +* return bool true suceeded +*/ +function scorm_delete_attempt($userid, $scormid, $attemptid) { + global $DB; + + $DB->delete_records('scorm_scoes_track', array('userid' => $userid, 'scormid' => $scormid, 'attempt' => $attemptid)); + return true; +} ?> \ No newline at end of file diff --git a/mod/scorm/report.php b/mod/scorm/report.php index 096940624c..02155de764 100755 --- a/mod/scorm/report.php +++ b/mod/scorm/report.php @@ -10,6 +10,8 @@ $b = optional_param('b', '', PARAM_INT); // SCO ID $user = optional_param('user', '', PARAM_INT); // User ID $attempt = optional_param('attempt', '1', PARAM_INT); // attempt number + $action = optional_param('action', '', PARAM_ALPHA); + $attemptids = optional_param('attemptid', array(), PARAM_RAW); //get array of responses to delete. if (!empty($id)) { if (! $cm = get_coursemodule_from_id('scorm', $id)) { @@ -43,9 +45,9 @@ require_login($course->id, false, $cm); - if (!has_capability('mod/scorm:viewreport', get_context_instance(CONTEXT_MODULE,$cm->id))) { - print_error('cannotcallscript'); - } + $contextmodule = get_context_instance(CONTEXT_MODULE,$cm->id); + + require_capability('mod/scorm:viewreport', $contextmodule); add_to_log($course->id, 'scorm', 'report', 'report.php?id='.$cm->id, $scorm->id, $cm->id); @@ -63,67 +65,86 @@ $strreport = get_string('report', 'scorm'); $strattempt = get_string('attempt', 'scorm'); $strname = get_string('name'); - + if (empty($b)) { if (empty($a)) { $navigation = build_navigation('', $cm); print_header("$course->shortname: ".format_string($scorm->name), $course->fullname,$navigation, '', '', true); } else { - + $navlinks = array(); - $navlinks[] = array('name' => $strreport, 'link' => "report.php?id=$cm->id", 'type' => 'title'); + $navlinks[] = array('name' => $strreport, 'link' => "report.php?id=$cm->id", 'type' => 'title'); $navlinks[] = array('name' => "$strattempt $attempt - ".fullname($userdata), 'link' => '', 'type' => 'title'); $navigation = build_navigation($navlinks, $cm); - + print_header("$course->shortname: ".format_string($scorm->name), $course->fullname, $navigation, '', '', true); } } else { $navlinks = array(); - $navlinks[] = array('name' => $strreport, 'link' => "report.php?id=$cm->id", 'type' => 'title'); + $navlinks[] = array('name' => $strreport, 'link' => "report.php?id=$cm->id", 'type' => 'title'); $navlinks[] = array('name' => "$strattempt $attempt - ".fullname($userdata), 'link' => "report.php?a=$a&user=$user&attempt=$attempt", 'type' => 'title'); $navlinks[] = array('name' => $sco->title, 'link' => '', 'type' => 'title'); $navigation = build_navigation($navlinks, $cm); - + print_header("$course->shortname: ".format_string($scorm->name), $course->fullname, $navigation, '', '', true); } print_heading(format_string($scorm->name)); } + if ($action == 'delete' && has_capability('mod/scorm:deleteresponses',$contextmodule)) { + if (scorm_delete_responses($attemptids, $scorm->id)) { //delete responses. + notify(get_string('scormresponsedeleted', 'scorm'), 'notifysuccess'); + } + } + $scormpixdir = $CFG->modpixpath.'/scorm/pix'; if (empty($b)) { if (empty($a)) { // No options, show the global scorm report - + if (!empty($CFG->enablegroupings) && !empty($cm->groupingid)) { $sql = "SELECT st.userid, st.scormid FROM {scorm_scoes_track} st INNER JOIN {groups_members} gm ON st.userid = gm.userid - INNER JOIN {groupings_groups} gg ON gm.groupid = gg.groupid + INNER JOIN {groupings_groups} gg ON gm.groupid = gg.groupid WHERE st.scormid = ? AND gg.groupingid = ? GROUP BY st.userid,st.scormid "; $params = array($scorm->id, $cm->groupingid); } else { $sql = "SELECT st.userid, st.scormid - FROM {scorm_scoes_track} st + FROM {scorm_scoes_track} st WHERE st.scormid = ? GROUP BY st.userid,st.scormid "; $params = array($scorm->id); } - + if ($scousers=$DB->get_records_sql($sql, $params)) { $table = new stdClass(); - $table->head = array(' ', get_string('name')); - $table->align = array('center', 'left'); - $table->wrap = array('nowrap', 'nowrap'); + $table->head = array(); $table->width = '100%'; - $table->size = array(10, '*'); + if (has_capability('mod/scorm:deleteresponses',$contextmodule)) { + $table->head[] = ' '; + $table->align[] = 'center'; + $table->wrap[] = 'nowrap'; + $table->size[] = '10'; + } + + $table->head[] = ' '; + $table->align[] = 'center'; + $table->wrap[] = 'nowrap'; + $table->size[] = '10'; + + $table->head[] = get_string('name'); + $table->align[] = 'left'; + $table->wrap[] = 'nowrap'; + $table->size[] = '*'; $table->head[]= get_string('attempt','scorm'); $table->align[] = 'center'; @@ -147,25 +168,52 @@ foreach($scousers as $scouser){ $userdata = scorm_get_user_data($scouser->userid); - $attempt = scorm_get_last_attempt($scorm->id,$scouser->userid); + $attempt = scorm_get_last_attempt($scorm->id,$scouser->userid); for ($a = 1; $a<=$attempt; $a++) { $row = array(); + if (has_capability('mod/scorm:deleteresponses',$contextmodule)) { + $row[] = ''; + } $row[] = print_user_picture($scouser->userid, $course->id, $userdata->picture, false, true); $row[] = ''. fullname($userdata).''; $row[] = ''.$a.''; $select = 'scormid = ? and userid = ? and attempt = ?'; $params = array($scorm->id, $scouser->userid, $a); - $timetracks = $DB->get_record_select('scorm_scoes_track', $select, $params, 'min(timemodified) as started, max(timemodified) as last'); + $timetracks = $DB->get_record_select('scorm_scoes_track', $select, $params, 'min(timemodified) as started, max(timemodified) as last'); + // jump out here if this attempt doesnt exist + if (!$timetracks->started) { + continue; + } $row[] = userdate($timetracks->started, get_string('strftimedaydatetime')); $row[] = userdate($timetracks->last, get_string('strftimedaydatetime')); - + $row[] = scorm_grade_user_attempt($scorm, $scouser->userid, $a); $table->data[] = $row; } } + echo '

'; + if (has_capability('mod/scorm:deleteresponses',$contextmodule)) { + echo '
'; + echo ''; + print_table($table); + echo ''.get_string('selectall', 'quiz').' / '; + echo ''.get_string('selectnone', 'quiz').' '; + echo '  '; + $options = array('delete' => get_string('delete')); + echo choose_from_menu($options, 'action', '', get_string('withselected', 'quiz'), 'if(this.selectedIndex > 0) submitFormById(\'attemptsform\');', '', true); + echo ''; + echo ''; + echo '
'; + } else { + print_table($table); + } + echo '
'; + } else { + notify(get_string('noactivity', 'scorm')); } - print_table($table); } else { if (!empty($user)) { // User SCORM report @@ -233,7 +281,7 @@ if (!empty($userdata)) { print_simple_box_start('center'); //print_heading(format_string($sco->title)); - print_heading(''.format_string($sco->title).''); + print_heading(''.format_string($sco->title).''); echo '
'."\n"; print_user_picture($user, $course->id, $userdata->picture, false, false); echo "wwwroot/user/view.php?id=$user&course=$course->id\">". @@ -255,7 +303,7 @@ $strstatus.'" /> '.$trackdata->total_time.'
'.$scoreview.'
'; echo '
'."\n"; echo '

'.get_string('details','scorm').'

'; - + // Print general score data $table = new stdClass(); $table->head = array(get_string('element','scorm'), get_string('value','scorm')); @@ -263,7 +311,7 @@ $table->wrap = array('nowrap', 'nowrap'); $table->width = '100%'; $table->size = array('*', '*'); - + $existelements = false; if ($scorm->version == 'SCORM_1.3') { $elements = array('raw' => 'cmi.score.raw', @@ -292,8 +340,8 @@ if ($existelements) { echo '

'.get_string('general','scorm').'

'; print_table($table); - } - + } + // Print Interactions data $table = new stdClass(); $table->head = array(get_string('identifier','scorm'), @@ -304,12 +352,12 @@ $table->wrap = array('nowrap', 'nowrap', 'nowrap', 'nowrap'); $table->width = '100%'; $table->size = array('*', '*', '*', '*', '*'); - + $existinteraction = false; - + $i = 0; $interactionid = 'cmi.interactions.'.$i.'.id'; - + while (isset($trackdata->$interactionid)) { $existinteraction = true; $printedelements[]=$interactionid; @@ -327,7 +375,7 @@ } } $table->data[] = $row; - + $i++; $interactionid = 'cmi.interactions.'.$i.'.id'; } @@ -336,7 +384,7 @@ echo '

'.get_string('interactions','scorm').'

'; print_table($table); } - + // Print Objectives data $table = new stdClass(); $table->head = array(get_string('identifier','scorm'), @@ -348,12 +396,12 @@ $table->wrap = array('nowrap', 'nowrap', 'nowrap', 'nowrap', 'nowrap'); $table->width = '100%'; $table->size = array('*', '*', '*', '*', '*'); - + $existobjective = false; - + $i = 0; $objectiveid = 'cmi.objectives.'.$i.'.id'; - + while (isset($trackdata->$objectiveid)) { $existobjective = true; $printedelements[]=$objectiveid; @@ -372,7 +420,7 @@ } } $table->data[] = $row; - + $i++; $objectiveid = 'cmi.objectives.'.$i.'.id'; } @@ -386,11 +434,11 @@ $table->wrap = array('nowrap', 'wrap'); $table->width = '100%'; $table->size = array('*', '*'); - + $existelements = false; - + foreach($trackdata as $element => $value) { - if (substr($element,0,3) == 'cmi') { + if (substr($element,0,3) == 'cmi') { if (!(in_array ($element, $printedelements))) { $existelements = true; $row = array(); @@ -403,7 +451,7 @@ if ($existelements) { echo '

'.get_string('othertracks','scorm').'

'; print_table($table); - } + } print_simple_box_end(); } else { print_error('missingparameter'); diff --git a/mod/scorm/version.php b/mod/scorm/version.php index 163d51b9c8..fa5aed7ede 100755 --- a/mod/scorm/version.php +++ b/mod/scorm/version.php @@ -10,7 +10,7 @@ // catch up now, so until 27th October please only increment in very tiny steps // in HEAD, until we get past that date.. -$module->version = 2008090308; // The (date) version of this module +$module->version = 2008090309; // The (date) version of this module $module->requires = 2008090108; // The version of Moodle that is required $module->cron = 300; // How often should cron check this module (seconds)?