From: skodak Date: Tue, 10 Jul 2007 18:08:24 +0000 (+0000) Subject: MDL-9137 new grade_grades field overridden; item edit form fixes; other minor fixes... X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=c86caae78acd0f20494564c54cc6e9388ea37c69;p=moodle.git MDL-9137 new grade_grades field overridden; item edit form fixes; other minor fixes and improvements --- diff --git a/grade/export/lib.php b/grade/export/lib.php index 46caa062a0..d241a79f13 100755 --- a/grade/export/lib.php +++ b/grade/export/lib.php @@ -84,7 +84,7 @@ class grade_export { // first make sure we have all final grades // TODO: check that no grade_item has needsupdate set - grade_update_final_grades($id); + grade_regrade_final_grades($id); /// Check to see if groups are being used in this course if ($groupmode = groupmode($course)) { // Groups are being used diff --git a/grade/report/grader/edit_feedback_form.php b/grade/report/grader/edit_feedback_form.php index 104f556534..dbd54c565b 100644 --- a/grade/report/grader/edit_feedback_form.php +++ b/grade/report/grader/edit_feedback_form.php @@ -8,7 +8,7 @@ class edit_feedback_form extends moodleform { $mform =& $this->_form; $feedbackformat = get_user_preferences('grade_report_feedbackformat', $CFG->grade_report_feedbackformat); - + // visible elements // User preference determines the format if ($CFG->htmleditor && $USER->htmleditor && $feedbackformat == GRADER_REPORT_FEEDBACK_FORMAT_HTML) { diff --git a/grade/report/grader/edit_item.php b/grade/report/grader/edit_item.php index 9448e019e3..d42429eea3 100644 --- a/grade/report/grader/edit_item.php +++ b/grade/report/grader/edit_item.php @@ -31,10 +31,6 @@ if ($mform->is_cancelled()) { redirect($returnurl); } else if ($data = $mform->get_data()) { - if (empty($data->checkbox)) { - $data->checkbox = 0; // work around the missing value if checkbox not selected - } - if (array_key_exists('calculation', $data)) { $data->calculation = grade_item::normalize_formula($data->calculation, $course->id); } diff --git a/grade/report/grader/edit_item_form.php b/grade/report/grader/edit_item_form.php index 518b426cda..9670c61d65 100644 --- a/grade/report/grader/edit_item_form.php +++ b/grade/report/grader/edit_item_form.php @@ -42,14 +42,20 @@ class edit_item_form extends moodleform { } } $mform->addElement('select', 'scaleid', get_string('scale'), $options); - $mform->disabledIf('scaleid', 'gradetype', 'noteq', GRADE_TYPE_SCALE); + $mform->disabledIf('scaleid', 'gradetype', 'eq', GRADE_TYPE_TEXT); + $mform->disabledIf('scaleid', 'gradetype', 'eq', GRADE_TYPE_NONE); + $mform->disabledIf('scaleid', 'gradetype', 'eq', GRADE_TYPE_VALUE); $mform->addElement('text', 'grademax', get_string('grademax', 'grades')); - $mform->disabledIf('grademax', 'gradetype', 'noteq', GRADE_TYPE_VALUE); - $mform->setDefault('grademin', 100); + $mform->disabledIf('grademax', 'gradetype', 'eq', GRADE_TYPE_TEXT); + $mform->disabledIf('grademax', 'gradetype', 'eq', GRADE_TYPE_NONE); + $mform->disabledIf('grademax', 'gradetype', 'eq', GRADE_TYPE_SCALE); + $mform->setDefault('grademax', 100); $mform->addElement('text', 'grademin', get_string('grademin', 'grades')); - $mform->disabledIf('grademin', 'gradetype', 'noteq', GRADE_TYPE_VALUE); + $mform->disabledIf('grademin', 'gradetype', 'eq', GRADE_TYPE_TEXT); + $mform->disabledIf('grademin', 'gradetype', 'eq', GRADE_TYPE_NONE); + $mform->disabledIf('grademin', 'gradetype', 'eq', GRADE_TYPE_SCALE); $mform->setDefault('grademin', 0); $mform->addElement('text', 'gradepass', get_string('gradepass', 'grades')); @@ -64,7 +70,7 @@ class edit_item_form extends moodleform { $mform->disabledIf('plusfactor', 'gradetype', 'eq', GRADE_TYPE_NONE); $mform->setDefault('plusfactor', 0); - $mform->addElement('checkbox', 'locked', get_string('locked', 'grades')); + $mform->addElement('advcheckbox', 'locked', get_string('locked', 'grades')); $mform->addElement('date_time_selector', 'locktime', get_string('locktime', 'grades'), array('optional'=>true)); $mform->disabledIf('locktime', 'gradetype', 'eq', GRADE_TYPE_NONE); @@ -93,10 +99,14 @@ class edit_item_form extends moodleform { if ($id = $mform->getElementValue('id')) { $grade_item = grade_item::fetch(array('id'=>$id)); - if (!in_array($grade_item->itemtype, array('manual', 'course', 'category'))) { + if ($grade_item->is_normal_item()) { // following items are set up from modules and should not be overrided by user $mform->hardFreeze('itemname,idnumber,calculation,gradetype,grademax,grademin,scaleid'); } + if ($grade_item->is_manual_item()) { + // manual grade item does not use these - uses only final grades + $mform->hardFreeze('plusfactor,multfactor'); + } } } @@ -112,6 +122,13 @@ class edit_item_form extends moodleform { } } + if (array_key_exists('grademin', $data) and array_key_exists('grademax', $data)) { + if ($data['grademax'] == $data['grademin'] or $data['grademax'] < $data['grademin']) { + $errors['grademin'] = get_String('incorrectminmax', 'grades'); + $errors['grademax'] = get_String('incorrectminmax', 'grades'); + } + } + if (0 == count($errors)){ return true; } else { diff --git a/grade/report/grader/index.php b/grade/report/grader/index.php index a4dbfed383..d976302aa5 100644 --- a/grade/report/grader/index.php +++ b/grade/report/grader/index.php @@ -3,17 +3,29 @@ /// This creates and handles the whole grader report interface, sans header and footer require_once($CFG->libdir.'/tablelib.php'); -include_once($CFG->libdir.'/gradelib.php'); +require_once($CFG->libdir.'/gradelib.php'); +$gradeserror = array(); /** - * format number using lang specific decimal point and thousand separator + * format grade using lang specific decimal point and thousand separator + * the result is suitable for printing on html page * @param float $gradeval raw grade value pulled from db * @return string $gradeval formatted grade value */ function get_grade_clean($gradeval) { global $CFG; - + + if (is_null($gradeval)) { + $gradeval = ''; + } else { + // decimal points as specified by user + $decimals = get_user_preferences('grade_report_decimalpoints', $CFG->grade_report_decimalpoints); + $gradeval = number_format($gradeval, $decimals, get_string('decpoint', 'langconfig'), get_string('thousandsep', 'langconfig')); + } + + return $gradeval; + /* // commenting this out, if this is added, we also need to find the number of decimal place preserved // so it can go into number_format @@ -23,11 +35,7 @@ function get_grade_clean($gradeval) { $gradeval = 0; } */ - // decimal points as specified by user - $decimals = get_user_preferences('grade_report_decimalpoints', $CFG->grade_report_decimalpoints); - $gradeval = number_format($gradeval, $decimals, get_string('decpoint', 'langconfig'), get_string('thousandsep', 'langconfig')); - return $gradeval; } /** @@ -97,15 +105,18 @@ function grader_report_print_toggle($type, $baseurl, $return=false) { } } + /// processing posted grades here -if ($data = data_submitted()) { - foreach ($data as $varname => $postedgrade) { +if ($data = data_submitted() and confirm_sesskey()) { - // clean posted values - $postedgrade = clean_param($postedgrade, PARAM_RAW); - // can not use param number here, because we can have "," in grade - $varname = clean_param($varname, PARAM_RAW); + // always initialize all arrays + $queue = array(); + + foreach ($data as $varname => $postedgrade) { + // this is a bit tricky - we have to first load all grades into memory, + // check if changed and only then start updating the final grades because + // columns might depend one on another - the result would be overriden calculated and category grades // skip, not a grade if (!strstr($varname, 'grade')) { @@ -114,40 +125,54 @@ if ($data = data_submitted()) { $gradeinfo = explode("_", $varname); - $grade = new object(); - $grade->userid = clean_param($gradeinfo[1], PARAM_INT); - $gradeitemid = clean_param($gradeinfo[2], PARAM_INT); - // grade needs to formatted to proper format for storage - $grade->rawgrade = format_grade($postedgrade); + $userid = clean_param($gradeinfo[1], PARAM_INT); + $itemid = clean_param($gradeinfo[2], PARAM_INT); - // put into grades array - $grades[$gradeitemid][] = $grade; - } -} - -// array to hold all error found during grade processing, e.g. outofrange -$gradeserror = array(); + if (!$grade_item = grade_item::fetch(array('id'=>$itemid, 'courseid'=>$course->id))) { // we must verify course id here! + error('Incorrect grade item id'); + } -// now we update the raw grade for each posted grades -if (!empty($grades)) { - foreach ($grades as $gradeitemid => $itemgrades) { - foreach ($itemgrades as $gradedata) { - $gradeitem = new grade_item(array('id'=>$gradeitemid), true); - - // cbeck if grade is in range, if not, add to error array - // MDL-10369 - - // -1 is accepted for scale grades (no grade) - if ($gradedata->rawgrade == -1 && $gradeitem->gradetype == 2) { - $gradeitem->update_raw_grade($gradedata->userid, $gradedata->rawgrade); + if ($grade_item->gradetype == GRADE_TYPE_SCALE) { + if ($postedgrade == -1) { // -1 means no grade + $finalgrade = null; } else { - if ($gradeitem->grademax < $gradedata->rawgrade || $gradeitem->grademin > $gradedata->rawgrade) { - $gradeserror[$gradeitem->id][$gradedata->userid] = 'outofrange'; - } else { - $gradeitem->update_raw_grade($gradedata->userid, $gradedata->rawgrade); - } + $finalgrade = (float)$postedgrade; + } + } else { + if ($postedgrade == '') { // empty string means no grade + $finalgrade = null; + } else { + $finalgrade = format_grade($postedgrade); + } + } + + if (!is_null($finalgrade) and ($finalgrade < $grade_item->grademin or $finalgrade > $grade_item->grademax)) { + $gradeserror[$grade_item->id][$userid] = 'outofrange'; //TODO: localize + // another possiblity is to use bounded number instead + continue; + } + + if ($grade = grade_grades::fetch(array('userid'=>$userid, 'itemid'=>$grade_item->id))) { + if (!is_null($grade->finalgrade)) { + $grade->finalgrade = (float)$grade->finalgrade; + } + if ($grade->finalgrade === $finalgrade) { + // we must not update all grades, only changed ones - we do not want to mark everything as overriden + continue; } } + + $gradedata = new object(); + $gradedata->grade_item = $grade_item; + $gradedata->finalgrade = $finalgrade; + $gradedata->userid = $userid; + + $queue[] = $gradedata; + } + + // now we update the new final grade for each changed grade + foreach ($queue as $gradedata) { + $gradedata->grade_item->update_final_grade($gradedata->userid, $gradedata->finalgrade, 'gradebook'); } } @@ -315,7 +340,7 @@ if (!empty($target) && !empty($action) && confirm_sesskey()) { // first make sure we have all final grades // TODO: check that no grade_item has needsupdate set -grade_update_final_grades($courseid); +grade_regrade_final_grades($courseid); // roles to be displaye in the gradebook $gradebookroles = $CFG->gradebookroles; @@ -370,7 +395,7 @@ if (empty($users)) { // phase 2 sql, we supply the userids in this query, and get all the grades // pulls out all the grades, this does not need to worry about paging -$sql = "SELECT g.id, g.itemid, g.userid, g.finalgrade, g.hidden, g.locked, g.locktime, gt.feedback +$sql = "SELECT g.id, g.itemid, g.userid, g.finalgrade, g.hidden, g.locked, g.locktime, g.overridden, gt.feedback FROM {$CFG->prefix}grade_items gi, {$CFG->prefix}grade_grades g LEFT JOIN {$CFG->prefix}grade_grades_text gt ON g.id = gt.gradeid @@ -462,7 +487,7 @@ foreach ($gtree->levels as $key=>$row) { $headerhtml .= ''; if ($key == $numrows - 1) { - $headerhtml .= 'Firstname ' + $headerhtml .= 'Firstname ' //TODO: localize . $firstarrow. '/ Lastname '. $lastarrow .''; } else { $headerhtml .= ' '; @@ -519,7 +544,7 @@ foreach ($gtree->levels as $key=>$row) { } else if ($object->itemtype == 'manual') { //TODO: add manual grading icon $icon = ''.get_string('manualgrade', 'grades')
-                      .''; // TODO: localize + .'"/>'; } @@ -546,29 +571,29 @@ foreach ($users as $userid => $user) { . $user->id . '">' . fullname($user) . ''; foreach ($items as $item) { - $studentshtml .= ''; - if (isset($finalgrades[$userid][$item->id])) { - - $gradeval = get_grade_clean($finalgrades[$userid][$item->id]->finalgrade); - + $gradeval = $finalgrades[$userid][$item->id]->finalgrade; $grade = new grade_grades($finalgrades[$userid][$item->id], false); $grade->feedback = $finalgrades[$userid][$item->id]->feedback; + } else { - // if itemtype is course or category, the grades in this item is not directly editable - if ($USER->gradeediting && $item->itemtype != 'course' && $item->itemtype != 'category') { - $gradeval =''; - } else { - $gradeval = '-'; - } + $gradeval = null; $grade = new grade_grades(array('userid' => $userid, 'itemid' => $item->id), false); + $grade->feedback = ''; + } + + if ($grade->is_overridden()) { + $studentshtml .= ''; + } else { + $studentshtml .= ''; } + // if in editting mode, we need to print either a text box // or a drop down (for scales) // grades in item of type grade category or course are not directly editable - if ($USER->gradeediting && $item->itemtype != 'course' && $item->itemtype != 'category') { + if ($USER->gradeediting) { // We need to retrieve each grade_grade object from DB in order to // know if they are hidden/locked @@ -600,9 +625,9 @@ foreach ($users as $userid => $user) { } } else { if ($quickgrading) { - $studentshtml .= ''; + $studentshtml .= ''; } else { - $studentshtml .= $gradeval; + $studentshtml .= get_grade_clean($gradeval); } } @@ -614,8 +639,9 @@ foreach ($users as $userid => $user) { } if ($showfeedback && $quickfeedback) { - $studentshtml .= ''; - } elseif ($showfeedback) { // If quickfeedback is off but showfeedback is on, print an edit feedback icon + $studentshtml .= ''; + + } else if ($showfeedback) { // If quickfeedback is off but showfeedback is on, print an edit feedback icon if (empty($grade->feedback)) { $icons_html .= grade_get_icons($element, $gtree, array('add_feedback')); } else { @@ -625,6 +651,7 @@ foreach ($users as $userid => $user) { $icons_html .= ''; $studentshtml .= $icons_html; + } else { // finalgrades[$userid][$itemid] could be null because of the outer join // in this case it's different than a 0 @@ -642,7 +669,11 @@ foreach ($users as $userid => $user) { // no such scale, throw error? } } else { - $studentshtml .= get_grade_clean($gradeval); + if (is_null($gradeval)) { + $studentshtml .= '-'; + } else { + $studentshtml .= get_grade_clean($gradeval); + } } } diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index 2def407a2e..371cb844c9 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -307,7 +307,7 @@ class grade_category extends grade_object { * * Please note that category grade is either calculated or aggregated - not both at the same time. * - * This method must be used ONLY from grade_item::update_final_grades(), + * This method must be used ONLY from grade_item::regrade_final_grades(), * because the calculation must be done in correct order! * * Steps to follow: @@ -404,8 +404,8 @@ class grade_category extends grade_object { $oldgrade->rawscaleid = $grade->rawscaleid; } - // locked grades are not regraded - if ($grade->is_locked()) { + // no need to recalculate locked or overridden grades + if ($grade->is_locked() or $grade->is_overridden()) { return; } diff --git a/lib/grade/grade_grades.php b/lib/grade/grade_grades.php index 6c383a015e..f205df3625 100644 --- a/lib/grade/grade_grades.php +++ b/lib/grade/grade_grades.php @@ -125,6 +125,12 @@ class grade_grades extends grade_object { */ var $exported = 0; + /** + * Overridden flag + * @var boolean $overridden + */ + var $overridden = 0; + /** * Loads the grade_grades_text object linked to this grade (through the intersection of itemid and userid), and * saves it as a class variable for this final object. @@ -162,6 +168,10 @@ class grade_grades extends grade_object { return !empty($this->locked) or $this->grade_item->is_locked(); } + function is_overridden() { + return !empty($this->overridden); + } + /** * Lock/unlopck this grade. * diff --git a/lib/grade/grade_item.php b/lib/grade/grade_item.php index 417ca9c179..c72ac89d93 100644 --- a/lib/grade/grade_item.php +++ b/lib/grade/grade_item.php @@ -516,12 +516,12 @@ class grade_item extends grade_object { * Performs the necessary calculations on the grades_final referenced by this grade_item. * Also resets the needsupdate flag once successfully performed. * - * This function must be used ONLY from lib/gradeslib.php/grade_update_final_grades(), + * This function must be used ONLY from lib/gradeslib.php/grade_regrade_final_grades(), * because the regrading must be done in correct order!! * * @return boolean true if ok, error string otherwise */ - function update_final_grades($userid=null) { + function regrade_final_grades($userid=null) { global $CFG; // locked grade items already have correct final grades @@ -547,6 +547,9 @@ class grade_item extends grade_object { } else { return "Could not aggregate final grades for category:".$this->id; // TODO: improve and localize } + } else if ($this->is_manual_item()) { + // manual items track only final grades, no raw grades + return true; } // normal grade item - just new final grades @@ -559,7 +562,7 @@ class grade_item extends grade_object { if ($rs) { if ($rs->RecordCount() > 0) { while ($grade_record = rs_fetch_next_record($rs)) { - if (!empty($grade_record->locked)) { + if (!empty($grade_record->locked) or !empty($grade_record->overridden)) { // this grade is locked - final grade must be ok continue; } @@ -649,8 +652,6 @@ class grade_item extends grade_object { dubugging("Unkown grade type"); return null;; } - - } /** @@ -772,12 +773,20 @@ class grade_item extends grade_object { return ($this->itemtype == 'course'); } + /** + * Is this a manualy graded item? + * @return boolean + */ + function is_manual_item() { + return ($this->itemtype == 'manual'); + } + /** * Is the grade item normal - associated with module, plugin or something else? * @return boolean */ function is_normal_item() { - return ($this->itemtype != 'course' and $this->itemtype != 'category'); + return ($this->itemtype != 'course' and $this->itemtype != 'category' and $this->itemtype != 'manual'); } /** @@ -1038,39 +1047,131 @@ class grade_item extends grade_object { } /** - * Updates raw grade value for given user, this is a only way to update raw - * grades from external source (module, gradebook, import, etc.), - * because it logs the change in history table and deals with final grade recalculation. - * - * The only exception is category grade item which stores the raw grades directly. - * Calculated grades do not use raw grades at all, the rawgrade changes there are not logged too. + * Updates final grade value for given user, this is a only way to update final + * grades from gradebook and import because it logs the change in history table + * and deals with overridden flag. This flag is set to prevent later overriding + * from raw grades submitted from modules. * * @param int $userid the graded user - * @param mixed $rawgrade float value of raw grade - false means do not change + * @param mixed $finalgrade float value of final grade - false means do not change * @param string $howmodified modification source * @param string $note optional note * @param mixed $feedback teachers feedback as string - false means do not change * @param int $feedbackformat - * @return mixed grade_grades object if ok, false if error + * @return boolean success */ - function update_raw_grade($userid, $rawgrade=false, $source='manual', $note=NULL, $feedback=false, $feedbackformat=FORMAT_MOODLE, $usermodified=null) { - global $CFG, $USER; - require_once($CFG->libdir.'/eventslib.php'); + function update_final_grade($userid, $finalgrade=false, $source=NULL, $note=NULL, $feedback=false, $feedbackformat=FORMAT_MOODLE, $usermodified=null) { + global $USER; if (empty($usermodified)) { $usermodified = $USER->id; } - // calculated grades can not be updated - if ($this->is_calculated()) { + // no grading used or locked + if ($this->gradetype == GRADE_TYPE_NONE or $this->is_locked()) { return false; } - // TODO: we should IMO prevent modification of raw grades for course and categroy item too because - // there is no way to prevent overriding of it + if (!$grade = grade_grades::fetch(array('itemid'=>$this->id, 'userid'=>$userid))) { + $grade = new grade_grades(array('itemid'=>$this->id, 'userid'=>$userid), false); + } - // do not allow grade updates when item locked - this prevents fetching of grade from db - if ($this->is_locked()) { + $grade->grade_item =& $this; // prevent db fetching of this grade_item + $oldgrade = new object(); + $oldgrade->finalgrade = $grade->finalgrade; + $oldgrade->rawgrade = $grade->rawgrade; + $oldgrade->rawgrademin = $grade->rawgrademin; + $oldgrade->rawgrademax = $grade->rawgrademax; + $oldgrade->rawscaleid = $grade->rawscaleid; + $oldgrade->overridden = $grade->overridden; + + if ($grade->is_locked()) { + // do not update locked grades at all + return false; + } + + if (!empty($grade->locktime) and $grade->locktime < time()) { + // do not update grades that should be already locked + // this does not solve all problems, cron is still needed to recalculate the final grades periodically + return false; + } + + if ($finalgrade !== false) { + $grade->finalgrade = $finalgrade; + // if we can update the raw grade, do update it + if (!$this->is_normal_item() or $this->plusfactor != 0 or $this->multfactor != 1 + or !events_is_registered('grade_updated', $this->itemtype.'/'.$this->itemmodule)) { + if (!$grade->overridden) { + $grade->overridden = time(); + } + } else { + $grade->rawgrade = $finalgrade; + // copy current grademin/max and scale + $grade->rawgrademin = $this->grademin; + $grade->rawgrademax = $this->grademax; + $grade->rawscaleid = $this->scaleid; + } + } + + if (empty($grade->id)) { + $result = (boolean)$grade->insert($source); + + } else if ($grade->finalgrade !== $oldgrade->finalgrade + or $grade->rawgrade !== $oldgrade->rawgrade + or $grade->rawgrademin !== $oldgrade->rawgrademin + or $grade->rawgrademax !== $oldgrade->rawgrademax + or $grade->rawscaleid !== $oldgrade->rawscaleid + or $grade->overridden !== $oldgrade->overridden) { + + $result = $grade->update($source); + } + + // do we have comment from teacher? + if ($result and $feedback !== false) { + $result = $grade->update_feedback($feedback, $feedbackformat, $usermodified); + } + + if (!$this->needsupdate) { + $course_item = grade_item::fetch_course_item($this->courseid); + if (!$course_item->needsupdate) { + if (!grade_regrade_final_grades($this->courseid, $userid, $this)) { + $this->force_regrading(); + } + } else { + $this->force_regrading(); + } + } + + if ($result and !$grade->overridden) { + $this->trigger_raw_updated($grade, $source); + } + + return $result; + } + + + /** + * Updates raw grade value for given user, this is a only way to update raw + * grades from external source (modules, etc.), + * because it logs the change in history table and deals with final grade recalculation. + * + * @param int $userid the graded user + * @param mixed $rawgrade float value of raw grade - false means do not change + * @param string $howmodified modification source + * @param string $note optional note + * @param mixed $feedback teachers feedback as string - false means do not change + * @param int $feedbackformat + * @return boolean success + */ + function update_raw_grade($userid, $rawgrade=false, $source=NULL, $note=NULL, $feedback=false, $feedbackformat=FORMAT_MOODLE, $usermodified=null) { + global $USER; + + if (empty($usermodified)) { + $usermodified = $USER->id; + } + + // calculated grades can not be updated; course and category can not be updated because they are aggregated + if ($this->is_calculated() or !$this->is_normal_item() or $this->gradetype == GRADE_TYPE_NONE or $this->is_locked()) { return false; } @@ -1126,7 +1227,7 @@ class grade_item extends grade_object { if (!$this->needsupdate) { $course_item = grade_item::fetch_course_item($this->courseid); if (!$course_item->needsupdate) { - if (!grade_update_final_grades($this->courseid, $userid, $this)) { + if (!grade_regrade_final_grades($this->courseid, $userid, $this)) { $this->force_regrading(); } } else { @@ -1135,36 +1236,42 @@ class grade_item extends grade_object { } if ($result) { + $this->trigger_raw_updated($grade, $source); + } - // trigger grade_updated event notification - $eventdata = new object(); - - $eventdata->source = $source; - $eventdata->itemid = $this->id; - $eventdata->courseid = $this->courseid; - $eventdata->itemtype = $this->itemtype; - $eventdata->itemmodule = $this->itemmodule; - $eventdata->iteminstance = $this->iteminstance; - $eventdata->itemnumber = $this->itemnumber; - $eventdata->idnumber = $this->idnumber; - $eventdata->userid = $grade->userid; - $eventdata->rawgrade = $grade->rawgrade; - - // load existing text annotation - if ($grade_text = $grade->load_text()) { - $eventdata->feedback = $grade_text->feedback; - $eventdata->feedbackformat = $grade_text->feedbackformat; - $eventdata->information = $grade_text->information; - $eventdata->informationformat = $grade_text->informationformat; - } - - events_trigger('grade_updated', $eventdata); + return $result; + } - return $grade; + /** + * Internal function used by update_final/raw_grade() only. + */ + function trigger_raw_updated($grade, $source) { + global $CFG; + require_once($CFG->libdir.'/eventslib.php'); - } else { - return false; - } + // trigger grade_updated event notification + $eventdata = new object(); + + $eventdata->source = $source; + $eventdata->itemid = $this->id; + $eventdata->courseid = $this->courseid; + $eventdata->itemtype = $this->itemtype; + $eventdata->itemmodule = $this->itemmodule; + $eventdata->iteminstance = $this->iteminstance; + $eventdata->itemnumber = $this->itemnumber; + $eventdata->idnumber = $this->idnumber; + $eventdata->userid = $grade->userid; + $eventdata->rawgrade = $grade->rawgrade; + + // load existing text annotation + if ($grade_text = $grade->load_text()) { + $eventdata->feedback = $grade_text->feedback; + $eventdata->feedbackformat = $grade_text->feedbackformat; + $eventdata->information = $grade_text->information; + $eventdata->informationformat = $grade_text->informationformat; + } + + events_trigger('grade_updated', $eventdata); } /** @@ -1274,8 +1381,8 @@ class grade_item extends grade_object { $oldgrade->rawgrade = $grade->rawgrade; } - // no need to recalculate locked grades - if ($grade->is_locked()) { + // no need to recalculate locked or overridden grades + if ($grade->is_locked() or $grade->is_overridden()) { return; } diff --git a/lib/gradelib.php b/lib/gradelib.php index 9c4156886d..73da1e8b18 100644 --- a/lib/gradelib.php +++ b/lib/gradelib.php @@ -311,7 +311,7 @@ function grade_force_full_regrading($courseid) { * @param object $updated_item the item in which * @return boolean true if ok, array of errors if problems found (item id is used as key) */ -function grade_update_final_grades($courseid, $userid=null, $updated_item=null) { +function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null) { $course_item = grade_item::fetch_course_item($courseid); @@ -374,7 +374,7 @@ function grade_update_final_grades($courseid, $userid=null, $updated_item=null) //oki - let's update, calculate or aggregate :-) if ($doupdate) { - $result = $grade_item->update_final_grades($userid); + $result = $grade_item->regrade_final_grades($userid); if ($result === true) { $grade_item->regrading_finished(); diff --git a/lib/simpletest/grade/simpletest/testgradeitem.php b/lib/simpletest/grade/simpletest/testgradeitem.php index c61fb7460a..933db6d277 100755 --- a/lib/simpletest/grade/simpletest/testgradeitem.php +++ b/lib/simpletest/grade/simpletest/testgradeitem.php @@ -287,10 +287,10 @@ class grade_item_test extends grade_test { /** * Test update of all final grades */ - function test_grade_item_update_final_grades() { + function test_grade_item_regrade_final_grades() { $grade_item = new grade_item($this->grade_items[0]); - $this->assertTrue(method_exists($grade_item, 'update_final_grades')); - $this->assertEqual(true, $grade_item->update_final_grades()); + $this->assertTrue(method_exists($grade_item, 'regrade_final_grades')); + $this->assertEqual(true, $grade_item->regrade_final_grades()); //TODO: add more tests } diff --git a/theme/standard/styles_color.css b/theme/standard/styles_color.css index e1ffefd12e..c8fc153516 100644 --- a/theme/standard/styles_color.css +++ b/theme/standard/styles_color.css @@ -712,6 +712,10 @@ body#grade-index .grades .r1 { background-color: #dddddd; } +#grade-report td.overridden { + background-color: #efefef; +} + /*** *** Login ***/