3 namespace BookStack\Permissions;
5 use BookStack\Permissions\Models\EntityPermission;
7 class MassEntityPermissionEvaluator extends EntityPermissionEvaluator
10 * @var SimpleEntityData[]
12 protected array $entitiesInvolved;
13 protected array $permissionMapCache;
15 public function __construct(array $entitiesInvolved, string $action)
17 $this->entitiesInvolved = $entitiesInvolved;
18 parent::__construct($action);
21 public function evaluateEntityForRole(SimpleEntityData $entity, int $roleId): ?int
23 $typeIdChain = $this->gatherEntityChainTypeIds($entity);
24 $relevantPermissions = $this->getPermissionMapByTypeIdForChainAndRole($typeIdChain, $roleId);
25 $permitsByType = $this->collapseAndCategorisePermissions($typeIdChain, $relevantPermissions);
27 return $this->evaluatePermitsByType($permitsByType);
31 * @param string[] $typeIdChain
32 * @return array<string, EntityPermission[]>
34 protected function getPermissionMapByTypeIdForChainAndRole(array $typeIdChain, int $roleId): array
36 $allPermissions = $this->getPermissionMapByTypeIdAndRoleForAllInvolved();
37 $relevantPermissions = [];
39 // Filter down permissions to just those for current typeId
40 // and current roleID or fallback permissions.
41 foreach ($typeIdChain as $typeId) {
42 $relevantPermissions[$typeId] = [
43 ...($allPermissions[$typeId][$roleId] ?? []),
44 ...($allPermissions[$typeId][0] ?? [])
48 return $relevantPermissions;
52 * @return array<string, array<int, EntityPermission[]>>
54 protected function getPermissionMapByTypeIdAndRoleForAllInvolved(): array
56 if (isset($this->permissionMapCache)) {
57 return $this->permissionMapCache;
60 $entityTypeIdChain = [];
61 foreach ($this->entitiesInvolved as $entity) {
62 $entityTypeIdChain[] = $entity->type . ':' . $entity->id;
65 $permissionMap = $this->getPermissionsMapByTypeId($entityTypeIdChain, []);
67 // Manipulate permission map to also be keyed by roleId.
68 foreach ($permissionMap as $typeId => $permissions) {
69 $permissionMap[$typeId] = [];
70 foreach ($permissions as $permission) {
71 $roleId = $permission->getRawAttribute('role_id');
72 if (!isset($permissionMap[$typeId][$roleId])) {
73 $permissionMap[$typeId][$roleId] = [];
75 $permissionMap[$typeId][$roleId][] = $permission;
79 $this->permissionMapCache = $permissionMap;
81 return $this->permissionMapCache;