MDL-35597 admin: categories now support localised alphabetical sorting
authorSam Hemelryk <sam@moodle.com>
Wed, 27 Nov 2013 21:57:14 +0000 (10:57 +1300)
committerSam Hemelryk <sam@moodle.com>
Sun, 12 Jan 2014 19:12:42 +0000 (08:12 +1300)
lib/adminlib.php

index 41c86ef..043e0af 100644 (file)
@@ -750,8 +750,8 @@ interface parentable_part_of_admin_tree extends part_of_admin_tree {
  */
 class admin_category implements parentable_part_of_admin_tree {
 
-    /** @var mixed An array of part_of_admin_tree objects that are this object's children */
-    public $children;
+    /** @var part_of_admin_tree[] An array of part_of_admin_tree objects that are this object's children */
+    protected $children;
     /** @var string An internal name for this category. Must be unique amongst ALL part_of_admin_tree objects */
     public $name;
     /** @var string The displayed name for this category. Usually obtained through get_string() */
@@ -766,6 +766,15 @@ class admin_category implements parentable_part_of_admin_tree {
     /** @var array fast lookup category cache, all categories of one tree point to one cache */
     protected $category_cache;
 
+    /** @var bool If set to true children will be sorted when calling {@link admin_category::get_children()} */
+    protected $sort = false;
+    /** @var bool If set to true children will be sorted in ascending order. */
+    protected $sortasc = true;
+    /** @var bool If set to true sub categories and pages will be split and then sorted.. */
+    protected $sortsplit = true;
+    /** @var bool $sorted True if the children have been sorted and don't need resorting */
+    protected $sorted = false;
+
     /**
      * Constructor for an empty admin category
      *
@@ -830,7 +839,7 @@ class admin_category implements parentable_part_of_admin_tree {
      */
     public function search($query) {
         $result = array();
-        foreach ($this->children as $child) {
+        foreach ($this->get_children() as $child) {
             $subsearch = $child->search($query);
             if (!is_array($subsearch)) {
                 debugging('Incorrect search result from '.$child->name);
@@ -991,6 +1000,104 @@ class admin_category implements parentable_part_of_admin_tree {
         }
         return false;
     }
+
+    /**
+     * Sets sorting on this category.
+     *
+     * Please note this function doesn't actually do the sorting.
+     * It can be called anytime.
+     * Sorting occurs when the user calls get_children.
+     * Code using the children array directly won't see the sorted results.
+     *
+     * @param bool $sort If set to true children will be sorted, if false they won't be.
+     * @param bool $asc If true sorting will be ascending, otherwise descending.
+     * @param bool $split If true we sort pages and sub categories separately.
+     */
+    public function set_sorting($sort, $asc = true, $split = true) {
+        $this->sort = (bool)$sort;
+        $this->sortasc = (bool)$asc;
+        $this->sortsplit = (bool)$split;
+    }
+
+    /**
+     * Returns the children associated with this category.
+     *
+     * @return part_of_admin_tree[]
+     */
+    public function get_children() {
+        // If we should sort and it hasn't already been sorted.
+        if ($this->sort && !$this->sorted) {
+            if ($this->sortsplit) {
+                $categories = array();
+                $pages = array();
+                foreach ($this->children as $child) {
+                    if ($child instanceof admin_category) {
+                        $categories[] = $child;
+                    } else {
+                        $pages[] = $child;
+                    }
+                }
+                core_collator::asort_objects_by_property($categories, 'visiblename');
+                core_collator::asort_objects_by_property($pages, 'visiblename');
+                if (!$this->sortasc) {
+                    $categories = array_reverse($categories);
+                    $pages = array_reverse($pages);
+                }
+                $this->children = array_merge($pages, $categories);
+            } else {
+                core_collator::asort_objects_by_property($this->children, 'visiblename');
+                if (!$this->sortasc) {
+                    $this->children = array_reverse($this->children);
+                }
+            }
+            $this->sorted = true;
+        }
+        return $this->children;
+    }
+
+    /**
+     * Magically gets a property from this object.
+     *
+     * @param $property
+     * @return part_of_admin_tree[]
+     * @throws coding_exception
+     */
+    public function __get($property) {
+        if ($property === 'children') {
+            return $this->get_children();
+        }
+        throw new coding_exception('Invalid property requested.');
+    }
+
+    /**
+     * Magically sets a property against this object.
+     *
+     * @param string $property
+     * @param mixed $value
+     * @throws coding_exception
+     */
+    public function __set($property, $value) {
+        if ($property === 'children') {
+            $this->sorted = false;
+            $this->children = $value;
+        } else {
+            throw new coding_exception('Invalid property requested.');
+        }
+    }
+
+    /**
+     * Checks if an inaccessible property is set.
+     *
+     * @param string $property
+     * @return bool
+     * @throws coding_exception
+     */
+    public function __isset($property) {
+        if ($property === 'children') {
+            return isset($this->children);
+        }
+        throw new coding_exception('Invalid property requested.');
+    }
 }