-
- /**
- * Create entity permission data for an entity and role
- * for a particular action.
- */
- protected function createJointPermissionData(SimpleEntityData $entity, int $roleId, array $permissionMap, array $rolePermissionMap, bool $isAdminRole): array
- {
- $permissionPrefix = $entity->type . '-view';
- $roleHasPermission = isset($rolePermissionMap[$roleId . ':' . $permissionPrefix . '-all']);
- $roleHasPermissionOwn = isset($rolePermissionMap[$roleId . ':' . $permissionPrefix . '-own']);
-
- if ($isAdminRole) {
- return $this->createJointPermissionDataArray($entity, $roleId, true, true);
- }
-
- if ($this->entityPermissionsActiveForRole($permissionMap, $entity, $roleId)) {
- $hasAccess = $this->mapHasActiveRestriction($permissionMap, $entity, $roleId);
-
- return $this->createJointPermissionDataArray($entity, $roleId, $hasAccess, $hasAccess);
- }
-
- if ($entity->type === 'book' || $entity->type === 'bookshelf') {
- return $this->createJointPermissionDataArray($entity, $roleId, $roleHasPermission, $roleHasPermissionOwn);
- }
-
- // For chapters and pages, Check if explicit permissions are set on the Book.
- $book = $this->getBook($entity->book_id);
- $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $book, $roleId);
- $hasPermissiveAccessToParents = !$this->entityPermissionsActiveForRole($permissionMap, $book, $roleId);
-
- // For pages with a chapter, Check if explicit permissions are set on the Chapter
- if ($entity->type === 'page' && $entity->chapter_id !== 0) {
- $chapter = $this->getChapter($entity->chapter_id);
- $chapterRestricted = $this->entityPermissionsActiveForRole($permissionMap, $chapter, $roleId);
- $hasPermissiveAccessToParents = $hasPermissiveAccessToParents && !$chapterRestricted;
- if ($chapterRestricted) {
- $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $chapter, $roleId);
- }
- }
-
- return $this->createJointPermissionDataArray(
- $entity,
- $roleId,
- ($hasExplicitAccessToParents || ($roleHasPermission && $hasPermissiveAccessToParents)),
- ($hasExplicitAccessToParents || ($roleHasPermissionOwn && $hasPermissiveAccessToParents))
- );
- }
-
- /**
- * Get the status of a user-specific permission override for the given entity user combo if existing.
- * This can return null where no user-specific permission overrides are applicable.
- */
- protected function getUserPermissionOverrideStatus(SimpleEntityData $entity, int $userId, array $permissionMap): ?bool
- {
- // If direct permissions exists, return those
- $directKey = $entity->type . ':' . $entity->id . ':user:' . $userId;
- if (isset($permissionMap[$directKey])) {
- return $permissionMap[$directKey];
- }
-
- // If a book or shelf, exit out since no parents to check
- if ($entity->type === 'book' || $entity->type === 'bookshelf') {
- return null;
- }
-
- // If a chapter or page, get the parent book permission status.
- // defaults to null where no permission is set.
- $bookKey = 'book:' . $entity->book_id . ':user:' . $userId;
- $bookPermission = $permissionMap[$bookKey] ?? null;
-
- // If a page within a chapter, return the chapter permission if existing otherwise
- // default ot the parent book permission.
- if ($entity->type === 'page' && $entity->chapter_id !== 0) {
- $chapterKey = 'chapter:' . $entity->chapter_id . ':user:' . $userId;
- $chapterPermission = $permissionMap[$chapterKey] ?? null;
- return $chapterPermission ?? $bookPermission;
- }
-
- // Return the book permission status
- return $bookPermission;
- }
-
- /**
- * Check if entity permissions are defined within the given map, for the given entity and role.
- * Checks for the default `role_id=0` backup option as a fallback.
- */
- protected function entityPermissionsActiveForRole(array $permissionMap, SimpleEntityData $entity, int $roleId): bool
- {
- $keyPrefix = $entity->type . ':' . $entity->id . ':';
- return isset($permissionMap[$keyPrefix . 'role:' . $roleId]) || isset($permissionMap[$keyPrefix . 'fallback:0']);
- }
-
- /**
- * Check for an active restriction in an entity map.
- */
- protected function mapHasActiveRestriction(array $permissionMap, SimpleEntityData $entity, int $roleId): bool
- {
- $roleKey = $entity->type . ':' . $entity->id . ':role:' . $roleId;
- $defaultKey = $entity->type . ':' . $entity->id . ':fallback:0';
-
- return $permissionMap[$roleKey] ?? $permissionMap[$defaultKey] ?? false;
- }
-
- /**
- * Create an array of data with the information of an entity jointPermissions.
- * Used to build data for bulk insertion.
- */
- protected function createJointPermissionDataArray(SimpleEntityData $entity, int $roleId, bool $permissionAll, bool $permissionOwn): array
- {
- return [
- 'entity_id' => $entity->id,
- 'entity_type' => $entity->type,
- 'has_permission' => $permissionAll,
- 'has_permission_own' => $permissionOwn,
- 'owned_by' => $entity->owned_by,
- 'role_id' => $roleId,
- ];
- }
-
- /**
- * Create an array of data with the information of an JointUserPermission.
- * Used to build data for bulk insertion.
- */
- protected function createJointUserPermissionDataArray(SimpleEntityData $entity, int $userId, bool $hasPermission): array
- {
- return [
- 'entity_id' => $entity->id,
- 'entity_type' => $entity->type,
- 'has_permission' => $hasPermission,
- 'user_id' => $userId,
- ];
- }