- })
- ->get(['role_id', 'user_id', $action])
- ->all();
-
- // See dev/docs/permission-scenario-testing.md for technical details
- // on how permissions should be enforced.
-
- $allowedByTypeById = ['fallback' => [], 'user' => [], 'role' => []];
- /** @var EntityPermission $permission */
- foreach ($relevantPermissions as $permission) {
- $allowedByTypeById[$permission->getAssignedType()][$permission->getAssignedTypeId()] = boolval($permission->$action);
- }
-
- $inheriting = !isset($allowedByTypeById['fallback'][0]);
-
- // Continue up the chain if no applicable entity permission overrides.
- if (count($relevantPermissions) === 0) {
- continue;
- }
-
- // If we have user-specific permissions set, return the status of that
- // since it's the most specific possible.
- if (isset($allowedByTypeById['user'][$userId])) {
- return $allowedByTypeById['user'][$userId];
- }
-
- // If we have role-specific permissions set, allow if any of those
- // role permissions allow access. We do not allow if the role has been previously
- // blocked by a high-priority inheriting level.
- // If we're inheriting at this level, and there's an explicit non-allow permission, we record
- // it for checking up the chain.
- foreach ($allowedByTypeById['role'] as $roleId => $allowed) {
- if ($allowed && !in_array($roleId, $blockedRoleIds)) {
- return true;
- } else if (!$allowed) {
- $blockedRoleIds[] = $roleId;
+ })->get(['entity_id', 'entity_type', 'role_id', 'user_id', $action])
+ ->all();
+
+ $permissionMap = new EntityPermissionMap($relevantPermissions);
+ $permitsByType = ['user' => [], 'fallback' => [], 'role' => []];
+
+ // Collapse and simplify permission structure
+ foreach ($typeIdList as $typeId) {
+ $permissions = $permissionMap->getForEntity($typeId);
+ foreach ($permissions as $permission) {
+ $related = $permission->getAssignedType();
+ $relatedId = $permission->getAssignedTypeId();
+ if (!isset($permitsByType[$related][$relatedId])) {
+ $permitsByType[$related][$relatedId] = $permission->$action;