}
}
+ /**
+ * In addition to update() as defined in grade_object, call flag_for_update of parent categories, if applicable.
+ */
+ function update() {
+ $qualifies = $this->qualifies_for_update();
+
+ $result = parent::update();
+
+ /**
+ // Notify parent category of need to update.
+ if ($result && $qualifies) {
+ $this->load_parent_category();
+ if (!empty($this->parent_category)) {
+ if (!$this->parent_category->flag_for_update()) {
+ return false;
+ }
+ }
+ }
+*/
+ return $result;
+ }
+
+ /**
+ * If parent::delete() is successful, send flag_for_update message to parent category.
+ * @return boolean Success or failure.
+ */
+ function delete() {
+ $result = parent::delete();
+
+ if ($result) {
+ $this->load_parent_category();
+ if (!empty($this->parent_category)) {
+ $result = $result && $this->parent_category->flag_for_update();
+ }
+ }
+
+ return $result;
+ }
+
/**
* In addition to the normal insert() defined in grade_object, this method sets the depth
* and path for this object, and update the record accordingly. The reason why this must
$this->grade_item = $grade_item;
}
-
+ /**
+ // Notify parent category of need to update.
+ if ($result) {
+ $this->load_parent_category();
+ if (!empty($this->parent_category)) {
+ if (!$this->parent_category->flag_for_update()) {
+ return false;
+ }
+ }
+ }
+*/
return $result;
}
+
+ /**
+ * Compares the values held by this object with those of the matching record in DB, and returns
+ * whether or not these differences are sufficient to justify an update of all parent objects.
+ * This assumes that this object has an id number and a matching record in DB. If not, it will return false.
+ * @return boolean
+ */
+ function qualifies_for_update() {
+ if (empty($this->id)) {
+ return false;
+ }
+
+ $db_item = new grade_category(array('id' => $this->id));
+
+ $aggregationdiff = $db_item->aggregation != $this->aggregation;
+ $keephighdiff = $db_item->keephigh != $this->keephigh;
+ $droplowdiff = $db_item->droplow != $this->droplow;
+
+ if ($aggregationdiff || $keephighdiff || $droplowdiff) {
+ return true;
+ } else {
+ return false;
+ }
+ }
/**
* Sets this category's and its parent's grade_item.needsupdate to true.
*/
function flag_for_update() {
$result = true;
-
+
$this->load_grade_item();
+
+ if (empty($this->grade_item)) {
+ die("Associated grade_item object does not exist for this grade_category!" . print_object($this));
+ // TODO Send error message, this is a critical error: each category MUST have a matching grade_item object
+ }
+
$this->grade_item->needsupdate = true;
+
+ $result = $result && $this->grade_item->update();
+
$this->load_parent_category();
if (!empty($this->parent_category)) {
$result = $result && $this->parent_category->flag_for_update();
* @return object Grade_item
*/
function load_grade_item() {
- $params = get_record('grade_items', 'categoryid', $this->id, 'itemtype', 'category');
+ $grade_items = get_records_select('grade_items', "iteminstance = $this->id AND itemtype = 'category'", null, '*', 0, 1);
+
+ $params = current($grade_items);
$this->grade_item = new grade_item($params);
- // If the associated grade_item isn't yet created, do it now
+ // If the associated grade_item isn't yet created, do it now. But first try loading it, in case it exists in DB.
if (empty($this->grade_item->id)) {
$this->grade_item->iteminstance = $this->id;
$this->grade_item->itemtype = 'category';
* @var int $itemid
*/
var $itemid;
+
+ /**
+ * The grade_item object referenced by $this->itemid.
+ * @var object $grade_item
+ */
+ var $grade_item;
/**
* The id of the user this final grade belongs to.
}
}
+ /**
+ * Loads the grade_item object referenced by $this->itemid and saves it as $this->grade_item for easy access.
+ * @return object grade_item.
+ */
+ function load_grade_item() {
+ if (empty($this->grade_item) && !empty($this->itemid)) {
+ $this->grade_item = grade_item::fetch('id', $this->itemid);
+ }
+ return $this->grade_item;
+ }
+
/**
* Finds and returns a grade_grades_final object based on 1-3 field values.
*
* @var int $itemid
*/
var $itemid;
+
+ /**
+ * The grade_item object referenced by $this->itemid.
+ * @var object $grade_item
+ */
+ var $grade_item;
/**
* The id of the user this raw grade belongs to.
*/
function load_text() {
if (empty($this->grade_grades_text)) {
- return $this->grade_grades_text = grade_grades_text::fetch('itemid', $this->itemid, 'userid', $this->userid);
+ $this->grade_grades_text = grade_grades_text::fetch('itemid', $this->itemid, 'userid', $this->userid);
}
+ return $this->grade_grades_text;
+ }
+
+ /**
+ * Loads the grade_item object referenced by $this->itemid and saves it as $this->grade_item for easy access.
+ * @return object grade_item.
+ */
+ function load_grade_item() {
+ if (empty($this->grade_item) && !empty($this->itemid)) {
+ $this->grade_item = grade_item::fetch('id', $this->itemid);
+ }
+ return $this->grade_item;
}
/**
/**
* In addition to the normal updating set up in grade_object, this object also records
- * its pre-update value and its new value in the grade_history table.
+ * its pre-update value and its new value in the grade_history table. The grade_item
+ * object is also flagged for update.
*
* @param float $newgrade The new gradevalue of this object
* @param string $howmodified What caused the modification? manual/module/import/cron...
if ($result) {
// TODO Handle history recording error, such as displaying a notice, but still return true
grade_history::insert_change($this, $oldgrade, $howmodified, $note);
- return true;
+
+ // Notify parent grade_item of need to update
+ $this->load_grade_item();
+ $result = $result && $this->grade_item->flag_for_update();
+
+ return $result;
} else {
return false;
}
$this->grademax = count ($this->scale->scale_items);
$this->grademin = 0;
}
+
+ $result = parent::insert();
+
+ // Notify parent grade_item of need to update
+ $this->load_grade_item();
+ $result = $result && $this->grade_item->flag_for_update();
+
+ return $result;
+ }
- return parent::insert();
+ /**
+ * If parent::delete() is successful, send flag_for_update message to parent grade_item.
+ * @return boolean Success or failure.
+ */
+ function delete() {
+ $result = parent::delete();
+ if ($result) {
+ $this->load_grade_item();
+ return $this->grade_item->flag_for_update();
+ }
+ return $result;
}
}
*/
var $itemid;
+ /**
+ * The grade_item object referenced by $this->itemid.
+ * @var object $grade_item
+ */
+ var $grade_item;
+
/**
* The user.id this text refers to.
* @var int $userid
return false;
}
}
+
+ /**
+ * Loads the grade_item object referenced by $this->itemid and saves it as $this->grade_item for easy access.
+ * @return object grade_item.
+ */
+ function load_grade_item() {
+ if (empty($this->grade_item) && !empty($this->itemid)) {
+ $this->grade_item = grade_item::fetch('id', $this->itemid);
+ }
+ return $this->grade_item;
+ }
}
?>
var $categoryid;
/**
- * The grade_category object referenced by $this->categoryid.
+ * The grade_category object referenced by $this->categoryid or $this->iteminstance (itemtype must be == 'category' in that case).
* @var object $category
*/
var $category;
}
return $this->outcome;
}
+
+ /**
+ * Loads all the grade_grades_raw objects for this grade_item from the DB into grade_item::$grade_grades_raw array.
+ * @return array grade_grades_raw objects
+ */
+ function load_raw() {
+ $grade_raw_array = get_records('grade_grades_raw', 'itemid', $this->id);
+
+ if (empty($grade_raw_array)) {
+ return null;
+ }
+
+ foreach ($grade_raw_array as $r) {
+ $this->grade_grades_raw[$r->userid] = new grade_grades_raw($r);
+ }
+ return $this->grade_grades_raw;
+ }
+
+ /**
+ * Loads all the grade_grades_final objects for this grade_item from the DB into grade_item::$grade_grades_final array.
+ * @return array grade_grades_final objects
+ */
+ function load_final() {
+ $grade_final_array = get_records('grade_grades_final', 'itemid', $this->id);
+
+ if (empty($grade_final_array)) {
+ $this->generate_final();
+ $grade_final_array = get_records('grade_grades_final', 'itemid', $this->id);
+ }
+
+ if (empty($grade_final_array)) {
+ return false;
+ }
+
+ foreach ($grade_final_array as $f) {
+ $this->grade_grades_final[$f->userid] = new grade_grades_final($f);
+ }
+ return $this->grade_grades_final;
+ }
+
+ /**
+ * Returns the grade_category object this grade_item belongs to (if any).
+ * This category object may be the parent (referenced by categoryid) or the associated category
+ * (referenced by iteminstance).
+ *
+ * @return mixed grade_category object if applicable, NULL otherwise
+ */
+ function get_category() {
+ $category = null;
+
+ if (!empty($this->categoryid)) {
+ $category = grade_category::fetch('id', $this->categoryid);
+ } elseif (!empty($this->iteminstance) && $this->itemtype == 'category') {
+ $category = grade_category::fetch('id', $this->iteminstance);
+ }
+
+ return $category;
+ }
/**
* In addition to update() as defined in grade_object, handle the grade_outcome and grade_scale objects.
if (!empty($this->scale->id)) {
$this->scaleid = $this->scale->id;
}
+
+ $qualifies = $this->qualifies_for_update();
- return parent::update();
+ $result = parent::update();
+
+ if ($result && $qualifies) {
+ $category = $this->get_category();
+
+ if (!empty($category)) {
+ $result = $result && $category->flag_for_update();
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Compares the values held by this object with those of the matching record in DB, and returns
+ * whether or not these differences are sufficient to justify an update of all parent objects.
+ * This assumes that this object has an id number and a matching record in DB. If not, it will return false.
+ * @return boolean
+ */
+ function qualifies_for_update() {
+ if (empty($this->id)) {
+ return false;
+ }
+
+ $db_item = new grade_item(array('id' => $this->id));
+
+ $gradetypediff = $db_item->gradetype != $this->gradetype;
+ $grademaxdiff = $db_item->grademax != $this->grademax;
+ $grademindiff = $db_item->grademin != $this->grademin;
+ $scaleiddiff = $db_item->scaleid != $this->scaleid;
+ $outcomeiddiff = $db_item->outcomeid != $this->outcomeid;
+ $multfactordiff = $db_item->multfactor != $this->multfactor;
+ $plusfactordiff = $db_item->plusfactor != $this->plusfactor;
+ $needsupdatediff = $db_item->needsupdate != $this->needsupdate;
+
+ if ($gradetypediff || $grademaxdiff || $grademindiff || $scaleiddiff || $outcomeiddiff ||
+ $multfactordiff || $plusfactordiff || $needsupdatediff) {
+ return true;
+ } else {
+ return false;
+ }
}
/**
return false;
}
}
+
+ /**
+ * If parent::delete() is successful, send flag_for_update message to parent category.
+ * @return boolean Success or failure.
+ */
+ function delete() {
+ $result = parent::delete();
+ if ($result) {
+ $category = $this->get_category();
+ if (!empty($category)) {
+ return $category->flag_for_update();
+ }
+ }
+ return $result;
+ }
+ /**
+ * In addition to perform parent::insert(), this calls the grade_item's category's (if applicable) flag_for_update() method.
+ * @return int ID of the new grade_item record.
+ */
+ function insert() {
+ $result = parent::insert();
+
+ // Notify parent category of need to update. Note that a grade_item may not have a categoryid.
+ if ($result) {
+ $category = $this->get_category();
+ if (!empty($category)) {
+ if (!$category->flag_for_update()) {
+ return false;
+ }
+ }
+ }
+
+ return $result;
+ }
+
/**
* Returns the raw values for this grade item (as imported by module or other source).
* @param int $userid Optional: to retrieve a single raw grade
return $grade_raw_array;
}
- /**
- * Loads all the grade_grades_raw objects for this grade_item from the DB into grade_item::$grade_grades_raw array.
- * @return array grade_grades_raw objects
- */
- function load_raw() {
- $grade_raw_array = get_records('grade_grades_raw', 'itemid', $this->id);
-
- if (empty($grade_raw_array)) {
- return null;
- }
-
- foreach ($grade_raw_array as $r) {
- $this->grade_grades_raw[$r->userid] = new grade_grades_raw($r);
- }
- return $this->grade_grades_raw;
- }
-
/**
* Returns the final values for this grade item (as imported by module or other source).
* @param int $userid Optional: to retrieve a single final grade
return $grade_final_array;
}
- /**
- * Loads all the grade_grades_final objects for this grade_item from the DB into grade_item::$grade_grades_final array.
- * @return array grade_grades_final objects
- */
- function load_final() {
- $grade_final_array = get_records('grade_grades_final', 'itemid', $this->id);
-
- if (empty($grade_final_array)) {
- $this->generate_final();
- $grade_final_array = get_records('grade_grades_final', 'itemid', $this->id);
- }
-
- if (empty($grade_final_array)) {
- return false;
- }
-
- foreach ($grade_final_array as $f) {
- $this->grade_grades_final[$f->userid] = new grade_grades_final($f);
- }
- return $this->grade_grades_final;
- }
-
/**
* Once the raw_grades are imported or entered, this method uses the grade_item's calculation and rules to
* generate final grade entries in the DB.
}
}
- /**
- * Returns the grade_category object this grade_item belongs to (if any) and sets $this->category.
- *
- * @return mixed grade_category object if applicable, NULL otherwise
- */
- function load_category() {
- if (empty($this->category) && !empty($this->categoryid)) {
- $this->category = grade_category::fetch('id', $this->categoryid);
- }
- return $this->category;
- }
-
/**
* Returns the locked state of this grade_item (if the grade_item is locked OR no specific
* $userid is given) or the locked state of a specific grade within this item if a specific
$result = true;
$this->needsupdate = true;
- $this->load_parent_category();
- if (!empty($this->parent_category)) {
- $result = $result && $this->parent_category->flag_for_update();
+ $category = $this->get_category();
+
+ if (!empty($category)) {
+ $result = $result && $category->flag_for_update();
}
return $result;
$params = new stdClass();
$params->courseid = $this->courseid;
- $params->fullname = 'unittestcategory8';
+ $params->fullname = 'unittestcategory4';
$grade_category = new grade_category($params, false);
$grade_category->insert();
$params->fullname = 'unittestcategory5';
$grade_category = new grade_category($params, false);
$grade_category->insert();
+
$this->assertEqual(2, $grade_category->depth);
$this->assertEqual("$parentpath/$grade_category->id", $grade_category->path);
$parentpath = $grade_category->path;
$grade_category = new grade_category();
$this->assertTrue(method_exists($grade_category, 'insert'));
- $grade_category->fullname = 'unittestcategory3';
+ $grade_category->fullname = 'unittestcategory4';
$grade_category->courseid = $this->courseid;
$grade_category->aggregation = GRADE_AGGREGATE_MODE;
$grade_category->keephigh = 100;
$this->assertTrue($grade_category->update());
$fullname = get_field('grade_categories', 'fullname', 'id', $this->grade_categories[0]->id);
$this->assertEqual($grade_category->fullname, $fullname);
+
}
function test_grade_category_delete() {
$this->assertEqual($this->grade_grades_final[0]->gradevalue, $grade_grades_final->gradevalue);
}
+ function test_grade_grades_final_load_grade_item() {
+ $grade_grades_final = new grade_grades_final($this->grade_grades_final[0]);
+ $this->assertTrue(method_exists($grade_grades_final, 'load_grade_item'));
+ $this->assertNull($grade_grades_final->grade_item);
+ $this->assertTrue($grade_grades_final->itemid);
+ $this->assertNotNull($grade_grades_final->load_grade_item());
+ $this->assertNotNull($grade_grades_final->grade_item);
+ $this->assertEqual($this->grade_items[0]->id, $grade_grades_final->grade_item->id);
+ }
}
?>
// http://www.gnu.org/copyleft/gpl.html //
// //
///////////////////////////////////////////////////////////////////////////
-
+@set_time_limit(0);
/**
* Unit tests for grade_item object.
*
$grade_item->itemmodule = 'quiz';
$grade_item->iteminfo = 'Grade item used for unit testing';
+ // Check the grade_category's needsupdate variable first
+ $category = $grade_item->get_category();
+ $category->load_grade_item();
+ $this->assertNotNull($category->grade_item);
+ $this->assertFalse($category->grade_item->needsupdate);
+
$grade_item->insert();
+ // Now check the needsupdate variable, it should have been set to true
+ $this->assertTrue($category->grade_item->needsupdate);
+
$last_grade_item = end($this->grade_items);
$this->assertEqual($grade_item->id, $last_grade_item->id + 1);
$grade_item = new grade_item($this->grade_items[0]);
$this->assertTrue(method_exists($grade_item, 'delete'));
+ // Check the grade_category's needsupdate variable first
+ $category = $grade_item->get_category();
+ $category->load_grade_item();
+ $this->assertNotNull($category->grade_item);
+ $this->assertFalse($category->grade_item->needsupdate);
+
$this->assertTrue($grade_item->delete());
+
+ // Now check the needsupdate variable, it should have been set to true
+ $this->assertTrue($category->grade_item->needsupdate);
+
$this->assertFalse(get_record('grade_items', 'id', $grade_item->id));
}
$this->assertTrue(method_exists($grade_item, 'update'));
$grade_item->iteminfo = 'Updated info for this unittest grade_item';
+
+ // Check the grade_category's needsupdate variable first
+ $category= $grade_item->get_category();
+ $category->load_grade_item();
+ $this->assertNotNull($category->grade_item);
+ $this->assertFalse($category->grade_item->needsupdate);
+
$this->assertTrue($grade_item->update());
+
+ // Now check the needsupdate variable, it should NOT have been set to true, because insufficient changes to justify update.
+ $this->assertFalse($category->grade_item->needsupdate);
+
+ $grade_item->grademin = 14;
+ $this->assertTrue($grade_item->qualifies_for_update());
+ $this->assertTrue($grade_item->update(true));
+
+ // Now check the needsupdate variable, it should have been set to true
+ $this->assertTrue($category->grade_item->needsupdate);
+
$iteminfo = get_field('grade_items', 'iteminfo', 'id', $this->grade_items[0]->id);
$this->assertEqual($grade_item->iteminfo, $iteminfo);
}
+ function test_grade_item_qualifies_for_update() {
+ $grade_item = new grade_item($this->grade_items[0]);
+ $this->assertTrue(method_exists($grade_item, 'qualifies_for_update'));
+
+ $grade_item->iteminfo = 'Updated info for this unittest grade_item';
+
+ $this->assertFalse($grade_item->qualifies_for_update());
+
+ $grade_item->grademin = 14;
+
+ $this->assertTrue($grade_item->qualifies_for_update());
+ }
+
function test_grade_item_set_timecreated() {
$grade_item = new grade_item($this->grade_items[0]);
$this->assertTrue(method_exists($grade_item, 'set_timecreated'));
$this->assertEqual($calculation, $new_calculation->calculation);
}
- function test_grade_item_load_category() {
+ function test_grade_item_get_category() {
$grade_item = new grade_item($this->grade_items[0]);
- $this->assertTrue(method_exists($grade_item, 'load_category'));
+ $this->assertTrue(method_exists($grade_item, 'get_category'));
- $grade_item->load_category();
- $this->assertEqual($this->grade_categories[1]->fullname, $grade_item->category->fullname);
+ $category = $grade_item->get_category();
+ $this->assertEqual($this->grade_categories[1]->fullname, $category->fullname);
}
/**
$grade_grades_raw->grademax = 110;
$grade_grades_raw->grademin = 18;
+ // Check the grade_item's needsupdate variable first
+ $grade_grades_raw->load_grade_item();
+ $this->assertFalse($grade_grades_raw->grade_item->needsupdate);
+
$grade_grades_raw->insert();
+ // Now check the needsupdate variable, it should have been set to true
+ $this->assertTrue($grade_grades_raw->grade_item->needsupdate);
+
$last_grade_grades_raw = end($this->grade_grades_raw);
$this->assertEqual($grade_grades_raw->id, $last_grade_grades_raw->id + 1);
$grade_grades_raw = new grade_grades_raw($this->grade_grades_raw[0]);
$this->assertTrue(method_exists($grade_grades_raw, 'update'));
+ // Check the grade_item's needsupdate variable first
+ $grade_grades_raw->load_grade_item();
+ $this->assertFalse($grade_grades_raw->grade_item->needsupdate);
+
$this->assertTrue($grade_grades_raw->update(89));
$gradevalue = get_field('grade_grades_raw', 'gradevalue', 'id', $this->grade_grades_raw[0]->id);
$this->assertEqual($grade_grades_raw->gradevalue, $gradevalue);
+
+ // Now check the needsupdate variable, it should have been set to true
+ $this->assertTrue($grade_grades_raw->grade_item->needsupdate);
}
function test_grade_grades_raw_delete() {
$grade_grades_raw = new grade_grades_raw($this->grade_grades_raw[0]);
$this->assertTrue(method_exists($grade_grades_raw, 'delete'));
+ // Check the grade_item's needsupdate variable first
+ $grade_grades_raw->load_grade_item();
+ $this->assertFalse($grade_grades_raw->grade_item->needsupdate);
+
$this->assertTrue($grade_grades_raw->delete());
$this->assertFalse(get_record('grade_grades_raw', 'id', $grade_grades_raw->id));
+
+ // Now check the needsupdate variable, it should have been set to true
+ $this->assertTrue($grade_grades_raw->grade_item->needsupdate);
}
function test_grade_grades_raw_fetch() {
}
function test_grade_raw_load_text() {
+ $grade_grades_raw = new grade_grades_raw($this->grade_grades_raw[0]);
+ $this->assertTrue(method_exists($grade_grades_raw, 'load_text'));
+ $this->assertNull($grade_grades_raw->grade_grades_text);
+ $this->assertNotNull($grade_grades_raw->load_text());
+ $this->assertNotNull($grade_grades_raw->grade_grades_text);
+ $this->assertEqual($this->grade_grades_text[0]->id, $grade_grades_raw->grade_grades_text->id);
+ }
+ function test_grade_grades_raw_load_grade_item() {
+ $grade_grades_raw = new grade_grades_raw($this->grade_grades_raw[0]);
+ $this->assertTrue(method_exists($grade_grades_raw, 'load_grade_item'));
+ $this->assertNull($grade_grades_raw->grade_item);
+ $this->assertTrue($grade_grades_raw->itemid);
+ $this->assertNotNull($grade_grades_raw->load_grade_item());
+ $this->assertNotNull($grade_grades_raw->grade_item);
+ $this->assertEqual($this->grade_items[0]->id, $grade_grades_raw->grade_item->id);
}
+
}
?>
$this->assertEqual($this->grade_grades_text[0]->id, $grade_grades_text->id);
$this->assertEqual($this->grade_grades_text[0]->information, $grade_grades_text->information);
}
+
+ function test_grade_grades_text_load_grade_item() {
+ $grade_grades_text = new grade_grades_text($this->grade_grades_text[0]);
+ $this->assertTrue(method_exists($grade_grades_text, 'load_grade_item'));
+ $this->assertNull($grade_grades_text->grade_item);
+ $this->assertTrue($grade_grades_text->itemid);
+ $this->assertNotNull($grade_grades_text->load_grade_item());
+ $this->assertNotNull($grade_grades_text->grade_item);
+ $this->assertEqual($this->grade_items[0]->id, $grade_grades_text->grade_item->id);
+ }
}
?>
function load_grade_grades_text() {
$grade_grades_text = new stdClass();
- $grade_grades_text->gradesid = $this->grade_grades_raw[0]->id;
+ $grade_grades_text->itemid = $this->grade_grades_raw[0]->itemid;
+ $grade_grades_text->userid = $this->grade_grades_raw[0]->userid;
$grade_grades_text->information = 'Thumbs down';
$grade_grades_text->informationformat = FORMAT_PLAIN;
$grade_grades_text->feedback = 'Good, but not good enough..';