BestowalTodoAssigneeResolver
in package
uses
LocatorAwareTrait
Resolves the live set of members eligible to complete a bestowal to-do item.
Bestowal to-do items are materialized as core ActionItems of the dynamic
assignee type so that "who can flip this check" is recomputed on every access
(officers rotate, role/permission assignments change). The branch context is
pre-resolved and stored on the ActionItem (branch_id); this resolver applies
the same branch-scoped role / permission / office logic used by the award
approval resolver, keeping the two flows consistent while leaving the core
action-item subsystem free of any Awards/Officers dependency.
The dynamic resolver contract (see ActionItemAssigneeResolver) calls
resolveMemberIds(ActionItem $item) and expects an int[] of member IDs. The
per-item configuration is carried in assignee_config:
{ "kind": "role|permission|office", "source_id":
Table of Contents
Constants
- KIND_OFFICE : mixed = 'office'
- KIND_PERMISSION : mixed = 'permission'
- KIND_ROLE : mixed = 'role'
Properties
- $memberOfficeScopeCache : array<int, array<int, array<int, bool>>>
- Request-local cache of a member's branch-scoped current offices.
- $memberRoleScopeCache : array<int, array<int, array<int, bool>>>
- Request-local cache of a member's branch-scoped role assignments.
Methods
- clearMemberScopeCache() : void
- Clear the request-local role/office scope caches.
- isMemberEligible() : bool
- Whether a member may complete a dynamic bestowal to-do, resolved member-centrically (one scope lookup per member, matched in memory).
- resolveMemberIds() : array<string|int, int>
- Resolve eligible member IDs for a dynamic bestowal to-do action item.
- memberHasPermission() : bool
- Permission eligibility via the canonical PermissionsLoader.
- memberOfficeScope() : array<int, array<int, bool>>
- Resolve (and request-cache) a member's branch-indexed current offices.
- memberRoleScope() : array<int, array<int, bool>>
- Resolve (and request-cache) a member's branch-indexed role assignments.
- membersByOffice() : array<string|int, int>
- Current office holders for an office within a branch.
- membersByPermission() : array<string|int, int>
- Members who hold a permission within a branch.
- membersByRole() : array<string|int, int>
- Active members holding a role within a branch.
Constants
KIND_OFFICE
public
mixed
KIND_OFFICE
= 'office'
KIND_PERMISSION
public
mixed
KIND_PERMISSION
= 'permission'
KIND_ROLE
public
mixed
KIND_ROLE
= 'role'
Properties
$memberOfficeScopeCache
Request-local cache of a member's branch-scoped current offices.
protected
static array<int, array<int, array<int, bool>>>
$memberOfficeScopeCache
= []
$memberRoleScopeCache
Request-local cache of a member's branch-scoped role assignments.
protected
static array<int, array<int, array<int, bool>>>
$memberRoleScopeCache
= []
Roles and offices are not covered by PermissionsLoader (which is the canonical, cache-and-validation-backed source for permissions), so the rarely-used role/office assignee kinds resolve them once per member per request and match in memory. Permission eligibility never touches these — it always flows through PermissionsLoader.
Methods
clearMemberScopeCache()
Clear the request-local role/office scope caches.
public
static clearMemberScopeCache() : void
Permission eligibility is served by PermissionsLoader, whose cache
is invalidated by the security cache group on role/permission writes;
this only resets the role/office lookups used by the non-permission kinds.
Useful for long-running CLI workers / tests that mutate state mid-process.
isMemberEligible()
Whether a member may complete a dynamic bestowal to-do, resolved member-centrically (one scope lookup per member, matched in memory).
public
isMemberEligible(ActionItem $item, int $memberId) : bool
This is the cheap counterpart to self::resolveMemberIds() used by the eligibility hot path (My To-Dos badge/list). It never performs a reverse "who holds this permission" query per item. Permission eligibility is delegated to PermissionsLoader::getPermissions() so warrant, membership-status, scoping, and caching are all honored consistently with the rest of the application.
Parameters
- $item : ActionItem
-
The action item to test.
- $memberId : int
-
The member to test.
Return values
boolresolveMemberIds()
Resolve eligible member IDs for a dynamic bestowal to-do action item.
public
resolveMemberIds(ActionItem $item) : array<string|int, int>
Parameters
- $item : ActionItem
-
The action item to resolve.
Return values
array<string|int, int> —Distinct eligible member IDs.
memberHasPermission()
Permission eligibility via the canonical PermissionsLoader.
protected
memberHasPermission(int $memberId, int $permissionId, int $branchId) : bool
PermissionsLoader is the single source of truth for a member's effective
permissions: it validates warrants, membership status, and role windows,
resolves the permission's scoping rule into concrete branch ids, and
caches the result cross-request (member_permissions, invalidated by the
security cache group). A Global-scoped permission carries
branch_ids === null, meaning every branch.
Parameters
- $memberId : int
-
The member to test.
- $permissionId : int
-
The required permission id.
- $branchId : int
-
The branch the to-do is scoped to.
Return values
boolmemberOfficeScope()
Resolve (and request-cache) a member's branch-indexed current offices.
protected
memberOfficeScope(int $memberId) : array<int, array<int, bool>>
Parameters
- $memberId : int
-
The member to resolve.
Return values
array<int, array<int, bool>> —branchId => [officeId => true]
memberRoleScope()
Resolve (and request-cache) a member's branch-indexed role assignments.
protected
memberRoleScope(int $memberId) : array<int, array<int, bool>>
Parameters
- $memberId : int
-
The member to resolve.
Return values
array<int, array<int, bool>> —branchId => [roleId => true]
membersByOffice()
Current office holders for an office within a branch.
protected
membersByOffice(int $officeId, int $branchId) : array<string|int, int>
Parameters
- $officeId : int
-
Office ID.
- $branchId : int
-
Branch scope.
Return values
array<string|int, int>membersByPermission()
Members who hold a permission within a branch.
protected
membersByPermission(int $permissionId, int $branchId) : array<string|int, int>
Delegates to PermissionsLoader::getMembersWithPermissionsQuery() — the canonical, scope-aware reverse lookup — so warrant/membership/scoping validation is applied consistently and never duplicated here.
Parameters
- $permissionId : int
-
Permission ID.
- $branchId : int
-
Branch scope.
Return values
array<string|int, int>membersByRole()
Active members holding a role within a branch.
protected
membersByRole(int $roleId, int $branchId) : array<string|int, int>
Parameters
- $roleId : int
-
Role ID.
- $branchId : int
-
Branch scope.