]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-9628 Move work on the category edit page
authornicolasconnault <nicolasconnault>
Thu, 31 May 2007 08:57:05 +0000 (08:57 +0000)
committernicolasconnault <nicolasconnault>
Thu, 31 May 2007 08:57:05 +0000 (08:57 +0000)
grade/report/grader/category.php
lib/grade/grade_category.php
lib/grade/grade_item.php
lib/grade/grade_tree.php
theme/standard/styles_layout.css

index 851350035d3e6fb62acb6ae09cedb099d4ddfad7..7f178b03d78b2179df672560be74ee3f44e24aec 100644 (file)
@@ -34,16 +34,13 @@ $param->movedown = optional_param('movedown', 0, PARAM_INT);
 $param->source = optional_param('source', 0, PARAM_INT);
 $param->action = optional_param('action', 0, PARAM_ALPHA);
 $param->move = optional_param('move', 0, PARAM_INT);
+$param->type = optional_param('type', 0, PARAM_ALPHA);
 
 $tree = new grade_tree(641);
 $select_source = false;
 
 if (!empty($param->action)) {
-    if (empty($param->source)) {
-        $select_source = true;
-    } else {
-        print_heading("Select the destination for the selected element."); 
-    }
+    print_heading("Select the destination for the selected element."); 
 } elseif (!empty($param->source)) {
     if (!empty($param->moveup)) {
         $tree->move_element($param->source, $param->moveup); 
@@ -61,12 +58,7 @@ if ($select_source) {
     print_heading("Select an element to move");
 }
 
-echo $tree->get_edit_tree($select_source, 1, null, $param->source, $param->action);
-
-echo '<form id="move_button" action="category.php" method="post"><div>' . "\n";
-echo '<input type="hidden" name="action" value="move" />' . "\n";
-echo '<input type="submit" value="Move" />' . "\n";
-echo '</div></form>';
+echo $tree->get_edit_tree(1, null, $param->source, $param->action, $param->type);
 
 print_footer();
 ?>
index e104d89ec28af8825e6027d666b1ecfec2753ace..9dd1d96997ac04c0577517327d095973b869495a 100644 (file)
@@ -56,6 +56,12 @@ class grade_category extends grade_object {
      */
     var $parent_category;
 
+    /**
+     * A grade_category object this category used to belong to before getting updated. Will be deleted shortly.
+     * @var object $old_parent
+     */
+    var $old_parent;
+
     /**
      * The number of parents this category has.
      * @var int $depth
@@ -841,7 +847,13 @@ class grade_category extends grade_object {
      * @param id $parentid
      */
     function set_parent_id($parentid) {
+        if ($this->parent != $parentid) {
+            $this->old_parent = $this->get_parent_category();
+        }
+
         $this->parent = $parentid;
+        $this->path = grade_category::build_path($this);
+        $this->depth = $this->get_depth_from_path();
     }
     
     /**
@@ -870,6 +882,18 @@ class grade_category extends grade_object {
     function set_sortorder($sortorder) {
         $this->sortorder = $sortorder;
     }
-
+    
+    /** 
+     * If the old parent is set (after an update), this checks and returns whether it has any children. Important for
+     * deleting childless categories.
+     * @return boolean
+     */
+    function is_old_parent_childless() {
+        if (!empty($this->old_parent)) {
+            return !$this->old_parent->has_children();
+        } else {
+            return false;
+        }
+    } 
 } 
 ?>
index 5e9d76dd40e48b43418216bd6db5d7c8d6ea87ce..f7343cbee027c62b8156aeea0f3c1c1d99d759da 100644 (file)
@@ -60,6 +60,12 @@ class grade_item extends grade_object {
      */
     var $category;
     
+    /**
+     * A grade_category object this item used to belong to before getting updated. Will be deleted shortly.
+     * @var object $old_parent
+     */
+    var $old_parent;
+
     /**
      * The name of this grade_item (pushed by the module).
      * @var string $itemname
@@ -965,7 +971,24 @@ class grade_item extends grade_object {
      * @param int $parentid
      */
     function set_parent_id($parentid) {
+        if ($this->categoryid != $parentid) {
+            $this->old_parent = $this->get_category();
+        }
+
         $this->categoryid = $parentid;
     }
+    
+    /** 
+     * If the old parent is set (after an update), this checks and returns whether it has any children. Important for
+     * deleting childless categories.
+     * @return boolean
+     */
+    function is_old_parent_childless() {
+        if (!empty($this->old_parent)) {
+            return !$this->old_parent->has_children();
+        } else {
+            return false;
+        }
+    } 
 }
 ?>
index b38af6add533df54134db8f98e1274e5fbd7a273..fda1951de8542146409274f920ad40f2abd5f541 100644 (file)
@@ -533,7 +533,7 @@ class grade_tree {
      */
     function include_fillers($tree, $object=NULL) {
         if (empty($this->fillers)) {
-            return null;
+            return $tree;
         }
 
         // Look at the current key of the fillers array. It is a sortorder.
@@ -649,8 +649,8 @@ class grade_tree {
         
         // Get all top categories
         $query = "SELECT $category_table.*, sortorder FROM $category_table, $items_table 
-                  WHERE iteminstance = $category_table.id $catconstraint ORDER BY sortorder";
-
+                  WHERE iteminstance = $category_table.id AND itemtype = 'category' $catconstraint ORDER BY sortorder";
+        
         $topcats = get_records_sql($query);
         
         if (empty($topcats)) {
@@ -662,7 +662,7 @@ class grade_tree {
 
         // If any of these categories has grade_items as children, create a topcategory filler with colspan=count(children)
         $topcats = $this->add_fillers($topcats);
-        
+
         foreach ($topcats as $topcatid => $topcat) {
 
             // Check the fillers array, see if one must be inserted before this topcat
@@ -714,7 +714,7 @@ class grade_tree {
             $topcat->sortorder = $sortorder;
             $tree[$topcat->sortorder] = array('object' => $topcat, 'children' => $subcattree); 
         }
-
+        
         // If there are still grade_items or grade_categories without a top category, add another filler
         if (!empty($this->fillers)) {
             ksort($this->fillers);
@@ -773,7 +773,11 @@ class grade_tree {
                 
                 $children_for_tree[$itemid] = array('object' => $item, 'finalgrades' => $finals); 
             }
-
+            
+            if (empty($object->childrencount)) {
+                $object->childrencount = 1;
+            }
+            
             $filler_array = array('object' => 'filler', 'colspan' => $object->childrencount, 'children' =>
                 array(0 => array('object' => $object, 'children' => $children_for_tree)));
         } 
@@ -847,6 +851,7 @@ class grade_tree {
     /**
      * Using $this->tree_array, builds $this->tree_filled, which is the same array but with fake categories as
      * fillers. These are used by display_grades, to print out empty cells over orphan grade_items and grade_categories.
+     * Recursive method
      * @return boolean Success or Failure.
      */
     function build_tree_filled() {
@@ -856,7 +861,8 @@ class grade_tree {
         }
         
         $this->tree_filled = array();
-
+        
+        // Detect any category that is now child-less and delete it
         foreach ($this->tree_array as $level1order => $level1) {
             if ($this->get_element_type($level1) == 'item' || $this->get_element_type($level1) == 'subcat') {
                 $this->tree_filled[$level1order] = $this->get_filler($level1['object']);
@@ -876,7 +882,16 @@ class grade_tree {
      * @return boolean Success or Failure
      */
     function update_db() {
-        // Perform deletions first
+        // Updates
+        foreach ($this->need_update as $object) {
+            if (!$object->update()) {
+                debugging("Could not update the object in DB.");
+            } elseif ($object->is_old_parent_childless()) { 
+                $this->need_delete[$object->old_parent->id] = $object->old_parent;
+            }
+        } 
+
+        // Deletions 
         foreach ($this->need_delete as $id => $object) {
             // If an item is both in the delete AND insert arrays, it must be an existing object that only needs updating, so ignore it.
             if (empty($this->need_insert[$id])) {
@@ -886,6 +901,7 @@ class grade_tree {
             }
         }
 
+        // Insertions
         foreach ($this->need_insert as $id => $object) {
             if (empty($this->need_delete[$id])) {
                 if (!$object->insert()) {
@@ -894,45 +910,48 @@ class grade_tree {
             }
         }
 
+        $this->need_update = array();
         $this->need_delete = array();
         $this->need_insert = array();
 
-        // The objects are updated
-        foreach ($this->need_update as $object) {
-            if (!$object->update()) {
-                debugging("Could not update the object in DB.");
-            } 
-        } 
-
-        $this->need_update = array();
         $this->reset_first_sortorder();
         $this->renumber();
     }
 
     /**
      * Returns a HTML list with sorting arrows and insert boxes. This is a recursive method.
-     * @param boolean $select_source Whether or not to display each element as a link to be selected as a source for an action
      * @param int $level The level of recursion
      * @param array $elements The elements to display in a list. Defaults to this->tree_array
      * @param int $source_sortorder A source sortorder, given when an element needs to be moved or inserted.
      * @param string $action 'move' or 'insert'
+     * @param string $source_type 'topcat', 'subcat' or 'item'
      * @return string HTML code
      */
-    function get_edit_tree($select_source=false, $level=1, $elements=NULL, $source_sortorder=NULL, $action=NULL) {
+    function get_edit_tree($level=1, $elements=NULL, $source_sortorder=NULL, $action=NULL, $source_type=NULL) {
         if (empty($this->tree_array)) {
             return null;
         } else {
             global $USER;
             global $CFG;
 
+            $strmove     = get_string("move");
             $strmoveup   = get_string("moveup");
             $strmovedown = get_string("movedown");
+            $strmovehere = get_string("movehere");
+            $strcancel   = get_string("cancel");
 
-            $sesskey_input = '<input type="hidden" name="sesskey" value="' . $USER->sesskey . '" />';
-            $courseid_input = '<input type="hidden" name="courseid" value="' . $this->courseid . '" />';
+            $list = '';
+
+            $commonvars = "&amp;sesskey=$USER->sesskey&amp;courseid=$this->courseid";
             
             if (empty($elements)) {
-                $list = '<ul id="grade_edit_tree">' . "\n";
+                if ($source_sortorder && $action) {
+                    $element = $this->locate_element($source_sortorder);
+                    $list .= 'Moving ' . $element->element['object']->get_name() . ' (';
+                    $list .= '<a href="category.php?cancelmove=true' . $commonvars . '">' . $strcancel . '</a>)' . "\n";
+                }
+
+                $list .= '<ul id="grade_edit_tree">' . "\n";
                 $elements = $this->tree_array;
             } else {
                 $list = '<ul class="level' . $level . 'children">' . "\n";
@@ -953,55 +972,46 @@ class grade_tree {
                 }
 
                 $object_name = $element['object']->get_name();
-                if ($select_source) {
-                    $formname = "select_source_$sortorder";
-                    $object_name = '<form id="' . $formname . '" class="movearrow" action="category.php" method="post"><div>
-                        <input type="hidden" name="source" value="' . $sortorder . '" />
-                        <input type="hidden" name="action" value="' . $action . '" />
-                        <a href="#" onclick="document.getElementById(\'' . $formname . '\').submit();" title="Select this element">'
-                      . $object_name . '</a></div></form>';
+                $object_class = get_class($element['object']); 
+                $object_parent = $element['object']->get_parent_id();
+                $element_type = $this->get_element_type($element);
+                
+                $highlight_class = '';
+                
+                if ($source_sortorder == $sortorder && !empty($action)) {
+                    $highlight_class = ' selected_element ';
                 }
 
                 $list .= '<li class="level' . $level . 'element sortorder' 
-                      . $element['object']->get_sortorder() . '">' . "\n" 
+                      . $element['object']->get_sortorder() . $highlight_class . '">' . "\n" 
                       . $object_name;
                 
+                // Print up arrow
                 if (!$first) {
-                    $formname = "moveup_$sortorder";
-                    $list .= '<form method="post" action="category.php" class="movearrow" id="' . $formname . '"><div>
-                        <input type="hidden" name="source" value="' . $sortorder . '" />
-                        <input type="hidden" name="moveup" value="' . $element['object']->previous_sortorder . '" />' . "\n";
-                    
-                    $list .= $sesskey_input . "\n" . $courseid_input;
-
-                    $list .= '<div class="moveuparrow">'
-                          . '<img src="'.$CFG->pixpath.'/t/up.gif" class="iconsmall" '
-                          . 'alt="'.$strmoveup.'" title="'.$strmoveup.'"' 
-                          . 'onclick="document.getElementById(\'' . $formname . '\').submit();" /> </div>'. "\n";
-                    $list .= '</div></form>';
+                    $list .= '<a href="category.php?'."source=$sortorder&amp;moveup={$element['object']->previous_sortorder}$commonvars\">\n"; 
+                    $list .= '<img src="'.$CFG->pixpath.'/t/up.gif" class="iconsmall" ' . 'alt="'.$strmoveup.'" title="'.$strmoveup.'" /></a>'. "\n"; 
                 } else {
                     $list .= '<img src="'.$CFG->wwwroot.'/pix/spacer.gif" class="iconsmall" alt="" /> '. "\n";
                 }
 
+                // Print down arrow
                 if (!$last) {
-                    $formname = "movedown_$sortorder";
-                    $list .= '<form method="post" action="category.php" class="movearrow" id="' . $formname . '"><div>
-                        <input type="hidden" name="source" value="' . $sortorder . '" />
-                        <input type="hidden" name="movedown" value="' . $element['object']->next_sortorder . '" />' . "\n";
-                    
-                    $list .= $sesskey_input . "\n" . $courseid_input;
-
-                    $list .= '<div class="movedownarrow">'
-                          . '<img src="'.$CFG->pixpath.'/t/down.gif" class="iconsmall" '
-                          . 'alt="'.$strmovedown.'" title="'.$strmovedown.'"' 
-                          . 'onclick="document.getElementById(\'' . $formname . '\').submit();" /></div>'. "\n";
-                    $list .= '</div></form>';
+                    $list .= '<a href="category.php?'."source=$sortorder&amp;movedown={$element['object']->next_sortorder}$commonvars\">\n"; 
+                    $list .= '<img src="'.$CFG->pixpath.'/t/down.gif" class="iconsmall" ' . 'alt="'.$strmovedown.'" title="'.$strmovedown.'" /></a>'. "\n"; 
                 } else {
                     $list .= '<img src="'.$CFG->wwwroot.'/pix/spacer.gif" class="iconsmall" alt="" /> ' . "\n";
                 }
                 
+                // Print move icon
+                if ($element_type != 'topcat') { 
+                    $list .= '<a href="category.php?'."source=$sortorder&amp;action=move&amp;type=$element_type&amp;sesskey=$commonvars\">\n";
+                    $list .= '<img src="'.$CFG->pixpath.'/t/move.gif" class="iconsmall" alt="'.$strmove.'" title="'.$strmove.'" /></a>'. "\n";                
+                } else {
+                    $list .= '<img src="'.$CFG->wwwroot.'/pix/spacer.gif" class="iconsmall" alt="" /> ' . "\n";
+                }
+
                 if (!empty($element['children'])) {
-                    $list .= $this->get_edit_tree($select_source, $level + 1, $element['children'], $source_sortorder, $action);
+                    $list .= $this->get_edit_tree($level + 1, $element['children'], $source_sortorder, $action, $source_type);
                 }
                 
                 $list .= '</li>' . "\n";
@@ -1015,17 +1025,19 @@ class grade_tree {
                 $last_sortorder = $sortorder;
             }
             
-            // Add an insertion box if source_sortorder is given
+            // Add an insertion box if source_sortorder is given and a few other constraints are satisfied
             if ($source_sortorder && !empty($action)) {
-                $list .= '<li class="insertion">
-                    <form method="post" action="category.php" id="insertion_' . $last_sortorder . '">
-                    <div>
-                        <input type="hidden" name="source" value="' . $source_sortorder . '" />
-                        <input type="hidden" name="' . $action . '" value="' . $last_sortorder . '" />
-                        <div class="insertion_box" onclick="document.getElementById(\'insertion_' . $last_sortorder . '\').submit();"></div>                        
-                    </div>
-                    </form>
-                </li>';
+                $moving_item_near_subcat = $element_type == 'subcat' && $source_type == 'item' && $level > 1;
+                $moving_cat_to_lower_level = ($level == 2 && $source_type == 'topcat') || ($level > 2 && $source_type == 'subcat');
+                $moving_subcat_near_item_in_cat = $element_type == 'item' && $source_type == 'subcat' && $level > 1;
+                $moving_element_near_itself = $sortorder == $source_sortorder;
+                
+                if (!$moving_item_near_subcat && !$moving_cat_to_lower_level && !$moving_subcat_near_item_in_cat && !$moving_element_near_itself) { 
+                    $list .= '<li class="insertion">' . "\n";
+                    $list .= '<a href="category.php?' . "source=$source_sortorder&amp;$action=$last_sortorder$commonvars\">\n";
+                    $list .= '<img class="movetarget" src="'.$CFG->wwwroot.'/pix/movehere.gif" alt="'.$strmovehere.'" title="'.$strmovehere.'" />' . "\n";
+                    $list .= "</a>\n</li>";
+                }
             }
 
             $list .= '</ul>' . "\n";
index 9ff369573a839ecb46bad7c3f9f0e3d2ef75fe64..e802c8ff684b377e155bdbbaab40c71ebc0a23d8 100644 (file)
@@ -2007,12 +2007,10 @@ body#grade-index .grades .weighted {
    margin:0px 20px 0px 20px;
 }
 
-#grade_edit_tree .insertion_box {
-  border: 1px #999999 solid;
-  background-color: #CCCCCC;
+#grade_edit_tree .movetarget {
   position: relative;
-  width: 40px;
-  height: 20px;
+  width: 80px;
+  height: 16px;
 }
 
 #grade_edit_tree li {
@@ -2038,6 +2036,10 @@ body#grade-index .grades .weighted {
 #grade_edit_tree form.movearrow {
   display: inline;
 }
+
+#grade_edit_tree .selected_element {
+  background-color: #E8EEF7;
+}
 /***
  *** Login
  ***/