1<?php 2/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */ 3 4namespace Icinga\Protocol\Ldap; 5 6use Icinga\Exception\IcingaException; 7 8/** 9 * This class is a special node object, representing your connections root node 10 * 11 * @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.com> 12 * @author Icinga-Web Team <info@icinga.com> 13 * @package Icinga\Protocol\Ldap 14 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 15 * @package Icinga\Protocol\Ldap 16 */ 17class Root 18{ 19 /** 20 * @var string 21 */ 22 protected $rdn; 23 24 /** 25 * @var LdapConnection 26 */ 27 protected $connection; 28 29 /** 30 * @var array 31 */ 32 protected $children = array(); 33 34 /** 35 * @var array 36 */ 37 protected $props = array(); 38 39 /** 40 * @param LdapConnection $connection 41 */ 42 protected function __construct(LdapConnection $connection) 43 { 44 $this->connection = $connection; 45 } 46 47 /** 48 * @return bool 49 */ 50 public function hasParent() 51 { 52 return false; 53 } 54 55 /** 56 * @param LdapConnection $connection 57 * @return Root 58 */ 59 public static function forConnection(LdapConnection $connection) 60 { 61 $root = new Root($connection); 62 return $root; 63 } 64 65 /** 66 * @param $dn 67 * @param array $props 68 * @return Node 69 */ 70 public function createChildByDN($dn, $props = array()) 71 { 72 $dn = $this->stripMyDN($dn); 73 $parts = array_reverse(LdapUtils::explodeDN($dn)); 74 $parent = $this; 75 while ($rdn = array_shift($parts)) { 76 if ($parent->hasChildRDN($rdn)) { 77 $child = $parent->getChildByRDN($rdn); 78 } else { 79 $child = Node::createWithRDN($parent, $rdn, (array)$props); 80 $parent->addChild($child); 81 } 82 $parent = $child; 83 } 84 return $child; 85 } 86 87 /** 88 * @param $rdn 89 * @return bool 90 */ 91 public function hasChildRDN($rdn) 92 { 93 return array_key_exists(strtolower($rdn), $this->children); 94 } 95 96 /** 97 * @param $rdn 98 * @return mixed 99 * @throws IcingaException 100 */ 101 public function getChildByRDN($rdn) 102 { 103 if (!$this->hasChildRDN($rdn)) { 104 throw new IcingaException( 105 'The child RDN "%s" is not available', 106 $rdn 107 ); 108 } 109 return $this->children[strtolower($rdn)]; 110 } 111 112 /** 113 * @return array 114 */ 115 public function children() 116 { 117 return $this->children; 118 } 119 120 public function countChildren() 121 { 122 return count($this->children); 123 } 124 125 /** 126 * @return bool 127 */ 128 public function hasChildren() 129 { 130 return !empty($this->children); 131 } 132 133 /** 134 * @param Node $child 135 * @return $this 136 */ 137 public function addChild(Node $child) 138 { 139 $this->children[strtolower($child->getRDN())] = $child; 140 return $this; 141 } 142 143 /** 144 * @param $dn 145 * @return string 146 */ 147 protected function stripMyDN($dn) 148 { 149 $this->assertSubDN($dn); 150 return substr($dn, 0, strlen($dn) - strlen($this->getDN()) - 1); 151 } 152 153 /** 154 * @param $dn 155 * @return $this 156 * @throws IcingaException 157 */ 158 protected function assertSubDN($dn) 159 { 160 $mydn = $this->getDN(); 161 $end = substr($dn, -1 * strlen($mydn)); 162 if (strtolower($end) !== strtolower($mydn)) { 163 throw new IcingaException( 164 '"%s" is not a child of "%s"', 165 $dn, 166 $mydn 167 ); 168 } 169 if (strlen($dn) === strlen($mydn)) { 170 throw new IcingaException( 171 '"%s" is not a child of "%s", they are equal', 172 $dn, 173 $mydn 174 ); 175 } 176 return $this; 177 } 178 179 /** 180 * @param LdapConnection $connection 181 * @return $this 182 */ 183 public function setConnection(LdapConnection $connection) 184 { 185 $this->connection = $connection; 186 return $this; 187 } 188 189 /** 190 * @return LdapConnection 191 */ 192 public function getConnection() 193 { 194 return $this->connection; 195 } 196 197 /** 198 * @return bool 199 */ 200 public function hasBeenChanged() 201 { 202 return false; 203 } 204 205 /** 206 * @return mixed 207 */ 208 public function getRDN() 209 { 210 return $this->getDN(); 211 } 212 213 /** 214 * @return mixed 215 */ 216 public function getDN() 217 { 218 return $this->connection->getDn(); 219 } 220 221 /** 222 * @param $key 223 * @return null 224 */ 225 public function __get($key) 226 { 227 if (!array_key_exists($key, $this->props)) { 228 return null; 229 } 230 return $this->props[$key]; 231 } 232 233 /** 234 * @param $key 235 * @return bool 236 */ 237 public function __isset($key) 238 { 239 return array_key_exists($key, $this->props); 240 } 241} 242