fwrite ($bf,full_tag("LOCKTIME",7,false,$final->locktime));
fwrite ($bf,full_tag("EXPORTED",7,false,$final->exported));
fwrite ($bf,full_tag("OVERRIDDEN",7,false,$final->overridden));
+ fwrite ($bf,full_tag("EXCLUDED",7,false,$final->excluded));
fwrite ($bf,end_tag("GRADE",6,true));
}
$stauts = fwrite ($bf,end_tag("GRADE_GRADES",5,true));
$grade->locktime = backup_todb($ite_info['#']['LOCKTIME']['0']['#']);
$grade->exported = backup_todb($ite_info['#']['EXPORTED']['0']['#']);
$grade->overridden = backup_todb($ite_info['#']['OVERRIDDEN']['0']['#']);
+ $grade->excluded = backup_todb($ite_info['#']['EXCLUDED']['0']['#']);
insert_record('grade_grades', $grade);
require_once 'grade_form.php';
$courseid = required_param('courseid', PARAM_INT);
-$id = optional_param('id', 0, PARAM_INT); // grade_grade id
-$action = optional_param('action', 'view', PARAM_ALPHA);
+$id = optional_param('id', 0, PARAM_INT);
+$itemid = optional_param('itemid', 0, PARAM_INT);
+$userid = optional_param('userid', 0, PARAM_INT);
if (!$course = get_record('course', 'id', $courseid)) {
print_error('nocourseid');
}
-// capabilities check
+// TODO: fix capabilities check
+// TODO: add proper check that grade is editable
require_login($course);
$context = get_context_instance(CONTEXT_COURSE, $course->id);
require_capability('gradereport/grader:manage', $context);
$gpr = new grade_plugin_return();
$returnurl = $gpr->get_return_url($CFG->wwwroot.'/grade/report.php?id='.$course->id);
-// TODO: add proper check that grade is editable
+// security checks!
+if (!empty($id)) {
+ if (!$grade = get_record('grade_grades', 'id', $id)) {
+ error('Incorrect grade id');
+ }
+
+ if (!empty($itemid) and $itemid != $grade->itemid) {
+ error('Incorrect itemid');
+ }
+ $itemid = $grade->itemid;
+
+ if (!empty($userid) and $userid != $grade->userid) {
+ error('Incorrect userid');
+ }
+ $userid = $grade->userid;
-$grade_grade = get_record('grade_grades', 'id', $id);
-$gradeitem = get_record('grade_items', 'id', $grade_grade->itemid);
+ unset($grade);
-$mform = new edit_grade_form(null, array('gradeitem'=>$gradeitem, 'gpr'=>$gpr));
-if ($grade_grade = get_record('grade_grades', 'id', $id)) {
- if ($grade_text = get_record('grade_grades_text', 'gradeid', $id)) {
+} else if (empty($userid) or empty($itemid)) {
+ error('Missing userid and itemid');
+}
+
+if (!$grade_item = grade_item::fetch(array('id'=>$itemid, 'courseid'=>$courseid))) {
+ error('Can not find grade_item');
+}
+
+
+$mform = new edit_grade_form(null, array('grade_item'=>$grade_item, 'gpr'=>$gpr));
+
+if ($grade = get_record('grade_grades', 'itemid', $id, 'userid', $userid)) {
+ if ($grade_text = get_record('grade_grades_text', 'gradeid', $grade->id)) {
+ // always clean existing feedback - grading should not have XSS risk
if (can_use_html_editor()) {
$options = new object();
- $options->smiley = false;
- $options->filter = false;
- $grade_text->feedback = format_text($grade_text->feedback, $grade_text->feedbackformat, $options);
- $grade_text->feedbackformat = FORMAT_HTML;
+ $options->smiley = false;
+ $options->filter = false;
+ $options->noclean = false;
+ $grade->feedback = format_text($grade_text->feedback, $grade_text->feedbackformat, $options);
+ $grade->feedbackformat = FORMAT_HTML;
+ } else {
+ $grade->feedback = clean_text($grade_text->feedback, $grade_text->feedbackformat);
+ $grade->feedbackformat = $grade_text->feedbackformat;
}
- $mform->set_data($grade_text);
}
- $grade_grade->locked = $grade_grade->locked > 0 ? 1:0;
- $grade_grade->courseid = $courseid;
- $mform->set_data($grade_grade);
+ $grade->locked = $grade->locked > 0 ? 1:0;
+ $grade->overridden = $grade->overridden > 0 ? 1:0;
+ $grade->excluded = $grade->excluded > 0 ? 1:0;
+
+ $mform->set_data($grade);
} else {
- $mform->set_data(array('courseid'=>$course->id, 'id' => $id));
+ $mform->set_data(array('itemid'=>$itemid, 'userid'=>$userid));
}
if ($mform->is_cancelled()) {
redirect($returnurl);
+
// form processing
} else if ($data = $mform->get_data()) {
- $grade_grade = new grade_grade(array('id'=>$id));
- $grade_item = new grade_item(array('id'=>$grade_grade->itemid));
- $grade_item->update_final_grade($grade_grade->userid, $data->finalgrade, NULL, NULL, $data->feedback, $data->feedbackformat);
+ $old_grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true); //might not exist yet
- // Assign finalgrade value
- $grade_grade->finalgrade = $data->finalgrade;
+ // update final grade or feedback
+ $grade_item->update_final_grade($data->userid, $data->finalgrade, NULL, 'editgrade', $data->feedback, $data->feedbackformat);
- // set locked
- $grade_grade->set_locked($data->locked);
+ $grade_grade = grade_grade::fetch(array('userid'=>$data->userid, 'itemid'=>$grade_item->id));
- // set hidden
- $grade_grade->set_hidden($data->hidden);
+ $grade_grade->set_hidden($data->hidden); // TODO: this is wrong!
+
+ // ignore overridden flag when changing final grade
+ if ($old_grade_grade->finalgrade == $grade_grade->finalgrade) {
+ if ($grade_grade->set_overridden($data->overridden) and empty($data->overridden)) {
+ $grade_item->force_regrading(); // force regrading only when clearing the flag
+ }
+ }
+
+ if ($grade_grade->set_excluded($data->excluded)) {
+ $grade_item->force_regrading();
+ }
- // set locktime
+ $grade_grade->set_locked($data->locked);
$grade_grade->set_locktime($data->locktime);
redirect($returnurl);
}
-// Get extra data related to this feedback
-$query = "SELECT a.id AS userid, a.firstname, a.lastname,
- b.id AS itemid, b.itemname, b.grademin, b.grademax, b.iteminstance, b.itemmodule, b.scaleid,
- c.finalgrade
- FROM {$CFG->prefix}user a,
- {$CFG->prefix}grade_items b,
- {$CFG->prefix}grade_grades c
- WHERE c.id = $id
- AND b.id = c.itemid
- AND a.id = c.userid";
-
-$extra_info = get_record_sql($query) ;
-$extra_info->grademin = round($extra_info->grademin);
-$extra_info->grademax = round($extra_info->grademax);
-$extra_info->finalgrade = round($extra_info->finalgrade);
-
-if (!empty($extra_info->itemmodule) && !empty($extra_info->iteminstance)) {
- $extra_info->course_module = get_coursemodule_from_instance($extra_info->itemmodule, $extra_info->iteminstance, $courseid);
-}
-
-$stronascaleof = get_string('onascaleof', 'grades', $extra_info);
$strgrades = get_string('grades');
-$strgrade = get_string('grade');
$strgraderreport = get_string('graderreport', 'grades');
-$strgrade = get_string('grade', 'grades');
-$strgradeedit = get_string('gradeedit', 'grades');
-$strgradeview = get_string('gradeview', 'grades');
-$strstudent = get_string('student', 'grades');
-$strgradeitem = get_string('gradeitem', 'grades');
-
-$feedback = null;
-$heading = ${"strgrade$action"};
-if (!empty($action) && $action == 'view' && !empty($grade_text->feedback)) {
- $feedback = "<p><strong>$strgrade</strong>:</p><p>$grade_text->feedback</p>";
-}
+$strgradeedit = get_string('editgrade', 'grades');
+$struser = get_string('user');
$nav = array(array('name'=>$strgrades,'link'=>$CFG->wwwroot.'/grade/index.php?id='.$courseid, 'type'=>'misc'),
- array('name'=>$heading, 'link'=>'', 'type'=>'misc'));
+ array('name'=>$strgradeedit, 'link'=>'', 'type'=>'misc'));
$navigation = build_navigation($nav);
/*********** BEGIN OUTPUT *************/
-print_header_simple($strgrades . ': ' . $strgraderreport . ': ' . $heading,
- ': ' . $heading , $navigation, '', '', true, '', navmenu($course));
+print_header_simple($strgrades . ': ' . $strgraderreport . ': ' . $strgradeedit,
+ ': ' . $strgradeedit , $navigation, '', '', true, '', navmenu($course));
-print_heading($heading);
+print_heading($strgradeedit);
print_simple_box_start("center");
-// Student name and link
-echo "<p><strong>$strstudent:</strong> <a href=\"" . $CFG->wwwroot . '/user/view.php?id='
- . $extra_info->userid . '">' . fullname($extra_info) . "</a></p>";
-
-// Grade item name and link
-if (!empty($extra_info->course_module) && !empty($extra_info->itemmodule)) {
- echo "<p><strong>$strgradeitem:</strong> <a href=\"" . $CFG->wwwroot . '/mod/' . $extra_info->itemmodule
- . '/view.php?id=' . $extra_info->course_module->id . "&courseid=$courseid\">$extra_info->itemname</a></p>";
-}
-
// Form if in edit or add modes
$mform->display();
require_once $CFG->libdir.'/formslib.php';
class edit_grade_form extends moodleform {
+
function definition() {
+ global $CFG, $COURSE;
- global $CFG, $USER;
$mform =& $this->_form;
- $gradeitem = $this->_customdata['gradeitem'];
+ $grade_item = $this->_customdata['grade_item'];
+ $gpr = $this->_customdata['gpr'];
+
+ /// information fields
+ $mform->addElement('static', 'user', get_string('user'));
+ $mform->addElement('static', 'itemname', get_string('itemname', 'grades'));
- /// actual grade - numeric or scale
- if ($gradeitem->gradetype == GRADE_TYPE_VALUE) {
+ /// actual grade - numeric or scale
+ if ($grade_item->gradetype == GRADE_TYPE_VALUE) {
// numeric grade
$mform->addElement('text', 'finalgrade', get_string('finalgrade', 'grades'));
- } else if ($gradeitem->gradetype == GRADE_TYPE_SCALE) {
+ } else if ($grade_item->gradetype == GRADE_TYPE_SCALE) {
// scale grade
+ $scaleopt = array();
$scaleopt[-1] = get_string('nograde');
$i = 1;
- if ($scale = get_record('scale', 'id', $gradeitem->scaleid)) {
+ if ($scale = get_record('scale', 'id', $grade_item->scaleid)) {
foreach (split(",", $scale->scale) as $option) {
$scaleopt[$i] = $option;
$i++;
$mform->addElement('select', 'finalgrade', get_string('finalgrade', 'grades'), $scaleopt);
}
- /// hidden
$mform->addElement('advcheckbox', 'hidden', get_string('hidden', 'grades'));
+ $mform->addElement('advcheckbox', 'overridden', get_string('overridden', 'grades'));
+ $mform->addElement('advcheckbox', 'excluded', get_string('excluded', 'grades'));
- /// locked
+ /// locking
$mform->addElement('advcheckbox', 'locked', get_string('locked', 'grades'));
-
- /// locktime
$mform->addElement('date_time_selector', 'locktime', get_string('locktime', 'grades'), array('optional'=>true));
$mform->disabledIf('locktime', 'gradetype', 'eq', GRADE_TYPE_NONE);
// Feedback format is automatically converted to html if user has enabled editor
$mform->addElement('htmleditor', 'feedback', get_string('feedback', 'grades'),
- array('rows'=> '15', 'course' => $gradeitem->courseid, 'cols'=>'45'));
- $mform->setType('text', PARAM_RAW); // to be cleaned before display
+ array('rows'=>'15', 'course'=>$COURSE->id, 'cols'=>'45'));
+ $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')));
// hidden params
$mform->addElement('hidden', 'id', 0);
- $mform->setType('gradeid', PARAM_INT);
+ $mform->setType('id', PARAM_INT);
+
+ $mform->addElement('hidden', 'itemid', 0);
+ $mform->setType('itemid', PARAM_INT);
- $mform->addElement('hidden', 'courseid', 0);
+ $mform->addElement('hidden', 'userid', 0);
+ $mform->setType('userid', PARAM_INT);
+
+ $mform->addElement('hidden', 'courseid', $COURSE->id);
$mform->setType('courseid', PARAM_INT);
/// add return tracking info
- $gpr = $this->_customdata['gpr'];
$gpr->add_mform_elements($mform);
//-------------------------------------------------------------------------------
// buttons
$this->add_action_buttons();
}
+
+ function definition_after_data() {
+ global $CFG;
+
+ $mform =& $this->_form;
+ $grade_item = $this->_customdata['grade_item'];
+
+ if ($userid = $mform->getElementValue('userid')) {
+ $user = get_record('user', 'id', $userid);
+ $username = '<a href="'.$CFG->wwwroot.'/user/view.php?id='.$userid.'">'.fullname($user).'</a>';
+ $user_el =& $mform->getElement('user');
+ $user_el->setValue($username);
+ }
+
+ if ($grade_item->itemtype == 'mod') {
+ $cm = get_coursemodule_from_instance($grade_item->itemmodule, $grade_item->iteminstance, $grade_item->courseid);
+ $itemname = '<a href="'.$CFG->wwwroot.'/mod/'.$grade_item->itemmodule.'/view.php?id='.$cm->id.'">'.$grade_item->get_name().'</a>';
+ } else {
+ $itemname = $grade_item->get_name();
+ }
+ $itemname_el =& $mform->getElement('itemname');
+ $itemname_el->setValue($itemname);
+ }
}
?>
\ No newline at end of file
function load_final_grades() {
global $CFG;
- $sql = "SELECT g.id, g.itemid, g.userid, g.finalgrade, g.hidden, g.locked, g.locktime, g.overridden,
- gt.feedback, gt.feedbackformat,
- gi.grademin, gi.grademax
- FROM {$CFG->prefix}grade_items gi,
- {$CFG->prefix}grade_grades g
- LEFT JOIN {$CFG->prefix}grade_grades_text gt ON g.id = gt.gradeid
- WHERE g.itemid = gi.id
- AND gi.courseid = $this->courseid $this->userselect";
+ // please note that we must fetch all grade_grades fields if we want to contruct grade_grade object from it!
+ $sql = "SELECT g.*, gt.feedback, gt.feedbackformat, gi.grademin, gi.grademax
+ FROM {$CFG->prefix}grade_items gi,
+ {$CFG->prefix}grade_grades g
+ LEFT JOIN {$CFG->prefix}grade_grades_text gt ON g.id = gt.gradeid
+ WHERE g.itemid = gi.id AND gi.courseid = $this->courseid $this->userselect";
if ($grades = get_records_sql($sql)) {
foreach ($grades as $grade) {
$studentshtml .= '<td>';
}
+ if ($grade->is_excluded()) {
+ $studentshtml .= get_string('excluded', 'grades'); // TODO: improve visual representation of excluded grades
+ }
+
// emulate grade element
$grade->courseid = $this->courseid;
$grade->grade_item = $item; // this may speedup is_hidden() and other grade_grade methods
$data = array();
- $params->itemid = $grade_item->id;
- $params->userid = $this->user->id;
- $grade_grade = new grade_grade($params);
+ $grade_grade = new grade_grade(array('itemid'=>$grade_item->id, 'userid'=>$this->user->id));
$grade_text = $grade_grade->load_text();
/// prints mod icon if available
/// prints the grade
+ if ($grade_grade->is_excluded()) {
+ $excluded = get_tring('excluded', 'grades').' ';
+ } else {
+ $excluded = '';
+ }
+
if ($grade_item->scaleid) {
// using scales
if ($scale = get_record('scale', 'id', $grade_item->scaleid)) {
// reindex because scale is off 1
// invalid grade if gradeval < 1
if ((int) $grade_grade->finalgrade < 1) {
- $data[] = '-';
+ $data[] = $excluded.'-';
} else {
- $data[] = $scales[$grade_grade->finalgrade-1];
+ $data[] = $excluded.$scales[$grade_grade->finalgrade-1];
}
}
} else {
// normal grade, or text, just display
- $data[] = $this->get_grade_clean($grade_grade->finalgrade);
+ $data[] = $excluded.$this->get_grade_clean($grade_grade->finalgrade);
}
/// prints percentage
$string['dropped'] = 'Dropped';
$string['dropxlowest'] = 'Drop X Lowest';
$string['dropxlowestwarning'] = 'Note: If you use drop x lowest the grading assumes that all items in the category have the same point value. If point values differ results will be unpredictable';
-$string['editcalculation'] = 'Edit calculation';
+$string['editcalculation'] = 'Edit Calculation';
$string['editfeedback'] = 'Edit Feedback';
+$string['editgrade'] = 'Edit Grade';
$string['edittree'] = 'Categories';
$string['enableajax'] = 'Enable AJAX';
$string['encoding'] = 'Encoding';
$string['notteachererror'] = 'You must be a teacher to use this feature.';
$string['onascaleof'] = ' on a scale of $a->grademin to $a->grademax';
$string['outcome'] = 'Outcome';
+$string['overridden'] = 'Overridden';
$string['pctoftotalgrade'] = '%% of total grade';
$string['percent'] = 'Percent';
$string['percentage'] = 'Percentage';
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20070719" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20070721" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
<FIELD NAME="locked" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="not locked 0, locked from date" PREVIOUS="hidden" NEXT="locktime"/>
<FIELD NAME="locktime" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="automatic locking of final grade, 0 means none, date otherwise" PREVIOUS="locked" NEXT="exported"/>
<FIELD NAME="exported" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="date of last grade export, 0 if none" PREVIOUS="locktime" NEXT="overridden"/>
- <FIELD NAME="overridden" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="indicates grade overridden from gradebook, 0 means none, date means overridden" PREVIOUS="exported" NEXT="timecreated"/>
- <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="the time this grade was first created" PREVIOUS="overridden" NEXT="timemodified"/>
+ <FIELD NAME="overridden" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="indicates grade overridden from gradebook, 0 means none, date means overridden" PREVIOUS="exported" NEXT="excluded"/>
+ <FIELD NAME="excluded" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="grade excluded from aggregation functions, date means when excluded" PREVIOUS="overridden" NEXT="timecreated"/>
+ <FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="the time this grade was first created" PREVIOUS="excluded" NEXT="timemodified"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="false" UNSIGNED="true" SEQUENCE="false" ENUM="false" COMMENT="the time this grade was last modified" PREVIOUS="timecreated"/>
</FIELDS>
<KEYS>
<FIELD NAME="locked" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="not locked 0, locked from date" PREVIOUS="hidden" NEXT="locktime"/>
<FIELD NAME="locktime" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="automatic locking of final grade, 0 means none, date otherwise" PREVIOUS="locked" NEXT="exported"/>
<FIELD NAME="exported" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="date of last grade export, 0 if none" PREVIOUS="locktime" NEXT="overridden"/>
- <FIELD NAME="overridden" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="indicates grade overridden from gradebook, 0 means none, date means overridden" PREVIOUS="exported"/>
+ <FIELD NAME="overridden" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="indicates grade overridden from gradebook, 0 means none, date means overridden" PREVIOUS="exported" NEXT="excluded"/>
+ <FIELD NAME="excluded" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" ENUM="false" COMMENT="grade excluded from aggregation functions, date means when excluded" PREVIOUS="overridden"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="primary key of the table, please edit me" NEXT="oldid"/>
$table->addFieldInfo('locktime', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
$table->addFieldInfo('exported', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
$table->addFieldInfo('overridden', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
+ $table->addFieldInfo('excluded', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
$table->addFieldInfo('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
$table->addFieldInfo('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
$table->addFieldInfo('locktime', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
$table->addFieldInfo('exported', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
$table->addFieldInfo('overridden', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
+ $table->addFieldInfo('excluded', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
/// Adding keys to table grade_grades_history
$table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id'));
}
if ($result && $oldversion < 2007071000) {
- /// Remove obsoleted unitt tests tables - they will be recreated automatically
- $tables = array('grade_categories',
- 'scale',
- 'grade_items',
- 'grade_calculations',
- 'grade_grades',
- 'grade_grades_raw',
- 'grade_grades_final',
- 'grade_grades_text',
- 'grade_outcomes',
- 'grade_history');
-
- foreach ($tables as $table) {
- $table = new XMLDBTable('unittest_'.$table);
- if (table_exists($table)) {
- drop_table($table);
- }
- }
/// Define field overridden to be added to grade_grades
$table = new XMLDBTable('grade_grades');
$result = $result && create_table($table);
}
+ if ($result && $oldversion < 2007072100) {
+ /// Remove obsoleted unit tests tables - they will be recreated automatically
+ $tables = array('grade_categories',
+ 'scale',
+ 'grade_items',
+ 'grade_calculations',
+ 'grade_grades',
+ 'grade_grades_raw',
+ 'grade_grades_final',
+ 'grade_grades_text',
+ 'grade_outcomes',
+ 'grade_history');
+
+ foreach ($tables as $table) {
+ $table = new XMLDBTable('unittest_'.$table);
+ if (table_exists($table)) {
+ drop_table($table);
+ }
+ }
+
+ /// Define field excluded to be added to grade_grades
+ $table = new XMLDBTable('grade_grades');
+ $field = new XMLDBField('excluded');
+ $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'overridden');
+
+ /// Launch add field excluded
+ if (!field_exists($table, $field)) {
+ $result = $result && add_field($table, $field);
+ }
+
+ /// Define field excluded to be added to grade_grades
+ $table = new XMLDBTable('grade_grades_history');
+ $field = new XMLDBField('excluded');
+ $field->setAttributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0', 'overridden');
+
+ /// Launch add field excluded
+ if (!field_exists($table, $field)) {
+ $result = $result && add_field($table, $field);
+ }
+ }
+
return $result;
}
?>
if ($rs->RecordCount() > 0) {
$prevuser = 0;
$grade_values = array();
+ $excluded = array();
$oldgrade = null;
while ($used = rs_fetch_next_record($rs)) {
if ($used->userid != $prevuser) {
- $this->aggregate_grades($prevuser, $items, $grade_values, $oldgrade);
+ $this->aggregate_grades($prevuser, $items, $grade_values, $oldgrade, $excluded);
$prevuser = $used->userid;
$grade_values = array();
+ $excluded = array();
$oldgrade = null;
}
$grade_values[$used->itemid] = $used->finalgrade;
+ if ($used->excluded) {
+ $excluded[] = $used->itemid;
+ }
if ($this->grade_item->id == $used->itemid) {
$oldgrade = $used;
}
}
- $this->aggregate_grades($prevuser, $items, $grade_values, $oldgrade);//the last one
+ $this->aggregate_grades($prevuser, $items, $grade_values, $oldgrade, $excluded);//the last one
}
}
/**
* internal function for category grades aggregation
*/
- function aggregate_grades($userid, $items, $grade_values, $oldgrade) {
+ function aggregate_grades($userid, $items, $grade_values, $oldgrade, $excluded) {
if (empty($userid)) {
//ignore first call
return;
/// normalize the grades first - all will have value 0...1
// ungraded items are not used in aggregation
- foreach ($grade_values as $k=>$v) {
+ foreach ($grade_values as $itemid=>$v) {
if (is_null($v)) {
// null means no grade
- unset($grade_values[$k]);
+ unset($grade_values[$itemid]);
+ continue;
+ } else if (in_array($itemid, $excluded)) {
+ unset($grade_values[$itemid]);
continue;
}
- $grade_values[$k] = grade_grade::standardise_score($v, $items[$k]->grademin, $items[$k]->grademax, 0, 1);
+
+ $grade_values[$itemid] = grade_grade::standardise_score($v, $items[$itemid]->grademin, $items[$itemid]->grademax, 0, 1);
}
// use min grade if grade missing for these types
case GRADE_AGGREGATE_WEIGHTED_MEAN_ALL:
case GRADE_AGGREGATE_EXTRACREDIT_MEAN_ALL:
foreach($items as $itemid=>$value) {
- if (!isset($grade_values[$itemid])) {
+ if (!isset($grade_values[$itemid]) and !in_array($itemid, $excluded)) {
$grade_values[$itemid] = 0;
}
}
*/
var $overridden = 0;
+ /**
+ * Grade excluded from aggregation functions
+ * @var boolean $excluded
+ */
+ var $excluded = 0;
+
/**
* Loads the grade_grade_text object linked to this grade (through the intersection of itemid and userid), and
* saves it as a class variable for this final object.
return !empty($this->locked) or $this->grade_item->is_locked();
}
+ /**
+ * Checks if grade overridden
+ * @return boolean
+ */
function is_overridden() {
return !empty($this->overridden);
}
+ /**
+ * Set the overridden status of grade
+ * @param boolean $state requested overridden state
+ * @return boolean true is db state changed
+ */
+ function set_overridden($state) {
+ if (empty($this->overridden) and $state) {
+ $this->overridden = time();
+ $this->update();
+ return true;
+
+ } else if (!empty($this->overridden) and !$state) {
+ $this->overridden = 0;
+ $this->update();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if grade excluded from aggregation functions
+ * @return boolean
+ */
+ function is_excluded() {
+ return !empty($this->excluded);
+ }
+
+ /**
+ * Set the excluded status of grade
+ * @param boolean $state requested excluded state
+ * @return boolean true is db state changed
+ */
+ function set_excluded($state) {
+ if (empty($this->excluded) and $state) {
+ $this->excluded = time();
+ $this->update();
+ return true;
+
+ } else if (!empty($this->excluded) and !$state) {
+ $this->excluded = 0;
+ $this->update();
+ return true;
+ }
+ return false;
+ }
+
/**
* Lock/unlock this grade.
*
}
}
+ /**
+ * Get (or create if not exist yet) grade for this user
+ * @param int $userid
+ * @return object grade_grade object instance
+ */
+ function get_grade($userid) {
+ if (empty($this->id)) {
+ debugging('Can not use before insert');
+ return false;
+ }
+
+ $grade = new grade_grade(array('userid'=>$userid, 'itemid'=>$this->id));
+ if (empty($grade->id)) {
+ $grade->insert();
+ }
+
+ return $grade;
+ }
+
/**
* Returns the sortorder of this grade_item. This method is also available in
* grade_category, for cases where the object type is not know.
}
/**
- * This function is used to migrade old date and settings from old gradebook into new grading system.
+ * This function is used to migrade old data and settings from old gradebook into new grading system.
* @param int $courseid
*/
function grade_upgrade_oldgradebook($courseid) {
$course_category->update('upgrade');
}
+
+ $newitems = array();
// get all grade items with mod details
$sql = "SELECT gi.*, cm.idnumber as cmidnumber, m.name as modname
FROM {$CFG->prefix}grade_item gi, {$CFG->prefix}course_modules cm, {$CFG->prefix}modules m
if (!empty($olditem->category)) {
$newitem->set_parent($categories[$olditem->category]->id);
}
+ $newitems[$olditem->id] = $newitem;
}
}
- // setup up exception handling
+ // setup up exception handling - override grade with NULL
+ if ($exceptions = get_records('grade_exceptions', 'courseid', $courseid)) {
+ foreach ($exceptions as $exception) {
+ if (!array_key_exists($exception->grade_itemid, $newitems)) {
+ continue; // broken record
+ }
+ $grade_item = grade_item::fetch(array('id'=>$newitems[$exception->grade_itemid]));
+ $grade = $grade_item->get_grade($exception->userid);
+ $grade->excluded = time();
+ $grade->update();
+ }
+ }
}
/**
$table->addFieldInfo('locktime', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
$table->addFieldInfo('exported', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
$table->addFieldInfo('overridden', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
+ $table->addFieldInfo('excluded', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
$table->addFieldInfo('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
$table->addFieldInfo('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, null, null);
$table->addFieldInfo('locktime', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
$table->addFieldInfo('exported', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
$table->addFieldInfo('overridden', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
+ $table->addFieldInfo('excluded', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null, null, '0');
/// Adding keys to table grade_grades_history
$table->addKeyInfo('primary', XMLDB_KEY_PRIMARY, array('id'));
// This is compared against the values stored in the database to determine
// whether upgrades should be performed (see lib/db/*.php)
- $version = 2007071900; // YYYYMMDD = date
+ $version = 2007072100; // YYYYMMDD = date
// XY = increments within a single day
$release = '1.9 dev'; // Human-friendly version name