1<?php 2/** 3 * This file is part of the FreeDSx LDAP package. 4 * 5 * (c) Chad Sikorra <Chad.Sikorra@gmail.com> 6 * 7 * For the full copyright and license information, please view the LICENSE 8 * file that was distributed with this source code. 9 */ 10 11namespace FreeDSx\Ldap\Entry; 12 13/** 14 * Represents an Entry in LDAP. 15 * 16 * @author Chad Sikorra <Chad.Sikorra@gmail.com> 17 */ 18class Entry implements \IteratorAggregate, \Countable 19{ 20 /** 21 * @var Attribute[] 22 */ 23 protected $attributes; 24 25 /** 26 * @var Dn 27 */ 28 protected $dn; 29 30 /** 31 * @var Changes 32 */ 33 protected $changes; 34 35 /** 36 * @param string|Dn $dn 37 * @param Attribute ...$attributes 38 */ 39 public function __construct($dn, Attribute ...$attributes) 40 { 41 $this->dn = $dn instanceof Dn ? $dn : new Dn($dn); 42 $this->attributes = $attributes; 43 $this->changes = new Changes(); 44 } 45 46 /** 47 * Add an attribute and its values. 48 * 49 * @param string|Attribute $attribute 50 * @param string[] ...$values 51 * @return $this 52 */ 53 public function add($attribute, ...$values) 54 { 55 $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute, ...$values); 56 57 if (($exists = $this->get($attribute, true)) !== null) { 58 $exists->add(...$attribute->getValues()); 59 } else { 60 $this->attributes[] = $attribute; 61 } 62 $this->changes->add(Change::add(clone $attribute)); 63 64 return $this; 65 } 66 67 /** 68 * Remove an attribute's value(s). 69 * 70 * @param string|Attribute $attribute 71 * @param array ...$values 72 * @return $this 73 */ 74 public function remove($attribute, ...$values) 75 { 76 $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute, ...$values); 77 78 if (\count($attribute->getValues()) !== 0) { 79 if (($exists = $this->get($attribute, true)) !== null) { 80 $exists->remove(...$attribute->getValues()); 81 } 82 $this->changes->add(Change::delete(clone $attribute)); 83 } 84 85 return $this; 86 } 87 88 /** 89 * Reset an attribute, which removes any values it may have. 90 * 91 * @param string[]|Attribute[] ...$attributes 92 * @return $this 93 */ 94 public function reset(...$attributes) 95 { 96 foreach ($attributes as $attribute) { 97 $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute); 98 foreach ($this->attributes as $i => $attr) { 99 if ($attr->equals($attribute, true)) { 100 unset($this->attributes[$i]); 101 break; 102 } 103 } 104 $this->changes()->add(Change::reset(clone $attribute)); 105 } 106 107 return $this; 108 } 109 110 /** 111 * Set an attribute on the entry, replacing any value(s) that may exist on it. 112 * 113 * @param string|Attribute $attribute 114 * @param array ...$values 115 * @return $this 116 */ 117 public function set($attribute, ...$values) 118 { 119 $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute, ...$values); 120 121 $exists = false; 122 foreach ($this->attributes as $i => $attr) { 123 if ($attr->equals($attribute, true)) { 124 $exists = true; 125 $this->attributes[$i] = $attribute; 126 break; 127 } 128 } 129 if (!$exists) { 130 $this->attributes[] = $attribute; 131 } 132 $this->changes->add(Change::replace(clone $attribute)); 133 134 return $this; 135 } 136 137 /** 138 * Get a specific attribute by name (or Attribute object). 139 * 140 * @param string|Attribute $attribute 141 * @param bool $strict If set to true, then options on the attribute must also match. 142 * @return null|Attribute 143 */ 144 public function get($attribute, bool $strict = false): ?Attribute 145 { 146 $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute); 147 148 foreach ($this->attributes as $attr) { 149 if ($attr->equals($attribute, $strict)) { 150 return $attr; 151 } 152 } 153 154 return null; 155 } 156 157 /** 158 * Check if a specific attribute exists on the entry. 159 * 160 * @param string|Attribute $attribute 161 * @param bool $strict 162 * @return bool 163 */ 164 public function has($attribute, bool $strict = false): bool 165 { 166 $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute); 167 168 return (bool) $this->get($attribute, $strict); 169 } 170 171 /** 172 * @return Attribute[] 173 */ 174 public function getAttributes(): array 175 { 176 return $this->attributes; 177 } 178 179 /** 180 * @return Dn 181 */ 182 public function getDn(): Dn 183 { 184 return $this->dn; 185 } 186 187 /** 188 * Get the changes accumulated for this entry. 189 * 190 * @return Changes 191 */ 192 public function changes(): Changes 193 { 194 return $this->changes; 195 } 196 197 /** 198 * Get the entry representation as an associative array. 199 * 200 * @return array 201 */ 202 public function toArray(): array 203 { 204 $attributes = []; 205 206 foreach ($this->attributes as $attribute) { 207 $attributes[$attribute->getDescription()] = $attribute->getValues(); 208 } 209 210 return $attributes; 211 } 212 213 /** 214 * @return \ArrayIterator 215 */ 216 public function getIterator(): \ArrayIterator 217 { 218 return new \ArrayIterator($this->attributes); 219 } 220 221 /** 222 * @return int 223 */ 224 public function count(): int 225 { 226 return \count($this->attributes); 227 } 228 229 public function __toString(): string 230 { 231 return $this->dn->toString(); 232 } 233 234 public function __get(string $name): ?Attribute 235 { 236 return $this->get($name); 237 } 238 239 /** 240 * @param string[]|string $value 241 */ 242 public function __set(string $name, $value): void 243 { 244 $this->set($name, ...(\is_array($value) ? $value : [$value])); 245 } 246 247 public function __isset(string $name): bool 248 { 249 return $this->has($name); 250 } 251 252 public function __unset(string $name): void 253 { 254 $this->reset($name); 255 } 256 257 /** 258 * An alias of fromArray(). 259 * 260 * @param string $dn 261 * @param array $attributes 262 * @return Entry 263 */ 264 public static function create(string $dn, array $attributes = []): Entry 265 { 266 return self::fromArray($dn, $attributes); 267 } 268 269 /** 270 * Construct an entry from an associative array. 271 * 272 * @param string $dn 273 * @param array $attributes 274 * @return Entry 275 */ 276 public static function fromArray(string $dn, array $attributes = []): Entry 277 { 278 /** @var Attribute[] $entryAttr */ 279 $entryAttr = []; 280 281 foreach ($attributes as $attribute => $value) { 282 $entryAttr[] = new Attribute($attribute, ...(\is_array($value) ? $value : [$value])); 283 } 284 285 return new self($dn, ...$entryAttr); 286 } 287} 288