10b3fd2d3SAndreas Gohr<?php 2*dad993c5SAndreas Gohr 30b3fd2d3SAndreas Gohr/** 40b3fd2d3SAndreas Gohr * This file is part of the FreeDSx LDAP package. 50b3fd2d3SAndreas Gohr * 60b3fd2d3SAndreas Gohr * (c) Chad Sikorra <Chad.Sikorra@gmail.com> 70b3fd2d3SAndreas Gohr * 80b3fd2d3SAndreas Gohr * For the full copyright and license information, please view the LICENSE 90b3fd2d3SAndreas Gohr * file that was distributed with this source code. 100b3fd2d3SAndreas Gohr */ 110b3fd2d3SAndreas Gohr 120b3fd2d3SAndreas Gohrnamespace FreeDSx\Ldap\Entry; 130b3fd2d3SAndreas Gohr 14*dad993c5SAndreas Gohruse ArrayIterator; 15*dad993c5SAndreas Gohruse Countable; 16*dad993c5SAndreas Gohruse IteratorAggregate; 17*dad993c5SAndreas Gohruse Traversable; 18*dad993c5SAndreas Gohruse function count; 19*dad993c5SAndreas Gohruse function is_array; 20*dad993c5SAndreas Gohr 210b3fd2d3SAndreas Gohr/** 220b3fd2d3SAndreas Gohr * Represents an Entry in LDAP. 230b3fd2d3SAndreas Gohr * 240b3fd2d3SAndreas Gohr * @author Chad Sikorra <Chad.Sikorra@gmail.com> 250b3fd2d3SAndreas Gohr */ 26*dad993c5SAndreas Gohrclass Entry implements IteratorAggregate, Countable 270b3fd2d3SAndreas Gohr{ 280b3fd2d3SAndreas Gohr /** 290b3fd2d3SAndreas Gohr * @var Attribute[] 300b3fd2d3SAndreas Gohr */ 310b3fd2d3SAndreas Gohr protected $attributes; 320b3fd2d3SAndreas Gohr 330b3fd2d3SAndreas Gohr /** 340b3fd2d3SAndreas Gohr * @var Dn 350b3fd2d3SAndreas Gohr */ 360b3fd2d3SAndreas Gohr protected $dn; 370b3fd2d3SAndreas Gohr 380b3fd2d3SAndreas Gohr /** 390b3fd2d3SAndreas Gohr * @var Changes 400b3fd2d3SAndreas Gohr */ 410b3fd2d3SAndreas Gohr protected $changes; 420b3fd2d3SAndreas Gohr 430b3fd2d3SAndreas Gohr /** 440b3fd2d3SAndreas Gohr * @param string|Dn $dn 450b3fd2d3SAndreas Gohr * @param Attribute ...$attributes 460b3fd2d3SAndreas Gohr */ 470b3fd2d3SAndreas Gohr public function __construct($dn, Attribute ...$attributes) 480b3fd2d3SAndreas Gohr { 490b3fd2d3SAndreas Gohr $this->dn = $dn instanceof Dn ? $dn : new Dn($dn); 500b3fd2d3SAndreas Gohr $this->attributes = $attributes; 510b3fd2d3SAndreas Gohr $this->changes = new Changes(); 520b3fd2d3SAndreas Gohr } 530b3fd2d3SAndreas Gohr 540b3fd2d3SAndreas Gohr /** 550b3fd2d3SAndreas Gohr * Add an attribute and its values. 560b3fd2d3SAndreas Gohr * 570b3fd2d3SAndreas Gohr * @param string|Attribute $attribute 58*dad993c5SAndreas Gohr * @param string ...$values 590b3fd2d3SAndreas Gohr * @return $this 600b3fd2d3SAndreas Gohr */ 610b3fd2d3SAndreas Gohr public function add($attribute, ...$values) 620b3fd2d3SAndreas Gohr { 630b3fd2d3SAndreas Gohr $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute, ...$values); 640b3fd2d3SAndreas Gohr 650b3fd2d3SAndreas Gohr if (($exists = $this->get($attribute, true)) !== null) { 660b3fd2d3SAndreas Gohr $exists->add(...$attribute->getValues()); 670b3fd2d3SAndreas Gohr } else { 680b3fd2d3SAndreas Gohr $this->attributes[] = $attribute; 690b3fd2d3SAndreas Gohr } 700b3fd2d3SAndreas Gohr $this->changes->add(Change::add(clone $attribute)); 710b3fd2d3SAndreas Gohr 720b3fd2d3SAndreas Gohr return $this; 730b3fd2d3SAndreas Gohr } 740b3fd2d3SAndreas Gohr 750b3fd2d3SAndreas Gohr /** 760b3fd2d3SAndreas Gohr * Remove an attribute's value(s). 770b3fd2d3SAndreas Gohr * 780b3fd2d3SAndreas Gohr * @param string|Attribute $attribute 79*dad993c5SAndreas Gohr * @param mixed|string ...$values 800b3fd2d3SAndreas Gohr * @return $this 810b3fd2d3SAndreas Gohr */ 820b3fd2d3SAndreas Gohr public function remove($attribute, ...$values) 830b3fd2d3SAndreas Gohr { 840b3fd2d3SAndreas Gohr $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute, ...$values); 850b3fd2d3SAndreas Gohr 86*dad993c5SAndreas Gohr if (count($attribute->getValues()) !== 0) { 870b3fd2d3SAndreas Gohr if (($exists = $this->get($attribute, true)) !== null) { 880b3fd2d3SAndreas Gohr $exists->remove(...$attribute->getValues()); 890b3fd2d3SAndreas Gohr } 900b3fd2d3SAndreas Gohr $this->changes->add(Change::delete(clone $attribute)); 910b3fd2d3SAndreas Gohr } 920b3fd2d3SAndreas Gohr 930b3fd2d3SAndreas Gohr return $this; 940b3fd2d3SAndreas Gohr } 950b3fd2d3SAndreas Gohr 960b3fd2d3SAndreas Gohr /** 970b3fd2d3SAndreas Gohr * Reset an attribute, which removes any values it may have. 980b3fd2d3SAndreas Gohr * 99*dad993c5SAndreas Gohr * @param string|Attribute ...$attributes 1000b3fd2d3SAndreas Gohr * @return $this 1010b3fd2d3SAndreas Gohr */ 1020b3fd2d3SAndreas Gohr public function reset(...$attributes) 1030b3fd2d3SAndreas Gohr { 1040b3fd2d3SAndreas Gohr foreach ($attributes as $attribute) { 1050b3fd2d3SAndreas Gohr $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute); 1060b3fd2d3SAndreas Gohr foreach ($this->attributes as $i => $attr) { 1070b3fd2d3SAndreas Gohr if ($attr->equals($attribute, true)) { 1080b3fd2d3SAndreas Gohr unset($this->attributes[$i]); 1090b3fd2d3SAndreas Gohr break; 1100b3fd2d3SAndreas Gohr } 1110b3fd2d3SAndreas Gohr } 1120b3fd2d3SAndreas Gohr $this->changes()->add(Change::reset(clone $attribute)); 1130b3fd2d3SAndreas Gohr } 1140b3fd2d3SAndreas Gohr 1150b3fd2d3SAndreas Gohr return $this; 1160b3fd2d3SAndreas Gohr } 1170b3fd2d3SAndreas Gohr 1180b3fd2d3SAndreas Gohr /** 1190b3fd2d3SAndreas Gohr * Set an attribute on the entry, replacing any value(s) that may exist on it. 1200b3fd2d3SAndreas Gohr * 1210b3fd2d3SAndreas Gohr * @param string|Attribute $attribute 122*dad993c5SAndreas Gohr * @param mixed ...$values 1230b3fd2d3SAndreas Gohr * @return $this 1240b3fd2d3SAndreas Gohr */ 1250b3fd2d3SAndreas Gohr public function set($attribute, ...$values) 1260b3fd2d3SAndreas Gohr { 1270b3fd2d3SAndreas Gohr $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute, ...$values); 1280b3fd2d3SAndreas Gohr 1290b3fd2d3SAndreas Gohr $exists = false; 1300b3fd2d3SAndreas Gohr foreach ($this->attributes as $i => $attr) { 1310b3fd2d3SAndreas Gohr if ($attr->equals($attribute, true)) { 1320b3fd2d3SAndreas Gohr $exists = true; 1330b3fd2d3SAndreas Gohr $this->attributes[$i] = $attribute; 1340b3fd2d3SAndreas Gohr break; 1350b3fd2d3SAndreas Gohr } 1360b3fd2d3SAndreas Gohr } 1370b3fd2d3SAndreas Gohr if (!$exists) { 1380b3fd2d3SAndreas Gohr $this->attributes[] = $attribute; 1390b3fd2d3SAndreas Gohr } 1400b3fd2d3SAndreas Gohr $this->changes->add(Change::replace(clone $attribute)); 1410b3fd2d3SAndreas Gohr 1420b3fd2d3SAndreas Gohr return $this; 1430b3fd2d3SAndreas Gohr } 1440b3fd2d3SAndreas Gohr 1450b3fd2d3SAndreas Gohr /** 1460b3fd2d3SAndreas Gohr * Get a specific attribute by name (or Attribute object). 1470b3fd2d3SAndreas Gohr * 1480b3fd2d3SAndreas Gohr * @param string|Attribute $attribute 1490b3fd2d3SAndreas Gohr * @param bool $strict If set to true, then options on the attribute must also match. 1500b3fd2d3SAndreas Gohr * @return null|Attribute 1510b3fd2d3SAndreas Gohr */ 1520b3fd2d3SAndreas Gohr public function get($attribute, bool $strict = false): ?Attribute 1530b3fd2d3SAndreas Gohr { 1540b3fd2d3SAndreas Gohr $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute); 1550b3fd2d3SAndreas Gohr 1560b3fd2d3SAndreas Gohr foreach ($this->attributes as $attr) { 1570b3fd2d3SAndreas Gohr if ($attr->equals($attribute, $strict)) { 1580b3fd2d3SAndreas Gohr return $attr; 1590b3fd2d3SAndreas Gohr } 1600b3fd2d3SAndreas Gohr } 1610b3fd2d3SAndreas Gohr 1620b3fd2d3SAndreas Gohr return null; 1630b3fd2d3SAndreas Gohr } 1640b3fd2d3SAndreas Gohr 1650b3fd2d3SAndreas Gohr /** 1660b3fd2d3SAndreas Gohr * Check if a specific attribute exists on the entry. 1670b3fd2d3SAndreas Gohr * 1680b3fd2d3SAndreas Gohr * @param string|Attribute $attribute 1690b3fd2d3SAndreas Gohr * @param bool $strict 1700b3fd2d3SAndreas Gohr * @return bool 1710b3fd2d3SAndreas Gohr */ 1720b3fd2d3SAndreas Gohr public function has($attribute, bool $strict = false): bool 1730b3fd2d3SAndreas Gohr { 1740b3fd2d3SAndreas Gohr $attribute = $attribute instanceof Attribute ? $attribute : new Attribute($attribute); 1750b3fd2d3SAndreas Gohr 1760b3fd2d3SAndreas Gohr return (bool) $this->get($attribute, $strict); 1770b3fd2d3SAndreas Gohr } 1780b3fd2d3SAndreas Gohr 1790b3fd2d3SAndreas Gohr /** 1800b3fd2d3SAndreas Gohr * @return Attribute[] 1810b3fd2d3SAndreas Gohr */ 1820b3fd2d3SAndreas Gohr public function getAttributes(): array 1830b3fd2d3SAndreas Gohr { 1840b3fd2d3SAndreas Gohr return $this->attributes; 1850b3fd2d3SAndreas Gohr } 1860b3fd2d3SAndreas Gohr 1870b3fd2d3SAndreas Gohr /** 1880b3fd2d3SAndreas Gohr * @return Dn 1890b3fd2d3SAndreas Gohr */ 1900b3fd2d3SAndreas Gohr public function getDn(): Dn 1910b3fd2d3SAndreas Gohr { 1920b3fd2d3SAndreas Gohr return $this->dn; 1930b3fd2d3SAndreas Gohr } 1940b3fd2d3SAndreas Gohr 1950b3fd2d3SAndreas Gohr /** 1960b3fd2d3SAndreas Gohr * Get the changes accumulated for this entry. 1970b3fd2d3SAndreas Gohr * 1980b3fd2d3SAndreas Gohr * @return Changes 1990b3fd2d3SAndreas Gohr */ 2000b3fd2d3SAndreas Gohr public function changes(): Changes 2010b3fd2d3SAndreas Gohr { 2020b3fd2d3SAndreas Gohr return $this->changes; 2030b3fd2d3SAndreas Gohr } 2040b3fd2d3SAndreas Gohr 2050b3fd2d3SAndreas Gohr /** 2060b3fd2d3SAndreas Gohr * Get the entry representation as an associative array. 2070b3fd2d3SAndreas Gohr * 2080b3fd2d3SAndreas Gohr * @return array 2090b3fd2d3SAndreas Gohr */ 2100b3fd2d3SAndreas Gohr public function toArray(): array 2110b3fd2d3SAndreas Gohr { 2120b3fd2d3SAndreas Gohr $attributes = []; 2130b3fd2d3SAndreas Gohr 2140b3fd2d3SAndreas Gohr foreach ($this->attributes as $attribute) { 2150b3fd2d3SAndreas Gohr $attributes[$attribute->getDescription()] = $attribute->getValues(); 2160b3fd2d3SAndreas Gohr } 2170b3fd2d3SAndreas Gohr 2180b3fd2d3SAndreas Gohr return $attributes; 2190b3fd2d3SAndreas Gohr } 2200b3fd2d3SAndreas Gohr 2210b3fd2d3SAndreas Gohr /** 222*dad993c5SAndreas Gohr * @inheritDoc 223*dad993c5SAndreas Gohr * @psalm-return \ArrayIterator<array-key, Attribute> 2240b3fd2d3SAndreas Gohr */ 225*dad993c5SAndreas Gohr public function getIterator(): Traversable 2260b3fd2d3SAndreas Gohr { 227*dad993c5SAndreas Gohr return new ArrayIterator($this->attributes); 2280b3fd2d3SAndreas Gohr } 2290b3fd2d3SAndreas Gohr 2300b3fd2d3SAndreas Gohr /** 2310b3fd2d3SAndreas Gohr * @return int 232*dad993c5SAndreas Gohr * @psalm-return 0|positive-int 2330b3fd2d3SAndreas Gohr */ 2340b3fd2d3SAndreas Gohr public function count(): int 2350b3fd2d3SAndreas Gohr { 236*dad993c5SAndreas Gohr return count($this->attributes); 2370b3fd2d3SAndreas Gohr } 2380b3fd2d3SAndreas Gohr 2390b3fd2d3SAndreas Gohr public function __toString(): string 2400b3fd2d3SAndreas Gohr { 2410b3fd2d3SAndreas Gohr return $this->dn->toString(); 2420b3fd2d3SAndreas Gohr } 2430b3fd2d3SAndreas Gohr 2440b3fd2d3SAndreas Gohr public function __get(string $name): ?Attribute 2450b3fd2d3SAndreas Gohr { 2460b3fd2d3SAndreas Gohr return $this->get($name); 2470b3fd2d3SAndreas Gohr } 2480b3fd2d3SAndreas Gohr 2490b3fd2d3SAndreas Gohr /** 2500b3fd2d3SAndreas Gohr * @param string[]|string $value 2510b3fd2d3SAndreas Gohr */ 2520b3fd2d3SAndreas Gohr public function __set(string $name, $value): void 2530b3fd2d3SAndreas Gohr { 254*dad993c5SAndreas Gohr $this->set($name, ...(is_array($value) ? $value : [$value])); 2550b3fd2d3SAndreas Gohr } 2560b3fd2d3SAndreas Gohr 2570b3fd2d3SAndreas Gohr public function __isset(string $name): bool 2580b3fd2d3SAndreas Gohr { 2590b3fd2d3SAndreas Gohr return $this->has($name); 2600b3fd2d3SAndreas Gohr } 2610b3fd2d3SAndreas Gohr 2620b3fd2d3SAndreas Gohr public function __unset(string $name): void 2630b3fd2d3SAndreas Gohr { 2640b3fd2d3SAndreas Gohr $this->reset($name); 2650b3fd2d3SAndreas Gohr } 2660b3fd2d3SAndreas Gohr 2670b3fd2d3SAndreas Gohr /** 2680b3fd2d3SAndreas Gohr * An alias of fromArray(). 2690b3fd2d3SAndreas Gohr * 2700b3fd2d3SAndreas Gohr * @param string $dn 2710b3fd2d3SAndreas Gohr * @param array $attributes 2720b3fd2d3SAndreas Gohr * @return Entry 2730b3fd2d3SAndreas Gohr */ 2740b3fd2d3SAndreas Gohr public static function create(string $dn, array $attributes = []): Entry 2750b3fd2d3SAndreas Gohr { 2760b3fd2d3SAndreas Gohr return self::fromArray($dn, $attributes); 2770b3fd2d3SAndreas Gohr } 2780b3fd2d3SAndreas Gohr 2790b3fd2d3SAndreas Gohr /** 2800b3fd2d3SAndreas Gohr * Construct an entry from an associative array. 2810b3fd2d3SAndreas Gohr * 2820b3fd2d3SAndreas Gohr * @param string $dn 2830b3fd2d3SAndreas Gohr * @param array $attributes 2840b3fd2d3SAndreas Gohr * @return Entry 2850b3fd2d3SAndreas Gohr */ 2860b3fd2d3SAndreas Gohr public static function fromArray(string $dn, array $attributes = []): Entry 2870b3fd2d3SAndreas Gohr { 2880b3fd2d3SAndreas Gohr /** @var Attribute[] $entryAttr */ 2890b3fd2d3SAndreas Gohr $entryAttr = []; 2900b3fd2d3SAndreas Gohr 2910b3fd2d3SAndreas Gohr foreach ($attributes as $attribute => $value) { 292*dad993c5SAndreas Gohr $entryAttr[] = new Attribute($attribute, ...(is_array($value) ? $value : [$value])); 2930b3fd2d3SAndreas Gohr } 2940b3fd2d3SAndreas Gohr 2950b3fd2d3SAndreas Gohr return new self($dn, ...$entryAttr); 2960b3fd2d3SAndreas Gohr } 2970b3fd2d3SAndreas Gohr} 298