From d7f1cc4c3b8c9825cbfea882701caea524b3cedc Mon Sep 17 00:00:00 2001 From: nicolasconnault Date: Fri, 18 May 2007 05:34:30 +0000 Subject: [PATCH] MDL-9506 Fixed up the grade_tree and its unit tests. The main change to notice is in grade_category, where the array returned by get_children() is indexed by sortorder. The associated unit tests have been updated to reflect this important change. --- lib/grade/grade_category.php | 3 +- lib/grade/grade_tree.php | 128 +++++++++++++++--- .../grade/simpletest/testgradecategory.php | 22 +-- .../grade/simpletest/testgradetree.php | 94 +++++++++---- 4 files changed, 189 insertions(+), 58 deletions(-) diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index 5a8ee86db1..dc7bd858ef 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -617,7 +617,6 @@ class grade_category extends grade_object { * @return string */ function get_childrentype() { - $children = $this->children; if (empty($this->children)) { $count_item_children = count_records('grade_items', 'categoryid', $this->id); $count_cat_children = count_records('grade_categories', 'parent', $this->id); @@ -630,7 +629,7 @@ class grade_category extends grade_object { return null; } } - return get_class($children[0]); + return get_class($this->children[0]); } /** diff --git a/lib/grade/grade_tree.php b/lib/grade/grade_tree.php index 3a9598203b..8cad32c30b 100644 --- a/lib/grade/grade_tree.php +++ b/lib/grade/grade_tree.php @@ -83,19 +83,21 @@ class grade_tree { function locate_element($sortorder) { $topcatcount = 0; $retval = false; - debugging($sortorder); + if (empty($this->tree_array)) { debugging("grade_tree->tree_array was empty, I could not locate the element at sortorder $sortorder"); return false; } - foreach ($this->tree_array as $key1 => $level1) { + $level1count = 0; + + foreach ($this->tree_array as $levelkey1 => $level1) { $level1count++; $level2count = 0; $retval = new stdClass(); - $retval->index = $key1; + $retval->index = $levelkey1; - if ($key1 == $sortorder) { + if ($levelkey1 == $sortorder) { $retval->element = $level1; $retval->position = $level1count; return $retval; @@ -106,7 +108,7 @@ class grade_tree { $level2count++; $level3count = 0; - $retval->index .= "/$level2key"; + $retval->index = "$levelkey1/$level2key"; if ($level2key == $sortorder) { $retval->element = $level2; $retval->position = $level2count; @@ -116,7 +118,7 @@ class grade_tree { if (!empty($level2['children'])) { foreach ($level2['children'] as $level3key => $level3) { $level3count++; - $retval->index .= "/$level3key"; + $retval->index = "$levelkey1/$level2key/$level3key"; if ($level3key == $sortorder) { $retval->element = $level3; @@ -131,6 +133,50 @@ class grade_tree { return $retval; } + /** + * Given an element object, returns its type (topcat, subcat or item). + * @param object $element + * @return string Type + */ + function get_element_type($element) { + if (!empty($element->element['object'])) { + $object = $element->element['object']; + } elseif (!empty($element['object'])) { + $object = $element['object']; + } elseif (is_object($element)) { + $object = $element; + } else { + debugging("Invalid element given to grade_tree::get_element_type."); + return false; + } + + if (get_class($object) == 'grade_item') { + return 'item'; + } elseif (get_class($object) == 'grade_category') { + $object->get_children(); + if (!empty($object->children)) { + $first_child = current($object->children); + if (get_class($first_child) == 'grade_item') { + return 'subcat'; + } elseif (get_class($first_child) == 'grade_category') { + return 'topcat'; + } else { + debugging("The category's first child was neither a category nor an item."); + return false; + } + } else { + debugging("The category did not have any children."); + return false; + } + } else { + debugging("Invalid element given to grade_tree::get_element_type."); + return false; + } + + debugging("Could not determine the type of the given element."); + return false; + } + /** * Removes the given element (a stdClass object or a sortorder), remove_elements * it from the tree. This does not renumber the tree. @@ -167,6 +213,9 @@ class grade_tree { return false; } } + + debugging("Unable to remove an element from the grade_tree."); + return false; } /** @@ -190,23 +239,48 @@ class grade_tree { debugging('move_element(..... $position) can only be "before" or "after", you gave ' . $position); return false; } + + if (is_array($element)) { + $new_element = new stdClass(); + $new_element->element = $element; + } elseif (is_object($element)) { + $new_element = $element; + } + + // If the object is a grade_item, but the final_grades index isn't yet loaded, make the switch now. Same for grade_category and children + if (get_class($new_element->element['object']) == 'grade_item' && empty($new_element->element['final_grades'])) { + $new_element->element['final_grades'] = $new_element->element['object']->load_final(); + unset($new_element->element['object']->grade_grades_final); + } elseif (get_class($new_element->element['object']) == 'grade_category' && + empty($new_element->element['children']) && + $new_element->element['object']->has_children()) { + $new_element->element['children'] = $new_element->element['object']->get_children(1); + unset($new_element->element['object']->children); + } + // TODO Problem when moving topcategories: sortorder gets reindexed when splicing the array - $destination_array = array($destination_sortorder => $element->element); + $destination_array = array($destination_sortorder => $new_element->element); // Get the position of the destination element $destination_element = $this->locate_element($destination_sortorder); $position = $destination_element->position; - + // Decompose the element's index and build string for eval(array_splice) statement to follow - $indices = explode('/', $element->index); + $indices = explode('/', $destination_element->index); + + if (empty($indices)) { + debugging("The destination element did not have a valid index (as assigned by grade_tree::locate_element)."); + return false; + } + $element_to_splice = '$this->tree_array'; - if (isset($indices[0])) { + if (isset($indices[1])) { $element_to_splice .= '[' . $indices[0] . "]['children']"; } - if (isset($indices[1])) { + if (isset($indices[2])) { $element_to_splice .= '[' . $indices[1] . "]['children']"; } @@ -235,11 +309,6 @@ class grade_tree { $this->remove_element($source); $destination = $this->locate_element($destination_sortorder); - - if (substr_count($destination->index, '/') != substr_count($source->index, '/')) { - debugging("Source and Destination were at different levels."); - return false; - } // Insert the element before the destination sortorder $this->insert_element($source, $destination_sortorder, $position); @@ -366,11 +435,21 @@ class grade_tree { unset($fillers[$sortorder]); $this->tree_filled[$sortorder] = $this->get_filler($object, $fullobjects); + $element = array(); + if (get_class($object) == 'grade_category') { - $object->get_children(); + $children = $object->get_children(1); + unset($object->children); + $element['children'] = $children; + } elseif (get_class($object) == 'grade_item') { + $final_grades = $object->get_final(); + unset($object->grade_grades_final); + $element['final_grades'] = $final_grades; } + $object->sortorder = $sortorder; - $tree[$sortorder] = $object; + $element['object'] = $object; + $tree[$sortorder] = $element; } $query = "SELECT $category_table.*, sortorder FROM $category_table, $items_table @@ -432,11 +511,20 @@ class grade_tree { if (!empty($fillers)) { foreach ($fillers as $sortorder => $object) { $this->tree_filled[$sortorder] = $this->get_filler($object, $fullobjects); + if (get_class($object) == 'grade_category') { - $object->get_children(); + $children = $object->get_children(1); + unset($object->children); + $element['children'] = $children; + } elseif (get_class($object) == 'grade_item') { + $final_grades = $object->get_final(); + unset($object->grade_grades_final); + $element['final_grades'] = $final_grades; } + $object->sortorder = $sortorder; - $tree[$sortorder] = $object; + $element['object'] = $object; + $tree[$sortorder] = $element; } } diff --git a/lib/simpletest/grade/simpletest/testgradecategory.php b/lib/simpletest/grade/simpletest/testgradecategory.php index 922f27e755..c50fb268a9 100755 --- a/lib/simpletest/grade/simpletest/testgradecategory.php +++ b/lib/simpletest/grade/simpletest/testgradecategory.php @@ -129,14 +129,14 @@ class grade_category_test extends gradelib_test { $children_array = $category->get_children(0); $this->assertTrue(is_array($children_array)); - $this->assertTrue(!empty($children_array[0])); - $this->assertTrue(!empty($children_array[0]['object'])); - $this->assertTrue(!empty($children_array[0]['children'])); - $this->assertEqual($this->grade_categories[1]->id, $children_array[0]['object']->id); - $this->assertEqual($this->grade_categories[2]->id, $children_array[1]['object']->id); - $this->assertEqual($this->grade_items[0]->id, $children_array[0]['children'][0]['object']->id); - $this->assertEqual($this->grade_items[1]->id, $children_array[0]['children'][1]['object']->id); - $this->assertEqual($this->grade_items[2]->id, $children_array[1]['children'][0]['object']->id); + $this->assertFalse(empty($children_array[2])); + $this->assertFalse(empty($children_array[2]['object'])); + $this->assertFalse(empty($children_array[2]['children'])); + $this->assertEqual($this->grade_categories[1]->id, $children_array[2]['object']->id); + $this->assertEqual($this->grade_categories[2]->id, $children_array[5]['object']->id); + $this->assertEqual($this->grade_items[0]->id, $children_array[2]['children'][3]['object']->id); + $this->assertEqual($this->grade_items[1]->id, $children_array[2]['children'][4]['object']->id); + $this->assertEqual($this->grade_items[2]->id, $children_array[5]['children'][6]['object']->id); $children_array = $category->get_children(0, 'flat'); $this->assertEqual(5, count($children_array)); @@ -149,9 +149,9 @@ class grade_category_test extends gradelib_test { $children = get_records('grade_items', 'categoryid', $this->grade_categories[1]->id); $children_array = grade_category::children_to_array($children, 'nested', 'grade_item'); $this->assertTrue(is_array($children_array)); - $this->assertTrue(isset($children_array[0])); - $this->assertTrue(isset($children_array[0]['object'])); - $this->assertEqual($this->grade_items[0]->id, $children_array[0]['object']->id); + $this->assertTrue(isset($children_array[3])); + $this->assertTrue(isset($children_array[3]['object'])); + $this->assertEqual($this->grade_items[0]->id, $children_array[3]['object']->id); } function test_grade_category_has_children() { diff --git a/lib/simpletest/grade/simpletest/testgradetree.php b/lib/simpletest/grade/simpletest/testgradetree.php index f657c14f30..bcbe23148c 100644 --- a/lib/simpletest/grade/simpletest/testgradetree.php +++ b/lib/simpletest/grade/simpletest/testgradetree.php @@ -35,23 +35,75 @@ global $CFG; require_once($CFG->libdir . '/simpletest/testgradelib.php'); class grade_tree_test extends gradelib_test { + /* + function test_grade_tree_locate_element() { + $tree = new grade_tree($this->courseid); + $element = $tree->locate_element(5); + $this->assertEqual('1/5', $element->index); + $this->assertNotNull($element->element); + $this->assertEqual('unittestcategory3', $element->element['object']->fullname); + $this->assertEqual('unittestgradeitem3', $element->element['children'][6]['object']->itemname); + + // Locate a grade_item + $element = $tree->locate_element(9); + $this->assertEqual('8/9', $element->index); + $this->assertNotNull($element->element); + $this->assertEqual('singleparentitem1', $element->element['object']->itemname); + } + + function test_grade_tree_insert_grade_subcategory() { + $tree = new grade_tree($this->courseid); + $grade_category = new grade_category($this->grade_categories[3]); + $element = array('object' => $grade_category); + + $tree->insert_element($element, 5); + $this->assertFalse(empty($tree->tree_array[1]['children'][1]['object']->fullname)); + $this->assertEqual($this->grade_categories[3]->fullname, $tree->tree_array[1]['children'][1]['object']->fullname); + $this->assertFalse(empty($tree->tree_array[1]['children'][1]['children'][9])); + $this->assertEqual($this->grade_items[7]->itemname, $tree->tree_array[1]['children'][1]['children'][9]['object']->itemname); + } + + function test_grade_tree_insert_grade_topcategory() { + $tree = new grade_tree($this->courseid); + $grade_category = new grade_category($this->grade_categories[0]); + $element = array('object' => $grade_category); + + $tree->insert_element($element, 8); + + $this->assertFalse(empty($tree->tree_array[2]['object']->fullname)); + $this->assertEqual($this->grade_categories[0]->fullname, $tree->tree_array[2]['object']->fullname); + $this->assertFalse(empty($tree->tree_array[2]['children'][2]['object']->fullname)); + $this->assertEqual($this->grade_categories[1]->fullname, $tree->tree_array[2]['children'][2]['object']->fullname); + } + + function test_grade_tree_insert_grade_item() { + $tree = new grade_tree($this->courseid); + $grade_item = new grade_item($this->grade_items[2]); + $element = array('object' => $grade_item); + $tree->insert_element($element, 4); + $this->assertFalse(empty($tree->tree_array[1]['children'][2]['children'][1]['object']->itemname)); + $this->assertEqual($this->grade_items[2]->itemname, $tree->tree_array[1]['children'][2]['children'][1]['object']->itemname); + $this->assertFalse(empty($tree->tree_array[1]['children'][2]['children'][1]['final_grades'][1])); + $this->assertEqual($this->grade_grades_final[6]->gradevalue, $tree->tree_array[1]['children'][2]['children'][1]['final_grades'][1]->gradevalue); + } +*/ function test_grade_tree_move_element() { $tree = new grade_tree($this->courseid); - $tree->move_element(4, 9); + $tree->move_element(4, 10); $this->assertFalse(empty($tree->tree_array[8]['children'][1])); $this->assertEqual('unittestgradeitem2', $tree->tree_array[8]['children'][1]['object']->itemname); $tree->renumber(); $this->assertFalse(empty($tree->tree_array[1]['children'][4]['children'][5])); - $this->assertEqual('unittestgradeitem2', $tree->tree_array[1]['children'][4]['children'][5]['object']->itemname); + $this->assertEqual('unittestgradeitem3', $tree->tree_array[1]['children'][4]['children'][5]['object']->itemname); $tree->move_element(6, 3, 'after'); $this->assertFalse(empty($tree->tree_array[1]['children'][2]['children'][1])); - $this->assertEqual('unittestgradeitem3', $tree->tree_array[1]['children'][2]['children'][1]['object']->itemname); + $this->assertEqual('unittestorphangradeitem1', $tree->tree_array[1]['children'][2]['children'][1]['object']->itemname); $tree->renumber(); $this->assertFalse(empty($tree->tree_array[1]['children'][2]['children'][4])); - $this->assertEqual('unittestgradeitem3', $tree->tree_array[1]['children'][2]['children'][4]['object']->itemname); + $this->assertEqual('unittestorphangradeitem1', $tree->tree_array[1]['children'][2]['children'][4]['object']->itemname); // Try moving a subcategory $tree->move_element(2, 5, 'after'); @@ -68,13 +120,21 @@ class grade_tree_test extends gradelib_test { $new_count = count($tree->tree_array, COUNT_RECURSIVE); $this->assertEqual($original_count, $new_count); $this->assertFalse(empty($tree->tree_array[1]['children'][1])); - $this->assertEqual('unittestcategory2', $tree->tree_array[1]['children'][1]['object']->fullname); + $this->assertEqual('level1category', $tree->tree_array[1]['children'][1]['object']->fullname); $tree->renumber(); $this->assertFalse(empty($tree->tree_array[1]['children'][5])); - $this->assertEqual('unittestcategory2', $tree->tree_array[1]['children'][5]['object']->fullname); - $this->assertEqual('unittestcategory2', $tree->tree_array[1]['children'][5]['children'][6]->itemname); - } + $this->assertEqual('level1category', $tree->tree_array[1]['children'][5]['object']->fullname); + $this->assertEqual('singleparentitem1', $tree->tree_array[1]['children'][5]['children'][6]['object']->itemname); + // Try moving a top category + $tree = new grade_tree($this->courseid); + $tree->move_element(1, 8); + $this->assertFalse(empty($tree->tree_array[1])); + $this->assertEqual('unittestcategory1', $tree->tree_array[1]['object']->fullname); + $tree->renumber(); + $this->assertFalse(empty($tree->tree_array[2])); + $this->assertEqual('unittestcategory1', $tree->tree_array[2]['object']->fullname); + } function test_grade_tree_constructor() { $tree = new grade_tree($this->courseid); @@ -92,31 +152,15 @@ class grade_tree_test extends gradelib_test { function test_grade_tree_get_tree() { $tree = new grade_tree($this->courseid); $this->assertEqual(58, count($tree->tree_filled, COUNT_RECURSIVE)); - $this->assertEqual(29, count($tree->tree_array, COUNT_RECURSIVE)); + $this->assertEqual(44, count($tree->tree_array, COUNT_RECURSIVE)); } - function test_grade_tree_locate_element() { - $tree = new grade_tree($this->courseid); - $element = $tree->locate_element(5); - $this->assertEqual(1, $element->topcatindex); - $this->assertEqual(5, $element->subcatindex); - $this->assertTrue(empty($element->itemindex)); - $this->assertNotNull($element->element); - $this->assertEqual('unittestcategory3', $element->element['object']->fullname); - $this->assertEqual('unittestgradeitem3', $element->element['children'][6]['object']->itemname); - } - function test_grade_tree_renumber() { $tree = new grade_tree($this->courseid); $tree->renumber(); } - function test_grade_tree_insert_element() { - $tree = new grade_tree($this->courseid); - - } - function test_grade_tree_remove_element() { $tree = new grade_tree($this->courseid); -- 2.39.5