From: skodak Date: Thu, 9 Aug 2007 09:03:14 +0000 (+0000) Subject: various locking improvements and fixes, cron locktime support stilll missing X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=fb0e357051d4d5109de514d5b34ae0c2fe4bd85a;p=moodle.git various locking improvements and fixes, cron locktime support stilll missing --- diff --git a/grade/edit/tree/action.php b/grade/edit/tree/action.php index b7b83e0aa7..a239781d87 100644 --- a/grade/edit/tree/action.php +++ b/grade/edit/tree/action.php @@ -62,7 +62,7 @@ switch ($action) { if ($type == 'grade' and empty($object->id)) { $object->insert(); } - $object->set_locked(1); + $object->set_locked(1, true, true); } break; @@ -74,7 +74,7 @@ switch ($action) { if ($type == 'grade' and empty($object->id)) { $object->insert(); } - $object->set_locked(0); + $object->set_locked(0, true, true); } break; } diff --git a/grade/edit/tree/grade.php b/grade/edit/tree/grade.php index 3a0b01753f..8e5bb5f48a 100644 --- a/grade/edit/tree/grade.php +++ b/grade/edit/tree/grade.php @@ -95,6 +95,10 @@ if ($grade = get_record('grade_grades', 'itemid', $grade_item->id, 'userid', $us $grade->hiddenuntil = 0; } + if ($grade_item->is_locked()) { + $grade->locked = 1; + } + $mform->set_data($grade); } else { @@ -109,14 +113,22 @@ if ($mform->is_cancelled()) { $old_grade_grade = new grade_grade(array('userid'=>$data->userid, 'itemid'=>$grade_item->id), true); //might not exist yet // fix no grade for scales - if ($grade_item->gradetype == GRADE_TYPE_SCALE and $data->finalgrade < 1) { + if (!isset($data->finalgrade)) { + $data->finalgrade = $old_grade_grade->finalgrade; + + } else if ($grade_item->gradetype == GRADE_TYPE_SCALE and $data->finalgrade < 1) { $data->finalgrade = NULL; } + if (!isset($data->feedback)) { + $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_grade = grade_grade::fetch(array('userid'=>$data->userid, 'itemid'=>$grade_item->id)); + $grade_grade->grade_item =& $grade_item; // no db fetching if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:hide', $context)) { if (empty($data->hidden)) { @@ -130,33 +142,43 @@ if ($mform->is_cancelled()) { } } - if (has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:override', $context)) { - // 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 (isset($data->locked) and !$grade_item->is_locked()) { + if (($old_grade_grade->locked or $old_grade_grade->locktime) + and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context))) { + //ignore data + + } else if ((!$old_grade_grade->locked and !$old_grade_grade->locktime) + and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context))) { + //ignore data + + } else { + $grade_grade->set_locktime($data->locktime); //set_lock may reset locktime + $grade_grade->set_locked($data->locked, false, true); } } - if (has_capability('moodle/grade:manage', $context)) { - if ($grade_grade->set_excluded($data->excluded)) { - $grade_item->force_regrading(); + if (isset($data->excluded) and has_capability('moodle/grade:manage', $context)) { + $grade_grade->set_excluded($data->excluded); + } + + if (isset($data->overridden) and has_capability('moodle/grade:manage', $context) or has_capability('moodle/grade:override', $context)) { + // ignore overridden flag when changing final grade + if ($old_grade_grade->finalgrade == $grade_grade->finalgrade) { + $grade_grade->set_overridden($data->overridden); } } - if (($old_grade_grade->locked or $old_grade_grade->locktime) - and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context))) { - //ignore data + // detect cases when we need to do full regrading + if ($old_grade_grade->excluded != $grade_grade->excluded) { + $parent = $grade_item->get_parent_category(); + $parent->force_regrading(); - } else if ((!$old_grade_grade->locked and !$old_grade_grade->locktime) - and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context))) { - //ignore data + } else if ($old_grade_grade->overridden != $grade_grade->overridden and empty($grade_grade->overridden)) { // only when unoverriding + $grade_item->force_regrading(); - } else { - $grade_grade->set_locked($data->locked); - $grade_grade->set_locktime($data->locktime); - } + } else if ($old_grade_grade->locktime != $grade_grade->locktime) { + $grade_item->force_regrading(); + } redirect($returnurl); } diff --git a/grade/edit/tree/grade_form.php b/grade/edit/tree/grade_form.php index 40c679517c..2a87ce8ac0 100755 --- a/grade/edit/tree/grade_form.php +++ b/grade/edit/tree/grade_form.php @@ -135,20 +135,33 @@ class edit_grade_form extends moodleform { } $old_grade_grade = new grade_grade(array('itemid'=>$grade_item->id, 'userid'=>$userid)); - if (empty($old_grade_grade->id)) { - $old_grade_grade->locked = $grade_item->locked; - $old_grade_grade->locktime = $grade_item->locktime; - } - if (($old_grade_grade->locked or $old_grade_grade->locktime) - and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context))) { - $mform->hardFreeze('locked'); - $mform->hardFreeze('locktime'); + if ($old_grade_grade->is_locked()) { + if ($grade_item->is_locked()) { + $mform->hardFreeze('locked'); + $mform->hardFreeze('locktime'); + } + + $mform->hardFreeze('overridden'); + $mform->hardFreeze('finalgrade'); + $mform->hardFreeze('feedback'); + + } else { + if (empty($old_grade_grade->id)) { + $old_grade_grade->locked = $grade_item->locked; + $old_grade_grade->locktime = $grade_item->locktime; + } - } else if ((!$old_grade_grade->locked and !$old_grade_grade->locktime) - and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context))) { - $mform->hardFreeze('locked'); - $mform->hardFreeze('locktime'); + if (($old_grade_grade->locked or $old_grade_grade->locktime) + and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:unlock', $context))) { + $mform->hardFreeze('locked'); + $mform->hardFreeze('locktime'); + + } else if ((!$old_grade_grade->locked and !$old_grade_grade->locktime) + and (!has_capability('moodle/grade:manage', $context) and !has_capability('moodle/grade:lock', $context))) { + $mform->hardFreeze('locked'); + $mform->hardFreeze('locktime'); + } } } } diff --git a/grade/edit/tree/item.php b/grade/edit/tree/item.php index 6156deedfa..3919c03b7c 100644 --- a/grade/edit/tree/item.php +++ b/grade/edit/tree/item.php @@ -40,6 +40,8 @@ if ($item = get_record('grade_items', 'id', $id, 'courseid', $course->id)) { $item->hiddenuntil = 0; } + $item->locked = !empty($item->locked); + // Get Item preferences $item->pref_gradedisplaytype = grade_report::get_pref('gradedisplaytype', $id); $item->pref_decimalpoints = grade_report::get_pref('decimalpoints', $id); @@ -58,6 +60,11 @@ if ($data = $mform->get_data(false)) { unset($data->hidden); unset($data->hiddenuntil); + $locked = empty($data->locked) ? 0: $data->locked; + $locktime = empty($data->locktime) ? 0: $data->locktime; + unset($data->locked); + unset($data->locktime); + $grade_item = new grade_item(array('id'=>$id, 'courseid'=>$courseid)); grade_item::set_properties($grade_item, $data); @@ -78,6 +85,9 @@ if ($data = $mform->get_data(false)) { $grade_item->set_hidden(1); } + $grade_item->set_locktime($locktime); // locktime first - it might be removed when unlocking + $grade_item->set_locked($locked, false, true); + // Handle user preferences if (isset($data->pref_gradedisplaytype)) { if (!grade_report::set_pref('gradedisplaytype', $data->pref_gradedisplaytype, $grade_item->id)) { diff --git a/grade/edit/tree/outcomeitem.php b/grade/edit/tree/outcomeitem.php index b22fadbf4d..1fe6457ed7 100644 --- a/grade/edit/tree/outcomeitem.php +++ b/grade/edit/tree/outcomeitem.php @@ -41,6 +41,8 @@ if ($item = get_record('grade_items', 'id', $id, 'courseid', $course->id)) { $item->hiddenuntil = 0; } + $item->locked = !empty($item->locked); + $item->calculation = grade_item::denormalize_formula($item->calculation, $course->id); if ($item->itemtype == 'mod') { @@ -63,6 +65,11 @@ if ($data = $mform->get_data(false)) { unset($data->hidden); unset($data->hiddenuntil); + $locked = empty($data->locked) ? 0: $data->locked; + $locktime = empty($data->locktime) ? 0: $data->locktime; + unset($data->locked); + unset($data->locktime); + $grade_item = new grade_item(array('id'=>$id, 'courseid'=>$courseid)); grade_item::set_properties($grade_item, $data); @@ -130,6 +137,9 @@ if ($data = $mform->get_data(false)) { $grade_item->set_hidden(1); } + $grade_item->set_locktime($locktime); // locktime first - it might be removed when unlocking + $grade_item->set_locked($locked, false, true); + redirect($returnurl); } diff --git a/grade/lib.php b/grade/lib.php index b03b962744..8f9c4e4afa 100644 --- a/grade/lib.php +++ b/grade/lib.php @@ -864,9 +864,9 @@ class grade_tree { $icon = 'unlock'; $tooltip = ''; - if ($element['object']->locktime > 1) { // Change the icon and add a tooltip showing the date + if ($element['type'] != 'category' and $element['object']->get_locktime() > 1) { // Change the icon and add a tooltip showing the date $icon = 'locktime'; - $tooltip = userdate($element['object']->locktime); + $tooltip = userdate($element['object']->get_locktime()); } if (!has_capability('moodle/grade:manage', $this->context) and !has_capability('moodle/grade:unlock', $this->context)) { diff --git a/lang/en_utf8/grades.php b/lang/en_utf8/grades.php index d7741c229c..ebbe0a557e 100644 --- a/lang/en_utf8/grades.php +++ b/lang/en_utf8/grades.php @@ -221,7 +221,7 @@ $string['linkedactivity'] = 'Linked activity'; $string['linkedactivityhelp'] = 'An optional activity this outcome item is linked to.'; $string['lock'] = 'Lock'; $string['locked'] = 'Locked'; -$string['locktime'] = 'Locked until'; +$string['locktime'] = 'Lock after'; $string['lowest'] = 'Lowest'; $string['lowgradeletter'] = 'Low'; $string['mapfrom'] = 'Map from'; diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index 921f188545..2b1ffd9f61 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -1009,29 +1009,33 @@ class grade_category extends grade_object { * Sets the grade_item's locked variable and updates the grade_item. * Method named after grade_item::set_locked(). * @param int $locked 0, 1 or a timestamp int(10) after which date the item will be locked. + * @param boolean $cascade lock/unlock child objects too * @param boolean $refresh refresh grades when unlocking * @return boolean success if category locked (not all children mayb be locked though) */ - function set_locked($lockedstate, $refresh=true) { + function set_locked($lockedstate, $cascade=false, $refresh=true) { $this->load_grade_item(); - $result = $this->grade_item->set_locked($lockedstate, true); - if ($children = grade_item::fetch_all(array('categoryid'=>$this->id))) { - foreach($children as $child) { - $child->set_locked($lockedstate, false); - if (empty($lockedstate) and $refresh) { - //refresh when unlocking - $child->refresh_grades(); + $result = $this->grade_item->set_locked($lockedstate, $cascade, true); + + if ($cascade) { + //process all children - items and categories + if ($children = grade_item::fetch_all(array('categoryid'=>$this->id))) { + foreach($children as $child) { + $child->set_locked($lockedstate, true, false); + if (empty($lockedstate) and $refresh) { + //refresh when unlocking + $child->refresh_grades(); + } } } - } - if ($children = grade_category::fetch_all(array('parent'=>$this->id))) { - foreach($children as $child) { - $child->set_locked($lockedstate, true); + if ($children = grade_category::fetch_all(array('parent'=>$this->id))) { + foreach($children as $child) { + $child->set_locked($lockedstate, true, true); + } } } - return $result; } diff --git a/lib/grade/grade_grade.php b/lib/grade/grade_grade.php index 59a90d014b..ff2e4ebad9 100644 --- a/lib/grade/grade_grade.php +++ b/lib/grade/grade_grade.php @@ -159,9 +159,20 @@ class grade_grade extends grade_object { * @return object grade_item. */ function load_grade_item() { - if (empty($this->grade_item) and !empty($this->itemid)) { + if (empty($this->itemid)) { + debugging('Missing itemid'); + $this->grade_item = null; + return null; + } + + if (empty($this->grade_item)) { + $this->grade_item = grade_item::fetch(array('id'=>$this->itemid)); + + } else if ($this->grade_item->id != $this->itemid) { + debugging('Itemid mismatch'); $this->grade_item = grade_item::fetch(array('id'=>$this->itemid)); } + return $this->grade_item; } @@ -254,17 +265,14 @@ class grade_grade extends grade_object { * Lock/unlock this grade. * * @param int $locked 0, 1 or a timestamp int(10) after which date the item will be locked. + * @param boolean $cascade ignored param * @param boolean $refresh refresh grades when unlocking * @return boolean true if sucessful, false if can not set new lock state for grade */ - function set_locked($lockedstate, $refresh=true) { + function set_locked($lockedstate, $cascade=false, $refresh=true) { $this->load_grade_item(); if ($lockedstate) { - if (!empty($this->locked)) { - return true; // already locked - } - if ($this->grade_item->needsupdate) { //can not lock grade if final not calculated! return false; @@ -276,17 +284,13 @@ class grade_grade extends grade_object { return true; } else { - if (empty($this->locked)) { - return true; // not locked - } - - if ($this->grade_item->is_locked()) { - return false; + if (!empty($this->locked) and $this->locktime < time()) { + //we have to reset locktime or else it would lock up again + $this->locktime = 0; } // remove the locked flag $this->locked = 0; - $this->update(); if ($refresh) { @@ -298,42 +302,79 @@ class grade_grade extends grade_object { } } - /** - * Set the locktime for this grade. - * - * @param int $locktime timestamp for lock to activate - * @return boolean true if sucessful, false if can not set new lock state for grade + * Lock the grade if needed - make sure this is called only when final grade is valid */ - function set_locktime($locktime) { + function check_locktime() { + if (!empty($this->locked)) { + return; // already locked - do not use is_locked() because we do not want the locking status of grade_item here + } - if ($locktime) { - // if current locktime is before, no need to reset + if ($this->locktime and $this->locktime < time()) { + $this->locked = time(); + $this->update('locktime'); + } + } - if ($this->locktime && $this->locktime <= $locktime) { - return true; - } - /* - if ($this->grade_item->needsupdate) { - //can not lock grade if final not calculated! - return false; + /** + * Lock the grade if needed - make sure this is called only when final grades are valid + * @param int $courseid + * @param array $items array of all grade item ids (speedup only) + * @return void + */ + function check_locktime_all($courseid, $items=null) { + global $CFG; + + if (!$items) { + if (!$items = get_records('grade_items', 'courseid', $courseid, '', 'id')) { + return; // no items? } - */ + $items = array_keys($items); + } - $this->locktime = $locktime; - $this->update(); + $items_sql = implode(',', $items); - return true; + $now = time(); // no rounding needed, this is not supposed to be called every 10 seconds - } else { + if ($rs = get_recordset_select('grade_grades', "itemid IN ($items_sql) AND locked = 0 AND locktime > 0 AND locktime < $now")) { + if ($rs->RecordCount() > 0) { + while ($grade = rs_fetch_next_record($rs)) { + $grade_grade = new grade_grade($grade, false); + $grade_grade->locked = time(); + $grade_grade->update('locktime'); + } + } + rs_close($rs); + } + } + + /** + * Set the locktime for this grade. + * + * @param int $locktime timestamp for lock to activate + * @return void + */ + function set_locktime($locktime) { + $this->locktime = $locktime; + $this->update(); + } - // remove the locktime timestamp - $this->locktime = 0; + /** + * Set the locktime for this grade. + * + * @return int $locktime timestamp for lock to activate + */ + function get_locktime() { + $this->load_grade_item(); - $this->update(); + $item_locktime = $this->grade_item->get_locktime(); - return true; + if (empty($this->locktime) or ($item_locktime and $item_locktime < $this->locktime)) { + return $item_locktime; + + } else { + return $this->locktime; } } diff --git a/lib/grade/grade_item.php b/lib/grade/grade_item.php index 1bd4c0e393..1c8aaa804b 100644 --- a/lib/grade/grade_item.php +++ b/lib/grade/grade_item.php @@ -266,6 +266,7 @@ class grade_item extends grade_object { $outcomeiddiff = $db_item->outcomeid != $this->outcomeid; $multfactordiff = $db_item->multfactor != $this->multfactor; $plusfactordiff = $db_item->plusfactor != $this->plusfactor; + $locktimediff = $db_item->locktime != $this->locktime; $acoefdiff = $db_item->aggregationcoef != $this->aggregationcoef; $needsupdatediff = !$db_item->needsupdate && $this->needsupdate; // force regrading only if setting the flag first time @@ -273,7 +274,7 @@ class grade_item extends grade_object { return ($calculationdiff || $categorydiff || $gradetypediff || $grademaxdiff || $grademindiff || $scaleiddiff || $outcomeiddiff || $multfactordiff || $plusfactordiff || $needsupdatediff - || $lockeddiff || $acoefdiff); + || $lockeddiff || $acoefdiff || $locktimediff); } /** @@ -425,61 +426,46 @@ class grade_item extends grade_object { /** * Locks or unlocks this grade_item and (optionally) all its associated final grades. * @param int $locked 0, 1 or a timestamp int(10) after which date the item will be locked. + * @param boolean $cascade lock/unlock child objects too * @param boolean $refresh refresh grades when unlocking * @return boolean true if grade_item all grades updated, false if at least one update fails */ - function set_locked($lockedstate, $refresh=true) { + function set_locked($lockedstate, $cascade=false, $refresh=true) { if ($lockedstate) { /// setting lock - if (!empty($this->locked)) { - return true; // already locked - } - if ($this->needsupdate) { - return false; // can not lock grade without first calculating final grade + return false; // can not lock grade without first having final grade } $this->locked = time(); $this->update(); - // this could be improved with direct SQL update - $result = true; - $grades = $this->get_final(); - foreach($grades as $g) { - $grade = new grade_grade($g, false); - $grade->grade_item =& $this; - if (!$grade->set_locked(1, false)) { - $result = false; + if ($cascade) { + $grades = $this->get_final(); + foreach($grades as $g) { + $grade = new grade_grade($g, false); + $grade->grade_item =& $this; + $grade->set_locked(1, null, false); } } - return $result; + return true; } else { /// removing lock - if (empty($this->locked)) { - return true; // not locked - } - - if (!empty($this->locktime) and $this->locktime < time()) { - return false; // can not unlock grade item that should be already locked + if (!empty($this->locked) and $this->locktime < time()) { + //we have to reset locktime or else it would lock up again + $this->locktime = 0; } $this->locked = 0; $this->update(); - // this could be improved with direct SQL update - $result = true; - if ($grades = grade_grade::fetch_all(array('itemid'=>$this->id))) { - foreach($grades as $grade) { - $grade->grade_item =& $this; - - if (!empty($grade->locktime) and $grade->locktime < time()) { - $result = false; // can not unlock grade that should be already locked - } - - if (!$grade->set_locked(0, false)) { - $result = false; + if ($cascade) { + if ($grades = grade_grade::fetch_all(array('itemid'=>$this->id))) { + foreach($grades as $grade) { + $grade->grade_item =& $this; + $grade->set_locked(0, null, false); } } } @@ -489,47 +475,64 @@ class grade_item extends grade_object { $this->refresh_grades(); } - return $result; - + return true; } } /** - * Set the locktime for this grade. - * - * @param int $locktime timestamp for lock to activate - * @return boolean true if sucessful, false if can not set new lock state for grade + * Lock the grade if needed - make sure this is called only when final grades are valid */ - function set_locktime($locktime) { - - if ($locktime) { - // if current locktime is before, no need to reset - - if ($this->locktime && $this->locktime <= $locktime) { - return true; - } - - /* - if ($this->grade_item->needsupdate) { - //can not lock grade if final not calculated! - return false; - } - */ + function check_locktime() { + if (!empty($this->locked)) { + return; // already locked + } - $this->locktime = $locktime; - $this->update(); + if ($this->locktime and $this->locktime < time()) { + $this->locked = time(); + $this->update('locktime'); + } + } - return true; + /** + * Lock all grade items if needed - make sure this is called only when final grades are valid + * @static + * @param int $courseid + * @return void + */ + function check_locktime_all($courseid) { + global $CFG; - } else { + $now = time(); // no need to round it here, executed from cron only + $sql = "SELECT * FROM {$CFG->prefix}grade_items + WHERE courseid=$courseid AND locked = 0 AND locktime > 0 AND locktime < $now"; - // remove the locktime timestamp - $this->locktime = 0; + if ($items = get_records_sql($sql)) { + foreach ($items as $item) { + $grade_item = new grade_grade($item, false); + $grade_item->locked = time(); + $grade_item->update('locktime'); + } + } + } - $this->update(); + /** + * Set the locktime for this grade item. + * + * @param int $locktime timestamp for lock to activate + * @return void + */ + function set_locktime($locktime) { + $this->locktime = $locktime; + $this->update(); + } - return true; - } + /** + * Set the locktime for this grade item. + * + * @return int $locktime timestamp for lock to activate + */ + function get_locktime() { + return $this->locktime; } /** @@ -579,11 +582,6 @@ class grade_item extends grade_object { $this->needsupdate = 0; //do not use $this->update() because we do not want this logged in grade_item_history set_field('grade_items', 'needsupdate', 0, 'id', $this->id); - - if (!empty($this->locktime) and empty($this->locked) and $this->locktime < time()) { - // time to lock this grade_item - $this->set_locked(true); - } } /** @@ -640,12 +638,13 @@ class grade_item extends grade_object { if ($rs) { if ($rs->RecordCount() > 0) { while ($grade_record = rs_fetch_next_record($rs)) { + $grade = new grade_grade($grade_record, false); + if (!empty($grade_record->locked) or !empty($grade_record->overridden)) { // this grade is locked - final grade must be ok continue; } - $grade = new grade_grade($grade_record, false); $grade->finalgrade = $this->adjust_grade($grade->rawgrade, $grade->rawgrademin, $grade->rawgrademax); if ($grade_record->finalgrade !== $grade->finalgrade) { @@ -653,13 +652,6 @@ class grade_item extends grade_object { $result = "Internal error updating final grade"; } } - - // time to lock this grade? - if (!empty($grade->locktime) and empty($grade->locked) and $grade->locktime < time()) { - $grade->locked = time(); - $grade->grade_item =& $this; - $grade->set_locked(true); - } } } rs_close($rs); @@ -1238,27 +1230,28 @@ class grade_item extends grade_object { if (!$grade = grade_grade::fetch(array('itemid'=>$this->id, 'userid'=>$userid))) { $grade = new grade_grade(array('itemid'=>$this->id, 'userid'=>$userid), false); } - $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 + $locktime = $grade->get_locktime(); + if ($locktime and $locktime < time()) { + // do not update grades that should be already locked and force regrade + $this->force_regrading(); return false; } + $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 ($finalgrade !== false) { if (!is_null($finalgrade)) { $grade->finalgrade = bounded_number($this->grademin, $finalgrade, $this->grademax); @@ -1266,7 +1259,10 @@ class grade_item extends grade_object { $grade->finalgrade = $finalgrade; } - if ($this->is_outcome_item()) { + if ($this->is_manual_item() and !$this->is_calculated()) { + // no overriding on manual grades - raw not used + + } else if ($this->is_outcome_item() and !$this->is_calculated()) { // no updates of raw grades for outcomes - raw grades not used } else if (!$this->is_normal_item() or $this->plusfactor != 0 or $this->multfactor != 1 @@ -1360,26 +1356,27 @@ class grade_item extends grade_object { if (!$grade = grade_grade::fetch(array('itemid'=>$this->id, 'userid'=>$userid))) { $grade = new grade_grade(array('itemid'=>$this->id, 'userid'=>$userid), false); } - $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; 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 + $locktime = $grade->get_locktime(); + if ($locktime and $locktime < time()) { + // do not update grades that should be already locked and force regrade + $this->force_regrading(); return false; } + $oldgrade = new object(); + $oldgrade->finalgrade = $grade->finalgrade; + $oldgrade->rawgrade = $grade->rawgrade; + $oldgrade->rawgrademin = $grade->rawgrademin; + $oldgrade->rawgrademax = $grade->rawgrademax; + $oldgrade->rawscaleid = $grade->rawscaleid; + // fist copy current grademin/max and scale $grade->rawgrademin = $this->grademin; $grade->rawgrademax = $this->grademax; @@ -1600,6 +1597,10 @@ class grade_item extends grade_object { $grade->update('system'); } + if ($result !== false) { + //lock grade if needed + } + if ($result === false) { return false; } else { diff --git a/lib/gradelib.php b/lib/gradelib.php index 8069ff2653..ad73350f68 100644 --- a/lib/gradelib.php +++ b/lib/gradelib.php @@ -435,8 +435,7 @@ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null) $depends_on = array(); // first mark all category and calculated items as needing regrading - // this is slower, but 100% accurate - this function is called only when there is - // a change in grading setup, update of individual grade does not trigger this function + // this is slower, but 100% accurate foreach ($grade_items as $gid=>$gitem) { if (!empty($updated_item) and $updated_item->id == $gid) { $grade_items[$gid]->needsupdate = 1; @@ -480,8 +479,10 @@ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null) if ($result === true) { $grade_items[$gid]->regrading_finished(); + $grade_items[$gid]->check_locktime(); // do the locktime item locking $count++; $finalids[] = $gid; + } else { $grade_items[$gid]->force_regrading(); $errors[$gid] = $result; @@ -508,6 +509,10 @@ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null) } if (count($errors) == 0) { + if (empty($userid)) { + // do the locktime locking of grades, but only when doing full regrading + grade_grade::check_locktime_all($courseid, $gids); + } return true; } else { return $errors;