}
// module items and items without grade can not have calculation
-if (($grade_item->is_normal_item() and !$grade_item->is_outcome_item())
+if (($grade_item->is_external_item() and !$grade_item->is_outcome_item())
or ($grade_item->gradetype != GRADE_TYPE_VALUE and $grade_item->gradetype != GRADE_TYPE_SCALE)) {
redirect($returnurl, get_string('errornocalculationallowed', 'grades')); //TODO: localize
}
// always clean existing feedback - grading should not have XSS risk
if (can_use_html_editor()) {
- $options = new object();
- $options->smiley = false;
- $options->filter = false;
- $options->noclean = false;
- $grade->feedback = format_text($grade->feedback, $grade->feedbackformat, $options);
+ if (empty($grade->feedback)) {
+ $grade->feedback = '';
+ } else {
+ $options = new object();
+ $options->smiley = false;
+ $options->filter = false;
+ $options->noclean = false;
+ $grade->feedback = format_text($grade->feedback, $grade->feedbackformat, $options);
+ }
$grade->feedbackformat = FORMAT_HTML;
} else {
$grade->feedback = clean_text($grade->feedback, $grade->feedbackformat);
$grade->finalgrade = format_float($grade->finalgrade, $grade_item->get_decimals());
}
- $grade->oldgrade = $grade->finalgrade;
+ $grade->oldgrade = $grade->finalgrade;
+ $grade->oldfeedback = $grade->feedback;
$mform->set_data($grade);
} else if ($data = $mform->get_data(false)) {
$old_grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true); //might not exist yet
+ if (!isset($data->overridden)) {
+ $data->overridden = 0; // checkbox
+ }
+
// fix no grade for scales
- if (!isset($data->finalgrade) or $data->finalgrade == $data->oldgrade) {
+ if (($grade_item->is_overridable_item() and !$data->overridden) or !isset($data->finalgrade) or $data->finalgrade == $data->oldgrade) {
$data->finalgrade = $old_grade_grade->finalgrade;
} else if ($grade_item->gradetype == GRADE_TYPE_SCALE and $data->finalgrade < 1) {
$data->finalgrade = unformat_float($data->finalgrade);
}
- if (!isset($data->feedback)) {
+ // the overriding of feedback is tricky - we have to care about external items only
+ if (!array_key_exists('feedback', $data) or $data->feedback == $data->oldfeedback) {
$data->feedback = $old_grade_grade->feedback;
$data->feedbackformat = $old_grade_grade->feedbackformat;
}
// update final grade or feedback
- $grade_item->update_final_grade($data->userid, $data->finalgrade, NULL, 'editgrade', $data->feedback, $data->feedbackformat);
+ $grade_item->update_final_grade($data->userid, $data->finalgrade, 'editgrade', $data->feedback, $data->feedbackformat);
$grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true);
$grade_grade->grade_item =& $grade_item; // no db fetching
+ if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:edit', $context)) {
+ $grade_grade->set_overridden($data->overridden);
+ }
+
if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:hide', $context)) {
$hidden = empty($data->hidden) ? 0: $data->hidden;
$hiddenuntil = empty($data->hiddenuntil) ? 0: $data->hiddenuntil;
$grade_grade->set_excluded($data->excluded);
}
- if (isset($data->overridden) and has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:edit', $context)) {
- // ignore overridden flag when changing final grade
- if ($old_grade_grade->finalgrade == $grade_grade->finalgrade) {
- $grade_grade->set_overridden($data->overridden);
- }
- }
-
// detect cases when we need to do full regrading
if ($old_grade_grade->excluded != $grade_grade->excluded) {
$parent = $grade_item->get_parent_category();
$mform->addElement('static', 'user', get_string('user'));
$mform->addElement('static', 'itemname', get_string('itemname', 'grades'));
+ $mform->addElement('checkbox', 'overridden', get_string('overridden', 'grades'));
+ $mform->setHelpButton('overridden', array(false, get_string('overridden', 'grades'),
+ false, true, false, get_string('overriddenhelp', 'grades')));
+
/// actual grade - numeric or scale
if ($grade_item->gradetype == GRADE_TYPE_VALUE) {
// numeric grade
$mform->addElement('text', 'finalgrade', get_string('finalgrade', 'grades'));
$mform->setHelpButton('finalgrade', array(false, get_string('finalgrade', 'grades'),
false, true, false, get_string('finalgradehelp', 'grades')));
+ $mform->disabledIf('finalgrade', 'overridden', 'notchecked');
} else if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
// scale grade
$mform->addElement('select', 'finalgrade', get_string('finalgrade', 'grades'), $scaleopt);
$mform->setHelpButton('finalgrade', array(false, get_string('finalgrade', 'grades'),
false, true, false, get_string('finalgradehelp', 'grades')));
+ $mform->disabledIf('finalgrade', 'overridden', 'notchecked');
}
- $mform->addElement('advcheckbox', 'overridden', get_string('overridden', 'grades'));
- $mform->setHelpButton('overridden', array(false, get_string('overridden', 'grades'),
- false, true, false, get_string('overriddenhelp', 'grades')));
$mform->addElement('advcheckbox', 'excluded', get_string('excluded', 'grades'));
$mform->setHelpButton('excluded', array(false, get_string('excluded', 'grades'),
false, true, false, get_string('excludedhelp', 'grades')));
$mform->setType('text', PARAM_RAW); // to be cleaned before display, no XSS risk
$mform->addElement('format', 'feedbackformat', get_string('format'));
$mform->setHelpButton('feedbackformat', array('textformat', get_string('helpformatting')));
+ //TODO: unfortunately we can not disable html editor for external grades when overridden off :-(
// hidden params
$mform->addElement('hidden', 'oldgrade');
+ $mform->addElement('hidden', 'oldfeedback');
$mform->addElement('hidden', 'id', 0);
$mform->setType('id', PARAM_INT);
$old_grade_grade = new grade_grade(array('itemid'=>$grade_item->id, 'userid'=>$userid));
+ if (!$grade_item->is_overridable_item()) {
+ $mform->removeElement('overridden');
+ }
+
if ($grade_item->is_hidden()) {
$mform->hardFreeze('hidden');
}
$mform->hardFreeze('scaleid');
} else {
- if ($grade_item->is_normal_item()) {
+ if ($grade_item->is_external_item()) {
// following items are set up from modules and should not be overrided by user
$mform->hardFreeze('itemname,idnumber,gradetype,grademax,grademin,scaleid');
//$mform->removeElement('calculation');
// insert each individual grade to this new grade item
foreach ($grades as $grade) {
- if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', NULL, $grade->feedback)) {
+ if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', $grade->feedback, FORMAT_MOODLE)) {
$failed = true;
break 2;
}
if (!$importfeedback) {
$grade->feedback = false; // ignore it
}
- if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', NULL, $grade->feedback)) {
+ if (!$gradeitem->update_final_grade($grade->userid, $grade->finalgrade, 'import', $grade->feedback)) {
$failed = 1;
break 2;
}
}
static $stredit = null;
+ static $strfeedback = null;
if (is_null($stredit)) {
$stredit = get_string('edit');
+ $strfeedback = get_string('feedback');
}
$object = $element['object'];
}
$url = $gpr->add_url_params($url);
if (!empty($object->feedback)) {
- $feedback = format_text($object->feedback, $object->feedbackformat);
- $function = "return overlib('".s(ltrim($object->feedback)."', FULLHTML);");
- $overlib = 'onmouseover="'.$function.'" onmouseout="return nd();"';
+ $feedback = addslashes_js(trim(format_string($object->feedback, $object->feedbackformat)));
+ $function = "return overlib('$feedback', BORDER, 0, FGCLASS, 'feedback', "
+ ."CAPTIONFONTCLASS, 'caption', CAPTION, '$strfeedback');";
+ $overlib = 'onmouseover="'.s($function).'" onmouseout="return nd();"';
}
break;
$streditcalculation = get_string('editcalculation', 'grades');
// show calculation icon only when calculation possible
- if ((!$object->is_normal_item() or $object->is_outcome_item())
+ if ((!$object->is_external_item() or $object->is_outcome_item())
and ($object->gradetype == GRADE_TYPE_SCALE or $object->gradetype == GRADE_TYPE_VALUE)) {
$url = $CFG->wwwroot.'/grade/edit/tree/calculation.php?courseid='.$this->courseid.'&id='.$object->id;
$url = $gpr->add_url_params($url);
foreach ($data as $varname => $postedvalue) {
$needsupdate = false;
- $note = false; // TODO implement note??
// skip, not a grade nor feedback
if (strpos($varname, 'grade') === 0) {
}
}
- $grade_item->update_final_grade($userid, $finalgrade, 'gradebook', $note, $feedback);
+ $grade_item->update_final_grade($userid, $finalgrade, 'gradebook', $feedback, FORMAT_MOODLE);
}
return true;
/**
* Set the overridden status of grade
* @param boolean $state requested overridden state
+ * @param boolean $refresh refresh grades from external activities if needed
* @return boolean true is db state changed
*/
- function set_overridden($state) {
+ function set_overridden($state, $refresh = true) {
if (empty($this->overridden) and $state) {
$this->overridden = time();
$this->update();
} else if (!empty($this->overridden) and !$state) {
$this->overridden = 0;
$this->update();
+
+ if ($refresh) {
+ //refresh when unlocking
+ $this->grade_item->refresh_grades($this->userid);
+ }
+
return true;
}
return false;
}
/**
- * Is the grade item normal - associated with module, plugin or something else?
+ * Is the grade item external - associated with module, plugin or something else?
* @return boolean
*/
- function is_normal_item() {
- return ($this->itemtype != 'course' and $this->itemtype != 'category' and $this->itemtype != 'manual');
+ function is_external_item() {
+ return ($this->itemtype == 'mod');
+ }
+
+ /**
+ * Is the grade item overridable
+ * @return boolean
+ */
+ function is_overridable_item() {
+ return !$this->is_outcome_item() and ($this->is_external_item() or $this->is_calculated() or $this->is_course_item() or $this->is_category_item());
}
/**
* @return boolean
*/
function is_raw_used() {
- return ($this->is_normal_item() and !$this->is_calculated() and !$this->is_outcome_item());
+ return ($this->is_external_item() and !$this->is_calculated() and !$this->is_outcome_item());
}
/**
* @param int $feedbackformat
* @return boolean success
*/
- function update_final_grade($userid, $finalgrade=false, $source=NULL, $note=NULL, $feedback=false, $feedbackformat=FORMAT_MOODLE, $usermodified=null) {
+ function update_final_grade($userid, $finalgrade=false, $source=NULL, $feedback=false, $feedbackformat=FORMAT_MOODLE, $usermodified=null) {
global $USER, $CFG;
if (empty($usermodified)) {
$oldgrade->feedback = $grade->feedback;
$oldgrade->feedbackformat = $grade->feedbackformat;
- if ($finalgrade !== false or $feedback !== false) {
- if (($this->is_outcome_item() or $this->is_manual_item()) and !$this->is_calculated()) {
- // final grades updated only by user - no need for overriding
- $grade->overridden = 0;
-
- } else {
+ // changed grade?
+ if ($finalgrade !== false) {
+ if ($this->is_overridable_item()) {
$grade->overridden = time();
+ } else {
+ $grade->overridden = 0;
}
- }
- if ($finalgrade !== false) {
if (!is_null($finalgrade)) {
$finalgrade = bounded_number($this->grademin, $finalgrade, $this->grademax);
} else {
// do we have comment from teacher?
if ($feedback !== false) {
+ if ($this->is_external_item()) {
+ // external items (modules, plugins) may have own feedback
+ $grade->overridden = time();
+ }
+
$grade->feedback = $feedback;
$grade->feedbackformat = $feedbackformat;
}
or $grade->feedback !== $oldgrade->feedback
or $grade->feedbackformat !== $oldgrade->feedbackformat) {
$result = $grade->update($source);
+ } else {
+ // no grade change
+ return $result;
}
if (!$result) {
* @param int $feedbackformat
* @return boolean success
*/
- function update_raw_grade($userid, $rawgrade=false, $source=NULL, $note=NULL, $feedback=false, $feedbackformat=FORMAT_MOODLE, $usermodified=null) {
+ function update_raw_grade($userid, $rawgrade=false, $source=NULL, $feedback=false, $feedbackformat=FORMAT_MOODLE, $usermodified=null) {
global $USER;
if (empty($usermodified)) {
$result = true;
// calculated grades can not be updated; course and category can not be updated because they are aggregated
- if ($this->is_calculated() or $this->is_outcome_item() or !$this->is_normal_item()
- or $this->gradetype == GRADE_TYPE_NONE or $this->is_locked()) {
+ if (!$this->is_raw_used() or $this->gradetype == GRADE_TYPE_NONE or $this->is_locked()) {
return false;
}
}
// update or insert the grade
- if (!$grade_item->update_raw_grade($userid, $rawgrade, $source, null, $feedback, $feedbackformat, $usermodified)) {
+ if (!$grade_item->update_raw_grade($userid, $rawgrade, $source, $feedback, $feedbackformat, $usermodified)) {
$failed = true;
}
}