summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Data/Tree
diff options
context:
space:
mode:
Diffstat (limited to 'library/Icinga/Data/Tree')
-rw-r--r--library/Icinga/Data/Tree/SimpleTree.php90
-rw-r--r--library/Icinga/Data/Tree/TreeNode.php109
-rw-r--r--library/Icinga/Data/Tree/TreeNodeIterator.php75
3 files changed, 274 insertions, 0 deletions
diff --git a/library/Icinga/Data/Tree/SimpleTree.php b/library/Icinga/Data/Tree/SimpleTree.php
new file mode 100644
index 0000000..e89f589
--- /dev/null
+++ b/library/Icinga/Data/Tree/SimpleTree.php
@@ -0,0 +1,90 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Data\Tree;
+
+use IteratorAggregate;
+use LogicException;
+use Traversable;
+
+/**
+ * A simple tree
+ */
+class SimpleTree implements IteratorAggregate
+{
+ /**
+ * Root node
+ *
+ * @var TreeNode
+ */
+ protected $sentinel;
+
+ /**
+ * Nodes
+ *
+ * @var array
+ */
+ protected $nodes = array();
+
+ /**
+ * Create a new simple tree
+ */
+ public function __construct()
+ {
+ $this->sentinel = new TreeNode();
+ }
+
+ /**
+ * Add a child node
+ *
+ * @param TreeNode $child
+ * @param TreeNode $parent
+ *
+ * @return $this
+ */
+ public function addChild(TreeNode $child, TreeNode $parent = null)
+ {
+ if ($parent === null) {
+ $parent = $this->sentinel;
+ } elseif (! isset($this->nodes[$parent->getId()])) {
+ throw new LogicException(sprintf(
+ 'Can\'t append child node %s to parent node %s: Parent node does not exist',
+ $child->getId(),
+ $parent->getId()
+ ));
+ }
+ if (isset($this->nodes[$child->getId()])) {
+ throw new LogicException(sprintf(
+ 'Can\'t append child node %s to parent node %s: Child node does already exist',
+ $child->getId(),
+ $parent->getId()
+ ));
+ }
+ $this->nodes[$child->getId()] = $child;
+ $parent->appendChild($child);
+ return $this;
+ }
+
+ /**
+ * Get a node by its ID
+ *
+ * @param mixed $id
+ *
+ * @return TreeNode|null
+ */
+ public function getNode($id)
+ {
+ if (! isset($this->nodes[$id])) {
+ return null;
+ }
+ return $this->nodes[$id];
+ }
+
+ /**
+ * @return TreeNodeIterator
+ */
+ public function getIterator(): Traversable
+ {
+ return new TreeNodeIterator($this->sentinel);
+ }
+}
diff --git a/library/Icinga/Data/Tree/TreeNode.php b/library/Icinga/Data/Tree/TreeNode.php
new file mode 100644
index 0000000..66bce79
--- /dev/null
+++ b/library/Icinga/Data/Tree/TreeNode.php
@@ -0,0 +1,109 @@
+<?php
+/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Data\Tree;
+
+use Icinga\Data\Identifiable;
+
+class TreeNode implements Identifiable
+{
+ /**
+ * The node's ID
+ *
+ * @var mixed
+ */
+ protected $id;
+
+ /**
+ * The node's value
+ *
+ * @var mixed
+ */
+ protected $value;
+
+ /**
+ * The node's children
+ *
+ * @var array
+ */
+ protected $children = array();
+
+ /**
+ * Set the node's ID
+ *
+ * @param mixed $id ID of the node
+ *
+ * @return $this
+ */
+ public function setId($id)
+ {
+ $this->id = $id;
+ return $this;
+ }
+
+ /**
+ * (non-PHPDoc)
+ * @see Identifiable::getId() For the method documentation.
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * Set the node's value
+ *
+ * @param mixed $value
+ *
+ * @return $this
+ */
+ public function setValue($value)
+ {
+ $this->value = $value;
+ return $this;
+ }
+
+ /**
+ * Get the node's value
+ *
+ * @return mixed
+ */
+ public function getValue()
+ {
+ return $this->value;
+ }
+
+ /**
+ * Append a child node as the last child of this node
+ *
+ * @param TreeNode $child The child to append
+ *
+ * @return $this
+ */
+ public function appendChild(TreeNode $child)
+ {
+ $this->children[] = $child;
+ return $this;
+ }
+
+
+ /**
+ * Get whether the node has children
+ *
+ * @return bool
+ */
+ public function hasChildren()
+ {
+ return ! empty($this->children);
+ }
+
+ /**
+ * Get the node's children
+ *
+ * @return array
+ */
+ public function getChildren()
+ {
+ return $this->children;
+ }
+}
diff --git a/library/Icinga/Data/Tree/TreeNodeIterator.php b/library/Icinga/Data/Tree/TreeNodeIterator.php
new file mode 100644
index 0000000..1c71787
--- /dev/null
+++ b/library/Icinga/Data/Tree/TreeNodeIterator.php
@@ -0,0 +1,75 @@
+<?php
+/* Icinga Web 2 | (c) 2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Data\Tree;
+
+use ArrayIterator;
+use RecursiveIterator;
+
+/**
+ * Iterator over a tree node's children
+ */
+class TreeNodeIterator implements RecursiveIterator
+{
+ /**
+ * The node's children
+ *
+ * @var ArrayIterator
+ */
+ protected $children;
+
+ /**
+ * Create a new iterator over a tree node's children
+ *
+ * @param TreeNode $node
+ */
+ public function __construct(TreeNode $node)
+ {
+ $this->children = new ArrayIterator($node->getChildren());
+ }
+
+ public function current(): TreeNode
+ {
+ return $this->children->current();
+ }
+
+ public function key(): int
+ {
+ return $this->children->key();
+ }
+
+ public function next(): void
+ {
+ $this->children->next();
+ }
+
+ public function rewind(): void
+ {
+ $this->children->rewind();
+ }
+
+ public function valid(): bool
+ {
+ return $this->children->valid();
+ }
+
+ public function hasChildren(): bool
+ {
+ return $this->current()->hasChildren();
+ }
+
+ public function getChildren(): TreeNodeIterator
+ {
+ return new static($this->current());
+ }
+
+ /**
+ * Get whether the iterator is empty
+ *
+ * @return bool
+ */
+ public function isEmpty()
+ {
+ return ! $this->children->count();
+ }
+}