PluginProbe
User Access Manager / 2.3.20
User Access Manager v2.3.20
2.3.20 2.3.19 2.3.18 2.3.17 2.3.16 2.3.15 2.3.14 2.3.13 trunk 0.6 0.6.1 0.6.2 0.7 0.7 Beta 0.7.0.1 0.8 0.8.0.1 0.8.0.2 0.9 0.9.1 0.9.1.1 0.9.1.2 0.9.1.3 0.9.1.4 1.0 All 136 releases
user-access-manager / src / UserGroup / AbstractUserGroup.php

AbstractUserGroup.php in User Access Manager 2.3.20, at src/UserGroup/AbstractUserGroup.php

458 lines 13.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace UserAccessManager\UserGroup;
6
7 use Exception;
8 use UserAccessManager\Config\MainConfig;
9 use UserAccessManager\Database\Database;
10 use UserAccessManager\Object\ObjectHandler;
11 use UserAccessManager\ObjectMembership\Exception\MissingObjectMembershipHandlerException;
12 use UserAccessManager\Wrapper\Wordpress;
13
14 abstract class AbstractUserGroup
15 {
16 public const NONE_ROLE = '_none-role_';
17
18 protected ?string $type = null;
19 protected ?string $name = null;
20 protected ?string $description = null;
21 protected string $readAccess = 'group';
22 protected string $writeAccess = 'group';
23 protected bool $ignoreDates = false;
24 protected array $assignedObjects = [];
25 protected array $objectMembership = [];
26 protected array $fullObjectMembership = [];
27 protected ?array $defaultTypes = null;
28
29 /**
30 * @throws UserGroupTypeException
31 */
32 public function __construct(
33 protected Wordpress $wordpress,
34 protected Database $database,
35 protected MainConfig $config,
36 protected ObjectHandler $objectHandler,
37 protected AssignedObjectsLoader $assignedObjectsLoader,
38 protected int|string|null $id = null
39 ) {
40 if ($this->type === null) {
41 throw new UserGroupTypeException('User group type must not null.');
42 }
43 }
44
45 public function getId(): int|string|null
46 {
47 return $this->id;
48 }
49
50 public function getType(): ?string
51 {
52 return $this->type;
53 }
54
55 public function getName(): ?string
56 {
57 return $this->name;
58 }
59
60 public function setName(string $name): void
61 {
62 $this->name = $name;
63 }
64
65 public function getDescription(): ?string
66 {
67 return $this->description;
68 }
69
70 public function setDescription(string $description): void
71 {
72 $this->description = $description;
73 }
74
75 public function getReadAccess(): string
76 {
77 return $this->readAccess;
78 }
79
80 public function setReadAccess(string $readAccess): void
81 {
82 $this->readAccess = $readAccess;
83 }
84
85 public function getWriteAccess(): string
86 {
87 return $this->writeAccess;
88 }
89
90 public function setWriteAccess(string $writeAccess): void
91 {
92 $this->writeAccess = $writeAccess;
93 }
94
95 public function setIgnoreDates(bool $ignoreDates): void
96 {
97 if ($this->ignoreDates !== $ignoreDates) {
98 $this->resetObjects();
99 }
100
101 $this->ignoreDates = $ignoreDates;
102 }
103
104 public function getIgnoreDates(): bool
105 {
106 return $this->ignoreDates;
107 }
108
109 protected function resetObjects(): void
110 {
111 $this->assignedObjects = [];
112 $this->objectMembership = [];
113 $this->fullObjectMembership = [];
114 }
115
116 private function resetObjectsAfterAssignmentChange(): void
117 {
118 $this->assignedObjectsLoader->flush();
119 $this->resetObjects();
120 }
121
122 /**
123 * Returns the general object type of an assignable object type, null if the object type can't be assigned.
124 */
125 private function getAssignableGeneralObjectType(string $objectType): ?string
126 {
127 $generalObjectType = $this->objectHandler->getGeneralObjectType($objectType);
128
129 return ($generalObjectType !== null && $this->objectHandler->isValidObjectType($objectType) === true) ?
130 $generalObjectType : null;
131 }
132
133 /**
134 * @throws Exception
135 */
136 public function delete(): bool
137 {
138 foreach ($this->objectHandler->getAllObjectTypes() as $objectType) {
139 $this->removeObject($objectType);
140 }
141
142 return true;
143 }
144
145 /**
146 * @throws Exception
147 */
148 public function addObject(string $objectType, int|string|null $objectId, $fromDate = null, $toDate = null): bool
149 {
150 $generalObjectType = $this->getAssignableGeneralObjectType($objectType);
151
152 if ($generalObjectType === null) {
153 return false;
154 }
155
156 $success = $this->database->replace(
157 $this->database->getUserGroupToObjectTable(),
158 [
159 'group_id' => $this->id,
160 'group_type' => $this->type,
161 'object_id' => $objectId,
162 'general_object_type' => $generalObjectType,
163 'object_type' => $objectType,
164 'from_date' => $fromDate,
165 'to_date' => $toDate
166 ],
167 ['%s', '%s', '%s', '%s', '%s', '%s', '%s']
168 ) !== false;
169
170 if ($success === true) {
171 $this->resetObjectsAfterAssignmentChange();
172 }
173
174 return $success;
175 }
176
177 /**
178 * @throws Exception
179 */
180 public function removeObject(string $objectType, $objectId = null, bool $ignoreGeneralType = false): bool
181 {
182 $generalObjectType = $this->getAssignableGeneralObjectType($objectType);
183
184 if ($generalObjectType === null) {
185 return false;
186 }
187
188 $objectTypeQuery = " AND `object_type` = '%s' ";
189 $values = [
190 $this->id,
191 $this->type,
192 $objectType
193 ];
194
195 if ($ignoreGeneralType === false) {
196 $objectTypeQuery = " AND (`object_type` = '%s' OR `general_object_type` = '%s') ";
197 $values[] = $generalObjectType;
198 }
199
200 $query = "DELETE FROM `{$this->database->getUserGroupToObjectTable()}`
201 WHERE `group_id` = %d
202 AND `group_type` = '%s'
203 $objectTypeQuery";
204
205 if ($objectId !== null) {
206 $query .= ' AND `object_id` = %d';
207 $values[] = $objectId;
208 }
209
210 $success = $this->database->query($this->database->prepare($query, $values)) !== false;
211
212 if ($success === true) {
213 $this->resetObjectsAfterAssignmentChange();
214 }
215
216 return $success;
217 }
218
219 /**
220 * @return AssignmentInformation[]
221 */
222 public function getAssignedObjects(string $objectType): array
223 {
224 return $this->assignedObjects[$objectType] ??= $this->assignedObjectsLoader->getAssignedObjects(
225 $this->type,
226 $this->id,
227 $objectType,
228 $this->ignoreDates
229 );
230 }
231
232 /**
233 * @throws Exception
234 */
235 public function addDefaultType(
236 string $objectType,
237 int|string|null $fromTime = null,
238 int|string|null $toTime = null
239 ): bool {
240 $fromDate = ($fromTime !== null) ? gmdate('Y-m-d H:i:s', $fromTime) : null;
241 $toTime = ($toTime !== null && $toTime <= $fromTime) ? $fromTime + 1 : $toTime;
242 $toDate = ($toTime !== null) ? gmdate('Y-m-d H:i:s', $toTime) : null;
243
244 return $this->addObject($objectType, '', $fromDate, $toDate);
245 }
246
247 /**
248 * @throws Exception
249 */
250 public function removeDefaultType(string $objectType): bool
251 {
252 return $this->removeObject($objectType, '', true);
253 }
254
255 /**
256 * @return array<string, array{0: int|null, 1: int|null}> Time ranges keyed by the object type.
257 */
258 public function getDefaultGroupForObjectTypes(): array
259 {
260 return $this->defaultTypes ??= $this->loadDefaultGroupForObjectTypes();
261 }
262
263 /**
264 * @return array<string, array{0: int|null, 1: int|null}>
265 */
266 private function loadDefaultGroupForObjectTypes(): array
267 {
268 $query = $this->database->prepare(
269 "SELECT `object_type` AS `objectType`, `from_date` AS `fromDate`, `to_date` AS `toDate`
270 FROM `{$this->database->getUserGroupToObjectTable()}`
271 WHERE `group_id` = '%s'
272 AND `group_type` = '%s'
273 AND `object_id` = ''",
274 [
275 $this->id,
276 $this->type
277 ]
278 );
279
280 $defaultTypes = [];
281
282 foreach ((array) $this->database->getResults($query) as $result) {
283 $defaultTypes[$result->objectType] = [
284 ($result->fromDate !== null) ? strtotime($result->fromDate) : null,
285 ($result->toDate !== null) ? strtotime($result->toDate) : null
286 ];
287 }
288
289 return $defaultTypes;
290 }
291
292 public function isDefaultGroupForObjectType(string $objectType, ?int &$fromTime = null, ?int &$toTime = null): bool
293 {
294 $defaultGroupForObjectTypes = $this->getDefaultGroupForObjectTypes();
295
296 // The reference values have to be reset even when the group is no default group for the object type
297 $fromTime = null;
298 $toTime = null;
299
300 if (isset($defaultGroupForObjectTypes[$objectType]) === false) {
301 return false;
302 }
303
304 [$fromTimestamp, $toTimestamp] = $defaultGroupForObjectTypes[$objectType];
305 $fromTime = ($fromTimestamp !== null) ? (int) $fromTimestamp : null;
306 $toTime = ($toTimestamp !== null) ? (int) $toTimestamp : null;
307
308 return true;
309 }
310
311 public function isObjectAssignedToGroup(
312 string $objectType,
313 int|string|null $objectId,
314 ?AssignmentInformation &$assignmentInformation = null
315 ): bool {
316 $assignmentInformation = $this->getAssignedObjects($objectType)[$objectId] ?? null;
317
318 return $assignmentInformation !== null;
319 }
320
321 /**
322 * @throws Exception
323 */
324 public function isObjectMember(
325 string $objectType,
326 int|string|null $objectId,
327 ?AssignmentInformation &$assignmentInformation = null
328 ): bool {
329 if (isset($this->objectMembership[$objectType][$objectId]) === false) {
330 try {
331 $isMember = $this->objectHandler->getObjectMembershipHandler($objectType)->isMember(
332 $this,
333 $this->config->lockRecursive(),
334 $objectId,
335 $assignmentInformation
336 );
337 } catch (MissingObjectMembershipHandlerException) {
338 $isMember = false;
339 }
340
341 $this->objectMembership[$objectType][$objectId] = ($isMember === true) ? $assignmentInformation : false;
342 }
343
344 $membership = $this->objectMembership[$objectType][$objectId];
345 $assignmentInformation = ($membership instanceof AssignmentInformation) ? $membership : null;
346
347 return $membership !== false;
348 }
349
350 /**
351 * @throws Exception
352 */
353 public function isRoleMember(int|string|null $roleId, ?AssignmentInformation &$assignmentInformation = null): bool
354 {
355 return $this->isObjectMember(ObjectHandler::GENERAL_ROLE_OBJECT_TYPE, $roleId, $assignmentInformation);
356 }
357
358 /**
359 * @throws Exception
360 */
361 public function isUserMember(int|string|null $userId, ?AssignmentInformation &$assignmentInformation = null): bool
362 {
363 return $this->isObjectMember(ObjectHandler::GENERAL_USER_OBJECT_TYPE, $userId, $assignmentInformation);
364 }
365
366 /**
367 * @throws Exception
368 */
369 public function isTermMember(int|string|null $termId, ?AssignmentInformation &$assignmentInformation = null): bool
370 {
371 return $this->isObjectMember(ObjectHandler::GENERAL_TERM_OBJECT_TYPE, $termId, $assignmentInformation);
372 }
373
374 /**
375 * @throws Exception
376 */
377 public function isPostMember(int|string|null $postId, ?AssignmentInformation &$assignmentInformation = null): bool
378 {
379 return $this->isObjectMember(ObjectHandler::GENERAL_POST_OBJECT_TYPE, $postId, $assignmentInformation);
380 }
381
382 /**
383 * @throws Exception
384 */
385 public function getRecursiveMembershipForObject(string $objectType, int|string|null $objectId): array
386 {
387 /**
388 * @var AssignmentInformation $assignmentInformation
389 */
390 if ($this->isObjectMember($objectType, $objectId, $assignmentInformation) === true) {
391 return $assignmentInformation->getRecursiveMembership();
392 }
393
394 return [];
395 }
396
397 /**
398 * @throws Exception
399 */
400 public function isLockedRecursive(string $objectType, int|string|null $objectId): bool
401 {
402 return count($this->getRecursiveMembershipForObject($objectType, $objectId)) > 0;
403 }
404
405 /**
406 * @throws Exception
407 */
408 public function getAssignedObjectsByType(string $objectType): array
409 {
410 if (isset($this->fullObjectMembership[$objectType]) === false) {
411 try {
412 $membershipHandler = $this->objectHandler->getObjectMembershipHandler($objectType);
413 $this->fullObjectMembership[$objectType] = $membershipHandler->getFullObjects(
414 $this,
415 $this->config->lockRecursive(),
416 ($objectType === $this->objectHandler->getGeneralObjectType($objectType)) ? null : $objectType
417 );
418 } catch (MissingObjectMembershipHandlerException) {
419 $this->fullObjectMembership[$objectType] = [];
420 }
421 }
422
423 return $this->fullObjectMembership[$objectType];
424 }
425
426 /**
427 * @throws Exception
428 */
429 public function getFullRoles(): array
430 {
431 return $this->getAssignedObjectsByType(ObjectHandler::GENERAL_ROLE_OBJECT_TYPE);
432 }
433
434 /**
435 * @throws Exception
436 */
437 public function getFullUsers(): array
438 {
439 return $this->getAssignedObjectsByType(ObjectHandler::GENERAL_USER_OBJECT_TYPE);
440 }
441
442 /**
443 * @throws Exception
444 */
445 public function getFullTerms(): array
446 {
447 return $this->getAssignedObjectsByType(ObjectHandler::GENERAL_TERM_OBJECT_TYPE);
448 }
449
450 /**
451 * @throws Exception
452 */
453 public function getFullPosts(): array
454 {
455 return $this->getAssignedObjectsByType(ObjectHandler::GENERAL_POST_OBJECT_TYPE);
456 }
457 }
458