xref: /plugin/pureldap/vendor/freedsx/ldap/src/FreeDSx/Ldap/Entry/Entry.php (revision dad993c57a70866aa1db59c43f043769c2eb7ed0)
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