summaryrefslogtreecommitdiffstats
path: root/library/Toplevelview/Tree/TLVTreeNode.php
diff options
context:
space:
mode:
Diffstat (limited to 'library/Toplevelview/Tree/TLVTreeNode.php')
-rw-r--r--library/Toplevelview/Tree/TLVTreeNode.php334
1 files changed, 334 insertions, 0 deletions
diff --git a/library/Toplevelview/Tree/TLVTreeNode.php b/library/Toplevelview/Tree/TLVTreeNode.php
new file mode 100644
index 0000000..fd70e49
--- /dev/null
+++ b/library/Toplevelview/Tree/TLVTreeNode.php
@@ -0,0 +1,334 @@
+<?php
+/* Copyright (C) 2017 Icinga Development Team <info@icinga.com> */
+
+namespace Icinga\Module\Toplevelview\Tree;
+
+use Icinga\Application\Benchmark;
+use Icinga\Data\Tree\TreeNode;
+use Icinga\Exception\ConfigurationError;
+use Icinga\Exception\NotImplementedError;
+use Icinga\Exception\ProgrammingError;
+
+class TLVTreeNode extends TreeNode
+{
+ /**
+ * @var string
+ */
+ protected $type = 'node';
+
+ protected $key = null;
+
+ /**
+ * @var TLVTree
+ */
+ protected $root;
+
+ /**
+ * @var TLVTreeNode
+ */
+ protected $parent;
+
+ /**
+ * @var string
+ */
+ protected $fullId;
+
+ /**
+ * @var TLVStatus
+ */
+ protected $status;
+
+ /**
+ * @var array
+ */
+ protected $properties = array();
+
+ protected static $canHaveChildren = true;
+
+ /**
+ * The key which represents the display title
+ *
+ * @var string
+ */
+ protected static $titleKey = 'name';
+
+ /**
+ * Mapping types to its implementation class
+ *
+ * @var array
+ */
+ protected static $typeMap = array(
+ 'host' => 'Icinga\\Module\\Toplevelview\\Tree\\TLVHostNode',
+ 'service' => 'Icinga\\Module\\Toplevelview\\Tree\\TLVServiceNode',
+ 'hostgroup' => 'Icinga\\Module\\Toplevelview\\Tree\\TLVHostGroupNode',
+ );
+
+ /**
+ * Mapping keys to a type
+ *
+ * Warning: order is important when keys overlap!
+ *
+ * @var array
+ */
+ protected static $typeKeyMap = array(
+ 'service' => array('host', 'service'),
+ 'host' => 'host',
+ 'hostgroup' => 'hostgroup',
+ );
+
+ /**
+ * @param $array
+ * @param TLVTreeNode|null $parent
+ * @param TLVTree $root
+ *
+ * @return static
+ *
+ * @throws NotImplementedError
+ * @throws ProgrammingError
+ */
+ public static function fromArray($array, TLVTreeNode $parent = null, TLVTree $root = null)
+ {
+ if ($root === null) {
+ Benchmark::measure('Begin loading TLVTree from array');
+ }
+
+ // try to detect type
+ if (! array_key_exists('type', $array)) {
+ foreach (self::$typeKeyMap as $type => $keys) {
+ if (! is_array($keys)) {
+ $keys = array($keys);
+ }
+ $matched = false;
+ foreach ($keys as $k) {
+ if (array_key_exists($k, $array)) {
+ $matched = true;
+ } else {
+ continue 2;
+ }
+ }
+ // if all keys are present
+ if ($matched === true) {
+ $array['type'] = $type;
+ break;
+ }
+ }
+ }
+
+ if (array_key_exists('type', $array)) {
+ $type = $array['type'];
+ if (array_key_exists($type, self::$typeMap)) {
+ $node = new self::$typeMap[$type];
+ $node->type = $type;
+ } else {
+ throw new NotImplementedError('Could not find type "%s" for %s', $type, var_export($array, true));
+ }
+ } elseif ($root === null) {
+ $node = new static;
+ } else {
+ $node = new self;
+ }
+
+ if ($root === null) {
+ $node->root = true; // is root
+ $node->parent = null;
+ $root = $parent = $node;
+ } elseif ($parent === null) {
+ throw new ProgrammingError('You must specify the direct parent!');
+ } else {
+ $node->root = $root;
+ $node->parent = $parent;
+ }
+
+ foreach ($array as $key => $value) {
+ if ($key !== 'children') {
+ $node->properties[$key] = $value;
+ } elseif (is_array($value)) { // only array values for children
+ foreach ($value as $i => $child) {
+ $childNode = self::fromArray($child, $node, $root);
+ $childNode->id = $i;
+ $node->appendChild($childNode);
+ }
+ }
+ }
+
+ $node->register();
+
+ if ($root === $node) {
+ Benchmark::measure('Finished loading TLVTree from array');
+ }
+
+ return $node;
+ }
+
+ /**
+ * Retrieve all objects as breadcrumb
+ *
+ * @param array $list for recursion
+ *
+ * @return TLVTreeNode[]
+ */
+ public function getBreadCrumb(&$list = array())
+ {
+ array_unshift($list, $this);
+ if ($this->parent !== $this->root) {
+ $this->parent->getBreadCrumb($list);
+ }
+ return $list;
+ }
+
+ /**
+ *
+ * @return mixed|string
+ */
+ public function getFullId()
+ {
+ if ($this->fullId === null) {
+ $id = (string) $this->id;
+ if ($this->parent !== $this->root) {
+ $this->fullId = $this->parent->getFullId() . '-' . $id;
+ } else {
+ $this->fullId = $id;
+ }
+ }
+ return $this->fullId;
+ }
+
+ /**
+ * @return mixed
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ public function getProperties()
+ {
+ return $this->properties;
+ }
+
+ public function setProperties($array)
+ {
+ $this->properties = $array;
+ return $this;
+ }
+
+ public function get($key)
+ {
+ if (array_key_exists($key, $this->properties)) {
+ return $this->properties[$key];
+ } else {
+ return null;
+ }
+ }
+
+ public function set($key, $value)
+ {
+ $this->properties[$key] = $value;
+ return $this;
+ }
+
+ public function getTitle()
+ {
+ if (array_key_exists(static::$titleKey, $this->properties)) {
+ return $this->properties[static::$titleKey];
+ } else {
+ return null;
+ }
+ }
+
+ public function getKey()
+ {
+ if ($this->key === null) {
+ throw new ProgrammingError('Can not get key for %s', get_class($this));
+ }
+
+ if (array_key_exists($this->key, $this->properties)) {
+ return $this->properties[$this->key];
+ } else {
+ throw new ProgrammingError(
+ 'Can not retrieve key for %s in %s',
+ $this->key,
+ get_class($this)
+ );
+ }
+ }
+
+ /**
+ * @return TLVTree
+ */
+ public function getRoot()
+ {
+ return $this->root;
+ }
+
+ /**
+ * @return TLVTreeNode
+ */
+ public function getParent()
+ {
+ return $this->parent;
+ }
+
+ /**
+ * @return TLVTreeNode[]
+ */
+ public function getChildren()
+ {
+ return parent::getChildren();
+ }
+
+ /**
+ * Append a child node as the last child of this node
+ *
+ * @param TreeNode $child The child to append
+ *
+ * @return $this
+ *
+ * @throws ConfigurationError When node does not allow children
+ */
+ public function appendChild(TreeNode $child)
+ {
+ if (static::$canHaveChildren === true) {
+ $this->children[] = $child;
+ } else {
+ throw new ConfigurationError('Can not add children below type %s', $this->type);
+ }
+ return $this;
+ }
+
+ protected function register()
+ {
+ if ($this->type !== 'node') {
+ $this->root->registerObject($this->type, $this->getKey(), get_class($this));
+ }
+ return $this;
+ }
+
+ /**
+ * @return TLVStatus
+ * @throws ProgrammingError
+ */
+ public function getStatus()
+ {
+ if (static::$canHaveChildren === true) {
+ if ($this->status === null) {
+ $this->status = new TLVStatus;
+
+ $missed = true;
+ foreach ($this->getChildren() as $child) {
+ $this->status->merge($child->getStatus());
+ $missed = false;
+ }
+
+ // Note: old TLV does not count an empty branch as missing...
+ if ($missed) {
+ $this->status->add('missing', 1);
+ }
+ }
+
+ return $this->status;
+ } else {
+ throw new ProgrammingError('getStatus() needs to be implemented for %s', get_class($this));
+ }
+ }
+}