blob: e610dbfda2d2d01194ca3499a04f00f395a302c6 [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3namespace Adldap\Models\Attributes;
4
5use Adldap\Utilities;
6
7class DistinguishedName
8{
9 /**
10 * The distinguished name components (in order of assembly).
11 *
12 * @var array
13 */
14 protected $components = [
15 'cn' => [],
16 'uid' => [],
17 'ou' => [],
18 'dc' => [],
19 'o' => [],
20 ];
21
22 /**
23 * Constructor.
24 *
25 * @param mixed $baseDn
26 */
27 public function __construct($baseDn = null)
28 {
29 $this->setBase($baseDn);
30 }
31
32 /**
33 * Returns the complete distinguished name.
34 *
35 * @return string
36 */
37 public function __toString()
38 {
39 return $this->get();
40 }
41
42 /**
43 * Returns the complete distinguished name by assembling the RDN components.
44 *
45 * @return string
46 */
47 public function get()
48 {
49 $components = [];
50
51 // We'll go through each component type and assemble its RDN.
52 foreach ($this->components as $component => $values) {
53 array_map(function ($value) use ($component, &$components) {
54 // Assemble the component and escape the value.
55 $components[] = sprintf('%s=%s', $component, ldap_escape($value, '', 2));
56 }, $values);
57 }
58
59 return implode(',', $components);
60 }
61
62 /**
63 * Adds a domain component.
64 *
65 * @param string $dc
66 *
67 * @return DistinguishedName
68 */
69 public function addDc($dc)
70 {
71 $this->addComponent('dc', $dc);
72
73 return $this;
74 }
75
76 /**
77 * Removes a domain component.
78 *
79 * @param string $dc
80 *
81 * @return DistinguishedName
82 */
83 public function removeDc($dc)
84 {
85 $this->removeComponent('dc', $dc);
86
87 return $this;
88 }
89
90 /**
91 * Adds an organization name.
92 *
93 * @param string $o
94 *
95 * @return $this
96 */
97 public function addO($o)
98 {
99 $this->addComponent('o', $o);
100
101 return $this;
102 }
103
104 /**
105 * Removes an organization name.
106 *
107 * @param string $o
108 *
109 * @return DistinguishedName
110 */
111 public function removeO($o)
112 {
113 $this->removeComponent('o', $o);
114
115 return $this;
116 }
117
118 /**
119 * Add a user identifier.
120 *
121 * @param string $uid
122 *
123 * @return DistinguishedName
124 */
125 public function addUid($uid)
126 {
127 $this->addComponent('uid', $uid);
128
129 return $this;
130 }
131
132 /**
133 * Removes a user identifier.
134 *
135 * @param string $uid
136 *
137 * @return DistinguishedName
138 */
139 public function removeUid($uid)
140 {
141 $this->removeComponent('uid', $uid);
142
143 return $this;
144 }
145
146 /**
147 * Adds a common name.
148 *
149 * @param string $cn
150 *
151 * @return DistinguishedName
152 */
153 public function addCn($cn)
154 {
155 $this->addComponent('cn', $cn);
156
157 return $this;
158 }
159
160 /**
161 * Removes a common name.
162 *
163 * @param string $cn
164 *
165 * @return DistinguishedName
166 */
167 public function removeCn($cn)
168 {
169 $this->removeComponent('cn', $cn);
170
171 return $this;
172 }
173
174 /**
175 * Adds an organizational unit.
176 *
177 * @param string $ou
178 *
179 * @return DistinguishedName
180 */
181 public function addOu($ou)
182 {
183 $this->addComponent('ou', $ou);
184
185 return $this;
186 }
187
188 /**
189 * Removes an organizational unit.
190 *
191 * @param string $ou
192 *
193 * @return DistinguishedName
194 */
195 public function removeOu($ou)
196 {
197 $this->removeComponent('ou', $ou);
198
199 return $this;
200 }
201
202 /**
203 * Sets the base RDN of the distinguished name.
204 *
205 * @param string|DistinguishedName $base
206 *
207 * @return DistinguishedName
208 */
209 public function setBase($base)
210 {
211 // Typecast base to string in case we've been given
212 // an instance of the distinguished name object.
213 $base = (string) $base;
214
215 // If the base DN isn't null we'll try to explode it.
216 $base = Utilities::explodeDn($base, false) ?: [];
217
218 // Remove the count key from the exploded distinguished name.
219 unset($base['count']);
220
221 foreach ($base as $key => $rdn) {
222 // We'll break the RDN into pieces
223 $pieces = explode('=', $rdn) ?: [];
224
225 // If there's exactly 2 pieces, then we can work with it.
226 if (count($pieces) === 2) {
227 $attribute = ucfirst(strtolower($pieces[0]));
228
229 $method = 'add'.$attribute;
230
231 if (method_exists($this, $method)) {
232 // We see what type of RDN it is and add each accordingly.
233 call_user_func_array([$this, $method], [$pieces[1]]);
234 }
235 }
236 }
237
238 return $this;
239 }
240
241 /**
242 * Returns an array of all components in the distinguished name.
243 *
244 * If a component name is given ('cn', 'dc' for example) then
245 * the values of that component will be returned.
246 *
247 * @param string|null $component The component to retrieve values of
248 *
249 * @return array
250 */
251 public function getComponents($component = null)
252 {
253 if (is_null($component)) {
254 return $this->components;
255 }
256
257 $this->validateComponentExists($component);
258
259 return $this->components[$component];
260 }
261
262 /**
263 * Adds a component to the distinguished name.
264 *
265 * @param string $component
266 * @param string $value
267 *
268 * @throws \UnexpectedValueException When the given name does not exist.
269 */
270 protected function addComponent($component, $value)
271 {
272 $this->validateComponentExists($component);
273
274 // We need to make sure the value we're given isn't empty before adding it into our components.
275 if (!empty($value)) {
276 $this->components[$component][] = $value;
277 }
278 }
279
280 /**
281 * Removes the given value from the given component.
282 *
283 * @param string $component
284 * @param string $value
285 *
286 * @throws \UnexpectedValueException When the given component does not exist.
287 *
288 * @return void
289 */
290 protected function removeComponent($component, $value)
291 {
292 $this->validateComponentExists($component);
293
294 $this->components[$component] = array_diff($this->components[$component], [$value]);
295 }
296
297 /**
298 * Validates that the given component exists in the available components.
299 *
300 * @param string $component The name of the component to validate.
301 *
302 * @throws \UnexpectedValueException When the given component does not exist.
303 *
304 * @return void
305 */
306 protected function validateComponentExists($component)
307 {
308 if (!array_key_exists($component, $this->components)) {
309 throw new \UnexpectedValueException("The RDN component '$component' does not exist.");
310 }
311 }
312}