]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-9506 Created new grade_tree object for working with a tree of grade_categories...
authornicolasconnault <nicolasconnault>
Wed, 16 May 2007 15:04:35 +0000 (15:04 +0000)
committernicolasconnault <nicolasconnault>
Wed, 16 May 2007 15:04:35 +0000 (15:04 +0000)
lib/grade/grade_tree.php [new file with mode: 0644]
lib/simpletest/grade/simpletest/testgradeitem.php
lib/simpletest/grade/simpletest/testgradetree.php [new file with mode: 0644]

diff --git a/lib/grade/grade_tree.php b/lib/grade/grade_tree.php
new file mode 100644 (file)
index 0000000..95105fe
--- /dev/null
@@ -0,0 +1,236 @@
+<?php // $Id$
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.com                                            //
+//                                                                       //
+// Copyright (C) 2001-2003  Martin Dougiamas  http://dougiamas.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * This class represents a complete tree of categories, grade_items and final grades,
+ * organises as an array primarily, but which can also be converted to other formats.
+ * It has simple method calls with complex implementations, allowing for easy insertion,
+ * deletion and moving of items and categories within the tree.
+ */ 
+class grade_tree {
+    /**
+     * The first sortorder for this tree, before any changes were made.
+     * @var int $first_sortorder
+     */
+    var $first_sortorder;
+
+    /**
+     * The basic representation of the tree as a hierarchical, 3-tiered array.
+     * @var $tree_array
+     */
+    var $tree_array = array();
+
+    /**
+     * Parses the array in search of a given sort order (the elements are indexed by 
+     * sortorder), and returns a stdClass object with vital information about the 
+     * element it has found.
+     * @param int $sortorder
+     * @return object element
+     */
+    function locate_element($sortorder) {
+        $topcatcount = 0;
+
+        foreach ($this->tree_array as $topcatkey => $topcat) {
+            $topcatcount++;
+            $subcatcount = 0;
+            $retval = new stdClass();
+            $retval->topcatindex = $topcatkey;
+
+            if ($topcatkey == $sortorder) {
+                $retval->depth = 1;
+                $retval->element = $topcat;
+                $retval->position = $topcatcount;
+                return $retval;
+            }
+
+            if (is_array($topcat)) {
+                foreach ($topcat as $subcatkey => $subcat) {
+                    $subcatcount++;
+                    $itemcount = 0;
+
+                    $retval->subcatindex = $subcatkey;
+                    if ($subcatkey == $sortorder) {
+                        $retval->depth = 2;
+                        $retval->element = $subcat;
+                        $retval->position = $subcatcount;
+                        return $retval;
+                    }
+                    
+                    if (is_array($subcat)) {
+                        foreach ($subcat as $itemkey => $item) {
+                            $itemcount++;
+                            $retval->itemindex = $itemkey;
+                            if ($itemkey == $sortorder) {
+                                $retval->depth = 3;
+                                $retval->element = $item;
+                                $retval->position = $itemcount;
+                                return $retval;
+                            } 
+                        }
+                    }
+                }
+            }
+        } 
+        return $retval;
+    }
+
+    /**
+     * Removes the given element (a stdClass object or a sortorder), remove_elements
+     * it from the tree. This does not renumber the tree.
+     * @var object $element An stdClass object typically returned by $this->locate(), or a sortorder
+     * @return boolean
+     */
+    function remove_element($element) {
+        if (isset($element->depth)) { 
+            switch ($element->depth) {
+                case 1:
+                    unset($this->tree_array[$element->topcatindex]);
+                    break;
+                case 2:
+                    unset($this->tree_array[$element->topcatindex][$element->subcatindex]);
+                    break;
+                case 3:
+                    unset($this->tree_array[$element->topcatindex][$element->subcatindex][$element->itemindex]);
+                    break;
+            }
+            return true;
+        } else {
+            $element = $this->locate_element($element);
+            if (!empty($element)) {
+                return $this->remove_element($element);
+            } else {
+                return false;
+            }
+        }
+    }
+    
+    /**
+     * Inserts an element in the tree. This can be either an array as returned by the grade_category methods, or
+     * an element object returned by grade_tree.
+     * @param mixed $element array or object. If object, the sub-tree is contained in $object->element
+     * @param int $destination_sortorder Where to insert the element
+     * @param string $position Either 'before' the destination_sortorder or 'after'
+     * @param boolean
+     */
+    function insert_element($element, $destination_sortorder, $position='before') {
+        if ($position == 'before') {
+            $offset = -1;
+        } elseif ($position == 'after') {
+            $offset = 0;
+        } else {
+            die ('move_element(..... $position) can only be "before" or "after", you gave ' . $position);
+        }
+
+        // TODO Problem when moving topcategories: sortorder gets reindexed when splicing the array
+        $destination_array = array($destination_sortorder => $source->element);
+        switch($element->depth) {
+            case 1:
+                array_splice($this->tree_array, 
+                    $element->position + $offset, 0, 
+                    $destination_array); 
+                break;
+            case 2:
+                array_splice($this->tree_array[$element->topcatindex], 
+                    $element->position + $offset, 0, 
+                    $destination_array); 
+                break;
+            case 3:
+                array_splice($this->tree_array[$element->topcatindex][$element->subcatindex], 
+                    $element->position + $offset, 0, 
+                    $destination_array); 
+                break; 
+        }
+
+        return true; 
+    }
+    
+    /**
+     * Moves an existing element in the tree to another position OF EQUAL LEVEL. This 
+     * constraint is essential and very important. 
+     * @param int $source_sortorder The sortorder of the element to move
+     * @param int $destination_sortorder The sortorder where the element will go
+     * @param string $position Either 'before' the destination_sortorder or 'after' it
+     * @return boolean
+     */ 
+    function move_element($source_sortorder, $destination_sortorder, $position='before') {
+        // Locate the position of the source element in the tree
+        $source = $this->locate_element($source_sortorder);
+
+        // Remove this element from the tree
+        $this->remove_element($source);
+
+        $destination = $this->locate_element($destination_sortorder);
+
+        if ($destination->depth != $source->depth) {
+            echo "Source and Destination were at different levels.";
+            return false; 
+        } 
+        
+        // Insert the element before the destination sortorder
+        $this->insert_element($destination, $destination_sortorder, $position); 
+
+        return true;
+    }
+    
+
+    /**
+     * One at a time, re-assigns new sort orders for every element in the tree, starting 
+     * with a base number.
+     * @return boolean;
+     */
+    function renumber($starting_sortorder=NULL) {
+        $sortorder = $starting_sortorder;
+        
+        if (empty($starting_sortorder)) { 
+            $sortorder = $this->first_sortorder;
+        }
+        
+        $newtree = array();
+
+        foreach ($this->tree_array as $topcat) {
+            $sortorder++; 
+            if (is_array($topcat)) {
+                $topcatsortorder = $sortorder;
+                foreach ($topcat as $subcat) {
+                    $sortorder++; 
+                    if(is_array($subcat)) {
+                        $subcatsortorder = $sortorder;
+                        foreach ($subcat as $item) {
+                            $sortorder++;
+                            $newtree[$topcatsortorder][$subcatsortorder][$sortorder] = $item;
+                        }
+                    } else {
+                        $newtree[$topcatsortorder][$sortorder] = $subcat; 
+                    } 
+                }
+            } else { 
+                $newtree[$sortorder] = $topcat;
+            } 
+        }
+            
+        $this->tree_array = $newtree;
+        return true;
+    }
+}
index b832134414f21b5a352f9ebbea81a48bad4414e9..88718661a4758682d15db0ddeac696211626e05d 100755 (executable)
@@ -481,5 +481,8 @@ class grade_item_test extends gradelib_test {
         $grade_item->load_final();\r
         $this->assertEqual(3, count($grade_item->grade_grades_final)); \r
     }\r
+\r
+    function test_float_keys() {\r
+    }\r
 } \r
 ?>\r
diff --git a/lib/simpletest/grade/simpletest/testgradetree.php b/lib/simpletest/grade/simpletest/testgradetree.php
new file mode 100644 (file)
index 0000000..ced5f6a
--- /dev/null
@@ -0,0 +1,39 @@
+<?php // $Id$
+
+///////////////////////////////////////////////////////////////////////////
+//                                                                       //
+// NOTICE OF COPYRIGHT                                                   //
+//                                                                       //
+// Moodle - Modular Object-Oriented Dynamic Learning Environment         //
+//          http://moodle.org                                            //
+//                                                                       //
+// Copyright (C) 1999-2004  Martin Dougiamas  http://dougiamas.com       //
+//                                                                       //
+// This program is free software; you can redistribute it and/or modify  //
+// it under the terms of the GNU General Public License as published by  //
+// the Free Software Foundation; either version 2 of the License, or     //
+// (at your option) any later version.                                   //
+//                                                                       //
+// This program is distributed in the hope that it will be useful,       //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of        //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
+// GNU General Public License for more details:                          //
+//                                                                       //
+//          http://www.gnu.org/copyleft/gpl.html                         //
+//                                                                       //
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ * Unit tests for grade_tree object.
+ *
+ * @author nicolas@moodle.com
+ * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
+ * @package moodlecore
+ */
+require_once(dirname(__FILE__) . '/../../../../config.php');
+global $CFG;
+require_once($CFG->libdir . '/simpletest/testgradelib.php');
+
+class grade_tree_test extends gradelib_test {
+
+}