1<?php
2
3/**
4 * This file is part of the FreeDSx LDAP package.
5 *
6 * (c) Chad Sikorra <Chad.Sikorra@gmail.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace FreeDSx\Ldap\Entry;
13
14use ArrayIterator;
15use Countable;
16use IteratorAggregate;
17use Traversable;
18use function array_merge;
19use function array_search;
20use function count;
21use function end;
22use function reset;
23
24/**
25 * Represents a collection of entry objects.
26 *
27 * @author Chad Sikorra <Chad.Sikorra@gmail.com>
28 */
29class Entries implements Countable, IteratorAggregate
30{
31    /**
32     * @var Entry[]
33     */
34    protected $entries = [];
35
36    /**
37     * @param Entry ...$entries
38     */
39    public function __construct(Entry ...$entries)
40    {
41        $this->entries = $entries;
42    }
43
44    /**
45     * @param Entry ...$entries
46     * @return $this
47     */
48    public function add(Entry ...$entries)
49    {
50        $this->entries = array_merge($this->entries, $entries);
51
52        return $this;
53    }
54
55    /**
56     * @param Entry ...$entries
57     * @return $this
58     */
59    public function remove(Entry ...$entries)
60    {
61        foreach ($entries as $entry) {
62            if (($index = array_search($entry, $this->entries, true)) !== false) {
63                unset($this->entries[$index]);
64            }
65        }
66
67        return $this;
68    }
69
70    /**
71     * Check whether or not an entry (either an Entry object or string DN) exists within the entries.
72     *
73     * @param Entry|Dn|string $entry
74     * @return bool
75     */
76    public function has($entry): bool
77    {
78        if ($entry instanceof Entry) {
79            return (array_search($entry, $this->entries, true) !== false);
80        }
81
82        foreach ($this->entries as $entryObj) {
83            if ((string) $entry === $entryObj->getDn()->toString()) {
84                return true;
85            }
86        }
87
88        return false;
89    }
90
91    /**
92     * Get an entry from the collection by its DN.
93     *
94     * @param string $dn
95     * @return Entry|null
96     */
97    public function get(string $dn): ?Entry
98    {
99        foreach ($this->entries as $entry) {
100            if ($entry->getDn()->toString() === $dn) {
101                return $entry;
102            }
103        }
104
105        return null;
106    }
107
108    /**
109     * Get the first entry object, if one exists.
110     *
111     * @return Entry|null
112     */
113    public function first(): ?Entry
114    {
115        $entry = reset($this->entries);
116
117        return $entry === false ? null : $entry;
118    }
119
120    /**
121     * Get the last entry object, if one exists.
122     *
123     * @return Entry|null
124     */
125    public function last(): ?Entry
126    {
127        $entry = end($this->entries);
128        reset($this->entries);
129
130        return $entry === false ? null : $entry;
131    }
132
133    /**
134     * @return Entry[]
135     */
136    public function toArray(): array
137    {
138        return $this->entries;
139    }
140
141    /**
142     * @inheritDoc
143     */
144    public function getIterator(): Traversable
145    {
146        return new ArrayIterator($this->entries);
147    }
148
149    /**
150     * @inheritDoc
151     */
152    public function count(): int
153    {
154        return count($this->entries);
155    }
156}
157