]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-9506 MDL-9137 MDL-9629
authornicolasconnault <nicolasconnault>
Thu, 31 May 2007 03:15:43 +0000 (03:15 +0000)
committernicolasconnault <nicolasconnault>
Thu, 31 May 2007 03:15:43 +0000 (03:15 +0000)
Added a number of small getters and setters to grade_item and grade_category, to hide the structural differences between the two, and provide a common interface for cases when we are not sure whether an $object is of one type or another.
The grade_tree::renumber() method now adds complete objects to the need_update array, because both grade_category and grade_item need to update their parent field when moved to a different parent. Amazingly, these important changes worked straight away (after 1 hour of coding without testing anything), and all the unit tests passed!

lib/grade/grade_category.php
lib/grade/grade_item.php
lib/grade/grade_tree.php
theme/standard/styles_layout.css

index 585b2ffea672a04738ace061b3afc47247598f19..e104d89ec28af8825e6027d666b1ecfec2753ace 100644 (file)
@@ -193,6 +193,16 @@ class grade_category extends grade_object {
     function update() { 
         $qualifies = $this->qualifies_for_update();
 
+        // Update the grade_item's sortorder if needed
+        if (!empty($this->sortorder)) {
+            $this->load_grade_item();
+            if (!empty($this->grade_item)) {
+                $this->grade_item->sortorder = $this->sortorder;
+                $this->grade_item->update();
+            }
+            unset($this->sortorder);
+        } 
+
         $result = parent::update();
        
         // Use $this->path to update all parent categories
@@ -491,6 +501,57 @@ class grade_category extends grade_object {
         return $aggregated_grades;
     }
 
+    /**
+     * Given an array of stdClass children of a certain $object_type, returns a flat or nested
+     * array of these children, ready for appending to a tree built by get_children.
+     * @static
+     * @param array $children
+     * @param string $arraytype
+     * @param string $object_type
+     * @return array
+     */
+    function children_to_array($children, $arraytype='nested', $object_type='grade_item') {
+        $children_array = array();
+
+        foreach ($children as $id => $child) {
+            $child = new $object_type($child, false);
+            if ($arraytype == 'nested') {
+                $children_array[$child->get_sortorder()] = array('object' => $child);
+            } else {
+                $children_array[$child->get_sortorder()] = $child;
+            }
+        }        
+
+        return $children_array;
+    }
+
+    /**
+     * Returns true if this category has any child grade_category or grade_item.
+     * @return int number of direct children, or false if none found.
+     */
+    function has_children() {
+        return count_records('grade_categories', 'parent', $this->id) + count_records('grade_items', 'categoryid', $this->id);
+    }
+
+    /**
+     * This method checks whether an existing child exists for this
+     * category. If the new child is of a different type, the method will return false (not allowed).
+     * Otherwise it will return true.
+     * @param object $child This must be a complete object, not a stdClass
+     * @return boolean Success or failure
+     */
+    function can_add_child($child) {
+        if ($this->has_children()) {
+            if (get_class($child) != $this->get_childrentype()) {
+                return false;
+            } else {
+                return true;
+            }
+        } else {
+            return true;
+        }
+    }
+
     /**
      * Looks at a path string (e.g. /2/45/56) and returns the depth level represented by this path (in this example, 3).
      * If no string is given, it looks at the obect's path and assigns the resulting depth to its $depth variable.
@@ -567,74 +628,6 @@ class grade_category extends grade_object {
         return $children_array;
     }
   
-    /**
-     * Returns the sortorder of the associated grade_item. This method is also available in 
-     * grade_item, for cases where the object type is not know. It will act as a virtual 
-     * variable for a grade_category.
-     * @return int Sort order
-     */
-    function get_sortorder() {
-        if (empty($this->sortorder)) {
-            $this->load_grade_item();
-            if (!empty($this->grade_item)) {
-                return $this->grade_item->sortorder;
-            }
-        } else {
-            return $this->sortorder;
-        }
-    }
-
-    /**
-     * Given an array of stdClass children of a certain $object_type, returns a flat or nested
-     * array of these children, ready for appending to a tree built by get_children.
-     * @static
-     * @param array $children
-     * @param string $arraytype
-     * @param string $object_type
-     * @return array
-     */
-    function children_to_array($children, $arraytype='nested', $object_type='grade_item') {
-        $children_array = array();
-
-        foreach ($children as $id => $child) {
-            $child = new $object_type($child, false);
-            if ($arraytype == 'nested') {
-                $children_array[$child->get_sortorder()] = array('object' => $child);
-            } else {
-                $children_array[$child->get_sortorder()] = $child;
-            }
-        }        
-
-        return $children_array;
-    }
-
-    /**
-     * Returns true if this category has any child grade_category or grade_item.
-     * @return int number of direct children, or false if none found.
-     */
-    function has_children() {
-        return count_records('grade_categories', 'parent', $this->id) + count_records('grade_items', 'categoryid', $this->id);
-    }
-
-    /**
-     * This method checks whether an existing child exists for this
-     * category. If the new child is of a different type, the method will return false (not allowed).
-     * Otherwise it will return true.
-     * @param object $child This must be a complete object, not a stdClass
-     * @return boolean Success or failure
-     */
-    function can_add_child($child) {
-        if ($this->has_children()) {
-            if (get_class($child) != $this->get_childrentype()) {
-                return false;
-            } else {
-                return true;
-            }
-        } else {
-            return true;
-        }
-    }
-
     /**
      * Check the type of the first child of this category, to see whether it is a 
      * grade_category or a grade_item, and returns that type as a string (get_class).
@@ -834,5 +827,49 @@ class grade_category extends grade_object {
         $this->load_grade_item();
         return $this->grade_item->id;
     }
+
+    /**
+     * Returns this category's parent id. A generic method shared by objects that have a parent id of some kind.
+     * @return id $parentid
+     */
+    function get_parent_id() {
+        return $this->parent;
+    }
+
+    /**
+     * Sets this category's parent id. A generic method shared by objects that have a parent id of some kind.
+     * @param id $parentid
+     */
+    function set_parent_id($parentid) {
+        $this->parent = $parentid;
+    }
+    
+    /**
+     * Returns the sortorder of the associated grade_item. This method is also available in 
+     * grade_item, for cases where the object type is not know. It will act as a virtual 
+     * variable for a grade_category.
+     * @return int Sort order
+     */
+    function get_sortorder() {
+        if (empty($this->sortorder)) {
+            $this->load_grade_item();
+            if (!empty($this->grade_item)) {
+                return $this->grade_item->sortorder;
+            }
+        } else {
+            return $this->sortorder;
+        }
+    }
+
+    /**
+     * Sets a temporary sortorder variable for this category. It is used in the update() method to update the grade_item. 
+     * This method is also available in grade_item, for cases where the object type is not know. 
+     * @param int $sortorder
+     * @return void
+     */
+    function set_sortorder($sortorder) {
+        $this->sortorder = $sortorder;
+    }
+
 } 
 ?>
index d91a87a412e071d260610e10e7973f716cc12a86..5e9d76dd40e48b43418216bd6db5d7c8d6ea87ce 100644 (file)
@@ -213,141 +213,6 @@ class grade_item extends grade_object {
         $this->grade_object($params, $fetch);
     }
    
-    /**
-     * Instantiates a grade_scale object whose data is retrieved from the DB, 
-     * if this item's scaleid variable is set.
-     * @return object grade_scale
-     */
-    function load_scale() {
-        if (!empty($this->scaleid)) {
-            $this->scale = grade_scale::fetch('id', $this->scaleid);
-            if (method_exists($this->scale, 'load_items')) {
-                $this->scale->load_items();
-            } else { 
-                $this->scale = null;
-            } 
-        } 
-        return $this->scale;
-    }
-
-    /**
-     * Instantiates a grade_outcome object whose data is retrieved from the DB, 
-     * if this item's outcomeid variable is set.
-     * @return object grade_outcome
-     */
-    function load_outcome() {
-        if (!empty($this->outcomeid)) {
-            $this->outcome = grade_outcome::fetch('id', $this->outcomeid);
-        } 
-        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.
-     * @param boolean $generatefakenullgrades If set to true, AND $CFG->usenullgrades is true, will replace missing grades with grades, gradevalue=grademin
-     * @return array grade_grades_final objects
-     */      
-    function load_final($generatefakenullgrades=false) {
-        global $CFG;
-
-        $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)) {
-            debugging("No final grades recorded for this grade_item");
-            return false;
-        }
-
-        foreach ($grade_final_array as $f) {
-            $this->grade_grades_final[$f->userid] = new grade_grades_final($f);
-        }
-
-        $returnarray = fullclone($this->grade_grades_final);
-
-        // If we are generating fake null grades, we have to get a list of users
-        if ($generatefakenullgrades && $CFG->usenullgrades) {
-            $users = get_records_sql_menu('SELECT userid AS "user", userid FROM ' . $CFG->prefix . 'grade_grades_final GROUP BY userid ORDER BY userid');
-            if (!empty($users) && is_array($users)) {
-                foreach ($users as $userid) {
-                    if (!isset($returnarray[$userid])) {
-                        $fakefinal = new grade_grades_final();
-                        $fakefinal->itemid = $this->id;
-                        $fakefinal->userid = $userid;
-                        $fakefinal->gradevalue = $this->grademin;
-                        $returnarray[$userid] = $fakefinal;
-                    }
-                }
-            }
-        }
-
-        return $returnarray;
-    }
-
-    /**
-     * Returns an array of values (NOT objects) standardised from the final grades of this grade_item. They are indexed by userid.
-     * @return array integers
-     */
-    function get_standardised_final() {
-        $standardised_finals = array();
-
-        $final_grades = $this->load_final(true);
-        foreach ($final_grades as $userid => $final) {
-            $standardised_finals[$userid] = standardise_score($final->gradevalue, $this->grademin, $this->grademax, 0, 1);
-        }
-
-        return $standardised_finals;
-    }
-
-    /**
-    * 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;
-    }
-    
-    /**
-     * Calls upon the get_category method to retrieve the grade_category object
-     * from the DB and assigns it to $this->category. It also returns the object.
-     * @return object Grade_category
-     */
-    function load_category() {
-        $this->category = $this->get_category();
-        return $this->category;
-    }
-
     /**
      * In addition to update() as defined in grade_object, handle the grade_outcome and grade_scale objects.
      */
@@ -514,26 +379,6 @@ class grade_item extends grade_object {
         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 mixed An array of all raw_grades (stdClass objects) for this grade_item, or a single raw_grade.
-     */
-    function get_raw($userid=NULL) {
-        if (empty($this->grade_grades_raw)) {
-            $this->load_raw();
-        }
-
-        $grade_raw_array = null;
-        if (!empty($userid)) {
-            $r = get_record('grade_grades_raw', 'itemid', $this->id, 'userid', $userid);
-            $grade_raw_array[$r->userid] = new grade_grades_raw($r);
-        } else {
-            $grade_raw_array = $this->grade_grades_raw;
-        }
-        return $grade_raw_array;
-    }
-    
     /**
      * Takes an array of grade_grades_raw objects, indexed by userid, and saves each as a raw grade
      * under this grade_item. This replaces any existing grades, after having logged each change in the history table.
@@ -563,26 +408,6 @@ class grade_item extends grade_object {
         }
     }
 
-    /**
-     * 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 mixed An array of all final_grades (stdClass objects) for this grade_item, or a single final_grade.
-     */
-    function get_final($userid=NULL) {
-        if (empty($this->grade_grades_final)) {
-            $this->load_final();
-        }
-
-        $grade_final_array = null;
-        if (!empty($userid)) {
-            $f = get_record('grade_grades_final', 'itemid', $this->id, 'userid', $userid);
-            $grade_final_array[$f->userid] = new grade_grades_final($f);
-        } else {
-            $grade_final_array = $this->grade_grades_final;
-        }
-        return $grade_final_array;
-    }
-
     /**
      * 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.
@@ -612,71 +437,6 @@ class grade_item extends grade_object {
         return $success;
     }
 
-    /**
-     * Returns this object's calculation.
-     * @param boolean $fetch Whether to fetch the value from the DB or not (false == just use the object's value)
-     * @return mixed $calculation A string if found, false otherwise.
-     */
-    function get_calculation($fetch = false) {
-        if (!$fetch && get_class($this->calculation) == 'grade_calculation') {
-            return $this->calculation;
-        } 
-        $grade_calculation = grade_calculation::fetch('itemid', $this->id);
-            
-        if (empty($grade_calculation)) { // There is no calculation in DB
-            return false;
-        } elseif (empty($this->calculation) || !is_object($this->calculation)) { // The calculation isn't yet loaded
-            $this->calculation = $grade_calculation;
-            return $grade_calculation;
-        } elseif ($grade_calculation->calculation != $this->calculation->calculation) { // The object's calculation is not in sync with the DB (new value??)
-            $this->calculation = $grade_calculation;
-            return $grade_calculation;
-        } else { // The object's calculation is already in sync with the database
-            return $this->calculation;
-        }
-    }
-
-    /**
-     * Sets this item's calculation (creates it) if not yet set, or
-     * updates it if already set (in the DB). If no calculation is given,
-     * the method will attempt to retrieve one from the Database, based on
-     * the variables set in the current object.
-     * @param string $calculation
-     * @return boolean
-     */
-    function set_calculation($calculation = null) {
-        if (empty($calculation)) { // We are setting this item object's calculation variable from the DB
-            $grade_calculation = $this->get_calculation(true);
-            if (empty($grade_calculation)) {
-                debugging("No calculation to set for this grade_item.");
-                return false;
-            } else {
-                $this->calculation = $grade_calculation;
-            }
-        } else { // We are updating or creating the calculation entry in the DB
-            $grade_calculation = $this->get_calculation();
-            
-            if (empty($grade_calculation)) { // Creating
-                $grade_calculation = new grade_calculation();
-                $grade_calculation->calculation = $calculation;
-                $grade_calculation->itemid = $this->id;
-
-                if ($grade_calculation->insert()) {
-                    $this->calculation = $grade_calculation;
-                    return true;
-                } else {
-                    debugging("Could not save the calculation in the database, for this grade_item.");
-                    return false;
-                }                
-            } else { // Updating
-                $grade_calculation->calculation = $calculation;
-                $grade_calculation = new grade_calculation($grade_calculation);
-                $this->calculation = $grade_calculation;
-                return $grade_calculation->update();
-            }
-        }
-    }
-    
     /**
      * 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
@@ -912,6 +672,246 @@ class grade_item extends grade_object {
         return $result;
     }
     
+    /**
+     * Instantiates a grade_scale object whose data is retrieved from the DB, 
+     * if this item's scaleid variable is set.
+     * @return object grade_scale
+     */
+    function load_scale() {
+        if (!empty($this->scaleid)) {
+            $this->scale = grade_scale::fetch('id', $this->scaleid);
+            if (method_exists($this->scale, 'load_items')) {
+                $this->scale->load_items();
+            } else { 
+                $this->scale = null;
+            } 
+        } 
+        return $this->scale;
+    }
+
+    /**
+     * Instantiates a grade_outcome object whose data is retrieved from the DB, 
+     * if this item's outcomeid variable is set.
+     * @return object grade_outcome
+     */
+    function load_outcome() {
+        if (!empty($this->outcomeid)) {
+            $this->outcome = grade_outcome::fetch('id', $this->outcomeid);
+        } 
+        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.
+     * @param boolean $generatefakenullgrades If set to true, AND $CFG->usenullgrades is true, will replace missing grades with grades, gradevalue=grademin
+     * @return array grade_grades_final objects
+     */      
+    function load_final($generatefakenullgrades=false) {
+        global $CFG;
+
+        $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)) {
+            debugging("No final grades recorded for this grade_item");
+            return false;
+        }
+
+        foreach ($grade_final_array as $f) {
+            $this->grade_grades_final[$f->userid] = new grade_grades_final($f);
+        }
+
+        $returnarray = fullclone($this->grade_grades_final);
+
+        // If we are generating fake null grades, we have to get a list of users
+        if ($generatefakenullgrades && $CFG->usenullgrades) {
+            $users = get_records_sql_menu('SELECT userid AS "user", userid FROM ' . $CFG->prefix . 'grade_grades_final GROUP BY userid ORDER BY userid');
+            if (!empty($users) && is_array($users)) {
+                foreach ($users as $userid) {
+                    if (!isset($returnarray[$userid])) {
+                        $fakefinal = new grade_grades_final();
+                        $fakefinal->itemid = $this->id;
+                        $fakefinal->userid = $userid;
+                        $fakefinal->gradevalue = $this->grademin;
+                        $returnarray[$userid] = $fakefinal;
+                    }
+                }
+            }
+        }
+
+        return $returnarray;
+    }
+
+    /**
+     * Returns an array of values (NOT objects) standardised from the final grades of this grade_item. They are indexed by userid.
+     * @return array integers
+     */
+    function get_standardised_final() {
+        $standardised_finals = array();
+
+        $final_grades = $this->load_final(true);
+        foreach ($final_grades as $userid => $final) {
+            $standardised_finals[$userid] = standardise_score($final->gradevalue, $this->grademin, $this->grademax, 0, 1);
+        }
+
+        return $standardised_finals;
+    }
+
+    /**
+    * 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;
+    }
+    
+    /**
+     * Calls upon the get_category method to retrieve the grade_category object
+     * from the DB and assigns it to $this->category. It also returns the object.
+     * @return object Grade_category
+     */
+    function load_category() {
+        $this->category = $this->get_category();
+        return $this->category;
+    }
+
+    /**
+     * Returns this object's calculation.
+     * @param boolean $fetch Whether to fetch the value from the DB or not (false == just use the object's value)
+     * @return mixed $calculation A string if found, false otherwise.
+     */
+    function get_calculation($fetch = false) {
+        if (!$fetch && get_class($this->calculation) == 'grade_calculation') {
+            return $this->calculation;
+        } 
+        $grade_calculation = grade_calculation::fetch('itemid', $this->id);
+            
+        if (empty($grade_calculation)) { // There is no calculation in DB
+            return false;
+        } elseif (empty($this->calculation) || !is_object($this->calculation)) { // The calculation isn't yet loaded
+            $this->calculation = $grade_calculation;
+            return $grade_calculation;
+        } elseif ($grade_calculation->calculation != $this->calculation->calculation) { // The object's calculation is not in sync with the DB (new value??)
+            $this->calculation = $grade_calculation;
+            return $grade_calculation;
+        } else { // The object's calculation is already in sync with the database
+            return $this->calculation;
+        }
+    }
+
+    /**
+     * Sets this item's calculation (creates it) if not yet set, or
+     * updates it if already set (in the DB). If no calculation is given,
+     * the method will attempt to retrieve one from the Database, based on
+     * the variables set in the current object.
+     * @param string $calculation
+     * @return boolean
+     */
+    function set_calculation($calculation = null) {
+        if (empty($calculation)) { // We are setting this item object's calculation variable from the DB
+            $grade_calculation = $this->get_calculation(true);
+            if (empty($grade_calculation)) {
+                debugging("No calculation to set for this grade_item.");
+                return false;
+            } else {
+                $this->calculation = $grade_calculation;
+            }
+        } else { // We are updating or creating the calculation entry in the DB
+            $grade_calculation = $this->get_calculation();
+            
+            if (empty($grade_calculation)) { // Creating
+                $grade_calculation = new grade_calculation();
+                $grade_calculation->calculation = $calculation;
+                $grade_calculation->itemid = $this->id;
+
+                if ($grade_calculation->insert()) {
+                    $this->calculation = $grade_calculation;
+                    return true;
+                } else {
+                    debugging("Could not save the calculation in the database, for this grade_item.");
+                    return false;
+                }                
+            } else { // Updating
+                $grade_calculation->calculation = $calculation;
+                $grade_calculation = new grade_calculation($grade_calculation);
+                $this->calculation = $grade_calculation;
+                return $grade_calculation->update();
+            }
+        }
+    }
+    
+    /**
+     * 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 mixed An array of all raw_grades (stdClass objects) for this grade_item, or a single raw_grade.
+     */
+    function get_raw($userid=NULL) {
+        if (empty($this->grade_grades_raw)) {
+            $this->load_raw();
+        }
+
+        $grade_raw_array = null;
+        if (!empty($userid)) {
+            $r = get_record('grade_grades_raw', 'itemid', $this->id, 'userid', $userid);
+            $grade_raw_array[$r->userid] = new grade_grades_raw($r);
+        } else {
+            $grade_raw_array = $this->grade_grades_raw;
+        }
+        return $grade_raw_array;
+    }
+    
+    /**
+     * 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 mixed An array of all final_grades (stdClass objects) for this grade_item, or a single final_grade.
+     */
+    function get_final($userid=NULL) {
+        if (empty($this->grade_grades_final)) {
+            $this->load_final();
+        }
+
+        $grade_final_array = null;
+        if (!empty($userid)) {
+            $f = get_record('grade_grades_final', 'itemid', $this->id, 'userid', $userid);
+            $grade_final_array[$f->userid] = new grade_grades_final($f);
+        } else {
+            $grade_final_array = $this->grade_grades_final;
+        }
+        return $grade_final_array;
+    }
+
     /**
      * Returns the sortorder of this grade_item. This method is also available in 
      * grade_category, for cases where the object type is not know. It will act as a virtual 
@@ -922,6 +922,17 @@ class grade_item extends grade_object {
         return $this->sortorder;
     }
 
+    /**
+     * Sets the sortorder of this grade_item. This method is also available in 
+     * grade_category, for cases where the object type is not know. It will act as a virtual 
+     * variable for a grade_category.
+     * @param int $sortorder
+     * @return void
+     */
+    function set_sortorder($sortorder) {
+        $this->sortorder = $sortorder;
+    }
+
     /**
      * Returns the most descriptive field for this object. This is a standard method used 
      * when we do not know the exact type of an object.
@@ -940,5 +951,21 @@ class grade_item extends grade_object {
     function get_item_id() {
         return $this->id;
     }
+
+    /**
+     * Returns this item's category id. A generic method shared by objects that have a parent id of some kind.
+     * @return int $parentid
+     */
+    function get_parent_id() {
+        return $this->categoryid;
+    }
+
+    /**
+     * Sets this item's categoryid. A generic method shared by objects that have a parent id of some kind.
+     * @param int $parentid
+     */
+    function set_parent_id($parentid) {
+        $this->categoryid = $parentid;
+    }
 }
 ?>
index 641a101e781f5eb270bfd8e9bc008c9233ac615a..b38af6add533df54134db8f98e1274e5fbd7a273 100644 (file)
@@ -287,19 +287,18 @@ class grade_tree {
             $new_element = $element;
         }
         
+        $new_element_class = get_class($new_element->element['object']);
+        $has_final_grades = !empty($new_element->element['final_grades']);
+        
         // 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']) && $this->include_grades) {
+        if ($new_element_class == 'grade_item' && !$has_final_grades && $this->include_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()) {
+        } elseif ($new_element_class == '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 => $new_element->element);
 
         // Get the position of the destination element
@@ -383,10 +382,11 @@ class grade_tree {
      * down and across the tree.
      * @param int $starting_sortorder Used by recursion to "seed" the first element in each sub-tree
      * @param array $element A sub-tree given to each layer of recursion. If null, level 0 of recursion is assumed.
+     * @param int $parentid The id of the element within which this iteration of the method is running. Used to reassign element parentage.
      * @return array A debugging array which shows the progression of variables throughout this method. This is very useful
      * to identify problems and implement new functionality.
      */
-    function renumber($starting_sortorder=NULL, $elements=NULL) {
+    function renumber($starting_sortorder=NULL, $elements=NULL, $parentid=NULL) {
         $sortorder = $starting_sortorder;
         
         if (empty($elements) && empty($starting_sortorder)) {
@@ -416,16 +416,15 @@ class grade_tree {
 
             if (!empty($element['children'])) {
                 $newtree[$this->first_sortorder] = $element;
-                $newtree[$this->first_sortorder]['children'] = $this->renumber($this->first_sortorder, $element['children']); 
+                $newtree[$this->first_sortorder]['children'] = $this->renumber($this->first_sortorder, $element['children'], $element['object']->id); 
             }  else { 
                 $newtree[$this->first_sortorder] = $element; 
             } 
             
             if ($new_sortorder != $old_sortorder) {
-                $this->need_update[$element['object']->get_item_id()] = 
-                    array('old_sortorder' => $old_sortorder, 
-                          'new_sortorder' => $new_sortorder,
-                          'name' => $element['object']->get_name());
+                $element['object']->set_parent_id($parentid);
+                $element['object']->set_sortorder($new_sortorder);
+                $this->need_update[] = $element['object'];
             }
         }
         
@@ -898,10 +897,10 @@ class grade_tree {
         $this->need_delete = array();
         $this->need_insert = array();
 
-        // The items' sortorder are updated
-        foreach ($this->need_update as $id => $element) {
-            if (!set_field('grade_items', 'sortorder', $element['new_sortorder'], 'id', $id)) {
-                debugging("Could not update the grade_item's sortorder in DB.");
+        // The objects are updated
+        foreach ($this->need_update as $object) {
+            if (!$object->update()) {
+                debugging("Could not update the object in DB.");
             } 
         } 
 
index e571115aca9dd5f94f141593e0f2bddbe201ad63..9ff369573a839ecb46bad7c3f9f0e3d2ef75fe64 100644 (file)
@@ -2007,6 +2007,37 @@ body#grade-index .grades .weighted {
    margin:0px 20px 0px 20px;
 }
 
+#grade_edit_tree .insertion_box {
+  border: 1px #999999 solid;
+  background-color: #CCCCCC;
+  position: relative;
+  width: 40px;
+  height: 20px;
+}
+
+#grade_edit_tree li {
+  list-style: none;
+}
+
+#grade_edit_tree li.insertion {
+  cursor: pointer;
+}
+
+#grade_edit_tree .moveuparrow {
+  cursor: pointer;
+}
+
+#grade_edit_tree .movedownarrow {
+  cursor: pointer;
+}
+
+#grade_edit_tree form.movearrow div {
+  display: inline;
+}
+
+#grade_edit_tree form.movearrow {
+  display: inline;
+}
 /***
  *** Login
  ***/