Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'MDL-27600-master' of git://github.com/sammarshallou/moodle

  • Loading branch information...
commit 5436561c7c25bad808c1b5690f5ffa857f4afcbc 2 parents 59023e7 + 188a812
@samhemelryk samhemelryk authored
Showing with 119 additions and 22 deletions.
  1. +97 −22 lib/navigationlib.php
  2. +22 −0 lib/simpletest/testnavigationlib.php
View
119 lib/navigationlib.php
@@ -237,8 +237,8 @@ public static function override_active_url(moodle_url $url) {
}
/**
- * Adds a navigation node as a child of this node.
- *
+ * Creates a navigation node, ready to add it as a child using add_node
+ * function. (The created node needs to be added before you can use it.)
* @param string $text
* @param moodle_url|action_link $action
* @param int $type
@@ -247,11 +247,8 @@ public static function override_active_url(moodle_url $url) {
* @param pix_icon $icon
* @return navigation_node
*/
- public function add($text, $action=null, $type=self::TYPE_CUSTOM, $shorttext=null, $key=null, pix_icon $icon=null) {
- // First convert the nodetype for this node to a branch as it will now have children
- if ($this->nodetype !== self::NODETYPE_BRANCH) {
- $this->nodetype = self::NODETYPE_BRANCH;
- }
+ public static function create($text, $action=null, $type=self::TYPE_CUSTOM,
+ $shorttext=null, $key=null, pix_icon $icon=null) {
// Properties array used when creating the new navigation node
$itemarray = array(
'text' => $text,
@@ -269,18 +266,58 @@ public function add($text, $action=null, $type=self::TYPE_CUSTOM, $shorttext=nul
if ($icon!==null) {
$itemarray['icon'] = $icon;
}
- // Default the key to the number of children if not provided
- if ($key === null) {
- $key = $this->children->count();
- }
// Set the key
$itemarray['key'] = $key;
+ // Construct and return
+ return new navigation_node($itemarray);
+ }
+
+ /**
+ * Adds a navigation node as a child of this node.
+ *
+ * @param string $text
+ * @param moodle_url|action_link $action
+ * @param int $type
+ * @param string $shorttext
+ * @param string|int $key
+ * @param pix_icon $icon
+ * @return navigation_node
+ */
+ public function add($text, $action=null, $type=self::TYPE_CUSTOM, $shorttext=null, $key=null, pix_icon $icon=null) {
+ // Create child node
+ $childnode = self::create($text, $action, $type, $shorttext, $key, $icon);
+
+ // Add the child to end and return
+ return $this->add_node($childnode);
+ }
+
+ /**
+ * Adds a navigation node as a child of this one, given a $node object
+ * created using the create function.
+ * @param navigation_node $childnode Node to add
+ * @param int|string $key The key of a node to add this before. If not
+ * specified, adds at end of list
+ * @return navigation_node The added node
+ */
+ public function add_node(navigation_node $childnode, $beforekey=null) {
+ // First convert the nodetype for this node to a branch as it will now have children
+ if ($this->nodetype !== self::NODETYPE_BRANCH) {
+ $this->nodetype = self::NODETYPE_BRANCH;
+ }
// Set the parent to this node
- $itemarray['parent'] = $this;
+ $childnode->parent = $this;
+
+ // Default the key to the number of children if not provided
+ if ($childnode->key === null) {
+ $childnode->key = $this->children->count();
+ }
+
// Add the child using the navigation_node_collections add method
- $node = $this->children->add(new navigation_node($itemarray));
- // If the node is a category node or the user is logged in and its a course
- // then mark this node as a branch (makes it expandable by AJAX)
+ $node = $this->children->add($childnode, $beforekey);
+
+ // If added node is a category node or the user is logged in and it's a course
+ // then mark added node as a branch (makes it expandable by AJAX)
+ $type = $childnode->type;
if (($type==self::TYPE_CATEGORY) || (isloggedin() && $type==self::TYPE_COURSE)) {
$node->nodetype = self::NODETYPE_BRANCH;
}
@@ -288,7 +325,7 @@ public function add($text, $action=null, $type=self::TYPE_CUSTOM, $shorttext=nul
if ($this->hidden) {
$node->hidden = true;
}
- // Return the node (reference returned by $this->children->add()
+ // Return added node (reference returned by $this->children->add()
return $node;
}
@@ -647,13 +684,16 @@ class navigation_node_collection implements IteratorAggregate {
/**
* Adds a navigation node to the collection
*
- * @param navigation_node $node
- * @return navigation_node
+ * @param navigation_node $node Node to add
+ * @param string $beforekey If specified, adds before a node with this key,
+ * otherwise adds at end
+ * @return navigation_node Added node
*/
- public function add(navigation_node $node) {
+ public function add(navigation_node $node, $beforekey=null) {
global $CFG;
$key = $node->key;
$type = $node->type;
+
// First check we have a 2nd dimension for this type
if (!array_key_exists($type, $this->orderedcollection)) {
$this->orderedcollection[$type] = array();
@@ -662,15 +702,50 @@ public function add(navigation_node $node) {
if ($CFG->debug && array_key_exists($key, $this->orderedcollection[$type])) {
debugging('Navigation node intersect: Adding a node that already exists '.$key, DEBUG_DEVELOPER);
}
- // Add the node to the appropriate place in the ordered structure.
+
+ // Find the key to add before
+ $newindex = $this->count;
+ $last = true;
+ if ($beforekey !== null) {
+ foreach ($this->collection as $index => $othernode) {
+ if ($othernode->key === $beforekey) {
+ $newindex = $index;
+ $last = false;
+ break;
+ }
+ }
+ if ($newindex === $this->count) {
+ $allkeys = '';
+ foreach ($this->collection as $othernode) {
+ $allkeys .= ' ' . $othernode->key;
+ }
+ debugging('Navigation node add_before: Reference node not found ' . $beforekey .
+ ', options: ' . $allkeys, DEBUG_DEVELOPER);
+ }
+ }
+
+ // Add the node to the appropriate place in the by-type structure (which
+ // is not ordered, despite the variable name)
$this->orderedcollection[$type][$key] = $node;
+ if (!$last) {
+ // Update existing references in the ordered collection (which is the
+ // one that isn't called 'ordered') to shuffle them along if required
+ for ($oldindex = $this->count; $oldindex > $newindex; $oldindex--) {
+ $this->collection[$oldindex] = $this->collection[$oldindex - 1];
+ }
+ }
// Add a reference to the node to the progressive collection.
- $this->collection[$this->count] = &$this->orderedcollection[$type][$key];
+ $this->collection[$newindex] = &$this->orderedcollection[$type][$key];
// Update the last property to a reference to this new node.
$this->last = &$this->orderedcollection[$type][$key];
+
+ // Reorder the array by index if needed
+ if (!$last) {
+ ksort($this->collection);
+ }
$this->count++;
// Return the reference to the now added node
- return $this->last;
+ return $node;
}
/**
View
22 lib/simpletest/testnavigationlib.php
@@ -98,6 +98,28 @@ public function test_add() {
$this->assertReference($node3, $this->node->get($node3->key, $node3->type));
}
+ public function test_add_before() {
+ global $CFG;
+ // Create 3 nodes
+ $node1 = navigation_node::create('test_add_1', null, navigation_node::TYPE_CUSTOM,
+ 'test 1', 'testadd1');
+ $node2 = navigation_node::create('test_add_2', null, navigation_node::TYPE_CUSTOM,
+ 'test 2', 'testadd2');
+ $node3 = navigation_node::create('test_add_3', null, navigation_node::TYPE_CUSTOM,
+ 'test 3', 'testadd3');
+ // Add node 2, then node 1 before 2, then node 3 at end
+ $this->node->add_node($node2);
+ $this->node->add_node($node1, 'testadd2');
+ $this->node->add_node($node3);
+ // Check the last 3 nodes are in 1, 2, 3 order and have those indexes
+ foreach($this->node->children as $child) {
+ $keys[] = $child->key;
+ }
+ $this->assertEqual('testadd1', $keys[count($keys)-3]);
+ $this->assertEqual('testadd2', $keys[count($keys)-2]);
+ $this->assertEqual('testadd3', $keys[count($keys)-1]);
+ }
+
public function test_add_class() {
$node = $this->node->get('demo1');
$this->assertIsA($node, 'navigation_node');
Please sign in to comment.
Something went wrong with that request. Please try again.