blob: 08ddca847ad77d3d94eb1a26d5ad94703ade4d8e [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3namespace Adldap\Models;
4
5use InvalidArgumentException;
6
7/**
8 * Class BatchModification.
9 *
10 * A utility class to assist in the creation of LDAP
11 * batch modifications and ensure their validity.
12 */
13class BatchModification
14{
15 /**
16 * The array keys to be used in batch modifications.
17 */
18 const KEY_ATTRIB = 'attrib';
19 const KEY_MODTYPE = 'modtype';
20 const KEY_VALUES = 'values';
21
22 /**
23 * The original value of the attribute before modification.
24 *
25 * @var null
26 */
27 protected $original = null;
28
29 /**
30 * The attribute of the modification.
31 *
32 * @var int|string
33 */
34 protected $attribute;
35
36 /**
37 * The values of the modification.
38 *
39 * @var array
40 */
41 protected $values = [];
42
43 /**
44 * The modtype integer of the batch modification.
45 *
46 * @var int
47 */
48 protected $type;
49
50 /**
51 * Constructor.
52 *
53 * @param string|null $attribute
54 * @param string|int|null $type
55 * @param array $values
56 */
57 public function __construct($attribute = null, $type = null, $values = [])
58 {
59 $this->setAttribute($attribute)
60 ->setType($type)
61 ->setValues($values);
62 }
63
64 /**
65 * Sets the original value of the attribute before modification.
66 *
67 * @param mixed $original
68 *
69 * @return $this
70 */
71 public function setOriginal($original = null)
72 {
73 $this->original = $original;
74
75 return $this;
76 }
77
78 /**
79 * Returns the original value of the attribute before modification.
80 *
81 * @return mixed
82 */
83 public function getOriginal()
84 {
85 return $this->original;
86 }
87
88 /**
89 * Sets the attribute of the modification.
90 *
91 * @param string $attribute
92 *
93 * @return $this
94 */
95 public function setAttribute($attribute)
96 {
97 $this->attribute = $attribute;
98
99 return $this;
100 }
101
102 /**
103 * Returns the attribute of the modification.
104 *
105 * @return string
106 */
107 public function getAttribute()
108 {
109 return $this->attribute;
110 }
111
112 /**
113 * Sets the values of the modification.
114 *
115 * @param array $values
116 *
117 * @return $this
118 */
119 public function setValues(array $values = [])
120 {
121 $this->values = array_map(function ($value) {
122 // We need to make sure all values given to a batch modification are
123 // strings, otherwise we'll receive an LDAP exception when
124 // we try to process the modification.
125 return (string) $value;
126 }, $values);
127
128 return $this;
129 }
130
131 /**
132 * Returns the values of the modification.
133 *
134 * @return array
135 */
136 public function getValues()
137 {
138 return $this->values;
139 }
140
141 /**
142 * Sets the type of the modification.
143 *
144 * @param int|null $type
145 *
146 * @return $this
147 */
148 public function setType($type = null)
149 {
150 if (!is_null($type) && !$this->isValidType($type)) {
151 throw new InvalidArgumentException('Given batch modification type is invalid.');
152 }
153
154 $this->type = $type;
155
156 return $this;
157 }
158
159 /**
160 * Returns the type of the modification.
161 *
162 * @return int
163 */
164 public function getType()
165 {
166 return $this->type;
167 }
168
169 /**
170 * Determines if the batch modification
171 * is valid in its current state.
172 *
173 * @return bool
174 */
175 public function isValid()
176 {
177 return !is_null($this->get());
178 }
179
180 /**
181 * Builds the type of modification automatically
182 * based on the current and original values.
183 *
184 * @return $this
185 */
186 public function build()
187 {
188 $filtered = array_diff(
189 array_map('trim', $this->values),
190 ['']
191 );
192
193 if (is_null($this->original)) {
194 // If the original value is null, we'll assume
195 // that the attribute doesn't exist yet.
196 if (!empty($filtered)) {
197 // If the filtered array is not empty, we can
198 // assume we're looking to add values
199 // to the current attribute.
200 $this->setType(LDAP_MODIFY_BATCH_ADD);
201 }
202
203 // If the filtered array is empty and there is no original
204 // value, then we can ignore this attribute since
205 // we can't push null values to the server.
206 } else {
207 if (empty($filtered)) {
208 // If there's an original value and the array is
209 // empty then we can assume we are looking
210 // to completely remove all values
211 // of the current attribute.
212 $this->setType(LDAP_MODIFY_BATCH_REMOVE_ALL);
213 } else {
214 // If the array isn't empty then we can assume
215 // we're looking to replace all attributes.
216 $this->setType(LDAP_MODIFY_BATCH_REPLACE);
217 }
218 }
219
220 return $this;
221 }
222
223 /**
224 * Returns the built batch modification array.
225 *
226 * @return array|null
227 */
228 public function get()
229 {
230 switch ($this->type) {
231 case LDAP_MODIFY_BATCH_REMOVE_ALL:
232 // A values key cannot be provided when
233 // a remove all type is selected.
234 return [
235 static::KEY_ATTRIB => $this->attribute,
236 static::KEY_MODTYPE => $this->type,
237 ];
238 case LDAP_MODIFY_BATCH_REMOVE:
239 // Fallthrough.
240 case LDAP_MODIFY_BATCH_ADD:
241 // Fallthrough.
242 case LDAP_MODIFY_BATCH_REPLACE:
243 return [
244 static::KEY_ATTRIB => $this->attribute,
245 static::KEY_MODTYPE => $this->type,
246 static::KEY_VALUES => $this->values,
247 ];
248 default:
249 // If the modtype isn't recognized, we'll return null.
250 return;
251 }
252 }
253
254 /**
255 * Determines if the given modtype is valid.
256 *
257 * @param int $type
258 *
259 * @return bool
260 */
261 protected function isValidType($type)
262 {
263 return in_array($type, [
264 LDAP_MODIFY_BATCH_REMOVE_ALL,
265 LDAP_MODIFY_BATCH_REMOVE,
266 LDAP_MODIFY_BATCH_REPLACE,
267 LDAP_MODIFY_BATCH_ADD,
268 ]);
269 }
270}